Linux Audio

Check our new training course

Loading...
v6.13.7
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// Ingenic JZ4770 CODEC driver
  4//
  5// Copyright (C) 2012, Maarten ter Huurne <maarten@treewalker.org>
  6// Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
  7
  8#include <linux/clk.h>
  9#include <linux/delay.h>
 10#include <linux/iopoll.h>
 11#include <linux/module.h>
 12#include <linux/regmap.h>
 13#include <linux/time64.h>
 14
 15#include <sound/pcm_params.h>
 16#include <sound/soc.h>
 17#include <sound/soc-dai.h>
 18#include <sound/soc-dapm.h>
 19#include <sound/tlv.h>
 20
 21#define ICDC_RGADW_OFFSET		0x00
 22#define ICDC_RGDATA_OFFSET		0x04
 23
 24/* ICDC internal register access control register(RGADW) */
 25#define ICDC_RGADW_RGWR			BIT(16)
 26
 27#define ICDC_RGADW_RGADDR_OFFSET	8
 28#define	ICDC_RGADW_RGADDR_MASK		GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
 29
 30#define ICDC_RGADW_RGDIN_OFFSET		0
 31#define	ICDC_RGADW_RGDIN_MASK		GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
 32
 33/* ICDC internal register data output register (RGDATA)*/
 34#define ICDC_RGDATA_IRQ			BIT(8)
 35
 36#define ICDC_RGDATA_RGDOUT_OFFSET	0
 37#define ICDC_RGDATA_RGDOUT_MASK		GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
 38
 39/* Internal register space, accessed through regmap */
 40enum {
 41	JZ4770_CODEC_REG_SR,
 42	JZ4770_CODEC_REG_AICR_DAC,
 43	JZ4770_CODEC_REG_AICR_ADC,
 44	JZ4770_CODEC_REG_CR_LO,
 45	JZ4770_CODEC_REG_CR_HP,
 46
 47	JZ4770_CODEC_REG_MISSING_REG1,
 48
 49	JZ4770_CODEC_REG_CR_DAC,
 50	JZ4770_CODEC_REG_CR_MIC,
 51	JZ4770_CODEC_REG_CR_LI,
 52	JZ4770_CODEC_REG_CR_ADC,
 53	JZ4770_CODEC_REG_CR_MIX,
 54	JZ4770_CODEC_REG_CR_VIC,
 55	JZ4770_CODEC_REG_CCR,
 56	JZ4770_CODEC_REG_FCR_DAC,
 57	JZ4770_CODEC_REG_FCR_ADC,
 58	JZ4770_CODEC_REG_ICR,
 59	JZ4770_CODEC_REG_IMR,
 60	JZ4770_CODEC_REG_IFR,
 61	JZ4770_CODEC_REG_GCR_HPL,
 62	JZ4770_CODEC_REG_GCR_HPR,
 63	JZ4770_CODEC_REG_GCR_LIBYL,
 64	JZ4770_CODEC_REG_GCR_LIBYR,
 65	JZ4770_CODEC_REG_GCR_DACL,
 66	JZ4770_CODEC_REG_GCR_DACR,
 67	JZ4770_CODEC_REG_GCR_MIC1,
 68	JZ4770_CODEC_REG_GCR_MIC2,
 69	JZ4770_CODEC_REG_GCR_ADCL,
 70	JZ4770_CODEC_REG_GCR_ADCR,
 71
 72	JZ4770_CODEC_REG_MISSING_REG2,
 73
 74	JZ4770_CODEC_REG_GCR_MIXADC,
 75	JZ4770_CODEC_REG_GCR_MIXDAC,
 76	JZ4770_CODEC_REG_AGC1,
 77	JZ4770_CODEC_REG_AGC2,
 78	JZ4770_CODEC_REG_AGC3,
 79	JZ4770_CODEC_REG_AGC4,
 80	JZ4770_CODEC_REG_AGC5,
 81};
 82
 83#define REG_AICR_DAC_ADWL_OFFSET	6
 84#define REG_AICR_DAC_ADWL_MASK		(0x3 << REG_AICR_DAC_ADWL_OFFSET)
 85#define REG_AICR_DAC_SERIAL		BIT(1)
 86#define REG_AICR_DAC_I2S		BIT(0)
 87
 88#define REG_AICR_ADC_ADWL_OFFSET	6
 89#define REG_AICR_ADC_ADWL_MASK		(0x3 << REG_AICR_ADC_ADWL_OFFSET)
 90#define REG_AICR_ADC_SERIAL		BIT(1)
 91#define REG_AICR_ADC_I2S		BIT(0)
 92
 93#define REG_CR_LO_MUTE_OFFSET		7
 94#define REG_CR_LO_SB_OFFSET		4
 95#define REG_CR_LO_SEL_OFFSET		0
 96#define REG_CR_LO_SEL_MASK		(0x3 << REG_CR_LO_SEL_OFFSET)
 97
 98#define REG_CR_HP_MUTE			BIT(7)
 99#define REG_CR_HP_LOAD			BIT(6)
100#define REG_CR_HP_SB_OFFSET		4
101#define REG_CR_HP_SB_HPCM_OFFSET	3
102#define REG_CR_HP_SEL_OFFSET		0
103#define REG_CR_HP_SEL_MASK		(0x3 << REG_CR_HP_SEL_OFFSET)
104
105#define REG_CR_DAC_MUTE			BIT(7)
106#define REG_CR_DAC_MONO			BIT(6)
107#define REG_CR_DAC_LEFT_ONLY		BIT(5)
108#define REG_CR_DAC_SB_OFFSET		4
109#define REG_CR_DAC_LRSWAP		BIT(3)
110
111#define REG_CR_MIC_STEREO_OFFSET	7
112#define REG_CR_MIC_IDIFF_OFFSET		6
113#define REG_CR_MIC_SB_MIC2_OFFSET	5
114#define REG_CR_MIC_SB_MIC1_OFFSET	4
115#define REG_CR_MIC_BIAS_V0_OFFSET	1
116#define REG_CR_MIC_BIAS_SB_OFFSET	0
117
118#define REG_CR_LI_LIBY_OFFSET		4
119#define REG_CR_LI_SB_OFFSET		0
120
121#define REG_CR_ADC_DMIC_SEL		BIT(7)
122#define REG_CR_ADC_MONO			BIT(6)
123#define REG_CR_ADC_LEFT_ONLY		BIT(5)
124#define REG_CR_ADC_SB_OFFSET		4
125#define REG_CR_ADC_LRSWAP		BIT(3)
126#define REG_CR_ADC_IN_SEL_OFFSET	0
127#define REG_CR_ADC_IN_SEL_MASK		(0x3 << REG_CR_ADC_IN_SEL_OFFSET)
128
129#define REG_CR_VIC_SB_SLEEP		BIT(1)
130#define REG_CR_VIC_SB			BIT(0)
131
132#define REG_CCR_CRYSTAL_OFFSET		0
133#define REG_CCR_CRYSTAL_MASK		(0xf << REG_CCR_CRYSTAL_OFFSET)
134
135#define REG_FCR_DAC_FREQ_OFFSET		0
136#define REG_FCR_DAC_FREQ_MASK		(0xf << REG_FCR_DAC_FREQ_OFFSET)
137
138#define REG_FCR_ADC_FREQ_OFFSET		0
139#define REG_FCR_ADC_FREQ_MASK		(0xf << REG_FCR_ADC_FREQ_OFFSET)
140
141#define REG_ICR_INT_FORM_OFFSET		6
142#define REG_ICR_INT_FORM_MASK		(0x3 << REG_ICR_INT_FORM_OFFSET)
143
144#define REG_IMR_ALL_MASK		(0x7f)
145#define REG_IMR_SCLR_MASK		BIT(6)
146#define REG_IMR_JACK_MASK		BIT(5)
147#define REG_IMR_SCMC_MASK		BIT(4)
148#define REG_IMR_RUP_MASK		BIT(3)
149#define REG_IMR_RDO_MASK		BIT(2)
150#define REG_IMR_GUP_MASK		BIT(1)
151#define REG_IMR_GDO_MASK		BIT(0)
152
153#define REG_IFR_ALL_MASK		(0x7f)
154#define REG_IFR_SCLR			BIT(6)
155#define REG_IFR_JACK			BIT(5)
156#define REG_IFR_SCMC			BIT(4)
157#define REG_IFR_RUP			BIT(3)
158#define REG_IFR_RDO			BIT(2)
159#define REG_IFR_GUP			BIT(1)
160#define REG_IFR_GDO			BIT(0)
161
162#define REG_GCR_HPL_LRGO		BIT(7)
163
164#define REG_GCR_DACL_RLGOD		BIT(7)
165
166#define REG_GCR_GAIN_OFFSET		0
167#define REG_GCR_GAIN_MAX		0x1f
168
169#define REG_GCR_MIC_GAIN_OFFSET		0
170#define REG_GCR_MIC_GAIN_MAX		5
171
172#define REG_GCR_ADC_GAIN_OFFSET		0
173#define REG_GCR_ADC_GAIN_MAX		23
174
175#define REG_AGC1_EN			BIT(7)
176
177/* codec private data */
178struct jz_codec {
179	struct device *dev;
180	struct regmap *regmap;
181	void __iomem *base;
182	struct clk *clk;
183};
184
185static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
186				       enum snd_soc_bias_level level)
187{
188	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
189	struct regmap *regmap = jz_codec->regmap;
190
191	switch (level) {
192	case SND_SOC_BIAS_PREPARE:
193		/* Reset all interrupt flags. */
194		regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
195
196		regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
197				  REG_CR_VIC_SB);
198		msleep(250);
199		regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
200				  REG_CR_VIC_SB_SLEEP);
201		msleep(400);
202		break;
203	case SND_SOC_BIAS_STANDBY:
204		regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
205				REG_CR_VIC_SB_SLEEP);
206		regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
207				REG_CR_VIC_SB);
208		fallthrough;
209	default:
210		break;
211	}
212
213	return 0;
214}
215
216static int jz4770_codec_startup(struct snd_pcm_substream *substream,
217				struct snd_soc_dai *dai)
218{
219	struct snd_soc_component *codec = dai->component;
220	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
221
222	/*
223	 * SYSCLK output from the codec to the AIC is required to keep the
224	 * DMA transfer going during playback when all audible outputs have
225	 * been disabled.
226	 */
227	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
228		snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
229
230	return 0;
231}
232
233static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
234				  struct snd_soc_dai *dai)
235{
236	struct snd_soc_component *codec = dai->component;
237	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
238
239	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
240		snd_soc_dapm_disable_pin(dapm, "SYSCLK");
241}
242
243
244static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
245				    int cmd, struct snd_soc_dai *dai)
246{
247	struct snd_soc_component *codec = dai->component;
248	int ret = 0;
249
250	switch (cmd) {
251	case SNDRV_PCM_TRIGGER_START:
252	case SNDRV_PCM_TRIGGER_RESUME:
253	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
254		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
255			snd_soc_component_force_bias_level(codec,
256							   SND_SOC_BIAS_ON);
257		break;
258	case SNDRV_PCM_TRIGGER_STOP:
259	case SNDRV_PCM_TRIGGER_SUSPEND:
260	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
261		/* do nothing */
262		break;
263	default:
264		ret = -EINVAL;
265	}
266
267	return ret;
268}
269
270static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
271{
272	struct snd_soc_component *codec = dai->component;
273	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
274	unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
275	unsigned int val;
276	int change, err;
277
278	change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
279					       REG_CR_DAC_MUTE,
280					       mute ? REG_CR_DAC_MUTE : 0);
281	if (change == 1) {
282		regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
283
284		if (val & BIT(REG_CR_DAC_SB_OFFSET))
285			return 1;
286
287		err = regmap_read_poll_timeout(jz_codec->regmap,
288					       JZ4770_CODEC_REG_IFR,
289					       val, val & gain_bit,
290					       1000, 1 * USEC_PER_SEC);
291		if (err) {
292			dev_err(jz_codec->dev,
293				"Timeout while setting digital mute: %d", err);
294			return err;
295		}
296
297		/* clear GUP/GDO flag */
298		regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
299				gain_bit);
300	}
301
302	return 0;
303}
304
305/* unit: 0.01dB */
306static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
307static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
308static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
309static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
310static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);
311
312/* Unconditional controls. */
313static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = {
314	/* record gain control */
315	SOC_DOUBLE_R_TLV("PCM Capture Volume",
316			 JZ4770_CODEC_REG_GCR_ADCL, JZ4770_CODEC_REG_GCR_ADCR,
317			 REG_GCR_ADC_GAIN_OFFSET, REG_GCR_ADC_GAIN_MAX,
318			 0, adc_tlv),
319
320	SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
321			 JZ4770_CODEC_REG_GCR_LIBYL, JZ4770_CODEC_REG_GCR_LIBYR,
322			 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
323
324	SOC_SINGLE_TLV("Mixer Capture Volume",
325		       JZ4770_CODEC_REG_GCR_MIXADC,
326		       REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
327
328	SOC_SINGLE_TLV("Mixer Playback Volume",
329		       JZ4770_CODEC_REG_GCR_MIXDAC,
330		       REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
331};
332
333static const struct snd_kcontrol_new jz4770_codec_pcm_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_READ
339			| SNDRV_CTL_ELEM_ACCESS_READWRITE,
340		.tlv.p = dac_tlv,
341		.get = snd_soc_dapm_get_volsw,
342		.put = snd_soc_dapm_put_volsw,
343		/*
344		 * NOTE: DACR/DACL are inversed; the gain value written to DACR
345		 * seems to affect the left channel, and the gain value written
346		 * to DACL seems to affect the right channel.
347		 */
348		.private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
349						    JZ4770_CODEC_REG_GCR_DACL,
350						    REG_GCR_GAIN_OFFSET,
351						    REG_GCR_GAIN_MAX, 1),
352	},
353};
354
355static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
356	{
357		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
358		.name = "Volume",
359		.info = snd_soc_info_volsw,
360		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
361			| SNDRV_CTL_ELEM_ACCESS_READWRITE,
362		.tlv.p = out_tlv,
363		.get = snd_soc_dapm_get_volsw,
364		.put = snd_soc_dapm_put_volsw,
365		/* HPR/HPL inversed for the same reason as above */
366		.private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR,
367						    JZ4770_CODEC_REG_GCR_HPL,
368						    REG_GCR_GAIN_OFFSET,
369						    REG_GCR_GAIN_MAX, 1),
370	},
371};
372
373static int hpout_event(struct snd_soc_dapm_widget *w,
374		       struct snd_kcontrol *kcontrol, int event)
375{
376	struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
377	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
378	unsigned int val;
379	int err;
380
381	switch (event) {
382	case SND_SOC_DAPM_PRE_PMU:
383		/* unmute HP */
384		regmap_clear_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
385				  REG_CR_HP_MUTE);
386		break;
387
388	case SND_SOC_DAPM_POST_PMU:
389		/* wait for ramp-up complete (RUP) */
390		err = regmap_read_poll_timeout(jz_codec->regmap,
391					       JZ4770_CODEC_REG_IFR,
392					       val, val & REG_IFR_RUP,
393					       1000, 1 * USEC_PER_SEC);
394		if (err) {
395			dev_err(jz_codec->dev, "RUP timeout: %d", err);
396			return err;
397		}
398
399		/* clear RUP flag */
400		regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
401				REG_IFR_RUP);
402
403		break;
404
405	case SND_SOC_DAPM_POST_PMD:
406		/* mute HP */
407		regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
408				REG_CR_HP_MUTE);
 
409
410		err = regmap_read_poll_timeout(jz_codec->regmap,
411					       JZ4770_CODEC_REG_IFR,
412					       val, val & REG_IFR_RDO,
413					       1000, 1 * USEC_PER_SEC);
414		if (err) {
415			dev_err(jz_codec->dev, "RDO timeout: %d", err);
416			return err;
417		}
418
419		/* clear RDO flag */
420		regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
421				REG_IFR_RDO);
422
423		break;
424	}
425
426	return 0;
427}
428
429static int adc_poweron_event(struct snd_soc_dapm_widget *w,
430			     struct snd_kcontrol *kcontrol, int event)
431{
432	if (event == SND_SOC_DAPM_POST_PMU)
433		msleep(1000);
434
435	return 0;
436}
437
438static const char * const jz4770_codec_hp_texts[] = {
439	"PCM", "Line In", "Mic 1", "Mic 2"
440};
441static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
442static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
443				  JZ4770_CODEC_REG_CR_HP,
444				  REG_CR_HP_SEL_OFFSET,
445				  REG_CR_HP_SEL_MASK,
446				  jz4770_codec_hp_texts,
447				  jz4770_codec_hp_values);
448static const struct snd_kcontrol_new jz4770_codec_hp_source =
449			SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
450
451static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
452				  JZ4770_CODEC_REG_CR_LO,
453				  REG_CR_LO_SEL_OFFSET,
454				  REG_CR_LO_SEL_MASK,
455				  jz4770_codec_hp_texts,
456				  jz4770_codec_hp_values);
457static const struct snd_kcontrol_new jz4770_codec_lo_source =
458			SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
459
460static const char * const jz4770_codec_cap_texts[] = {
461	"Line In", "Mic 1", "Mic 2"
462};
463static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
464static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
465				  JZ4770_CODEC_REG_CR_ADC,
466				  REG_CR_ADC_IN_SEL_OFFSET,
467				  REG_CR_ADC_IN_SEL_MASK,
468				  jz4770_codec_cap_texts,
469				  jz4770_codec_cap_values);
470static const struct snd_kcontrol_new jz4770_codec_cap_source =
471			SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
472
473static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
474	SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
475			REG_CR_MIC_STEREO_OFFSET, 1, 0),
476};
477
478static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
479	SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
480			   REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
481			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
482			   SND_SOC_DAPM_POST_PMD),
483
484	SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
485			 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
486
487	SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
488			 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
489
490	SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
491			 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
492
493	SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
494			 &jz4770_codec_hp_source),
495	SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
496			 &jz4770_codec_cap_source),
497	SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
498			 &jz4770_codec_lo_source),
499
500	SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
501			 REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
502	SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
503			 REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
504
505	SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
506			 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
507
508	SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
509			   jz4770_codec_mic_controls,
510			   ARRAY_SIZE(jz4770_codec_mic_controls)),
511
512	SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
513			 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
514
515	SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
516			   REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
517			   SND_SOC_DAPM_POST_PMU),
518	SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
519			 REG_CR_DAC_SB_OFFSET, 1),
520
521	SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
522			   jz4770_codec_pcm_playback_controls,
523			   ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
524	SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
525			   jz4770_codec_hp_playback_controls,
526			   ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
527
528	SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
529			    REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
530
531	SND_SOC_DAPM_SUPPLY("Cap-less", JZ4770_CODEC_REG_CR_HP,
532			    REG_CR_HP_SB_HPCM_OFFSET, 1, NULL, 0),
533
534	SND_SOC_DAPM_INPUT("MIC1P"),
535	SND_SOC_DAPM_INPUT("MIC1N"),
536	SND_SOC_DAPM_INPUT("MIC2P"),
537	SND_SOC_DAPM_INPUT("MIC2N"),
538
539	SND_SOC_DAPM_OUTPUT("LOUT"),
540	SND_SOC_DAPM_OUTPUT("ROUT"),
541
542	SND_SOC_DAPM_OUTPUT("LHPOUT"),
543	SND_SOC_DAPM_OUTPUT("RHPOUT"),
544
545	SND_SOC_DAPM_INPUT("LLINEIN"),
546	SND_SOC_DAPM_INPUT("RLINEIN"),
547
548	SND_SOC_DAPM_OUTPUT("SYSCLK"),
549};
550
551/* Unconditional routes. */
552static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
553	{ "Mic 1", NULL, "MIC1P" },
554	{ "Mic Diff", NULL, "MIC1N" },
555	{ "Mic 1", NULL, "Mic Diff" },
556	{ "Mic 2", NULL, "MIC2P" },
557	{ "Mic Diff", NULL, "MIC2N" },
558	{ "Mic 2", NULL, "Mic Diff" },
559
560	{ "Line In", NULL, "LLINEIN" },
561	{ "Line In", NULL, "RLINEIN" },
562
563	{ "Mic", "Stereo Capture Switch", "Mic 1" },
564	{ "Mic", "Stereo Capture Switch", "Mic 2" },
565	{ "Headphones Source", "Mic 1", "Mic" },
566	{ "Headphones Source", "Mic 2", "Mic" },
567	{ "Capture Source", "Mic 1", "Mic" },
568	{ "Capture Source", "Mic 2", "Mic" },
569
570	{ "Headphones Source", "Mic 1", "Mic 1" },
571	{ "Headphones Source", "Mic 2", "Mic 2" },
572	{ "Headphones Source", "Line In", "Line In Bypass" },
573	{ "Headphones Source", "PCM", "Headphones Playback" },
574	{ "HP Out", NULL, "Headphones Source" },
575
576	{ "Capture Source", "Line In", "Line In" },
577	{ "Capture Source", "Mic 1", "Mic 1" },
578	{ "Capture Source", "Mic 2", "Mic 2" },
579	{ "ADC", NULL, "Capture Source" },
580
581	{ "Line In Bypass", NULL, "Line In" },
582	{ "Line Out Source", "Line In", "Line In Bypass" },
583	{ "Line Out Source", "PCM", "PCM Playback" },
584
585	{ "LHPOUT", NULL, "HP Out"},
586	{ "RHPOUT", NULL, "HP Out"},
587
588	{ "Line Out", NULL, "Line Out Source" },
589	{ "Line Out Switch 2", NULL, "Line Out" },
590
591	{ "LOUT", NULL, "Line Out Switch 2"},
592	{ "ROUT", NULL, "Line Out Switch 2"},
593
594	{ "PCM Playback", "Volume", "DAC" },
595	{ "Headphones Playback", "Volume", "PCM Playback" },
596
597	{ "SYSCLK", NULL, "DAC" },
598};
599
600static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
601{
602	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
603	struct regmap *regmap = jz_codec->regmap;
604
605	/* Collect updates for later sending. */
606	regcache_cache_only(regmap, true);
607
608	/* default HP output to PCM */
609	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_SEL_MASK);
 
610
611	/* default line output to PCM */
612	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_LO, REG_CR_LO_SEL_MASK);
 
613
614	/* Disable stereo mic */
615	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
616			  BIT(REG_CR_MIC_STEREO_OFFSET));
617
618	/* Set mic 1 as default source for ADC */
619	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
620			  REG_CR_ADC_IN_SEL_MASK);
621
622	/* ADC/DAC: serial + i2s */
623	regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
624			REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
625	regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
626			REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
 
 
627
628	/* The generated IRQ is a high level */
629	regmap_clear_bits(regmap, JZ4770_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
 
630	regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
631			   REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
632			   REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
633			   REG_IMR_GDO_MASK);
634
635	/* 12M oscillator */
636	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CCR, REG_CCR_CRYSTAL_MASK);
 
637
638	/* 0: 16ohm/220uF, 1: 10kohm/1uF */
639	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_LOAD);
 
640
641	/* disable automatic gain */
642	regmap_clear_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN);
643
644	/* Disable DAC lrswap */
645	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_DAC, REG_CR_DAC_LRSWAP);
 
646
647	/* Independent L/R DAC gain control */
648	regmap_clear_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
649			  REG_GCR_DACL_RLGOD);
650
651	/* Disable ADC lrswap */
652	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_ADC, REG_CR_ADC_LRSWAP);
 
653
654	/* default to cap-less mode(0) */
655	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP,
656			  BIT(REG_CR_HP_SB_HPCM_OFFSET));
657
658	/* Send collected updates. */
659	regcache_cache_only(regmap, false);
660	regcache_sync(regmap);
 
 
 
661}
662
663static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
664{
665	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
666
667	clk_prepare_enable(jz_codec->clk);
668
669	jz4770_codec_codec_init_regs(codec);
670
671	return 0;
672}
673
674static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
675{
676	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
677
678	clk_disable_unprepare(jz_codec->clk);
679}
680
681static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
682	.probe			= jz4770_codec_codec_probe,
683	.remove			= jz4770_codec_codec_remove,
684	.set_bias_level		= jz4770_codec_set_bias_level,
685	.controls		= jz4770_codec_snd_controls,
686	.num_controls		= ARRAY_SIZE(jz4770_codec_snd_controls),
687	.dapm_widgets		= jz4770_codec_dapm_widgets,
688	.num_dapm_widgets	= ARRAY_SIZE(jz4770_codec_dapm_widgets),
689	.dapm_routes		= jz4770_codec_dapm_routes,
690	.num_dapm_routes	= ARRAY_SIZE(jz4770_codec_dapm_routes),
691	.suspend_bias_off	= 1,
692	.use_pmdown_time	= 1,
693};
694
695static const unsigned int jz4770_codec_sample_rates[] = {
696	96000, 48000, 44100, 32000,
697	24000, 22050, 16000, 12000,
698	11025, 9600, 8000,
699};
700
701static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
702				  struct snd_pcm_hw_params *params,
703				  struct snd_soc_dai *dai)
704{
705	struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
706	unsigned int rate, bit_width;
707
708	switch (params_format(params)) {
709	case SNDRV_PCM_FORMAT_S16_LE:
710		bit_width = 0;
711		break;
712	case SNDRV_PCM_FORMAT_S18_3LE:
713		bit_width = 1;
714		break;
715	case SNDRV_PCM_FORMAT_S20_3LE:
716		bit_width = 2;
717		break;
718	case SNDRV_PCM_FORMAT_S24_3LE:
719		bit_width = 3;
720		break;
721	default:
722		return -EINVAL;
723	}
724
725	for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
726		if (jz4770_codec_sample_rates[rate] == params_rate(params))
727			break;
728	}
729
730	if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
731		return -EINVAL;
732
733	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
734		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
735				   REG_AICR_DAC_ADWL_MASK,
736				   bit_width << REG_AICR_DAC_ADWL_OFFSET);
737		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
738				   REG_FCR_DAC_FREQ_MASK,
739				   rate << REG_FCR_DAC_FREQ_OFFSET);
740	} else {
741		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
742				   REG_AICR_ADC_ADWL_MASK,
743				   bit_width << REG_AICR_ADC_ADWL_OFFSET);
744		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
745				   REG_FCR_ADC_FREQ_MASK,
746				   rate << REG_FCR_ADC_FREQ_OFFSET);
747	}
748
749	return 0;
750}
751
752static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
753	.startup	= jz4770_codec_startup,
754	.shutdown	= jz4770_codec_shutdown,
755	.hw_params	= jz4770_codec_hw_params,
756	.trigger	= jz4770_codec_pcm_trigger,
757	.mute_stream	= jz4770_codec_mute_stream,
758	.no_capture_mute = 1,
759};
760
761#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | \
762			  SNDRV_PCM_FMTBIT_S18_3LE | \
763			  SNDRV_PCM_FMTBIT_S20_3LE | \
764			  SNDRV_PCM_FMTBIT_S24_3LE)
765
766static struct snd_soc_dai_driver jz4770_codec_dai = {
767	.name = "jz4770-hifi",
768	.playback = {
769		.stream_name = "Playback",
770		.channels_min = 2,
771		.channels_max = 2,
772		.rates = SNDRV_PCM_RATE_8000_96000,
773		.formats = JZ_CODEC_FORMATS,
774	},
775	.capture = {
776		.stream_name = "Capture",
777		.channels_min = 2,
778		.channels_max = 2,
779		.rates = SNDRV_PCM_RATE_8000_96000,
780		.formats = JZ_CODEC_FORMATS,
781	},
782	.ops = &jz4770_codec_dai_ops,
783};
784
785static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
786{
787	return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
788}
789
790static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
791{
792	switch (reg) {
793	case JZ4770_CODEC_REG_MISSING_REG1:
794	case JZ4770_CODEC_REG_MISSING_REG2:
795		return false;
796	default:
797		return true;
798	}
799}
800
801static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
802{
803	switch (reg) {
804	case JZ4770_CODEC_REG_SR:
805	case JZ4770_CODEC_REG_MISSING_REG1:
806	case JZ4770_CODEC_REG_MISSING_REG2:
807		return false;
808	default:
809		return true;
810	}
811}
812
813static int jz4770_codec_io_wait(struct jz_codec *codec)
814{
815	u32 reg;
816
817	return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
818				  !(reg & ICDC_RGADW_RGWR),
819				  1000, 1 * USEC_PER_SEC);
820}
821
822static int jz4770_codec_reg_read(void *context, unsigned int reg,
823				 unsigned int *val)
824{
825	struct jz_codec *codec = context;
826	unsigned int i;
827	u32 tmp;
828	int ret;
829
830	ret = jz4770_codec_io_wait(codec);
831	if (ret)
832		return ret;
833
834	tmp = readl(codec->base + ICDC_RGADW_OFFSET);
835	tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
836	    | (reg << ICDC_RGADW_RGADDR_OFFSET);
837	writel(tmp, codec->base + ICDC_RGADW_OFFSET);
838
839	/* wait 6+ cycles */
840	for (i = 0; i < 6; i++)
841		*val = readl(codec->base + ICDC_RGDATA_OFFSET) &
842			ICDC_RGDATA_RGDOUT_MASK;
843
844	return 0;
845}
846
847static int jz4770_codec_reg_write(void *context, unsigned int reg,
848				  unsigned int val)
849{
850	struct jz_codec *codec = context;
851	int ret;
852
853	ret = jz4770_codec_io_wait(codec);
854	if (ret)
855		return ret;
856
857	writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
858	       codec->base + ICDC_RGADW_OFFSET);
859
860	ret = jz4770_codec_io_wait(codec);
861	if (ret)
862		return ret;
863
864	return 0;
865}
866
867static const u8 jz4770_codec_reg_defaults[] = {
868	0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
869	0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
870	0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
871	0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
872	0x07, 0x44, 0x1F, 0x00
873};
874
875static const struct regmap_config jz4770_codec_regmap_config = {
876	.reg_bits = 7,
877	.val_bits = 8,
878
879	.max_register = JZ4770_CODEC_REG_AGC5,
880	.volatile_reg = jz4770_codec_volatile,
881	.readable_reg = jz4770_codec_readable,
882	.writeable_reg = jz4770_codec_writeable,
883
884	.reg_read = jz4770_codec_reg_read,
885	.reg_write = jz4770_codec_reg_write,
886
887	.reg_defaults_raw = jz4770_codec_reg_defaults,
888	.num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
889	.cache_type = REGCACHE_FLAT,
890};
891
892static int jz4770_codec_probe(struct platform_device *pdev)
893{
894	struct device *dev = &pdev->dev;
895	struct jz_codec *codec;
896	int ret;
897
898	codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
899	if (!codec)
900		return -ENOMEM;
901
902	codec->dev = dev;
903
904	codec->base = devm_platform_ioremap_resource(pdev, 0);
905	if (IS_ERR(codec->base))
906		return PTR_ERR(codec->base);
 
 
 
907
908	codec->regmap = devm_regmap_init(dev, NULL, codec,
909					&jz4770_codec_regmap_config);
910	if (IS_ERR(codec->regmap))
911		return PTR_ERR(codec->regmap);
912
913	codec->clk = devm_clk_get(dev, "aic");
914	if (IS_ERR(codec->clk))
915		return PTR_ERR(codec->clk);
916
917	platform_set_drvdata(pdev, codec);
918
919	ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
920					      &jz4770_codec_dai, 1);
921	if (ret) {
922		dev_err(dev, "Failed to register codec: %d\n", ret);
923		return ret;
924	}
925
926	return 0;
927}
928
929static const struct of_device_id jz4770_codec_of_matches[] = {
930	{ .compatible = "ingenic,jz4770-codec", },
931	{ /* sentinel */ }
932};
933MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
934
935static struct platform_driver jz4770_codec_driver = {
936	.probe			= jz4770_codec_probe,
937	.driver			= {
938		.name		= "jz4770-codec",
939		.of_match_table = jz4770_codec_of_matches,
940	},
941};
942module_platform_driver(jz4770_codec_driver);
943
944MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
945MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
946MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
947MODULE_LICENSE("GPL v2");
v5.9
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// Ingenic JZ4770 CODEC driver
  4//
  5// Copyright (C) 2012, Maarten ter Huurne <maarten@treewalker.org>
  6// Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
  7
  8#include <linux/clk.h>
  9#include <linux/delay.h>
 10#include <linux/iopoll.h>
 11#include <linux/module.h>
 12#include <linux/regmap.h>
 13#include <linux/time64.h>
 14
 15#include <sound/pcm_params.h>
 16#include <sound/soc.h>
 17#include <sound/soc-dai.h>
 18#include <sound/soc-dapm.h>
 19#include <sound/tlv.h>
 20
 21#define ICDC_RGADW_OFFSET		0x00
 22#define ICDC_RGDATA_OFFSET		0x04
 23
 24/* ICDC internal register access control register(RGADW) */
 25#define ICDC_RGADW_RGWR			BIT(16)
 26
 27#define ICDC_RGADW_RGADDR_OFFSET	8
 28#define	ICDC_RGADW_RGADDR_MASK		GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
 29
 30#define ICDC_RGADW_RGDIN_OFFSET		0
 31#define	ICDC_RGADW_RGDIN_MASK		GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
 32
 33/* ICDC internal register data output register (RGDATA)*/
 34#define ICDC_RGDATA_IRQ			BIT(8)
 35
 36#define ICDC_RGDATA_RGDOUT_OFFSET	0
 37#define ICDC_RGDATA_RGDOUT_MASK		GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
 38
 39/* Internal register space, accessed through regmap */
 40enum {
 41	JZ4770_CODEC_REG_SR,
 42	JZ4770_CODEC_REG_AICR_DAC,
 43	JZ4770_CODEC_REG_AICR_ADC,
 44	JZ4770_CODEC_REG_CR_LO,
 45	JZ4770_CODEC_REG_CR_HP,
 46
 47	JZ4770_CODEC_REG_MISSING_REG1,
 48
 49	JZ4770_CODEC_REG_CR_DAC,
 50	JZ4770_CODEC_REG_CR_MIC,
 51	JZ4770_CODEC_REG_CR_LI,
 52	JZ4770_CODEC_REG_CR_ADC,
 53	JZ4770_CODEC_REG_CR_MIX,
 54	JZ4770_CODEC_REG_CR_VIC,
 55	JZ4770_CODEC_REG_CCR,
 56	JZ4770_CODEC_REG_FCR_DAC,
 57	JZ4770_CODEC_REG_FCR_ADC,
 58	JZ4770_CODEC_REG_ICR,
 59	JZ4770_CODEC_REG_IMR,
 60	JZ4770_CODEC_REG_IFR,
 61	JZ4770_CODEC_REG_GCR_HPL,
 62	JZ4770_CODEC_REG_GCR_HPR,
 63	JZ4770_CODEC_REG_GCR_LIBYL,
 64	JZ4770_CODEC_REG_GCR_LIBYR,
 65	JZ4770_CODEC_REG_GCR_DACL,
 66	JZ4770_CODEC_REG_GCR_DACR,
 67	JZ4770_CODEC_REG_GCR_MIC1,
 68	JZ4770_CODEC_REG_GCR_MIC2,
 69	JZ4770_CODEC_REG_GCR_ADCL,
 70	JZ4770_CODEC_REG_GCR_ADCR,
 71
 72	JZ4770_CODEC_REG_MISSING_REG2,
 73
 74	JZ4770_CODEC_REG_GCR_MIXADC,
 75	JZ4770_CODEC_REG_GCR_MIXDAC,
 76	JZ4770_CODEC_REG_AGC1,
 77	JZ4770_CODEC_REG_AGC2,
 78	JZ4770_CODEC_REG_AGC3,
 79	JZ4770_CODEC_REG_AGC4,
 80	JZ4770_CODEC_REG_AGC5,
 81};
 82
 83#define REG_AICR_DAC_ADWL_OFFSET	6
 84#define REG_AICR_DAC_ADWL_MASK		(0x3 << REG_AICR_DAC_ADWL_OFFSET)
 85#define REG_AICR_DAC_SERIAL		BIT(1)
 86#define REG_AICR_DAC_I2S		BIT(0)
 87
 88#define REG_AICR_ADC_ADWL_OFFSET	6
 89#define REG_AICR_ADC_ADWL_MASK		(0x3 << REG_AICR_ADC_ADWL_OFFSET)
 90#define REG_AICR_ADC_SERIAL		BIT(1)
 91#define REG_AICR_ADC_I2S		BIT(0)
 92
 93#define REG_CR_LO_MUTE_OFFSET		7
 94#define REG_CR_LO_SB_OFFSET		4
 95#define REG_CR_LO_SEL_OFFSET		0
 96#define REG_CR_LO_SEL_MASK		(0x3 << REG_CR_LO_SEL_OFFSET)
 97
 98#define REG_CR_HP_MUTE			BIT(7)
 99#define REG_CR_HP_LOAD			BIT(6)
100#define REG_CR_HP_SB_OFFSET		4
101#define REG_CR_HP_SB_HPCM		BIT(3)
102#define REG_CR_HP_SEL_OFFSET		0
103#define REG_CR_HP_SEL_MASK		(0x3 << REG_CR_HP_SEL_OFFSET)
104
105#define REG_CR_DAC_MUTE			BIT(7)
106#define REG_CR_DAC_MONO			BIT(6)
107#define REG_CR_DAC_LEFT_ONLY		BIT(5)
108#define REG_CR_DAC_SB_OFFSET		4
109#define REG_CR_DAC_LRSWAP		BIT(3)
110
111#define REG_CR_MIC_STEREO_OFFSET	7
112#define REG_CR_MIC_IDIFF_OFFSET		6
113#define REG_CR_MIC_SB_MIC2_OFFSET	5
114#define REG_CR_MIC_SB_MIC1_OFFSET	4
115#define REG_CR_MIC_BIAS_V0_OFFSET	1
116#define REG_CR_MIC_BIAS_SB_OFFSET	0
117
118#define REG_CR_LI_LIBY_OFFSET		4
119#define REG_CR_LI_SB_OFFSET		0
120
121#define REG_CR_ADC_DMIC_SEL		BIT(7)
122#define REG_CR_ADC_MONO			BIT(6)
123#define REG_CR_ADC_LEFT_ONLY		BIT(5)
124#define REG_CR_ADC_SB_OFFSET		4
125#define REG_CR_ADC_LRSWAP		BIT(3)
126#define REG_CR_ADC_IN_SEL_OFFSET	0
127#define REG_CR_ADC_IN_SEL_MASK		(0x3 << REG_CR_ADC_IN_SEL_OFFSET)
128
129#define REG_CR_VIC_SB_SLEEP		BIT(1)
130#define REG_CR_VIC_SB			BIT(0)
131
132#define REG_CCR_CRYSTAL_OFFSET		0
133#define REG_CCR_CRYSTAL_MASK		(0xf << REG_CCR_CRYSTAL_OFFSET)
134
135#define REG_FCR_DAC_FREQ_OFFSET		0
136#define REG_FCR_DAC_FREQ_MASK		(0xf << REG_FCR_DAC_FREQ_OFFSET)
137
138#define REG_FCR_ADC_FREQ_OFFSET		0
139#define REG_FCR_ADC_FREQ_MASK		(0xf << REG_FCR_ADC_FREQ_OFFSET)
140
141#define REG_ICR_INT_FORM_OFFSET		6
142#define REG_ICR_INT_FORM_MASK		(0x3 << REG_ICR_INT_FORM_OFFSET)
143
144#define REG_IMR_ALL_MASK		(0x7f)
145#define REG_IMR_SCLR_MASK		BIT(6)
146#define REG_IMR_JACK_MASK		BIT(5)
147#define REG_IMR_SCMC_MASK		BIT(4)
148#define REG_IMR_RUP_MASK		BIT(3)
149#define REG_IMR_RDO_MASK		BIT(2)
150#define REG_IMR_GUP_MASK		BIT(1)
151#define REG_IMR_GDO_MASK		BIT(0)
152
153#define REG_IFR_ALL_MASK		(0x7f)
154#define REG_IFR_SCLR			BIT(6)
155#define REG_IFR_JACK			BIT(5)
156#define REG_IFR_SCMC			BIT(4)
157#define REG_IFR_RUP			BIT(3)
158#define REG_IFR_RDO			BIT(2)
159#define REG_IFR_GUP			BIT(1)
160#define REG_IFR_GDO			BIT(0)
161
162#define REG_GCR_HPL_LRGO		BIT(7)
163
164#define REG_GCR_DACL_RLGOD		BIT(7)
165
166#define REG_GCR_GAIN_OFFSET		0
167#define REG_GCR_GAIN_MAX		0x1f
168
169#define REG_GCR_MIC_GAIN_OFFSET		0
170#define REG_GCR_MIC_GAIN_MAX		5
171
172#define REG_GCR_ADC_GAIN_OFFSET		0
173#define REG_GCR_ADC_GAIN_MAX		23
174
175#define REG_AGC1_EN			BIT(7)
176
177/* codec private data */
178struct jz_codec {
179	struct device *dev;
180	struct regmap *regmap;
181	void __iomem *base;
182	struct clk *clk;
183};
184
185static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
186				       enum snd_soc_bias_level level)
187{
188	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
189	struct regmap *regmap = jz_codec->regmap;
190
191	switch (level) {
192	case SND_SOC_BIAS_PREPARE:
193		regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
194				   REG_CR_VIC_SB, 0);
 
 
 
195		msleep(250);
196		regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
197				   REG_CR_VIC_SB_SLEEP, 0);
198		msleep(400);
199		break;
200	case SND_SOC_BIAS_STANDBY:
201		regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
202				   REG_CR_VIC_SB_SLEEP, REG_CR_VIC_SB_SLEEP);
203		regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
204				   REG_CR_VIC_SB, REG_CR_VIC_SB);
205		fallthrough;
206	default:
207		break;
208	}
209
210	return 0;
211}
212
213static int jz4770_codec_startup(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	/*
220	 * SYSCLK output from the codec to the AIC is required to keep the
221	 * DMA transfer going during playback when all audible outputs have
222	 * been disabled.
223	 */
224	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
225		snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
226
227	return 0;
228}
229
230static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
231				  struct snd_soc_dai *dai)
232{
233	struct snd_soc_component *codec = dai->component;
234	struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
235
236	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
237		snd_soc_dapm_disable_pin(dapm, "SYSCLK");
238}
239
240
241static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
242				    int cmd, struct snd_soc_dai *dai)
243{
244	struct snd_soc_component *codec = dai->component;
245	int ret = 0;
246
247	switch (cmd) {
248	case SNDRV_PCM_TRIGGER_START:
249	case SNDRV_PCM_TRIGGER_RESUME:
250	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
251		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
252			snd_soc_component_force_bias_level(codec,
253							   SND_SOC_BIAS_ON);
254		break;
255	case SNDRV_PCM_TRIGGER_STOP:
256	case SNDRV_PCM_TRIGGER_SUSPEND:
257	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
258		/* do nothing */
259		break;
260	default:
261		ret = -EINVAL;
262	}
263
264	return ret;
265}
266
267static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
268{
269	struct snd_soc_component *codec = dai->component;
270	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
271	unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
272	unsigned int val;
273	int change, err;
274
275	change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
276					       REG_CR_DAC_MUTE,
277					       mute ? REG_CR_DAC_MUTE : 0);
278	if (change == 1) {
279		regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
280
281		if (val & BIT(REG_CR_DAC_SB_OFFSET))
282			return 1;
283
284		err = regmap_read_poll_timeout(jz_codec->regmap,
285					       JZ4770_CODEC_REG_IFR,
286					       val, val & gain_bit,
287					       1000, 100 * USEC_PER_MSEC);
288		if (err) {
289			dev_err(jz_codec->dev,
290				"Timeout while setting digital mute: %d", err);
291			return err;
292		}
293
294		/* clear GUP/GDO flag */
295		regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
296				   gain_bit, gain_bit);
297	}
298
299	return 0;
300}
301
302/* unit: 0.01dB */
303static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
304static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
305static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
306static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
 
307
308/* Unconditional controls. */
309static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = {
310	/* record gain control */
311	SOC_DOUBLE_R_TLV("PCM Capture Volume",
312			 JZ4770_CODEC_REG_GCR_ADCL, JZ4770_CODEC_REG_GCR_ADCR,
313			 REG_GCR_ADC_GAIN_OFFSET, REG_GCR_ADC_GAIN_MAX,
314			 0, adc_tlv),
315
316	SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
317			 JZ4770_CODEC_REG_GCR_LIBYL, JZ4770_CODEC_REG_GCR_LIBYR,
318			 REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
 
 
 
 
 
 
 
 
319};
320
321static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
322	{
323		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
324		.name = "Volume",
325		.info = snd_soc_info_volsw,
326		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
327			| SNDRV_CTL_ELEM_ACCESS_READWRITE,
328		.tlv.p = dac_tlv,
329		.get = snd_soc_dapm_get_volsw,
330		.put = snd_soc_dapm_put_volsw,
331		/*
332		 * NOTE: DACR/DACL are inversed; the gain value written to DACR
333		 * seems to affect the left channel, and the gain value written
334		 * to DACL seems to affect the right channel.
335		 */
336		.private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
337						    JZ4770_CODEC_REG_GCR_DACL,
338						    REG_GCR_GAIN_OFFSET,
339						    REG_GCR_GAIN_MAX, 1),
340	},
341};
342
343static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
344	{
345		.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
346		.name = "Volume",
347		.info = snd_soc_info_volsw,
348		.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
349			| SNDRV_CTL_ELEM_ACCESS_READWRITE,
350		.tlv.p = out_tlv,
351		.get = snd_soc_dapm_get_volsw,
352		.put = snd_soc_dapm_put_volsw,
353		/* HPR/HPL inversed for the same reason as above */
354		.private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR,
355						    JZ4770_CODEC_REG_GCR_HPL,
356						    REG_GCR_GAIN_OFFSET,
357						    REG_GCR_GAIN_MAX, 1),
358	},
359};
360
361static int hpout_event(struct snd_soc_dapm_widget *w,
362		       struct snd_kcontrol *kcontrol, int event)
363{
364	struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
365	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
366	unsigned int val;
367	int err;
368
369	switch (event) {
370	case SND_SOC_DAPM_PRE_PMU:
371		/* set cap-less, unmute HP */
372		regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
373				   REG_CR_HP_SB_HPCM | REG_CR_HP_MUTE, 0);
374		break;
375
376	case SND_SOC_DAPM_POST_PMU:
377		/* wait for ramp-up complete (RUP) */
378		err = regmap_read_poll_timeout(jz_codec->regmap,
379					       JZ4770_CODEC_REG_IFR,
380					       val, val & REG_IFR_RUP,
381					       1000, 100 * USEC_PER_MSEC);
382		if (err) {
383			dev_err(jz_codec->dev, "RUP timeout: %d", err);
384			return err;
385		}
386
387		/* clear RUP flag */
388		regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
389				   REG_IFR_RUP, REG_IFR_RUP);
390
391		break;
392
393	case SND_SOC_DAPM_POST_PMD:
394		/* set cap-couple, mute HP */
395		regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
396				   REG_CR_HP_SB_HPCM | REG_CR_HP_MUTE,
397				   REG_CR_HP_SB_HPCM | REG_CR_HP_MUTE);
398
399		err = regmap_read_poll_timeout(jz_codec->regmap,
400					       JZ4770_CODEC_REG_IFR,
401					       val, val & REG_IFR_RDO,
402					       1000, 100 * USEC_PER_MSEC);
403		if (err) {
404			dev_err(jz_codec->dev, "RDO timeout: %d", err);
405			return err;
406		}
407
408		/* clear RDO flag */
409		regmap_update_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
410				   REG_IFR_RDO, REG_IFR_RDO);
411
412		break;
413	}
414
415	return 0;
416}
417
418static int adc_poweron_event(struct snd_soc_dapm_widget *w,
419			     struct snd_kcontrol *kcontrol, int event)
420{
421	if (event == SND_SOC_DAPM_POST_PMU)
422		msleep(1000);
423
424	return 0;
425}
426
427static const char * const jz4770_codec_hp_texts[] = {
428	"PCM", "Line In", "Mic 1", "Mic 2"
429};
430static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
431static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
432				  JZ4770_CODEC_REG_CR_HP,
433				  REG_CR_HP_SEL_OFFSET,
434				  REG_CR_HP_SEL_MASK,
435				  jz4770_codec_hp_texts,
436				  jz4770_codec_hp_values);
437static const struct snd_kcontrol_new jz4770_codec_hp_source =
438			SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
439
440static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
441				  JZ4770_CODEC_REG_CR_LO,
442				  REG_CR_LO_SEL_OFFSET,
443				  REG_CR_LO_SEL_MASK,
444				  jz4770_codec_hp_texts,
445				  jz4770_codec_hp_values);
446static const struct snd_kcontrol_new jz4770_codec_lo_source =
447			SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
448
449static const char * const jz4770_codec_cap_texts[] = {
450	"Line In", "Mic 1", "Mic 2"
451};
452static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
453static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
454				  JZ4770_CODEC_REG_CR_ADC,
455				  REG_CR_ADC_IN_SEL_OFFSET,
456				  REG_CR_ADC_IN_SEL_MASK,
457				  jz4770_codec_cap_texts,
458				  jz4770_codec_cap_values);
459static const struct snd_kcontrol_new jz4770_codec_cap_source =
460			SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
461
462static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
463	SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
464			REG_CR_MIC_STEREO_OFFSET, 1, 0),
465};
466
467static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
468	SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
469			   REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
470			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
471			   SND_SOC_DAPM_POST_PMD),
472
473	SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
474			 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
475
476	SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
477			 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
478
479	SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
480			 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
481
482	SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
483			 &jz4770_codec_hp_source),
484	SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
485			 &jz4770_codec_cap_source),
486	SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
487			 &jz4770_codec_lo_source),
488
489	SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
490			 REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
491	SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
492			 REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
493
494	SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
495			 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
496
497	SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
498			   jz4770_codec_mic_controls,
499			   ARRAY_SIZE(jz4770_codec_mic_controls)),
500
501	SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
502			 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
503
504	SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
505			   REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
506			   SND_SOC_DAPM_POST_PMU),
507	SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
508			 REG_CR_DAC_SB_OFFSET, 1),
509
510	SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
511			   jz4770_codec_pcm_playback_controls,
512			   ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
513	SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
514			   jz4770_codec_hp_playback_controls,
515			   ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
516
517	SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
518			    REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
519
 
 
 
520	SND_SOC_DAPM_INPUT("MIC1P"),
521	SND_SOC_DAPM_INPUT("MIC1N"),
522	SND_SOC_DAPM_INPUT("MIC2P"),
523	SND_SOC_DAPM_INPUT("MIC2N"),
524
525	SND_SOC_DAPM_OUTPUT("LOUT"),
526	SND_SOC_DAPM_OUTPUT("ROUT"),
527
528	SND_SOC_DAPM_OUTPUT("LHPOUT"),
529	SND_SOC_DAPM_OUTPUT("RHPOUT"),
530
531	SND_SOC_DAPM_INPUT("LLINEIN"),
532	SND_SOC_DAPM_INPUT("RLINEIN"),
533
534	SND_SOC_DAPM_OUTPUT("SYSCLK"),
535};
536
537/* Unconditional routes. */
538static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
539	{ "Mic 1", NULL, "MIC1P" },
540	{ "Mic Diff", NULL, "MIC1N" },
541	{ "Mic 1", NULL, "Mic Diff" },
542	{ "Mic 2", NULL, "MIC2P" },
543	{ "Mic Diff", NULL, "MIC2N" },
544	{ "Mic 2", NULL, "Mic Diff" },
545
546	{ "Line In", NULL, "LLINEIN" },
547	{ "Line In", NULL, "RLINEIN" },
548
549	{ "Mic", "Stereo Capture Switch", "Mic 1" },
550	{ "Mic", "Stereo Capture Switch", "Mic 2" },
551	{ "Headphones Source", "Mic 1", "Mic" },
552	{ "Headphones Source", "Mic 2", "Mic" },
553	{ "Capture Source", "Mic 1", "Mic" },
554	{ "Capture Source", "Mic 2", "Mic" },
555
556	{ "Headphones Source", "Mic 1", "Mic 1" },
557	{ "Headphones Source", "Mic 2", "Mic 2" },
558	{ "Headphones Source", "Line In", "Line In Bypass" },
559	{ "Headphones Source", "PCM", "Headphones Playback" },
560	{ "HP Out", NULL, "Headphones Source" },
561
562	{ "Capture Source", "Line In", "Line In" },
563	{ "Capture Source", "Mic 1", "Mic 1" },
564	{ "Capture Source", "Mic 2", "Mic 2" },
565	{ "ADC", NULL, "Capture Source" },
566
567	{ "Line In Bypass", NULL, "Line In" },
568	{ "Line Out Source", "Line In", "Line In Bypass" },
569	{ "Line Out Source", "PCM", "PCM Playback" },
570
571	{ "LHPOUT", NULL, "HP Out"},
572	{ "RHPOUT", NULL, "HP Out"},
573
574	{ "Line Out", NULL, "Line Out Source" },
575	{ "Line Out Switch 2", NULL, "Line Out" },
576
577	{ "LOUT", NULL, "Line Out Switch 2"},
578	{ "ROUT", NULL, "Line Out Switch 2"},
579
580	{ "PCM Playback", "Volume", "DAC" },
581	{ "Headphones Playback", "Volume", "PCM Playback" },
582
583	{ "SYSCLK", NULL, "DAC" },
584};
585
586static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
587{
588	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
589	struct regmap *regmap = jz_codec->regmap;
590
591	/* Collect updates for later sending. */
592	regcache_cache_only(regmap, true);
593
594	/* default HP output to PCM */
595	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
596			   REG_CR_HP_SEL_MASK, REG_CR_HP_SEL_MASK);
597
598	/* default line output to PCM */
599	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_LO,
600			   REG_CR_LO_SEL_MASK, REG_CR_LO_SEL_MASK);
601
602	/* Disable stereo mic */
603	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
604			   BIT(REG_CR_MIC_STEREO_OFFSET), 0);
605
606	/* Set mic 1 as default source for ADC */
607	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
608			   REG_CR_ADC_IN_SEL_MASK, 0);
609
610	/* ADC/DAC: serial + i2s */
611	regmap_update_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
612			   REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S,
613			   REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
614	regmap_update_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
615			   REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S,
616			   REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
617
618	/* The generated IRQ is a high level */
619	regmap_update_bits(regmap, JZ4770_CODEC_REG_ICR,
620			   REG_ICR_INT_FORM_MASK, 0);
621	regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
622			   REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
623			   REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
624			   REG_IMR_GDO_MASK);
625
626	/* 12M oscillator */
627	regmap_update_bits(regmap, JZ4770_CODEC_REG_CCR,
628			   REG_CCR_CRYSTAL_MASK, 0);
629
630	/* 0: 16ohm/220uF, 1: 10kohm/1uF */
631	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
632			   REG_CR_HP_LOAD, 0);
633
634	/* disable automatic gain */
635	regmap_update_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN, 0);
636
637	/* Disable DAC lrswap */
638	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_DAC,
639			   REG_CR_DAC_LRSWAP, REG_CR_DAC_LRSWAP);
640
641	/* Independent L/R DAC gain control */
642	regmap_update_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
643			   REG_GCR_DACL_RLGOD, 0);
644
645	/* Disable ADC lrswap */
646	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
647			   REG_CR_ADC_LRSWAP, REG_CR_ADC_LRSWAP);
648
649	/* default to cap-less mode(0) */
650	regmap_update_bits(regmap, JZ4770_CODEC_REG_CR_HP,
651			   REG_CR_HP_SB_HPCM, 0);
652
653	/* Send collected updates. */
654	regcache_cache_only(regmap, false);
655	regcache_sync(regmap);
656
657	/* Reset all interrupt flags. */
658	regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
659}
660
661static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
662{
663	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
664
665	clk_prepare_enable(jz_codec->clk);
666
667	jz4770_codec_codec_init_regs(codec);
668
669	return 0;
670}
671
672static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
673{
674	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
675
676	clk_disable_unprepare(jz_codec->clk);
677}
678
679static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
680	.probe			= jz4770_codec_codec_probe,
681	.remove			= jz4770_codec_codec_remove,
682	.set_bias_level		= jz4770_codec_set_bias_level,
683	.controls		= jz4770_codec_snd_controls,
684	.num_controls		= ARRAY_SIZE(jz4770_codec_snd_controls),
685	.dapm_widgets		= jz4770_codec_dapm_widgets,
686	.num_dapm_widgets	= ARRAY_SIZE(jz4770_codec_dapm_widgets),
687	.dapm_routes		= jz4770_codec_dapm_routes,
688	.num_dapm_routes	= ARRAY_SIZE(jz4770_codec_dapm_routes),
689	.suspend_bias_off	= 1,
690	.use_pmdown_time	= 1,
691};
692
693static const unsigned int jz4770_codec_sample_rates[] = {
694	96000, 48000, 44100, 32000,
695	24000, 22050, 16000, 12000,
696	11025, 9600, 8000,
697};
698
699static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
700				  struct snd_pcm_hw_params *params,
701				  struct snd_soc_dai *dai)
702{
703	struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
704	unsigned int rate, bit_width;
705
706	switch (params_format(params)) {
707	case SNDRV_PCM_FORMAT_S16_LE:
708		bit_width = 0;
709		break;
710	case SNDRV_PCM_FORMAT_S18_3LE:
711		bit_width = 1;
712		break;
713	case SNDRV_PCM_FORMAT_S20_3LE:
714		bit_width = 2;
715		break;
716	case SNDRV_PCM_FORMAT_S24_3LE:
717		bit_width = 3;
718		break;
719	default:
720		return -EINVAL;
721	}
722
723	for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
724		if (jz4770_codec_sample_rates[rate] == params_rate(params))
725			break;
726	}
727
728	if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
729		return -EINVAL;
730
731	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
732		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
733				   REG_AICR_DAC_ADWL_MASK,
734				   bit_width << REG_AICR_DAC_ADWL_OFFSET);
735		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
736				   REG_FCR_DAC_FREQ_MASK,
737				   rate << REG_FCR_DAC_FREQ_OFFSET);
738	} else {
739		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
740				   REG_AICR_ADC_ADWL_MASK,
741				   bit_width << REG_AICR_ADC_ADWL_OFFSET);
742		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
743				   REG_FCR_ADC_FREQ_MASK,
744				   rate << REG_FCR_ADC_FREQ_OFFSET);
745	}
746
747	return 0;
748}
749
750static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
751	.startup	= jz4770_codec_startup,
752	.shutdown	= jz4770_codec_shutdown,
753	.hw_params	= jz4770_codec_hw_params,
754	.trigger	= jz4770_codec_pcm_trigger,
755	.mute_stream	= jz4770_codec_mute_stream,
756	.no_capture_mute = 1,
757};
758
759#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | \
760			  SNDRV_PCM_FMTBIT_S18_3LE | \
761			  SNDRV_PCM_FMTBIT_S20_3LE | \
762			  SNDRV_PCM_FMTBIT_S24_3LE)
763
764static struct snd_soc_dai_driver jz4770_codec_dai = {
765	.name = "jz4770-hifi",
766	.playback = {
767		.stream_name = "Playback",
768		.channels_min = 2,
769		.channels_max = 2,
770		.rates = SNDRV_PCM_RATE_8000_96000,
771		.formats = JZ_CODEC_FORMATS,
772	},
773	.capture = {
774		.stream_name = "Capture",
775		.channels_min = 2,
776		.channels_max = 2,
777		.rates = SNDRV_PCM_RATE_8000_96000,
778		.formats = JZ_CODEC_FORMATS,
779	},
780	.ops = &jz4770_codec_dai_ops,
781};
782
783static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
784{
785	return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
786}
787
788static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
789{
790	switch (reg) {
791	case JZ4770_CODEC_REG_MISSING_REG1:
792	case JZ4770_CODEC_REG_MISSING_REG2:
793		return false;
794	default:
795		return true;
796	}
797}
798
799static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
800{
801	switch (reg) {
802	case JZ4770_CODEC_REG_SR:
803	case JZ4770_CODEC_REG_MISSING_REG1:
804	case JZ4770_CODEC_REG_MISSING_REG2:
805		return false;
806	default:
807		return true;
808	}
809}
810
811static int jz4770_codec_io_wait(struct jz_codec *codec)
812{
813	u32 reg;
814
815	return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
816				  !(reg & ICDC_RGADW_RGWR),
817				  1000, 10 * USEC_PER_MSEC);
818}
819
820static int jz4770_codec_reg_read(void *context, unsigned int reg,
821				 unsigned int *val)
822{
823	struct jz_codec *codec = context;
824	unsigned int i;
825	u32 tmp;
826	int ret;
827
828	ret = jz4770_codec_io_wait(codec);
829	if (ret)
830		return ret;
831
832	tmp = readl(codec->base + ICDC_RGADW_OFFSET);
833	tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
834	    | (reg << ICDC_RGADW_RGADDR_OFFSET);
835	writel(tmp, codec->base + ICDC_RGADW_OFFSET);
836
837	/* wait 6+ cycles */
838	for (i = 0; i < 6; i++)
839		*val = readl(codec->base + ICDC_RGDATA_OFFSET) &
840			ICDC_RGDATA_RGDOUT_MASK;
841
842	return 0;
843}
844
845static int jz4770_codec_reg_write(void *context, unsigned int reg,
846				  unsigned int val)
847{
848	struct jz_codec *codec = context;
849	int ret;
850
851	ret = jz4770_codec_io_wait(codec);
852	if (ret)
853		return ret;
854
855	writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
856	       codec->base + ICDC_RGADW_OFFSET);
857
858	ret = jz4770_codec_io_wait(codec);
859	if (ret)
860		return ret;
861
862	return 0;
863}
864
865static const u8 jz4770_codec_reg_defaults[] = {
866	0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
867	0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
868	0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
869	0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
870	0x07, 0x44, 0x1F, 0x00
871};
872
873static struct regmap_config jz4770_codec_regmap_config = {
874	.reg_bits = 7,
875	.val_bits = 8,
876
877	.max_register = JZ4770_CODEC_REG_AGC5,
878	.volatile_reg = jz4770_codec_volatile,
879	.readable_reg = jz4770_codec_readable,
880	.writeable_reg = jz4770_codec_writeable,
881
882	.reg_read = jz4770_codec_reg_read,
883	.reg_write = jz4770_codec_reg_write,
884
885	.reg_defaults_raw = jz4770_codec_reg_defaults,
886	.num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
887	.cache_type = REGCACHE_FLAT,
888};
889
890static int jz4770_codec_probe(struct platform_device *pdev)
891{
892	struct device *dev = &pdev->dev;
893	struct jz_codec *codec;
894	int ret;
895
896	codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
897	if (!codec)
898		return -ENOMEM;
899
900	codec->dev = dev;
901
902	codec->base = devm_platform_ioremap_resource(pdev, 0);
903	if (IS_ERR(codec->base)) {
904		ret = PTR_ERR(codec->base);
905		dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret);
906		return ret;
907	}
908
909	codec->regmap = devm_regmap_init(dev, NULL, codec,
910					&jz4770_codec_regmap_config);
911	if (IS_ERR(codec->regmap))
912		return PTR_ERR(codec->regmap);
913
914	codec->clk = devm_clk_get(dev, "aic");
915	if (IS_ERR(codec->clk))
916		return PTR_ERR(codec->clk);
917
918	platform_set_drvdata(pdev, codec);
919
920	ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
921					      &jz4770_codec_dai, 1);
922	if (ret) {
923		dev_err(dev, "Failed to register codec: %d\n", ret);
924		return ret;
925	}
926
927	return 0;
928}
929
930static const struct of_device_id jz4770_codec_of_matches[] = {
931	{ .compatible = "ingenic,jz4770-codec", },
932	{ /* sentinel */ }
933};
934MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
935
936static struct platform_driver jz4770_codec_driver = {
937	.probe			= jz4770_codec_probe,
938	.driver			= {
939		.name		= "jz4770-codec",
940		.of_match_table = jz4770_codec_of_matches,
941	},
942};
943module_platform_driver(jz4770_codec_driver);
944
945MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
946MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
947MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
948MODULE_LICENSE("GPL v2");