brintos

brintos / linux-shallow public Read only

0
0
Text · 24.5 KiB · 6217e61 Raw
896 lines · c
1// SPDX-License-Identifier: GPL-2.02//3// Ingenic JZ4760 CODEC driver4//5// Copyright (C) 2021, Christophe Branchereau <cbranchereau@gmail.com>6// Copyright (C) 2021, Paul Cercueil <paul@crapouillou.net>7 8#include <linux/bitfield.h>9#include <linux/clk.h>10#include <linux/delay.h>11#include <linux/iopoll.h>12#include <linux/module.h>13#include <linux/regmap.h>14#include <linux/time64.h>15 16#include <sound/pcm_params.h>17#include <sound/soc.h>18#include <sound/soc-dai.h>19#include <sound/soc-dapm.h>20#include <sound/tlv.h>21 22#define ICDC_RGADW_OFFSET		0x0023#define ICDC_RGDATA_OFFSET		0x0424 25/* ICDC internal register access control register(RGADW) */26#define ICDC_RGADW_RGWR			BIT(16)27#define	ICDC_RGADW_RGADDR_MASK		GENMASK(14, 8)28#define	ICDC_RGADW_RGDIN_MASK		GENMASK(7, 0)29 30/* ICDC internal register data output register (RGDATA)*/31#define ICDC_RGDATA_IRQ			BIT(8)32#define ICDC_RGDATA_RGDOUT_MASK		GENMASK(7, 0)33 34/* Internal register space, accessed through regmap */35enum {36	JZ4760_CODEC_REG_SR,37	JZ4760_CODEC_REG_AICR,38	JZ4760_CODEC_REG_CR1,39	JZ4760_CODEC_REG_CR2,40	JZ4760_CODEC_REG_CR3,41	JZ4760_CODEC_REG_CR4,42	JZ4760_CODEC_REG_CCR1,43	JZ4760_CODEC_REG_CCR2,44	JZ4760_CODEC_REG_PMR1,45	JZ4760_CODEC_REG_PMR2,46	JZ4760_CODEC_REG_ICR,47	JZ4760_CODEC_REG_IFR,48	JZ4760_CODEC_REG_GCR1,49	JZ4760_CODEC_REG_GCR2,50	JZ4760_CODEC_REG_GCR3,51	JZ4760_CODEC_REG_GCR4,52	JZ4760_CODEC_REG_GCR5,53	JZ4760_CODEC_REG_GCR6,54	JZ4760_CODEC_REG_GCR7,55	JZ4760_CODEC_REG_GCR8,56	JZ4760_CODEC_REG_GCR9,57	JZ4760_CODEC_REG_AGC1,58	JZ4760_CODEC_REG_AGC2,59	JZ4760_CODEC_REG_AGC3,60	JZ4760_CODEC_REG_AGC4,61	JZ4760_CODEC_REG_AGC5,62	JZ4760_CODEC_REG_MIX1,63	JZ4760_CODEC_REG_MIX2,64};65 66#define REG_AICR_DAC_ADWL_MASK		GENMASK(7, 6)67#define REG_AICR_DAC_SERIAL		BIT(3)68#define REG_AICR_DAC_I2S		BIT(1)69 70#define REG_AICR_ADC_ADWL_MASK		GENMASK(5, 4)71 72#define REG_AICR_ADC_SERIAL		BIT(2)73#define REG_AICR_ADC_I2S		BIT(0)74 75#define REG_CR1_HP_LOAD			BIT(7)76#define REG_CR1_HP_MUTE			BIT(5)77#define REG_CR1_LO_MUTE_OFFSET		478#define REG_CR1_BTL_MUTE_OFFSET		379#define REG_CR1_OUTSEL_OFFSET		080#define REG_CR1_OUTSEL_MASK		GENMASK(1, REG_CR1_OUTSEL_OFFSET)81 82#define REG_CR2_DAC_MONO		BIT(7)83#define REG_CR2_DAC_MUTE		BIT(5)84#define REG_CR2_DAC_NOMAD		BIT(1)85#define REG_CR2_DAC_RIGHT_ONLY		BIT(0)86 87#define REG_CR3_ADC_INSEL_OFFSET	288#define REG_CR3_ADC_INSEL_MASK		GENMASK(3, REG_CR3_ADC_INSEL_OFFSET)89#define REG_CR3_MICSTEREO_OFFSET	190#define REG_CR3_MICDIFF_OFFSET		091 92#define REG_CR4_ADC_HPF_OFFSET		793#define REG_CR4_ADC_RIGHT_ONLY		BIT(0)94 95#define REG_CCR1_CRYSTAL_MASK		GENMASK(3, 0)96 97#define REG_CCR2_DAC_FREQ_MASK		GENMASK(7, 4)98#define REG_CCR2_ADC_FREQ_MASK		GENMASK(3, 0)99 100#define REG_PMR1_SB			BIT(7)101#define REG_PMR1_SB_SLEEP		BIT(6)102#define REG_PMR1_SB_AIP_OFFSET		5103#define REG_PMR1_SB_LINE_OFFSET		4104#define REG_PMR1_SB_MIC1_OFFSET		3105#define REG_PMR1_SB_MIC2_OFFSET		2106#define REG_PMR1_SB_BYPASS_OFFSET	1107#define REG_PMR1_SB_MICBIAS_OFFSET	0108 109#define REG_PMR2_SB_ADC_OFFSET		4110#define REG_PMR2_SB_HP_OFFSET		3111#define REG_PMR2_SB_BTL_OFFSET		2112#define REG_PMR2_SB_LOUT_OFFSET		1113#define REG_PMR2_SB_DAC_OFFSET		0114 115#define REG_ICR_INT_FORM_MASK		GENMASK(7, 6)116#define REG_ICR_ALL_MASK		GENMASK(5, 0)117#define REG_ICR_JACK_MASK		BIT(5)118#define REG_ICR_SCMC_MASK		BIT(4)119#define REG_ICR_RUP_MASK		BIT(3)120#define REG_ICR_RDO_MASK		BIT(2)121#define REG_ICR_GUP_MASK		BIT(1)122#define REG_ICR_GDO_MASK		BIT(0)123 124#define REG_IFR_ALL_MASK		GENMASK(5, 0)125#define REG_IFR_JACK			BIT(6)126#define REG_IFR_JACK_EVENT		BIT(5)127#define REG_IFR_SCMC			BIT(4)128#define REG_IFR_RUP			BIT(3)129#define REG_IFR_RDO			BIT(2)130#define REG_IFR_GUP			BIT(1)131#define REG_IFR_GDO			BIT(0)132 133#define REG_GCR_GAIN_OFFSET		0134#define REG_GCR_GAIN_MAX		0x1f135 136#define REG_GCR_RL			BIT(7)137 138#define REG_GCR_GIM1_MASK		GENMASK(5, 3)139#define REG_GCR_GIM2_MASK		GENMASK(2, 0)140#define REG_GCR_GIM_GAIN_MAX		7141 142#define REG_AGC1_EN			BIT(7)143#define REG_AGC1_TARGET_MASK		GENMASK(5, 2)144 145#define REG_AGC2_NG_THR_MASK		GENMASK(6, 4)146#define REG_AGC2_HOLD_MASK		GENMASK(3, 0)147 148#define REG_AGC3_ATK_MASK		GENMASK(7, 4)149#define REG_AGC3_DCY_MASK		GENMASK(3, 0)150 151#define REG_AGC4_AGC_MAX_MASK		GENMASK(4, 0)152 153#define REG_AGC5_AGC_MIN_MASK		GENMASK(4, 0)154 155#define REG_MIX1_MIX_REC_MASK		GENMASK(7, 6)156#define REG_MIX1_GIMIX_MASK		GENMASK(4, 0)157 158#define REG_MIX2_DAC_MIX_MASK		GENMASK(7, 6)159#define REG_MIX2_GOMIX_MASK		GENMASK(4, 0)160 161/* codec private data */162struct jz_codec {163	struct device *dev;164	struct regmap *regmap;165	void __iomem *base;166	struct clk *clk;167};168 169static int jz4760_codec_set_bias_level(struct snd_soc_component *codec,170				       enum snd_soc_bias_level level)171{172	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);173	struct regmap *regmap = jz_codec->regmap;174 175	switch (level) {176	case SND_SOC_BIAS_PREPARE:177		/* Reset all interrupt flags. */178		regmap_write(regmap, JZ4760_CODEC_REG_IFR, REG_IFR_ALL_MASK);179 180		regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);181		msleep(250);182		regmap_clear_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);183		msleep(400);184		break;185	case SND_SOC_BIAS_STANDBY:186		regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB_SLEEP);187		regmap_set_bits(regmap, JZ4760_CODEC_REG_PMR1, REG_PMR1_SB);188		break;189	default:190		break;191	}192 193	return 0;194}195 196static int jz4760_codec_startup(struct snd_pcm_substream *substream,197				struct snd_soc_dai *dai)198{199	struct snd_soc_component *codec = dai->component;200	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);201	int ret = 0;202 203	/*204	 * SYSCLK output from the codec to the AIC is required to keep the205	 * DMA transfer going during playback when all audible outputs have206	 * been disabled.207	 */208	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)209		ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");210	return ret;211}212 213static void jz4760_codec_shutdown(struct snd_pcm_substream *substream,214				  struct snd_soc_dai *dai)215{216	struct snd_soc_component *codec = dai->component;217	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);218 219	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)220		snd_soc_dapm_disable_pin(dapm, "SYSCLK");221}222 223 224static int jz4760_codec_pcm_trigger(struct snd_pcm_substream *substream,225				    int cmd, struct snd_soc_dai *dai)226{227	struct snd_soc_component *codec = dai->component;228	int ret = 0;229 230	switch (cmd) {231	case SNDRV_PCM_TRIGGER_START:232	case SNDRV_PCM_TRIGGER_RESUME:233	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:234		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)235			snd_soc_component_force_bias_level(codec, SND_SOC_BIAS_ON);236		break;237	case SNDRV_PCM_TRIGGER_STOP:238	case SNDRV_PCM_TRIGGER_SUSPEND:239	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:240		/* do nothing */241		break;242	default:243		ret = -EINVAL;244	}245 246	return ret;247}248 249static int jz4760_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)250{251	struct snd_soc_component *codec = dai->component;252	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);253	unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;254	unsigned int val, reg;255	int change, err;256 257	change = snd_soc_component_update_bits(codec, JZ4760_CODEC_REG_CR2,258					       REG_CR2_DAC_MUTE,259					       mute ? REG_CR2_DAC_MUTE : 0);260	if (change == 1) {261		regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_PMR2, &val);262 263		if (val & BIT(REG_PMR2_SB_DAC_OFFSET))264			return 1;265 266		err = regmap_read_poll_timeout(jz_codec->regmap,267					       JZ4760_CODEC_REG_IFR,268					       val, val & gain_bit,269					       1000, 1 * USEC_PER_SEC);270		if (err) {271			dev_err(jz_codec->dev,272				"Timeout while setting digital mute: %d", err);273			return err;274		}275 276		/* clear GUP/GDO flag */277		regmap_write(jz_codec->regmap, JZ4760_CODEC_REG_IFR, gain_bit);278	}279 280	regmap_read(jz_codec->regmap, JZ4760_CODEC_REG_CR2, &reg);281 282	return 0;283}284 285/* unit: 0.01dB */286static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 100);287static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);288static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 100);289static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);290static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);291 292/* Unconditional controls. */293static const struct snd_kcontrol_new jz4760_codec_snd_controls[] = {294	/* record gain control */295	SOC_DOUBLE_R_TLV("PCM Capture Volume",296			 JZ4760_CODEC_REG_GCR9, JZ4760_CODEC_REG_GCR8,297			 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 0, adc_tlv),298 299	SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",300			 JZ4760_CODEC_REG_GCR4, JZ4760_CODEC_REG_GCR3,301			 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),302 303	SOC_SINGLE_TLV("Mixer Capture Volume",304		       JZ4760_CODEC_REG_MIX1,305		       REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),306 307	SOC_SINGLE_TLV("Mixer Playback Volume",308		       JZ4760_CODEC_REG_MIX2,309		       REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),310 311	SOC_SINGLE("High-Pass Filter Capture Switch",312		   JZ4760_CODEC_REG_CR4,313		   REG_CR4_ADC_HPF_OFFSET, 1, 0),314};315 316static const struct snd_kcontrol_new jz4760_codec_pcm_playback_controls[] = {317	{318		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,319		.name = "Volume",320		.info = snd_soc_info_volsw,321		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ322			| SNDRV_CTL_ELEM_ACCESS_READWRITE,323		.tlv.p = dac_tlv,324		.get = snd_soc_dapm_get_volsw,325		.put = snd_soc_dapm_put_volsw,326		.private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR6,327						    JZ4760_CODEC_REG_GCR5,328						    REG_GCR_GAIN_OFFSET,329						    REG_GCR_GAIN_MAX, 1),330	},331};332 333static const struct snd_kcontrol_new jz4760_codec_hp_playback_controls[] = {334	{335		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,336		.name = "Volume",337		.info = snd_soc_info_volsw,338		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ339			| SNDRV_CTL_ELEM_ACCESS_READWRITE,340		.tlv.p = out_tlv,341		.get = snd_soc_dapm_get_volsw,342		.put = snd_soc_dapm_put_volsw,343		.private_value = SOC_DOUBLE_R_VALUE(JZ4760_CODEC_REG_GCR2,344						    JZ4760_CODEC_REG_GCR1,345						    REG_GCR_GAIN_OFFSET,346						    REG_GCR_GAIN_MAX, 1),347	},348};349 350static int hpout_event(struct snd_soc_dapm_widget *w,351		       struct snd_kcontrol *kcontrol, int event)352{353	struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);354	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);355	unsigned int val;356	int err;357 358	switch (event) {359	case SND_SOC_DAPM_PRE_PMU:360		/* unmute HP */361		regmap_clear_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,362				  REG_CR1_HP_MUTE);363		break;364 365	case SND_SOC_DAPM_POST_PMU:366		/* wait for ramp-up complete (RUP) */367		err = regmap_read_poll_timeout(jz_codec->regmap,368					       JZ4760_CODEC_REG_IFR,369					       val, val & REG_IFR_RUP,370					       1000, 1 * USEC_PER_SEC);371		if (err) {372			dev_err(jz_codec->dev, "RUP timeout: %d", err);373			return err;374		}375 376		/* clear RUP flag */377		regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,378				REG_IFR_RUP);379 380		break;381 382	case SND_SOC_DAPM_POST_PMD:383		/* mute HP */384		regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR1,385				REG_CR1_HP_MUTE);386 387		err = regmap_read_poll_timeout(jz_codec->regmap,388					       JZ4760_CODEC_REG_IFR,389					       val, val & REG_IFR_RDO,390					       1000, 1 * USEC_PER_SEC);391		if (err) {392			dev_err(jz_codec->dev, "RDO timeout: %d", err);393			return err;394		}395 396		/* clear RDO flag */397		regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_IFR,398				REG_IFR_RDO);399 400		break;401	}402 403	return 0;404}405 406static const char * const jz4760_codec_hp_texts[] = {407	"PCM", "Line In", "Mic 1", "Mic 2"408};409 410static const unsigned int jz4760_codec_hp_values[] = { 3, 2, 0, 1 };411 412static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_hp_enum,413				  JZ4760_CODEC_REG_CR1,414				  REG_CR1_OUTSEL_OFFSET,415				  REG_CR1_OUTSEL_MASK >> REG_CR1_OUTSEL_OFFSET,416				  jz4760_codec_hp_texts,417				  jz4760_codec_hp_values);418static const struct snd_kcontrol_new jz4760_codec_hp_source =419			SOC_DAPM_ENUM("Route", jz4760_codec_hp_enum);420 421static const char * const jz4760_codec_cap_texts[] = {422	"Line In", "Mic 1", "Mic 2"423};424 425static const unsigned int jz4760_codec_cap_values[] = { 2, 0, 1 };426 427static SOC_VALUE_ENUM_SINGLE_DECL(jz4760_codec_cap_enum,428				  JZ4760_CODEC_REG_CR3,429				  REG_CR3_ADC_INSEL_OFFSET,430				  REG_CR3_ADC_INSEL_MASK >> REG_CR3_ADC_INSEL_OFFSET,431				  jz4760_codec_cap_texts,432				  jz4760_codec_cap_values);433static const struct snd_kcontrol_new jz4760_codec_cap_source =434			SOC_DAPM_ENUM("Route", jz4760_codec_cap_enum);435 436static const struct snd_kcontrol_new jz4760_codec_mic_controls[] = {437	SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4760_CODEC_REG_CR3,438			REG_CR3_MICSTEREO_OFFSET, 1, 0),439};440 441static const struct snd_kcontrol_new jz4760_codec_line_out_switch =442	SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,443			REG_CR1_LO_MUTE_OFFSET, 0, 0);444static const struct snd_kcontrol_new jz4760_codec_btl_out_switch =445	SOC_DAPM_SINGLE("Switch", JZ4760_CODEC_REG_CR1,446			REG_CR1_BTL_MUTE_OFFSET, 0, 0);447 448static const struct snd_soc_dapm_widget jz4760_codec_dapm_widgets[] = {449	SND_SOC_DAPM_PGA_E("HP Out", JZ4760_CODEC_REG_PMR2,450			   REG_PMR2_SB_HP_OFFSET, 1, NULL, 0, hpout_event,451			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |452			   SND_SOC_DAPM_POST_PMD),453 454	SND_SOC_DAPM_SWITCH("Line Out", JZ4760_CODEC_REG_PMR2,455			    REG_PMR2_SB_LOUT_OFFSET, 1,456			    &jz4760_codec_line_out_switch),457 458	SND_SOC_DAPM_SWITCH("BTL Out", JZ4760_CODEC_REG_PMR2,459			    REG_PMR2_SB_BTL_OFFSET, 1,460			    &jz4760_codec_btl_out_switch),461 462	SND_SOC_DAPM_PGA("Line In", JZ4760_CODEC_REG_PMR1,463			 REG_PMR1_SB_LINE_OFFSET, 1, NULL, 0),464 465	SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,466			 &jz4760_codec_hp_source),467 468	SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,469			 &jz4760_codec_cap_source),470 471	SND_SOC_DAPM_PGA("Mic 1", JZ4760_CODEC_REG_PMR1,472			 REG_PMR1_SB_MIC1_OFFSET, 1, NULL, 0),473 474	SND_SOC_DAPM_PGA("Mic 2", JZ4760_CODEC_REG_PMR1,475			 REG_PMR1_SB_MIC2_OFFSET, 1, NULL, 0),476 477	SND_SOC_DAPM_PGA("Mic Diff", JZ4760_CODEC_REG_CR3,478			 REG_CR3_MICDIFF_OFFSET, 0, NULL, 0),479 480	SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,481			   jz4760_codec_mic_controls,482			   ARRAY_SIZE(jz4760_codec_mic_controls)),483 484	SND_SOC_DAPM_PGA("Line In Bypass", JZ4760_CODEC_REG_PMR1,485			 REG_PMR1_SB_BYPASS_OFFSET, 1, NULL, 0),486 487	SND_SOC_DAPM_ADC("ADC", "Capture", JZ4760_CODEC_REG_PMR2,488			 REG_PMR2_SB_ADC_OFFSET, 1),489 490	SND_SOC_DAPM_DAC("DAC", "Playback", JZ4760_CODEC_REG_PMR2,491			 REG_PMR2_SB_DAC_OFFSET, 1),492 493	SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,494			   jz4760_codec_pcm_playback_controls,495			   ARRAY_SIZE(jz4760_codec_pcm_playback_controls)),496 497	SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,498			   jz4760_codec_hp_playback_controls,499			   ARRAY_SIZE(jz4760_codec_hp_playback_controls)),500 501	SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4760_CODEC_REG_PMR1,502			    REG_PMR1_SB_MICBIAS_OFFSET, 1, NULL, 0),503 504	SND_SOC_DAPM_INPUT("MIC1P"),505	SND_SOC_DAPM_INPUT("MIC1N"),506	SND_SOC_DAPM_INPUT("MIC2P"),507	SND_SOC_DAPM_INPUT("MIC2N"),508 509	SND_SOC_DAPM_INPUT("LLINEIN"),510	SND_SOC_DAPM_INPUT("RLINEIN"),511 512	SND_SOC_DAPM_OUTPUT("LHPOUT"),513	SND_SOC_DAPM_OUTPUT("RHPOUT"),514 515	SND_SOC_DAPM_OUTPUT("LOUT"),516	SND_SOC_DAPM_OUTPUT("ROUT"),517 518	SND_SOC_DAPM_OUTPUT("BTLP"),519	SND_SOC_DAPM_OUTPUT("BTLN"),520 521	SND_SOC_DAPM_OUTPUT("SYSCLK"),522};523 524/* Unconditional routes. */525static const struct snd_soc_dapm_route jz4760_codec_dapm_routes[] = {526	{ "Mic 1", NULL, "MIC1P" },527	{ "Mic Diff", NULL, "MIC1N" },528	{ "Mic 1", NULL, "Mic Diff" },529	{ "Mic 2", NULL, "MIC2P" },530	{ "Mic Diff", NULL, "MIC2N" },531	{ "Mic 2", NULL, "Mic Diff" },532 533	{ "Line In", NULL, "LLINEIN" },534	{ "Line In", NULL, "RLINEIN" },535 536	{ "Mic", "Stereo Capture Switch", "Mic 1" },537	{ "Mic", "Stereo Capture Switch", "Mic 2" },538	{ "Headphones Source", "Mic 1", "Mic" },539	{ "Headphones Source", "Mic 2", "Mic" },540	{ "Capture Source", "Mic 1", "Mic" },541	{ "Capture Source", "Mic 2", "Mic" },542 543	{ "Capture Source", "Line In", "Line In" },544	{ "Capture Source", "Mic 1", "Mic 1" },545	{ "Capture Source", "Mic 2", "Mic 2" },546	{ "ADC", NULL, "Capture Source" },547 548	{ "Line In Bypass", NULL, "Line In" },549 550	{ "Headphones Source", "Mic 1", "Mic 1" },551	{ "Headphones Source", "Mic 2", "Mic 2" },552	{ "Headphones Source", "Line In", "Line In Bypass" },553	{ "Headphones Source", "PCM", "Headphones Playback" },554	{ "HP Out", NULL, "Headphones Source" },555 556	{ "LHPOUT", NULL, "HP Out" },557	{ "RHPOUT", NULL, "HP Out" },558	{ "Line Out", "Switch", "HP Out" },559 560	{ "LOUT", NULL, "Line Out" },561	{ "ROUT", NULL, "Line Out" },562	{ "BTL Out", "Switch", "Line Out" },563 564	{ "BTLP", NULL, "BTL Out"},565	{ "BTLN", NULL, "BTL Out"},566 567	{ "PCM Playback", "Volume", "DAC" },568	{ "Headphones Playback", "Volume", "PCM Playback" },569 570	{ "SYSCLK", NULL, "DAC" },571};572 573static void jz4760_codec_codec_init_regs(struct snd_soc_component *codec)574{575	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);576	struct regmap *regmap = jz_codec->regmap;577 578	/* Collect updates for later sending. */579	regcache_cache_only(regmap, true);580 581	/* default Amp output to PCM */582	regmap_set_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_OUTSEL_MASK);583 584	/* Disable stereo mic */585	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,586			  BIT(REG_CR3_MICSTEREO_OFFSET));587 588	/* Set mic 1 as default source for ADC */589	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR3,590			  REG_CR3_ADC_INSEL_MASK);591 592	/* ADC/DAC: serial + i2s */593	regmap_set_bits(regmap, JZ4760_CODEC_REG_AICR,594			REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S |595			REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);596 597	/* The generated IRQ is a high level */598	regmap_clear_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);599	regmap_update_bits(regmap, JZ4760_CODEC_REG_ICR, REG_ICR_ALL_MASK,600			   REG_ICR_JACK_MASK | REG_ICR_RUP_MASK |601			   REG_ICR_RDO_MASK  | REG_ICR_GUP_MASK |602			   REG_ICR_GDO_MASK);603 604	/* 12M oscillator */605	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CCR1, REG_CCR1_CRYSTAL_MASK);606 607	/* 0: 16ohm/220uF, 1: 10kohm/1uF */608	regmap_clear_bits(regmap, JZ4760_CODEC_REG_CR1, REG_CR1_HP_LOAD);609 610	/* default to NOMAD */611	regmap_set_bits(jz_codec->regmap, JZ4760_CODEC_REG_CR2,612			REG_CR2_DAC_NOMAD);613 614	/* disable automatic gain */615	regmap_clear_bits(regmap, JZ4760_CODEC_REG_AGC1, REG_AGC1_EN);616 617	/* Independent L/R DAC gain control */618	regmap_clear_bits(regmap, JZ4760_CODEC_REG_GCR5,619			  REG_GCR_RL);620 621	/* Send collected updates. */622	regcache_cache_only(regmap, false);623	regcache_sync(regmap);624}625 626static int jz4760_codec_codec_probe(struct snd_soc_component *codec)627{628	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);629 630	clk_prepare_enable(jz_codec->clk);631 632	jz4760_codec_codec_init_regs(codec);633 634	return 0;635}636 637static void jz4760_codec_codec_remove(struct snd_soc_component *codec)638{639	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);640 641	clk_disable_unprepare(jz_codec->clk);642}643 644static const struct snd_soc_component_driver jz4760_codec_soc_codec_dev = {645	.probe			= jz4760_codec_codec_probe,646	.remove			= jz4760_codec_codec_remove,647	.set_bias_level		= jz4760_codec_set_bias_level,648	.controls		= jz4760_codec_snd_controls,649	.num_controls		= ARRAY_SIZE(jz4760_codec_snd_controls),650	.dapm_widgets		= jz4760_codec_dapm_widgets,651	.num_dapm_widgets	= ARRAY_SIZE(jz4760_codec_dapm_widgets),652	.dapm_routes		= jz4760_codec_dapm_routes,653	.num_dapm_routes	= ARRAY_SIZE(jz4760_codec_dapm_routes),654	.suspend_bias_off	= 1,655	.use_pmdown_time	= 1,656};657 658static const unsigned int jz4760_codec_sample_rates[] = {659	96000, 48000, 44100, 32000,660	24000, 22050, 16000, 12000,661	11025, 9600, 8000,662};663 664static int jz4760_codec_hw_params(struct snd_pcm_substream *substream,665				  struct snd_pcm_hw_params *params,666				  struct snd_soc_dai *dai)667{668	struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);669	unsigned int rate, bit_width;670 671	switch (params_format(params)) {672	case SNDRV_PCM_FORMAT_S16_LE:673		bit_width = 0;674		break;675	case SNDRV_PCM_FORMAT_S18_3LE:676		bit_width = 1;677		break;678	case SNDRV_PCM_FORMAT_S20_3LE:679		bit_width = 2;680		break;681	case SNDRV_PCM_FORMAT_S24_3LE:682		bit_width = 3;683		break;684	default:685		return -EINVAL;686	}687 688	for (rate = 0; rate < ARRAY_SIZE(jz4760_codec_sample_rates); rate++) {689		if (jz4760_codec_sample_rates[rate] == params_rate(params))690			break;691	}692 693	if (rate == ARRAY_SIZE(jz4760_codec_sample_rates))694		return -EINVAL;695 696	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {697		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,698				   REG_AICR_DAC_ADWL_MASK,699				   FIELD_PREP(REG_AICR_DAC_ADWL_MASK, bit_width));700		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,701				   REG_CCR2_DAC_FREQ_MASK,702				   FIELD_PREP(REG_CCR2_DAC_FREQ_MASK, rate));703	} else {704		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_AICR,705				   REG_AICR_ADC_ADWL_MASK,706				   FIELD_PREP(REG_AICR_ADC_ADWL_MASK, bit_width));707		regmap_update_bits(codec->regmap, JZ4760_CODEC_REG_CCR2,708				   REG_CCR2_ADC_FREQ_MASK,709				   FIELD_PREP(REG_CCR2_ADC_FREQ_MASK, rate));710	}711 712	return 0;713}714 715static const struct snd_soc_dai_ops jz4760_codec_dai_ops = {716	.startup	= jz4760_codec_startup,717	.shutdown	= jz4760_codec_shutdown,718	.hw_params	= jz4760_codec_hw_params,719	.trigger	= jz4760_codec_pcm_trigger,720	.mute_stream	= jz4760_codec_mute_stream,721	.no_capture_mute = 1,722};723 724#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | \725			  SNDRV_PCM_FMTBIT_S18_3LE | \726			  SNDRV_PCM_FMTBIT_S20_3LE | \727			  SNDRV_PCM_FMTBIT_S24_3LE)728 729static struct snd_soc_dai_driver jz4760_codec_dai = {730	.name = "jz4760-hifi",731	.playback = {732		.stream_name = "Playback",733		.channels_min = 2,734		.channels_max = 2,735		.rates = SNDRV_PCM_RATE_8000_96000,736		.formats = JZ_CODEC_FORMATS,737	},738	.capture = {739		.stream_name = "Capture",740		.channels_min = 2,741		.channels_max = 2,742		.rates = SNDRV_PCM_RATE_8000_96000,743		.formats = JZ_CODEC_FORMATS,744	},745	.ops = &jz4760_codec_dai_ops,746};747 748static bool jz4760_codec_volatile(struct device *dev, unsigned int reg)749{750	return reg == JZ4760_CODEC_REG_SR || reg == JZ4760_CODEC_REG_IFR;751}752 753static bool jz4760_codec_writeable(struct device *dev, unsigned int reg)754{755	switch (reg) {756	case JZ4760_CODEC_REG_SR:757		return false;758	default:759		return true;760	}761}762 763static int jz4760_codec_io_wait(struct jz_codec *codec)764{765	u32 reg;766 767	return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,768				  !(reg & ICDC_RGADW_RGWR),769				  1000, 1 * USEC_PER_SEC);770}771 772static int jz4760_codec_reg_read(void *context, unsigned int reg,773				 unsigned int *val)774{775	struct jz_codec *codec = context;776	unsigned int i;777	u32 tmp;778	int ret;779 780	ret = jz4760_codec_io_wait(codec);781	if (ret)782		return ret;783 784	tmp = readl(codec->base + ICDC_RGADW_OFFSET);785	tmp &= ~ICDC_RGADW_RGADDR_MASK;786	tmp |= FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg);787	writel(tmp, codec->base + ICDC_RGADW_OFFSET);788 789	/* wait 6+ cycles */790	for (i = 0; i < 6; i++)791		*val = readl(codec->base + ICDC_RGDATA_OFFSET) &792			ICDC_RGDATA_RGDOUT_MASK;793 794	return 0;795}796 797static int jz4760_codec_reg_write(void *context, unsigned int reg,798				  unsigned int val)799{800	struct jz_codec *codec = context;801	int ret;802 803	ret = jz4760_codec_io_wait(codec);804	if (ret)805		return ret;806 807	writel(ICDC_RGADW_RGWR | FIELD_PREP(ICDC_RGADW_RGADDR_MASK, reg) | val,808	       codec->base + ICDC_RGADW_OFFSET);809 810	ret = jz4760_codec_io_wait(codec);811	if (ret)812		return ret;813 814	return 0;815}816 817static const u8 jz4760_codec_reg_defaults[] = {818	0x00, 0xFC, 0x1B, 0x20, 0x00, 0x80, 0x00, 0x00,819	0xFF, 0x1F, 0x3F, 0x00, 0x06, 0x06, 0x06, 0x06,820	0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x07, 0x44,821	0x1F, 0x00, 0x00, 0x00822};823 824static const struct regmap_config jz4760_codec_regmap_config = {825	.reg_bits = 7,826	.val_bits = 8,827 828	.max_register = JZ4760_CODEC_REG_MIX2,829	.volatile_reg = jz4760_codec_volatile,830	.writeable_reg = jz4760_codec_writeable,831 832	.reg_read = jz4760_codec_reg_read,833	.reg_write = jz4760_codec_reg_write,834 835	.reg_defaults_raw = jz4760_codec_reg_defaults,836	.num_reg_defaults_raw = ARRAY_SIZE(jz4760_codec_reg_defaults),837	.cache_type = REGCACHE_FLAT,838};839 840static int jz4760_codec_probe(struct platform_device *pdev)841{842	struct device *dev = &pdev->dev;843	struct jz_codec *codec;844	int ret;845 846	codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);847	if (!codec)848		return -ENOMEM;849 850	codec->dev = dev;851 852	codec->base = devm_platform_ioremap_resource(pdev, 0);853	if (IS_ERR(codec->base))854		return PTR_ERR(codec->base);855 856	codec->regmap = devm_regmap_init(dev, NULL, codec,857					&jz4760_codec_regmap_config);858	if (IS_ERR(codec->regmap))859		return PTR_ERR(codec->regmap);860 861	codec->clk = devm_clk_get(dev, "aic");862	if (IS_ERR(codec->clk))863		return PTR_ERR(codec->clk);864 865	platform_set_drvdata(pdev, codec);866 867	ret = devm_snd_soc_register_component(dev, &jz4760_codec_soc_codec_dev,868					      &jz4760_codec_dai, 1);869	if (ret) {870		dev_err(dev, "Failed to register codec: %d\n", ret);871		return ret;872	}873 874	return 0;875}876 877static const struct of_device_id jz4760_codec_of_matches[] = {878	{ .compatible = "ingenic,jz4760-codec", },879	{ /* sentinel */ }880};881MODULE_DEVICE_TABLE(of, jz4760_codec_of_matches);882 883static struct platform_driver jz4760_codec_driver = {884	.probe			= jz4760_codec_probe,885	.driver			= {886		.name		= "jz4760-codec",887		.of_match_table = jz4760_codec_of_matches,888	},889};890module_platform_driver(jz4760_codec_driver);891 892MODULE_DESCRIPTION("JZ4760 SoC internal codec driver");893MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");894MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");895MODULE_LICENSE("GPL v2");896