File Index
Files and directories
Sign in
FILE

jz4770.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/codecs/jz4770.c C
  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_to_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_to_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	struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(codec);
249	int ret = 0;
250
251	switch (cmd) {
252	case SNDRV_PCM_TRIGGER_START:
253	case SNDRV_PCM_TRIGGER_RESUME:
254	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
255		if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
256			snd_soc_dapm_force_bias_level(dapm, 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	SOC_DAPM_DOUBLE_R_TLV("Volume", JZ4770_CODEC_REG_GCR_DACR,
335			      JZ4770_CODEC_REG_GCR_DACL, REG_GCR_GAIN_OFFSET,
336			      REG_GCR_GAIN_MAX, 1, dac_tlv),
337};
338
339static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
340	SOC_DAPM_DOUBLE_R_TLV("Volume", JZ4770_CODEC_REG_GCR_HPR,
341			      JZ4770_CODEC_REG_GCR_HPL, REG_GCR_GAIN_OFFSET,
342			      REG_GCR_GAIN_MAX, 1, out_tlv),
343};
344
345static int hpout_event(struct snd_soc_dapm_widget *w,
346		       struct snd_kcontrol *kcontrol, int event)
347{
348	struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
349	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
350	unsigned int val;
351	int err;
352
353	switch (event) {
354	case SND_SOC_DAPM_PRE_PMU:
355		/* unmute HP */
356		regmap_clear_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
357				  REG_CR_HP_MUTE);
358		break;
359
360	case SND_SOC_DAPM_POST_PMU:
361		/* wait for ramp-up complete (RUP) */
362		err = regmap_read_poll_timeout(jz_codec->regmap,
363					       JZ4770_CODEC_REG_IFR,
364					       val, val & REG_IFR_RUP,
365					       1000, 1 * USEC_PER_SEC);
366		if (err) {
367			dev_err(jz_codec->dev, "RUP timeout: %d", err);
368			return err;
369		}
370
371		/* clear RUP flag */
372		regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
373				REG_IFR_RUP);
374
375		break;
376
377	case SND_SOC_DAPM_POST_PMD:
378		/* mute HP */
379		regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
380				REG_CR_HP_MUTE);
381
382		err = regmap_read_poll_timeout(jz_codec->regmap,
383					       JZ4770_CODEC_REG_IFR,
384					       val, val & REG_IFR_RDO,
385					       1000, 1 * USEC_PER_SEC);
386		if (err) {
387			dev_err(jz_codec->dev, "RDO timeout: %d", err);
388			return err;
389		}
390
391		/* clear RDO flag */
392		regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
393				REG_IFR_RDO);
394
395		break;
396	}
397
398	return 0;
399}
400
401static int adc_poweron_event(struct snd_soc_dapm_widget *w,
402			     struct snd_kcontrol *kcontrol, int event)
403{
404	if (event == SND_SOC_DAPM_POST_PMU)
405		msleep(1000);
406
407	return 0;
408}
409
410static const char * const jz4770_codec_hp_texts[] = {
411	"PCM", "Line In", "Mic 1", "Mic 2"
412};
413static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
414static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
415				  JZ4770_CODEC_REG_CR_HP,
416				  REG_CR_HP_SEL_OFFSET,
417				  REG_CR_HP_SEL_MASK,
418				  jz4770_codec_hp_texts,
419				  jz4770_codec_hp_values);
420static const struct snd_kcontrol_new jz4770_codec_hp_source =
421			SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
422
423static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
424				  JZ4770_CODEC_REG_CR_LO,
425				  REG_CR_LO_SEL_OFFSET,
426				  REG_CR_LO_SEL_MASK,
427				  jz4770_codec_hp_texts,
428				  jz4770_codec_hp_values);
429static const struct snd_kcontrol_new jz4770_codec_lo_source =
430			SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
431
432static const char * const jz4770_codec_cap_texts[] = {
433	"Line In", "Mic 1", "Mic 2"
434};
435static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
436static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
437				  JZ4770_CODEC_REG_CR_ADC,
438				  REG_CR_ADC_IN_SEL_OFFSET,
439				  REG_CR_ADC_IN_SEL_MASK,
440				  jz4770_codec_cap_texts,
441				  jz4770_codec_cap_values);
442static const struct snd_kcontrol_new jz4770_codec_cap_source =
443			SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
444
445static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
446	SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
447			REG_CR_MIC_STEREO_OFFSET, 1, 0),
448};
449
450static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
451	SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
452			   REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
453			   SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
454			   SND_SOC_DAPM_POST_PMD),
455
456	SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
457			 REG_CR_LO_SB_OFFSET, 1, NULL, 0),
458
459	SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
460			 REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
461
462	SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
463			 REG_CR_LI_SB_OFFSET, 1, NULL, 0),
464
465	SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
466			 &jz4770_codec_hp_source),
467	SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
468			 &jz4770_codec_cap_source),
469	SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
470			 &jz4770_codec_lo_source),
471
472	SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
473			 REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
474	SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
475			 REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
476
477	SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
478			 REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
479
480	SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
481			   jz4770_codec_mic_controls,
482			   ARRAY_SIZE(jz4770_codec_mic_controls)),
483
484	SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
485			 REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
486
487	SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
488			   REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
489			   SND_SOC_DAPM_POST_PMU),
490	SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
491			 REG_CR_DAC_SB_OFFSET, 1),
492
493	SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
494			   jz4770_codec_pcm_playback_controls,
495			   ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
496	SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
497			   jz4770_codec_hp_playback_controls,
498			   ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
499
500	SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
501			    REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
502
503	SND_SOC_DAPM_SUPPLY("Cap-less", JZ4770_CODEC_REG_CR_HP,
504			    REG_CR_HP_SB_HPCM_OFFSET, 1, NULL, 0),
505
506	SND_SOC_DAPM_INPUT("MIC1P"),
507	SND_SOC_DAPM_INPUT("MIC1N"),
508	SND_SOC_DAPM_INPUT("MIC2P"),
509	SND_SOC_DAPM_INPUT("MIC2N"),
510
511	SND_SOC_DAPM_OUTPUT("LOUT"),
512	SND_SOC_DAPM_OUTPUT("ROUT"),
513
514	SND_SOC_DAPM_OUTPUT("LHPOUT"),
515	SND_SOC_DAPM_OUTPUT("RHPOUT"),
516
517	SND_SOC_DAPM_INPUT("LLINEIN"),
518	SND_SOC_DAPM_INPUT("RLINEIN"),
519
520	SND_SOC_DAPM_OUTPUT("SYSCLK"),
521};
522
523/* Unconditional routes. */
524static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
525	{ "Mic 1", NULL, "MIC1P" },
526	{ "Mic Diff", NULL, "MIC1N" },
527	{ "Mic 1", NULL, "Mic Diff" },
528	{ "Mic 2", NULL, "MIC2P" },
529	{ "Mic Diff", NULL, "MIC2N" },
530	{ "Mic 2", NULL, "Mic Diff" },
531
532	{ "Line In", NULL, "LLINEIN" },
533	{ "Line In", NULL, "RLINEIN" },
534
535	{ "Mic", "Stereo Capture Switch", "Mic 1" },
536	{ "Mic", "Stereo Capture Switch", "Mic 2" },
537	{ "Headphones Source", "Mic 1", "Mic" },
538	{ "Headphones Source", "Mic 2", "Mic" },
539	{ "Capture Source", "Mic 1", "Mic" },
540	{ "Capture Source", "Mic 2", "Mic" },
541
542	{ "Headphones Source", "Mic 1", "Mic 1" },
543	{ "Headphones Source", "Mic 2", "Mic 2" },
544	{ "Headphones Source", "Line In", "Line In Bypass" },
545	{ "Headphones Source", "PCM", "Headphones Playback" },
546	{ "HP Out", NULL, "Headphones Source" },
547
548	{ "Capture Source", "Line In", "Line In" },
549	{ "Capture Source", "Mic 1", "Mic 1" },
550	{ "Capture Source", "Mic 2", "Mic 2" },
551	{ "ADC", NULL, "Capture Source" },
552
553	{ "Line In Bypass", NULL, "Line In" },
554	{ "Line Out Source", "Line In", "Line In Bypass" },
555	{ "Line Out Source", "PCM", "PCM Playback" },
556
557	{ "LHPOUT", NULL, "HP Out"},
558	{ "RHPOUT", NULL, "HP Out"},
559
560	{ "Line Out", NULL, "Line Out Source" },
561	{ "Line Out Switch 2", NULL, "Line Out" },
562
563	{ "LOUT", NULL, "Line Out Switch 2"},
564	{ "ROUT", NULL, "Line Out Switch 2"},
565
566	{ "PCM Playback", "Volume", "DAC" },
567	{ "Headphones Playback", "Volume", "PCM Playback" },
568
569	{ "SYSCLK", NULL, "DAC" },
570};
571
572static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
573{
574	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
575	struct regmap *regmap = jz_codec->regmap;
576
577	/* Collect updates for later sending. */
578	regcache_cache_only(regmap, true);
579
580	/* default HP output to PCM */
581	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_SEL_MASK);
582
583	/* default line output to PCM */
584	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_LO, REG_CR_LO_SEL_MASK);
585
586	/* Disable stereo mic */
587	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
588			  BIT(REG_CR_MIC_STEREO_OFFSET));
589
590	/* Set mic 1 as default source for ADC */
591	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
592			  REG_CR_ADC_IN_SEL_MASK);
593
594	/* ADC/DAC: serial + i2s */
595	regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
596			REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
597	regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
598			REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
599
600	/* The generated IRQ is a high level */
601	regmap_clear_bits(regmap, JZ4770_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
602	regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
603			   REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
604			   REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
605			   REG_IMR_GDO_MASK);
606
607	/* 12M oscillator */
608	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CCR, REG_CCR_CRYSTAL_MASK);
609
610	/* 0: 16ohm/220uF, 1: 10kohm/1uF */
611	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_LOAD);
612
613	/* disable automatic gain */
614	regmap_clear_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN);
615
616	/* Disable DAC lrswap */
617	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_DAC, REG_CR_DAC_LRSWAP);
618
619	/* Independent L/R DAC gain control */
620	regmap_clear_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
621			  REG_GCR_DACL_RLGOD);
622
623	/* Disable ADC lrswap */
624	regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_ADC, REG_CR_ADC_LRSWAP);
625
626	/* default to cap-less mode(0) */
627	regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP,
628			  BIT(REG_CR_HP_SB_HPCM_OFFSET));
629
630	/* Send collected updates. */
631	regcache_cache_only(regmap, false);
632	regcache_sync(regmap);
633}
634
635static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
636{
637	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
638
639	clk_prepare_enable(jz_codec->clk);
640
641	jz4770_codec_codec_init_regs(codec);
642
643	return 0;
644}
645
646static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
647{
648	struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
649
650	clk_disable_unprepare(jz_codec->clk);
651}
652
653static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
654	.probe			= jz4770_codec_codec_probe,
655	.remove			= jz4770_codec_codec_remove,
656	.set_bias_level		= jz4770_codec_set_bias_level,
657	.controls		= jz4770_codec_snd_controls,
658	.num_controls		= ARRAY_SIZE(jz4770_codec_snd_controls),
659	.dapm_widgets		= jz4770_codec_dapm_widgets,
660	.num_dapm_widgets	= ARRAY_SIZE(jz4770_codec_dapm_widgets),
661	.dapm_routes		= jz4770_codec_dapm_routes,
662	.num_dapm_routes	= ARRAY_SIZE(jz4770_codec_dapm_routes),
663	.suspend_bias_off	= 1,
664	.use_pmdown_time	= 1,
665};
666
667static const unsigned int jz4770_codec_sample_rates[] = {
668	96000, 48000, 44100, 32000,
669	24000, 22050, 16000, 12000,
670	11025, 9600, 8000,
671};
672
673static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
674				  struct snd_pcm_hw_params *params,
675				  struct snd_soc_dai *dai)
676{
677	struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
678	unsigned int rate, bit_width;
679
680	switch (params_format(params)) {
681	case SNDRV_PCM_FORMAT_S16_LE:
682		bit_width = 0;
683		break;
684	case SNDRV_PCM_FORMAT_S18_3LE:
685		bit_width = 1;
686		break;
687	case SNDRV_PCM_FORMAT_S20_3LE:
688		bit_width = 2;
689		break;
690	case SNDRV_PCM_FORMAT_S24_3LE:
691		bit_width = 3;
692		break;
693	default:
694		return -EINVAL;
695	}
696
697	for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
698		if (jz4770_codec_sample_rates[rate] == params_rate(params))
699			break;
700	}
701
702	if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
703		return -EINVAL;
704
705	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
706		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
707				   REG_AICR_DAC_ADWL_MASK,
708				   bit_width << REG_AICR_DAC_ADWL_OFFSET);
709		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
710				   REG_FCR_DAC_FREQ_MASK,
711				   rate << REG_FCR_DAC_FREQ_OFFSET);
712	} else {
713		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
714				   REG_AICR_ADC_ADWL_MASK,
715				   bit_width << REG_AICR_ADC_ADWL_OFFSET);
716		regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
717				   REG_FCR_ADC_FREQ_MASK,
718				   rate << REG_FCR_ADC_FREQ_OFFSET);
719	}
720
721	return 0;
722}
723
724static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
725	.startup	= jz4770_codec_startup,
726	.shutdown	= jz4770_codec_shutdown,
727	.hw_params	= jz4770_codec_hw_params,
728	.trigger	= jz4770_codec_pcm_trigger,
729	.mute_stream	= jz4770_codec_mute_stream,
730	.no_capture_mute = 1,
731};
732
733#define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | \
734			  SNDRV_PCM_FMTBIT_S18_3LE | \
735			  SNDRV_PCM_FMTBIT_S20_3LE | \
736			  SNDRV_PCM_FMTBIT_S24_3LE)
737
738static struct snd_soc_dai_driver jz4770_codec_dai = {
739	.name = "jz4770-hifi",
740	.playback = {
741		.stream_name = "Playback",
742		.channels_min = 2,
743		.channels_max = 2,
744		.rates = SNDRV_PCM_RATE_8000_96000,
745		.formats = JZ_CODEC_FORMATS,
746	},
747	.capture = {
748		.stream_name = "Capture",
749		.channels_min = 2,
750		.channels_max = 2,
751		.rates = SNDRV_PCM_RATE_8000_96000,
752		.formats = JZ_CODEC_FORMATS,
753	},
754	.ops = &jz4770_codec_dai_ops,
755};
756
757static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
758{
759	return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
760}
761
762static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
763{
764	switch (reg) {
765	case JZ4770_CODEC_REG_MISSING_REG1:
766	case JZ4770_CODEC_REG_MISSING_REG2:
767		return false;
768	default:
769		return true;
770	}
771}
772
773static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
774{
775	switch (reg) {
776	case JZ4770_CODEC_REG_SR:
777	case JZ4770_CODEC_REG_MISSING_REG1:
778	case JZ4770_CODEC_REG_MISSING_REG2:
779		return false;
780	default:
781		return true;
782	}
783}
784
785static int jz4770_codec_io_wait(struct jz_codec *codec)
786{
787	u32 reg;
788
789	return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
790				  !(reg & ICDC_RGADW_RGWR),
791				  1000, 1 * USEC_PER_SEC);
792}
793
794static int jz4770_codec_reg_read(void *context, unsigned int reg,
795				 unsigned int *val)
796{
797	struct jz_codec *codec = context;
798	unsigned int i;
799	u32 tmp;
800	int ret;
801
802	ret = jz4770_codec_io_wait(codec);
803	if (ret)
804		return ret;
805
806	tmp = readl(codec->base + ICDC_RGADW_OFFSET);
807	tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
808	    | (reg << ICDC_RGADW_RGADDR_OFFSET);
809	writel(tmp, codec->base + ICDC_RGADW_OFFSET);
810
811	/* wait 6+ cycles */
812	for (i = 0; i < 6; i++)
813		*val = readl(codec->base + ICDC_RGDATA_OFFSET) &
814			ICDC_RGDATA_RGDOUT_MASK;
815
816	return 0;
817}
818
819static int jz4770_codec_reg_write(void *context, unsigned int reg,
820				  unsigned int val)
821{
822	struct jz_codec *codec = context;
823	int ret;
824
825	ret = jz4770_codec_io_wait(codec);
826	if (ret)
827		return ret;
828
829	writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
830	       codec->base + ICDC_RGADW_OFFSET);
831
832	ret = jz4770_codec_io_wait(codec);
833	if (ret)
834		return ret;
835
836	return 0;
837}
838
839static const u8 jz4770_codec_reg_defaults[] = {
840	0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
841	0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
842	0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
843	0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
844	0x07, 0x44, 0x1F, 0x00
845};
846
847static const struct regmap_config jz4770_codec_regmap_config = {
848	.reg_bits = 7,
849	.val_bits = 8,
850
851	.max_register = JZ4770_CODEC_REG_AGC5,
852	.volatile_reg = jz4770_codec_volatile,
853	.readable_reg = jz4770_codec_readable,
854	.writeable_reg = jz4770_codec_writeable,
855
856	.reg_read = jz4770_codec_reg_read,
857	.reg_write = jz4770_codec_reg_write,
858
859	.reg_defaults_raw = jz4770_codec_reg_defaults,
860	.num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
861	.cache_type = REGCACHE_FLAT,
862};
863
864static int jz4770_codec_probe(struct platform_device *pdev)
865{
866	struct device *dev = &pdev->dev;
867	struct jz_codec *codec;
868	int ret;
869
870	codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
871	if (!codec)
872		return -ENOMEM;
873
874	codec->dev = dev;
875
876	codec->base = devm_platform_ioremap_resource(pdev, 0);
877	if (IS_ERR(codec->base))
878		return PTR_ERR(codec->base);
879
880	codec->regmap = devm_regmap_init(dev, NULL, codec,
881					&jz4770_codec_regmap_config);
882	if (IS_ERR(codec->regmap))
883		return PTR_ERR(codec->regmap);
884
885	codec->clk = devm_clk_get(dev, "aic");
886	if (IS_ERR(codec->clk))
887		return PTR_ERR(codec->clk);
888
889	platform_set_drvdata(pdev, codec);
890
891	ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
892					      &jz4770_codec_dai, 1);
893	if (ret) {
894		dev_err(dev, "Failed to register codec: %d\n", ret);
895		return ret;
896	}
897
898	return 0;
899}
900
901static const struct of_device_id jz4770_codec_of_matches[] = {
902	{ .compatible = "ingenic,jz4770-codec", },
903	{ /* sentinel */ }
904};
905MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
906
907static struct platform_driver jz4770_codec_driver = {
908	.probe			= jz4770_codec_probe,
909	.driver			= {
910		.name		= "jz4770-codec",
911		.of_match_table = jz4770_codec_of_matches,
912	},
913};
914module_platform_driver(jz4770_codec_driver);
915
916MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
917MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
918MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
919MODULE_LICENSE("GPL v2");
~/ Read-only file preview.