Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Ingenic JZ4770 CODEC driver
0004 //
0005 // Copyright (C) 2012, Maarten ter Huurne <maarten@treewalker.org>
0006 // Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net>
0007 
0008 #include <linux/clk.h>
0009 #include <linux/delay.h>
0010 #include <linux/iopoll.h>
0011 #include <linux/module.h>
0012 #include <linux/regmap.h>
0013 #include <linux/time64.h>
0014 
0015 #include <sound/pcm_params.h>
0016 #include <sound/soc.h>
0017 #include <sound/soc-dai.h>
0018 #include <sound/soc-dapm.h>
0019 #include <sound/tlv.h>
0020 
0021 #define ICDC_RGADW_OFFSET       0x00
0022 #define ICDC_RGDATA_OFFSET      0x04
0023 
0024 /* ICDC internal register access control register(RGADW) */
0025 #define ICDC_RGADW_RGWR         BIT(16)
0026 
0027 #define ICDC_RGADW_RGADDR_OFFSET    8
0028 #define ICDC_RGADW_RGADDR_MASK      GENMASK(14, ICDC_RGADW_RGADDR_OFFSET)
0029 
0030 #define ICDC_RGADW_RGDIN_OFFSET     0
0031 #define ICDC_RGADW_RGDIN_MASK       GENMASK(7, ICDC_RGADW_RGDIN_OFFSET)
0032 
0033 /* ICDC internal register data output register (RGDATA)*/
0034 #define ICDC_RGDATA_IRQ         BIT(8)
0035 
0036 #define ICDC_RGDATA_RGDOUT_OFFSET   0
0037 #define ICDC_RGDATA_RGDOUT_MASK     GENMASK(7, ICDC_RGDATA_RGDOUT_OFFSET)
0038 
0039 /* Internal register space, accessed through regmap */
0040 enum {
0041     JZ4770_CODEC_REG_SR,
0042     JZ4770_CODEC_REG_AICR_DAC,
0043     JZ4770_CODEC_REG_AICR_ADC,
0044     JZ4770_CODEC_REG_CR_LO,
0045     JZ4770_CODEC_REG_CR_HP,
0046 
0047     JZ4770_CODEC_REG_MISSING_REG1,
0048 
0049     JZ4770_CODEC_REG_CR_DAC,
0050     JZ4770_CODEC_REG_CR_MIC,
0051     JZ4770_CODEC_REG_CR_LI,
0052     JZ4770_CODEC_REG_CR_ADC,
0053     JZ4770_CODEC_REG_CR_MIX,
0054     JZ4770_CODEC_REG_CR_VIC,
0055     JZ4770_CODEC_REG_CCR,
0056     JZ4770_CODEC_REG_FCR_DAC,
0057     JZ4770_CODEC_REG_FCR_ADC,
0058     JZ4770_CODEC_REG_ICR,
0059     JZ4770_CODEC_REG_IMR,
0060     JZ4770_CODEC_REG_IFR,
0061     JZ4770_CODEC_REG_GCR_HPL,
0062     JZ4770_CODEC_REG_GCR_HPR,
0063     JZ4770_CODEC_REG_GCR_LIBYL,
0064     JZ4770_CODEC_REG_GCR_LIBYR,
0065     JZ4770_CODEC_REG_GCR_DACL,
0066     JZ4770_CODEC_REG_GCR_DACR,
0067     JZ4770_CODEC_REG_GCR_MIC1,
0068     JZ4770_CODEC_REG_GCR_MIC2,
0069     JZ4770_CODEC_REG_GCR_ADCL,
0070     JZ4770_CODEC_REG_GCR_ADCR,
0071 
0072     JZ4770_CODEC_REG_MISSING_REG2,
0073 
0074     JZ4770_CODEC_REG_GCR_MIXADC,
0075     JZ4770_CODEC_REG_GCR_MIXDAC,
0076     JZ4770_CODEC_REG_AGC1,
0077     JZ4770_CODEC_REG_AGC2,
0078     JZ4770_CODEC_REG_AGC3,
0079     JZ4770_CODEC_REG_AGC4,
0080     JZ4770_CODEC_REG_AGC5,
0081 };
0082 
0083 #define REG_AICR_DAC_ADWL_OFFSET    6
0084 #define REG_AICR_DAC_ADWL_MASK      (0x3 << REG_AICR_DAC_ADWL_OFFSET)
0085 #define REG_AICR_DAC_SERIAL     BIT(1)
0086 #define REG_AICR_DAC_I2S        BIT(0)
0087 
0088 #define REG_AICR_ADC_ADWL_OFFSET    6
0089 #define REG_AICR_ADC_ADWL_MASK      (0x3 << REG_AICR_ADC_ADWL_OFFSET)
0090 #define REG_AICR_ADC_SERIAL     BIT(1)
0091 #define REG_AICR_ADC_I2S        BIT(0)
0092 
0093 #define REG_CR_LO_MUTE_OFFSET       7
0094 #define REG_CR_LO_SB_OFFSET     4
0095 #define REG_CR_LO_SEL_OFFSET        0
0096 #define REG_CR_LO_SEL_MASK      (0x3 << REG_CR_LO_SEL_OFFSET)
0097 
0098 #define REG_CR_HP_MUTE          BIT(7)
0099 #define REG_CR_HP_LOAD          BIT(6)
0100 #define REG_CR_HP_SB_OFFSET     4
0101 #define REG_CR_HP_SB_HPCM_OFFSET    3
0102 #define REG_CR_HP_SEL_OFFSET        0
0103 #define REG_CR_HP_SEL_MASK      (0x3 << REG_CR_HP_SEL_OFFSET)
0104 
0105 #define REG_CR_DAC_MUTE         BIT(7)
0106 #define REG_CR_DAC_MONO         BIT(6)
0107 #define REG_CR_DAC_LEFT_ONLY        BIT(5)
0108 #define REG_CR_DAC_SB_OFFSET        4
0109 #define REG_CR_DAC_LRSWAP       BIT(3)
0110 
0111 #define REG_CR_MIC_STEREO_OFFSET    7
0112 #define REG_CR_MIC_IDIFF_OFFSET     6
0113 #define REG_CR_MIC_SB_MIC2_OFFSET   5
0114 #define REG_CR_MIC_SB_MIC1_OFFSET   4
0115 #define REG_CR_MIC_BIAS_V0_OFFSET   1
0116 #define REG_CR_MIC_BIAS_SB_OFFSET   0
0117 
0118 #define REG_CR_LI_LIBY_OFFSET       4
0119 #define REG_CR_LI_SB_OFFSET     0
0120 
0121 #define REG_CR_ADC_DMIC_SEL     BIT(7)
0122 #define REG_CR_ADC_MONO         BIT(6)
0123 #define REG_CR_ADC_LEFT_ONLY        BIT(5)
0124 #define REG_CR_ADC_SB_OFFSET        4
0125 #define REG_CR_ADC_LRSWAP       BIT(3)
0126 #define REG_CR_ADC_IN_SEL_OFFSET    0
0127 #define REG_CR_ADC_IN_SEL_MASK      (0x3 << REG_CR_ADC_IN_SEL_OFFSET)
0128 
0129 #define REG_CR_VIC_SB_SLEEP     BIT(1)
0130 #define REG_CR_VIC_SB           BIT(0)
0131 
0132 #define REG_CCR_CRYSTAL_OFFSET      0
0133 #define REG_CCR_CRYSTAL_MASK        (0xf << REG_CCR_CRYSTAL_OFFSET)
0134 
0135 #define REG_FCR_DAC_FREQ_OFFSET     0
0136 #define REG_FCR_DAC_FREQ_MASK       (0xf << REG_FCR_DAC_FREQ_OFFSET)
0137 
0138 #define REG_FCR_ADC_FREQ_OFFSET     0
0139 #define REG_FCR_ADC_FREQ_MASK       (0xf << REG_FCR_ADC_FREQ_OFFSET)
0140 
0141 #define REG_ICR_INT_FORM_OFFSET     6
0142 #define REG_ICR_INT_FORM_MASK       (0x3 << REG_ICR_INT_FORM_OFFSET)
0143 
0144 #define REG_IMR_ALL_MASK        (0x7f)
0145 #define REG_IMR_SCLR_MASK       BIT(6)
0146 #define REG_IMR_JACK_MASK       BIT(5)
0147 #define REG_IMR_SCMC_MASK       BIT(4)
0148 #define REG_IMR_RUP_MASK        BIT(3)
0149 #define REG_IMR_RDO_MASK        BIT(2)
0150 #define REG_IMR_GUP_MASK        BIT(1)
0151 #define REG_IMR_GDO_MASK        BIT(0)
0152 
0153 #define REG_IFR_ALL_MASK        (0x7f)
0154 #define REG_IFR_SCLR            BIT(6)
0155 #define REG_IFR_JACK            BIT(5)
0156 #define REG_IFR_SCMC            BIT(4)
0157 #define REG_IFR_RUP         BIT(3)
0158 #define REG_IFR_RDO         BIT(2)
0159 #define REG_IFR_GUP         BIT(1)
0160 #define REG_IFR_GDO         BIT(0)
0161 
0162 #define REG_GCR_HPL_LRGO        BIT(7)
0163 
0164 #define REG_GCR_DACL_RLGOD      BIT(7)
0165 
0166 #define REG_GCR_GAIN_OFFSET     0
0167 #define REG_GCR_GAIN_MAX        0x1f
0168 
0169 #define REG_GCR_MIC_GAIN_OFFSET     0
0170 #define REG_GCR_MIC_GAIN_MAX        5
0171 
0172 #define REG_GCR_ADC_GAIN_OFFSET     0
0173 #define REG_GCR_ADC_GAIN_MAX        23
0174 
0175 #define REG_AGC1_EN         BIT(7)
0176 
0177 /* codec private data */
0178 struct jz_codec {
0179     struct device *dev;
0180     struct regmap *regmap;
0181     void __iomem *base;
0182     struct clk *clk;
0183 };
0184 
0185 static int jz4770_codec_set_bias_level(struct snd_soc_component *codec,
0186                        enum snd_soc_bias_level level)
0187 {
0188     struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0189     struct regmap *regmap = jz_codec->regmap;
0190 
0191     switch (level) {
0192     case SND_SOC_BIAS_PREPARE:
0193         /* Reset all interrupt flags. */
0194         regmap_write(regmap, JZ4770_CODEC_REG_IFR, REG_IFR_ALL_MASK);
0195 
0196         regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0197                   REG_CR_VIC_SB);
0198         msleep(250);
0199         regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0200                   REG_CR_VIC_SB_SLEEP);
0201         msleep(400);
0202         break;
0203     case SND_SOC_BIAS_STANDBY:
0204         regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0205                 REG_CR_VIC_SB_SLEEP);
0206         regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_VIC,
0207                 REG_CR_VIC_SB);
0208         fallthrough;
0209     default:
0210         break;
0211     }
0212 
0213     return 0;
0214 }
0215 
0216 static int jz4770_codec_startup(struct snd_pcm_substream *substream,
0217                 struct snd_soc_dai *dai)
0218 {
0219     struct snd_soc_component *codec = dai->component;
0220     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
0221 
0222     /*
0223      * SYSCLK output from the codec to the AIC is required to keep the
0224      * DMA transfer going during playback when all audible outputs have
0225      * been disabled.
0226      */
0227     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0228         snd_soc_dapm_force_enable_pin(dapm, "SYSCLK");
0229 
0230     return 0;
0231 }
0232 
0233 static void jz4770_codec_shutdown(struct snd_pcm_substream *substream,
0234                   struct snd_soc_dai *dai)
0235 {
0236     struct snd_soc_component *codec = dai->component;
0237     struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec);
0238 
0239     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
0240         snd_soc_dapm_disable_pin(dapm, "SYSCLK");
0241 }
0242 
0243 
0244 static int jz4770_codec_pcm_trigger(struct snd_pcm_substream *substream,
0245                     int cmd, struct snd_soc_dai *dai)
0246 {
0247     struct snd_soc_component *codec = dai->component;
0248     int ret = 0;
0249 
0250     switch (cmd) {
0251     case SNDRV_PCM_TRIGGER_START:
0252     case SNDRV_PCM_TRIGGER_RESUME:
0253     case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0254         if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
0255             snd_soc_component_force_bias_level(codec,
0256                                SND_SOC_BIAS_ON);
0257         break;
0258     case SNDRV_PCM_TRIGGER_STOP:
0259     case SNDRV_PCM_TRIGGER_SUSPEND:
0260     case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0261         /* do nothing */
0262         break;
0263     default:
0264         ret = -EINVAL;
0265     }
0266 
0267     return ret;
0268 }
0269 
0270 static int jz4770_codec_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
0271 {
0272     struct snd_soc_component *codec = dai->component;
0273     struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0274     unsigned int gain_bit = mute ? REG_IFR_GDO : REG_IFR_GUP;
0275     unsigned int val;
0276     int change, err;
0277 
0278     change = snd_soc_component_update_bits(codec, JZ4770_CODEC_REG_CR_DAC,
0279                            REG_CR_DAC_MUTE,
0280                            mute ? REG_CR_DAC_MUTE : 0);
0281     if (change == 1) {
0282         regmap_read(jz_codec->regmap, JZ4770_CODEC_REG_CR_DAC, &val);
0283 
0284         if (val & BIT(REG_CR_DAC_SB_OFFSET))
0285             return 1;
0286 
0287         err = regmap_read_poll_timeout(jz_codec->regmap,
0288                            JZ4770_CODEC_REG_IFR,
0289                            val, val & gain_bit,
0290                            1000, 1 * USEC_PER_SEC);
0291         if (err) {
0292             dev_err(jz_codec->dev,
0293                 "Timeout while setting digital mute: %d", err);
0294             return err;
0295         }
0296 
0297         /* clear GUP/GDO flag */
0298         regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
0299                 gain_bit);
0300     }
0301 
0302     return 0;
0303 }
0304 
0305 /* unit: 0.01dB */
0306 static const DECLARE_TLV_DB_MINMAX_MUTE(dac_tlv, -3100, 0);
0307 static const DECLARE_TLV_DB_SCALE(adc_tlv, 0, 100, 0);
0308 static const DECLARE_TLV_DB_MINMAX(out_tlv, -2500, 600);
0309 static const DECLARE_TLV_DB_SCALE(linein_tlv, -2500, 100, 0);
0310 static const DECLARE_TLV_DB_MINMAX(mixer_tlv, -3100, 0);
0311 
0312 /* Unconditional controls. */
0313 static const struct snd_kcontrol_new jz4770_codec_snd_controls[] = {
0314     /* record gain control */
0315     SOC_DOUBLE_R_TLV("PCM Capture Volume",
0316              JZ4770_CODEC_REG_GCR_ADCL, JZ4770_CODEC_REG_GCR_ADCR,
0317              REG_GCR_ADC_GAIN_OFFSET, REG_GCR_ADC_GAIN_MAX,
0318              0, adc_tlv),
0319 
0320     SOC_DOUBLE_R_TLV("Line In Bypass Playback Volume",
0321              JZ4770_CODEC_REG_GCR_LIBYL, JZ4770_CODEC_REG_GCR_LIBYR,
0322              REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, linein_tlv),
0323 
0324     SOC_SINGLE_TLV("Mixer Capture Volume",
0325                JZ4770_CODEC_REG_GCR_MIXADC,
0326                REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
0327 
0328     SOC_SINGLE_TLV("Mixer Playback Volume",
0329                JZ4770_CODEC_REG_GCR_MIXDAC,
0330                REG_GCR_GAIN_OFFSET, REG_GCR_GAIN_MAX, 1, mixer_tlv),
0331 };
0332 
0333 static const struct snd_kcontrol_new jz4770_codec_pcm_playback_controls[] = {
0334     {
0335         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0336         .name = "Volume",
0337         .info = snd_soc_info_volsw,
0338         .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
0339             | SNDRV_CTL_ELEM_ACCESS_READWRITE,
0340         .tlv.p = dac_tlv,
0341         .get = snd_soc_dapm_get_volsw,
0342         .put = snd_soc_dapm_put_volsw,
0343         /*
0344          * NOTE: DACR/DACL are inversed; the gain value written to DACR
0345          * seems to affect the left channel, and the gain value written
0346          * to DACL seems to affect the right channel.
0347          */
0348         .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_DACR,
0349                             JZ4770_CODEC_REG_GCR_DACL,
0350                             REG_GCR_GAIN_OFFSET,
0351                             REG_GCR_GAIN_MAX, 1),
0352     },
0353 };
0354 
0355 static const struct snd_kcontrol_new jz4770_codec_hp_playback_controls[] = {
0356     {
0357         .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
0358         .name = "Volume",
0359         .info = snd_soc_info_volsw,
0360         .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ
0361             | SNDRV_CTL_ELEM_ACCESS_READWRITE,
0362         .tlv.p = out_tlv,
0363         .get = snd_soc_dapm_get_volsw,
0364         .put = snd_soc_dapm_put_volsw,
0365         /* HPR/HPL inversed for the same reason as above */
0366         .private_value = SOC_DOUBLE_R_VALUE(JZ4770_CODEC_REG_GCR_HPR,
0367                             JZ4770_CODEC_REG_GCR_HPL,
0368                             REG_GCR_GAIN_OFFSET,
0369                             REG_GCR_GAIN_MAX, 1),
0370     },
0371 };
0372 
0373 static int hpout_event(struct snd_soc_dapm_widget *w,
0374                struct snd_kcontrol *kcontrol, int event)
0375 {
0376     struct snd_soc_component *codec = snd_soc_dapm_to_component(w->dapm);
0377     struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0378     unsigned int val;
0379     int err;
0380 
0381     switch (event) {
0382     case SND_SOC_DAPM_PRE_PMU:
0383         /* unmute HP */
0384         regmap_clear_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
0385                   REG_CR_HP_MUTE);
0386         break;
0387 
0388     case SND_SOC_DAPM_POST_PMU:
0389         /* wait for ramp-up complete (RUP) */
0390         err = regmap_read_poll_timeout(jz_codec->regmap,
0391                            JZ4770_CODEC_REG_IFR,
0392                            val, val & REG_IFR_RUP,
0393                            1000, 1 * USEC_PER_SEC);
0394         if (err) {
0395             dev_err(jz_codec->dev, "RUP timeout: %d", err);
0396             return err;
0397         }
0398 
0399         /* clear RUP flag */
0400         regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
0401                 REG_IFR_RUP);
0402 
0403         break;
0404 
0405     case SND_SOC_DAPM_POST_PMD:
0406         /* mute HP */
0407         regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_CR_HP,
0408                 REG_CR_HP_MUTE);
0409 
0410         err = regmap_read_poll_timeout(jz_codec->regmap,
0411                            JZ4770_CODEC_REG_IFR,
0412                            val, val & REG_IFR_RDO,
0413                            1000, 1 * USEC_PER_SEC);
0414         if (err) {
0415             dev_err(jz_codec->dev, "RDO timeout: %d", err);
0416             return err;
0417         }
0418 
0419         /* clear RDO flag */
0420         regmap_set_bits(jz_codec->regmap, JZ4770_CODEC_REG_IFR,
0421                 REG_IFR_RDO);
0422 
0423         break;
0424     }
0425 
0426     return 0;
0427 }
0428 
0429 static int adc_poweron_event(struct snd_soc_dapm_widget *w,
0430                  struct snd_kcontrol *kcontrol, int event)
0431 {
0432     if (event == SND_SOC_DAPM_POST_PMU)
0433         msleep(1000);
0434 
0435     return 0;
0436 }
0437 
0438 static const char * const jz4770_codec_hp_texts[] = {
0439     "PCM", "Line In", "Mic 1", "Mic 2"
0440 };
0441 static const unsigned int jz4770_codec_hp_values[] = { 3, 2, 0, 1 };
0442 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_hp_enum,
0443                   JZ4770_CODEC_REG_CR_HP,
0444                   REG_CR_HP_SEL_OFFSET,
0445                   REG_CR_HP_SEL_MASK,
0446                   jz4770_codec_hp_texts,
0447                   jz4770_codec_hp_values);
0448 static const struct snd_kcontrol_new jz4770_codec_hp_source =
0449             SOC_DAPM_ENUM("Route", jz4770_codec_hp_enum);
0450 
0451 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_lo_enum,
0452                   JZ4770_CODEC_REG_CR_LO,
0453                   REG_CR_LO_SEL_OFFSET,
0454                   REG_CR_LO_SEL_MASK,
0455                   jz4770_codec_hp_texts,
0456                   jz4770_codec_hp_values);
0457 static const struct snd_kcontrol_new jz4770_codec_lo_source =
0458             SOC_DAPM_ENUM("Route", jz4770_codec_lo_enum);
0459 
0460 static const char * const jz4770_codec_cap_texts[] = {
0461     "Line In", "Mic 1", "Mic 2"
0462 };
0463 static const unsigned int jz4770_codec_cap_values[] = { 2, 0, 1 };
0464 static SOC_VALUE_ENUM_SINGLE_DECL(jz4770_codec_cap_enum,
0465                   JZ4770_CODEC_REG_CR_ADC,
0466                   REG_CR_ADC_IN_SEL_OFFSET,
0467                   REG_CR_ADC_IN_SEL_MASK,
0468                   jz4770_codec_cap_texts,
0469                   jz4770_codec_cap_values);
0470 static const struct snd_kcontrol_new jz4770_codec_cap_source =
0471             SOC_DAPM_ENUM("Route", jz4770_codec_cap_enum);
0472 
0473 static const struct snd_kcontrol_new jz4770_codec_mic_controls[] = {
0474     SOC_DAPM_SINGLE("Stereo Capture Switch", JZ4770_CODEC_REG_CR_MIC,
0475             REG_CR_MIC_STEREO_OFFSET, 1, 0),
0476 };
0477 
0478 static const struct snd_soc_dapm_widget jz4770_codec_dapm_widgets[] = {
0479     SND_SOC_DAPM_PGA_E("HP Out", JZ4770_CODEC_REG_CR_HP,
0480                REG_CR_HP_SB_OFFSET, 1, NULL, 0, hpout_event,
0481                SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU |
0482                SND_SOC_DAPM_POST_PMD),
0483 
0484     SND_SOC_DAPM_PGA("Line Out", JZ4770_CODEC_REG_CR_LO,
0485              REG_CR_LO_SB_OFFSET, 1, NULL, 0),
0486 
0487     SND_SOC_DAPM_PGA("Line Out Switch 2", JZ4770_CODEC_REG_CR_LO,
0488              REG_CR_LO_MUTE_OFFSET, 1, NULL, 0),
0489 
0490     SND_SOC_DAPM_PGA("Line In", JZ4770_CODEC_REG_CR_LI,
0491              REG_CR_LI_SB_OFFSET, 1, NULL, 0),
0492 
0493     SND_SOC_DAPM_MUX("Headphones Source", SND_SOC_NOPM, 0, 0,
0494              &jz4770_codec_hp_source),
0495     SND_SOC_DAPM_MUX("Capture Source", SND_SOC_NOPM, 0, 0,
0496              &jz4770_codec_cap_source),
0497     SND_SOC_DAPM_MUX("Line Out Source", SND_SOC_NOPM, 0, 0,
0498              &jz4770_codec_lo_source),
0499 
0500     SND_SOC_DAPM_PGA("Mic 1", JZ4770_CODEC_REG_CR_MIC,
0501              REG_CR_MIC_SB_MIC1_OFFSET, 1, NULL, 0),
0502     SND_SOC_DAPM_PGA("Mic 2", JZ4770_CODEC_REG_CR_MIC,
0503              REG_CR_MIC_SB_MIC2_OFFSET, 1, NULL, 0),
0504 
0505     SND_SOC_DAPM_PGA("Mic Diff", JZ4770_CODEC_REG_CR_MIC,
0506              REG_CR_MIC_IDIFF_OFFSET, 0, NULL, 0),
0507 
0508     SND_SOC_DAPM_MIXER("Mic", SND_SOC_NOPM, 0, 0,
0509                jz4770_codec_mic_controls,
0510                ARRAY_SIZE(jz4770_codec_mic_controls)),
0511 
0512     SND_SOC_DAPM_PGA("Line In Bypass", JZ4770_CODEC_REG_CR_LI,
0513              REG_CR_LI_LIBY_OFFSET, 1, NULL, 0),
0514 
0515     SND_SOC_DAPM_ADC_E("ADC", "HiFi Capture", JZ4770_CODEC_REG_CR_ADC,
0516                REG_CR_ADC_SB_OFFSET, 1, adc_poweron_event,
0517                SND_SOC_DAPM_POST_PMU),
0518     SND_SOC_DAPM_DAC("DAC", "HiFi Playback", JZ4770_CODEC_REG_CR_DAC,
0519              REG_CR_DAC_SB_OFFSET, 1),
0520 
0521     SND_SOC_DAPM_MIXER("PCM Playback", SND_SOC_NOPM, 0, 0,
0522                jz4770_codec_pcm_playback_controls,
0523                ARRAY_SIZE(jz4770_codec_pcm_playback_controls)),
0524     SND_SOC_DAPM_MIXER("Headphones Playback", SND_SOC_NOPM, 0, 0,
0525                jz4770_codec_hp_playback_controls,
0526                ARRAY_SIZE(jz4770_codec_hp_playback_controls)),
0527 
0528     SND_SOC_DAPM_SUPPLY("MICBIAS", JZ4770_CODEC_REG_CR_MIC,
0529                 REG_CR_MIC_BIAS_SB_OFFSET, 1, NULL, 0),
0530 
0531     SND_SOC_DAPM_SUPPLY("Cap-less", JZ4770_CODEC_REG_CR_HP,
0532                 REG_CR_HP_SB_HPCM_OFFSET, 1, NULL, 0),
0533 
0534     SND_SOC_DAPM_INPUT("MIC1P"),
0535     SND_SOC_DAPM_INPUT("MIC1N"),
0536     SND_SOC_DAPM_INPUT("MIC2P"),
0537     SND_SOC_DAPM_INPUT("MIC2N"),
0538 
0539     SND_SOC_DAPM_OUTPUT("LOUT"),
0540     SND_SOC_DAPM_OUTPUT("ROUT"),
0541 
0542     SND_SOC_DAPM_OUTPUT("LHPOUT"),
0543     SND_SOC_DAPM_OUTPUT("RHPOUT"),
0544 
0545     SND_SOC_DAPM_INPUT("LLINEIN"),
0546     SND_SOC_DAPM_INPUT("RLINEIN"),
0547 
0548     SND_SOC_DAPM_OUTPUT("SYSCLK"),
0549 };
0550 
0551 /* Unconditional routes. */
0552 static const struct snd_soc_dapm_route jz4770_codec_dapm_routes[] = {
0553     { "Mic 1", NULL, "MIC1P" },
0554     { "Mic Diff", NULL, "MIC1N" },
0555     { "Mic 1", NULL, "Mic Diff" },
0556     { "Mic 2", NULL, "MIC2P" },
0557     { "Mic Diff", NULL, "MIC2N" },
0558     { "Mic 2", NULL, "Mic Diff" },
0559 
0560     { "Line In", NULL, "LLINEIN" },
0561     { "Line In", NULL, "RLINEIN" },
0562 
0563     { "Mic", "Stereo Capture Switch", "Mic 1" },
0564     { "Mic", "Stereo Capture Switch", "Mic 2" },
0565     { "Headphones Source", "Mic 1", "Mic" },
0566     { "Headphones Source", "Mic 2", "Mic" },
0567     { "Capture Source", "Mic 1", "Mic" },
0568     { "Capture Source", "Mic 2", "Mic" },
0569 
0570     { "Headphones Source", "Mic 1", "Mic 1" },
0571     { "Headphones Source", "Mic 2", "Mic 2" },
0572     { "Headphones Source", "Line In", "Line In Bypass" },
0573     { "Headphones Source", "PCM", "Headphones Playback" },
0574     { "HP Out", NULL, "Headphones Source" },
0575 
0576     { "Capture Source", "Line In", "Line In" },
0577     { "Capture Source", "Mic 1", "Mic 1" },
0578     { "Capture Source", "Mic 2", "Mic 2" },
0579     { "ADC", NULL, "Capture Source" },
0580 
0581     { "Line In Bypass", NULL, "Line In" },
0582     { "Line Out Source", "Line In", "Line In Bypass" },
0583     { "Line Out Source", "PCM", "PCM Playback" },
0584 
0585     { "LHPOUT", NULL, "HP Out"},
0586     { "RHPOUT", NULL, "HP Out"},
0587 
0588     { "Line Out", NULL, "Line Out Source" },
0589     { "Line Out Switch 2", NULL, "Line Out" },
0590 
0591     { "LOUT", NULL, "Line Out Switch 2"},
0592     { "ROUT", NULL, "Line Out Switch 2"},
0593 
0594     { "PCM Playback", "Volume", "DAC" },
0595     { "Headphones Playback", "Volume", "PCM Playback" },
0596 
0597     { "SYSCLK", NULL, "DAC" },
0598 };
0599 
0600 static void jz4770_codec_codec_init_regs(struct snd_soc_component *codec)
0601 {
0602     struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0603     struct regmap *regmap = jz_codec->regmap;
0604 
0605     /* Collect updates for later sending. */
0606     regcache_cache_only(regmap, true);
0607 
0608     /* default HP output to PCM */
0609     regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_SEL_MASK);
0610 
0611     /* default line output to PCM */
0612     regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_LO, REG_CR_LO_SEL_MASK);
0613 
0614     /* Disable stereo mic */
0615     regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_MIC,
0616               BIT(REG_CR_MIC_STEREO_OFFSET));
0617 
0618     /* Set mic 1 as default source for ADC */
0619     regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_ADC,
0620               REG_CR_ADC_IN_SEL_MASK);
0621 
0622     /* ADC/DAC: serial + i2s */
0623     regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_ADC,
0624             REG_AICR_ADC_SERIAL | REG_AICR_ADC_I2S);
0625     regmap_set_bits(regmap, JZ4770_CODEC_REG_AICR_DAC,
0626             REG_AICR_DAC_SERIAL | REG_AICR_DAC_I2S);
0627 
0628     /* The generated IRQ is a high level */
0629     regmap_clear_bits(regmap, JZ4770_CODEC_REG_ICR, REG_ICR_INT_FORM_MASK);
0630     regmap_update_bits(regmap, JZ4770_CODEC_REG_IMR, REG_IMR_ALL_MASK,
0631                REG_IMR_JACK_MASK | REG_IMR_RUP_MASK |
0632                REG_IMR_RDO_MASK | REG_IMR_GUP_MASK |
0633                REG_IMR_GDO_MASK);
0634 
0635     /* 12M oscillator */
0636     regmap_clear_bits(regmap, JZ4770_CODEC_REG_CCR, REG_CCR_CRYSTAL_MASK);
0637 
0638     /* 0: 16ohm/220uF, 1: 10kohm/1uF */
0639     regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP, REG_CR_HP_LOAD);
0640 
0641     /* disable automatic gain */
0642     regmap_clear_bits(regmap, JZ4770_CODEC_REG_AGC1, REG_AGC1_EN);
0643 
0644     /* Disable DAC lrswap */
0645     regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_DAC, REG_CR_DAC_LRSWAP);
0646 
0647     /* Independent L/R DAC gain control */
0648     regmap_clear_bits(regmap, JZ4770_CODEC_REG_GCR_DACL,
0649               REG_GCR_DACL_RLGOD);
0650 
0651     /* Disable ADC lrswap */
0652     regmap_set_bits(regmap, JZ4770_CODEC_REG_CR_ADC, REG_CR_ADC_LRSWAP);
0653 
0654     /* default to cap-less mode(0) */
0655     regmap_clear_bits(regmap, JZ4770_CODEC_REG_CR_HP,
0656               BIT(REG_CR_HP_SB_HPCM_OFFSET));
0657 
0658     /* Send collected updates. */
0659     regcache_cache_only(regmap, false);
0660     regcache_sync(regmap);
0661 }
0662 
0663 static int jz4770_codec_codec_probe(struct snd_soc_component *codec)
0664 {
0665     struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0666 
0667     clk_prepare_enable(jz_codec->clk);
0668 
0669     jz4770_codec_codec_init_regs(codec);
0670 
0671     return 0;
0672 }
0673 
0674 static void jz4770_codec_codec_remove(struct snd_soc_component *codec)
0675 {
0676     struct jz_codec *jz_codec = snd_soc_component_get_drvdata(codec);
0677 
0678     clk_disable_unprepare(jz_codec->clk);
0679 }
0680 
0681 static const struct snd_soc_component_driver jz4770_codec_soc_codec_dev = {
0682     .probe          = jz4770_codec_codec_probe,
0683     .remove         = jz4770_codec_codec_remove,
0684     .set_bias_level     = jz4770_codec_set_bias_level,
0685     .controls       = jz4770_codec_snd_controls,
0686     .num_controls       = ARRAY_SIZE(jz4770_codec_snd_controls),
0687     .dapm_widgets       = jz4770_codec_dapm_widgets,
0688     .num_dapm_widgets   = ARRAY_SIZE(jz4770_codec_dapm_widgets),
0689     .dapm_routes        = jz4770_codec_dapm_routes,
0690     .num_dapm_routes    = ARRAY_SIZE(jz4770_codec_dapm_routes),
0691     .suspend_bias_off   = 1,
0692     .use_pmdown_time    = 1,
0693 };
0694 
0695 static const unsigned int jz4770_codec_sample_rates[] = {
0696     96000, 48000, 44100, 32000,
0697     24000, 22050, 16000, 12000,
0698     11025, 9600, 8000,
0699 };
0700 
0701 static int jz4770_codec_hw_params(struct snd_pcm_substream *substream,
0702                   struct snd_pcm_hw_params *params,
0703                   struct snd_soc_dai *dai)
0704 {
0705     struct jz_codec *codec = snd_soc_component_get_drvdata(dai->component);
0706     unsigned int rate, bit_width;
0707 
0708     switch (params_format(params)) {
0709     case SNDRV_PCM_FORMAT_S16_LE:
0710         bit_width = 0;
0711         break;
0712     case SNDRV_PCM_FORMAT_S18_3LE:
0713         bit_width = 1;
0714         break;
0715     case SNDRV_PCM_FORMAT_S20_3LE:
0716         bit_width = 2;
0717         break;
0718     case SNDRV_PCM_FORMAT_S24_3LE:
0719         bit_width = 3;
0720         break;
0721     default:
0722         return -EINVAL;
0723     }
0724 
0725     for (rate = 0; rate < ARRAY_SIZE(jz4770_codec_sample_rates); rate++) {
0726         if (jz4770_codec_sample_rates[rate] == params_rate(params))
0727             break;
0728     }
0729 
0730     if (rate == ARRAY_SIZE(jz4770_codec_sample_rates))
0731         return -EINVAL;
0732 
0733     if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
0734         regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_DAC,
0735                    REG_AICR_DAC_ADWL_MASK,
0736                    bit_width << REG_AICR_DAC_ADWL_OFFSET);
0737         regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_DAC,
0738                    REG_FCR_DAC_FREQ_MASK,
0739                    rate << REG_FCR_DAC_FREQ_OFFSET);
0740     } else {
0741         regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_AICR_ADC,
0742                    REG_AICR_ADC_ADWL_MASK,
0743                    bit_width << REG_AICR_ADC_ADWL_OFFSET);
0744         regmap_update_bits(codec->regmap, JZ4770_CODEC_REG_FCR_ADC,
0745                    REG_FCR_ADC_FREQ_MASK,
0746                    rate << REG_FCR_ADC_FREQ_OFFSET);
0747     }
0748 
0749     return 0;
0750 }
0751 
0752 static const struct snd_soc_dai_ops jz4770_codec_dai_ops = {
0753     .startup    = jz4770_codec_startup,
0754     .shutdown   = jz4770_codec_shutdown,
0755     .hw_params  = jz4770_codec_hw_params,
0756     .trigger    = jz4770_codec_pcm_trigger,
0757     .mute_stream    = jz4770_codec_mute_stream,
0758     .no_capture_mute = 1,
0759 };
0760 
0761 #define JZ_CODEC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE  | \
0762               SNDRV_PCM_FMTBIT_S18_3LE | \
0763               SNDRV_PCM_FMTBIT_S20_3LE | \
0764               SNDRV_PCM_FMTBIT_S24_3LE)
0765 
0766 static struct snd_soc_dai_driver jz4770_codec_dai = {
0767     .name = "jz4770-hifi",
0768     .playback = {
0769         .stream_name = "Playback",
0770         .channels_min = 2,
0771         .channels_max = 2,
0772         .rates = SNDRV_PCM_RATE_8000_96000,
0773         .formats = JZ_CODEC_FORMATS,
0774     },
0775     .capture = {
0776         .stream_name = "Capture",
0777         .channels_min = 2,
0778         .channels_max = 2,
0779         .rates = SNDRV_PCM_RATE_8000_96000,
0780         .formats = JZ_CODEC_FORMATS,
0781     },
0782     .ops = &jz4770_codec_dai_ops,
0783 };
0784 
0785 static bool jz4770_codec_volatile(struct device *dev, unsigned int reg)
0786 {
0787     return reg == JZ4770_CODEC_REG_SR || reg == JZ4770_CODEC_REG_IFR;
0788 }
0789 
0790 static bool jz4770_codec_readable(struct device *dev, unsigned int reg)
0791 {
0792     switch (reg) {
0793     case JZ4770_CODEC_REG_MISSING_REG1:
0794     case JZ4770_CODEC_REG_MISSING_REG2:
0795         return false;
0796     default:
0797         return true;
0798     }
0799 }
0800 
0801 static bool jz4770_codec_writeable(struct device *dev, unsigned int reg)
0802 {
0803     switch (reg) {
0804     case JZ4770_CODEC_REG_SR:
0805     case JZ4770_CODEC_REG_MISSING_REG1:
0806     case JZ4770_CODEC_REG_MISSING_REG2:
0807         return false;
0808     default:
0809         return true;
0810     }
0811 }
0812 
0813 static int jz4770_codec_io_wait(struct jz_codec *codec)
0814 {
0815     u32 reg;
0816 
0817     return readl_poll_timeout(codec->base + ICDC_RGADW_OFFSET, reg,
0818                   !(reg & ICDC_RGADW_RGWR),
0819                   1000, 1 * USEC_PER_SEC);
0820 }
0821 
0822 static int jz4770_codec_reg_read(void *context, unsigned int reg,
0823                  unsigned int *val)
0824 {
0825     struct jz_codec *codec = context;
0826     unsigned int i;
0827     u32 tmp;
0828     int ret;
0829 
0830     ret = jz4770_codec_io_wait(codec);
0831     if (ret)
0832         return ret;
0833 
0834     tmp = readl(codec->base + ICDC_RGADW_OFFSET);
0835     tmp = (tmp & ~ICDC_RGADW_RGADDR_MASK)
0836         | (reg << ICDC_RGADW_RGADDR_OFFSET);
0837     writel(tmp, codec->base + ICDC_RGADW_OFFSET);
0838 
0839     /* wait 6+ cycles */
0840     for (i = 0; i < 6; i++)
0841         *val = readl(codec->base + ICDC_RGDATA_OFFSET) &
0842             ICDC_RGDATA_RGDOUT_MASK;
0843 
0844     return 0;
0845 }
0846 
0847 static int jz4770_codec_reg_write(void *context, unsigned int reg,
0848                   unsigned int val)
0849 {
0850     struct jz_codec *codec = context;
0851     int ret;
0852 
0853     ret = jz4770_codec_io_wait(codec);
0854     if (ret)
0855         return ret;
0856 
0857     writel(ICDC_RGADW_RGWR | (reg << ICDC_RGADW_RGADDR_OFFSET) | val,
0858            codec->base + ICDC_RGADW_OFFSET);
0859 
0860     ret = jz4770_codec_io_wait(codec);
0861     if (ret)
0862         return ret;
0863 
0864     return 0;
0865 }
0866 
0867 static const u8 jz4770_codec_reg_defaults[] = {
0868     0x00, 0xC3, 0xC3, 0x90, 0x98, 0xFF, 0x90, 0xB1,
0869     0x11, 0x10, 0x00, 0x03, 0x00, 0x00, 0x40, 0x00,
0870     0xFF, 0x00, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00,
0871     0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x34,
0872     0x07, 0x44, 0x1F, 0x00
0873 };
0874 
0875 static struct regmap_config jz4770_codec_regmap_config = {
0876     .reg_bits = 7,
0877     .val_bits = 8,
0878 
0879     .max_register = JZ4770_CODEC_REG_AGC5,
0880     .volatile_reg = jz4770_codec_volatile,
0881     .readable_reg = jz4770_codec_readable,
0882     .writeable_reg = jz4770_codec_writeable,
0883 
0884     .reg_read = jz4770_codec_reg_read,
0885     .reg_write = jz4770_codec_reg_write,
0886 
0887     .reg_defaults_raw = jz4770_codec_reg_defaults,
0888     .num_reg_defaults_raw = ARRAY_SIZE(jz4770_codec_reg_defaults),
0889     .cache_type = REGCACHE_FLAT,
0890 };
0891 
0892 static int jz4770_codec_probe(struct platform_device *pdev)
0893 {
0894     struct device *dev = &pdev->dev;
0895     struct jz_codec *codec;
0896     int ret;
0897 
0898     codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL);
0899     if (!codec)
0900         return -ENOMEM;
0901 
0902     codec->dev = dev;
0903 
0904     codec->base = devm_platform_ioremap_resource(pdev, 0);
0905     if (IS_ERR(codec->base))
0906         return PTR_ERR(codec->base);
0907 
0908     codec->regmap = devm_regmap_init(dev, NULL, codec,
0909                     &jz4770_codec_regmap_config);
0910     if (IS_ERR(codec->regmap))
0911         return PTR_ERR(codec->regmap);
0912 
0913     codec->clk = devm_clk_get(dev, "aic");
0914     if (IS_ERR(codec->clk))
0915         return PTR_ERR(codec->clk);
0916 
0917     platform_set_drvdata(pdev, codec);
0918 
0919     ret = devm_snd_soc_register_component(dev, &jz4770_codec_soc_codec_dev,
0920                           &jz4770_codec_dai, 1);
0921     if (ret) {
0922         dev_err(dev, "Failed to register codec: %d\n", ret);
0923         return ret;
0924     }
0925 
0926     return 0;
0927 }
0928 
0929 static const struct of_device_id jz4770_codec_of_matches[] = {
0930     { .compatible = "ingenic,jz4770-codec", },
0931     { /* sentinel */ }
0932 };
0933 MODULE_DEVICE_TABLE(of, jz4770_codec_of_matches);
0934 
0935 static struct platform_driver jz4770_codec_driver = {
0936     .probe          = jz4770_codec_probe,
0937     .driver         = {
0938         .name       = "jz4770-codec",
0939         .of_match_table = jz4770_codec_of_matches,
0940     },
0941 };
0942 module_platform_driver(jz4770_codec_driver);
0943 
0944 MODULE_DESCRIPTION("JZ4770 SoC internal codec driver");
0945 MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>");
0946 MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
0947 MODULE_LICENSE("GPL v2");