~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/codecs/jz4770.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 */
 40 enum {
 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 */
178 struct jz_codec {
179         struct device *dev;
180         struct regmap *regmap;
181         void __iomem *base;
182         struct clk *clk;
183 };
184 
185 static 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 
216 static 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 
233 static 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 
244 static 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 
270 static 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 */
306 static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
307 static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
308 static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
309 static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
310 static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);
311 
312 /* Unconditional controls. */
313 static 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 
333 static 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 
355 static 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 
373 static 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 
429 static 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 
438 static const char * const jz4770_codec_hp_texts[] = {
439         "PCM", "Line In", "Mic 1", "Mic 2"
440 };
441 static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
442 static 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);
448 static const struct snd_kcontrol_new jz4770_codec_hp_source =
449                         SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
450 
451 static 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);
457 static const struct snd_kcontrol_new jz4770_codec_lo_source =
458                         SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
459 
460 static const char * const jz4770_codec_cap_texts[] = {
461         "Line In", "Mic 1", "Mic 2"
462 };
463 static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
464 static 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);
470 static const struct snd_kcontrol_new jz4770_codec_cap_source =
471                         SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
472 
473 static 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 
478 static 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. */
552 static 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 
600 static 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 
663 static 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 
674 static 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 
681 static 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 
695 static const unsigned int jz4770_codec_sample_rates[] = {
696         96000, 48000, 44100, 32000,
697         24000, 22050, 16000, 12000,
698         11025, 9600, 8000,
699 };
700 
701 static 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 
752 static 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 
766 static 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 
785 static 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 
790 static 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 
801 static 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 
813 static 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 
822 static 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 
847 static 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 
867 static 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 
875 static 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 
892 static 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 
929 static const struct of_device_id jz4770_codec_of_matches[] = {
930         { .compatible = "ingenic,jz4770-codec", },
931         { /* sentinel */ }
932 };
933 MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
934 
935 static 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 };
942 module_platform_driver(jz4770_codec_driver);
943 
944 MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
945 MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
946 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
947 MODULE_LICENSE("GPL v2");
948 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php