Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // rk817 ALSA SoC Audio driver
0004 //
0005 // Copyright (c) 2018, Fuzhou Rockchip Electronics Co., Ltd All rights reserved.
0006 
0007 #include <linux/clk.h>
0008 #include <linux/device.h>
0009 #include <linux/delay.h>
0010 #include <linux/mfd/rk808.h>
0011 #include <linux/module.h>
0012 #include <linux/of.h>
0013 #include <linux/of_gpio.h>
0014 #include <linux/platform_device.h>
0015 #include <linux/regmap.h>
0016 #include <sound/core.h>
0017 #include <sound/pcm_params.h>
0018 #include <sound/soc.h>
0019 #include <sound/tlv.h>
0020 
0021 struct rk817_codec_priv {
0022     struct snd_soc_component *component;
0023     struct rk808 *rk808;
0024     struct clk *mclk;
0025     unsigned int stereo_sysclk;
0026     bool mic_in_differential;
0027 };
0028 
0029 /*
0030  * This sets the codec up with the values defined in the default implementation including the APLL
0031  * from the Rockchip vendor kernel. I do not know if these values are universal despite differing
0032  * from the default values defined above and taken from the datasheet, or implementation specific.
0033  * I don't have another implementation to compare from the Rockchip sources. Hard-coding for now.
0034  * Additionally, I do not know according to the documentation the units accepted for the clock
0035  * values, so for the moment those are left unvalidated.
0036  */
0037 
0038 static int rk817_init(struct snd_soc_component *component)
0039 {
0040     struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
0041 
0042     snd_soc_component_write(component, RK817_CODEC_DDAC_POPD_DACST, 0x02);
0043     snd_soc_component_write(component, RK817_CODEC_DDAC_SR_LMT0, 0x02);
0044     snd_soc_component_write(component, RK817_CODEC_DADC_SR_ACL0, 0x02);
0045     snd_soc_component_write(component, RK817_CODEC_DTOP_VUCTIME, 0xf4);
0046     if (rk817->mic_in_differential) {
0047         snd_soc_component_update_bits(component, RK817_CODEC_AMIC_CFG0, MIC_DIFF_MASK,
0048             MIC_DIFF_EN);
0049     }
0050 
0051     return 0;
0052 }
0053 
0054 static int rk817_set_component_pll(struct snd_soc_component *component,
0055         int pll_id, int source, unsigned int freq_in,
0056         unsigned int freq_out)
0057 {
0058     /* Set resistor value and charge pump current for PLL. */
0059     snd_soc_component_write(component, RK817_CODEC_APLL_CFG1, 0x58);
0060     /* Set the PLL feedback clock divide value (values not documented). */
0061     snd_soc_component_write(component, RK817_CODEC_APLL_CFG2, 0x2d);
0062     /* Set the PLL pre-divide value (values not documented). */
0063     snd_soc_component_write(component, RK817_CODEC_APLL_CFG3, 0x0c);
0064     /* Set the PLL VCO output clock divide and PLL divided ratio of PLL High Clk (values not
0065      * documented).
0066      */
0067     snd_soc_component_write(component, RK817_CODEC_APLL_CFG4, 0xa5);
0068 
0069     return 0;
0070 }
0071 
0072 /*
0073  * DDAC/DADC L/R volume setting
0074  * 0db~-95db, 0.375db/step, for example:
0075  * 0x00: 0dB
0076  * 0xff: -95dB
0077  */
0078 
0079 static const DECLARE_TLV_DB_MINMAX(rk817_vol_tlv, -9500, 0);
0080 
0081 /*
0082  * PGA GAIN L/R volume setting
0083  * 27db~-18db, 3db/step, for example:
0084  * 0x0: -18dB
0085  * 0xf: 27dB
0086  */
0087 
0088 static const DECLARE_TLV_DB_MINMAX(rk817_gain_tlv, -1800, 2700);
0089 
0090 static const struct snd_kcontrol_new rk817_volume_controls[] = {
0091     SOC_DOUBLE_R_RANGE_TLV("Master Playback Volume", RK817_CODEC_DDAC_VOLL,
0092         RK817_CODEC_DDAC_VOLR, 0, 0x00, 0xff, 1, rk817_vol_tlv),
0093     SOC_DOUBLE_R_RANGE_TLV("Master Capture Volume", RK817_CODEC_DADC_VOLL,
0094         RK817_CODEC_DADC_VOLR, 0, 0x00, 0xff, 1, rk817_vol_tlv),
0095     SOC_DOUBLE_TLV("Mic Capture Gain", RK817_CODEC_DMIC_PGA_GAIN, 4, 0, 0xf, 0,
0096         rk817_gain_tlv),
0097 };
0098 
0099 /* Since the speaker output and L headphone pin are internally the same, make audio path mutually
0100  * exclusive with a mux.
0101  */
0102 
0103 static const char *dac_mux_text[] = {
0104     "HP",
0105     "SPK",
0106 };
0107 
0108 static SOC_ENUM_SINGLE_VIRT_DECL(dac_enum, dac_mux_text);
0109 
0110 static const struct snd_kcontrol_new dac_mux =
0111     SOC_DAPM_ENUM("Playback Mux", dac_enum);
0112 
0113 static const struct snd_soc_dapm_widget rk817_dapm_widgets[] = {
0114 
0115     /* capture/playback common */
0116     SND_SOC_DAPM_SUPPLY("LDO Regulator", RK817_CODEC_AREF_RTCFG1, 6, 0, NULL, 0),
0117     SND_SOC_DAPM_SUPPLY("IBIAS Block", RK817_CODEC_AREF_RTCFG1, 2, 1, NULL, 0),
0118     SND_SOC_DAPM_SUPPLY("VAvg Buffer", RK817_CODEC_AREF_RTCFG1, 1, 1, NULL, 0),
0119     SND_SOC_DAPM_SUPPLY("PLL Power", RK817_CODEC_APLL_CFG5, 0, 1, NULL, 0),
0120     SND_SOC_DAPM_SUPPLY("I2S TX1 Transfer Start", RK817_CODEC_DI2S_RXCMD_TSD, 5, 0, NULL, 0),
0121 
0122     /* capture path common */
0123     SND_SOC_DAPM_SUPPLY("ADC Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 7, 0, NULL, 0),
0124     SND_SOC_DAPM_SUPPLY("I2S TX Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 6, 0, NULL, 0),
0125     SND_SOC_DAPM_SUPPLY("ADC Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 5, 0, NULL, 0),
0126     SND_SOC_DAPM_SUPPLY("I2S TX Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 4, 0, NULL, 0),
0127     SND_SOC_DAPM_SUPPLY("MIC Power On", RK817_CODEC_AMIC_CFG0, 6, 1, NULL, 0),
0128     SND_SOC_DAPM_SUPPLY("I2S TX3 Transfer Start", RK817_CODEC_DI2S_TXCR3_TXCMD, 7, 0, NULL, 0),
0129     SND_SOC_DAPM_SUPPLY("I2S TX3 Right Justified", RK817_CODEC_DI2S_TXCR3_TXCMD, 3, 0, NULL, 0),
0130 
0131     /* capture path L */
0132     SND_SOC_DAPM_ADC("ADC L", "Capture", RK817_CODEC_AADC_CFG0, 7, 1),
0133     SND_SOC_DAPM_SUPPLY("PGA L Power On", RK817_CODEC_AMIC_CFG0, 5, 1, NULL, 0),
0134     SND_SOC_DAPM_SUPPLY("Mic Boost L1", RK817_CODEC_AMIC_CFG0, 3, 0, NULL, 0),
0135     SND_SOC_DAPM_SUPPLY("Mic Boost L2", RK817_CODEC_AMIC_CFG0, 2, 0, NULL, 0),
0136 
0137     /* capture path R */
0138     SND_SOC_DAPM_ADC("ADC R", "Capture", RK817_CODEC_AADC_CFG0, 6, 1),
0139     SND_SOC_DAPM_SUPPLY("PGA R Power On", RK817_CODEC_AMIC_CFG0, 4, 1, NULL, 0),
0140     SND_SOC_DAPM_SUPPLY("Mic Boost R1", RK817_CODEC_AMIC_CFG0, 3, 0, NULL, 0),
0141     SND_SOC_DAPM_SUPPLY("Mic Boost R2", RK817_CODEC_AMIC_CFG0, 3, 0, NULL, 0),
0142 
0143     /* playback path common */
0144     SND_SOC_DAPM_SUPPLY("DAC Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 3, 0, NULL, 0),
0145     SND_SOC_DAPM_SUPPLY("I2S RX Clock", RK817_CODEC_DTOP_DIGEN_CLKE, 2, 0, NULL, 0),
0146     SND_SOC_DAPM_SUPPLY("DAC Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 1, 0, NULL, 0),
0147     SND_SOC_DAPM_SUPPLY("I2S RX Channel Enable", RK817_CODEC_DTOP_DIGEN_CLKE, 0, 0, NULL, 0),
0148     SND_SOC_DAPM_SUPPLY("DAC Bias", RK817_CODEC_ADAC_CFG1, 3, 1, NULL, 0),
0149     SND_SOC_DAPM_SUPPLY("DAC Mute Off", RK817_CODEC_DDAC_MUTE_MIXCTL, 0, 1, NULL, 0),
0150 
0151     /* playback path speaker */
0152     SND_SOC_DAPM_SUPPLY("Class D Mode", RK817_CODEC_DDAC_MUTE_MIXCTL, 4, 0, NULL, 0),
0153     SND_SOC_DAPM_SUPPLY("High Pass Filter", RK817_CODEC_DDAC_MUTE_MIXCTL, 7, 0, NULL, 0),
0154     SND_SOC_DAPM_DAC("SPK DAC", "Playback", RK817_CODEC_ADAC_CFG1, 2, 1),
0155     SND_SOC_DAPM_SUPPLY("Enable Class D", RK817_CODEC_ACLASSD_CFG1, 7, 0, NULL, 0),
0156     SND_SOC_DAPM_SUPPLY("Disable Class D Mute Ramp", RK817_CODEC_ACLASSD_CFG1, 6, 1, NULL, 0),
0157     SND_SOC_DAPM_SUPPLY("Class D Mute Rate 1", RK817_CODEC_ACLASSD_CFG1, 3, 0, NULL, 0),
0158     SND_SOC_DAPM_SUPPLY("Class D Mute Rate 2", RK817_CODEC_ACLASSD_CFG1, 2, 1, NULL, 0),
0159     SND_SOC_DAPM_SUPPLY("Class D OCPP 2", RK817_CODEC_ACLASSD_CFG2, 5, 0, NULL, 0),
0160     SND_SOC_DAPM_SUPPLY("Class D OCPP 3", RK817_CODEC_ACLASSD_CFG2, 4, 0, NULL, 0),
0161     SND_SOC_DAPM_SUPPLY("Class D OCPN 2", RK817_CODEC_ACLASSD_CFG2, 1, 0, NULL, 0),
0162     SND_SOC_DAPM_SUPPLY("Class D OCPN 3", RK817_CODEC_ACLASSD_CFG2, 0, 0, NULL, 0),
0163 
0164     /* playback path headphones */
0165     SND_SOC_DAPM_SUPPLY("Headphone Charge Pump", RK817_CODEC_AHP_CP, 4, 0, NULL, 0),
0166     SND_SOC_DAPM_SUPPLY("Headphone CP Discharge LDO", RK817_CODEC_AHP_CP, 3, 1, NULL, 0),
0167     SND_SOC_DAPM_SUPPLY("Headphone OStage", RK817_CODEC_AHP_CFG0, 6, 1, NULL, 0),
0168     SND_SOC_DAPM_SUPPLY("Headphone Pre Amp", RK817_CODEC_AHP_CFG0, 5, 1, NULL, 0),
0169     SND_SOC_DAPM_DAC("DAC L", "Playback", RK817_CODEC_ADAC_CFG1, 1, 1),
0170     SND_SOC_DAPM_DAC("DAC R", "Playback", RK817_CODEC_ADAC_CFG1, 0, 1),
0171 
0172     /* Mux for input/output path selection */
0173     SND_SOC_DAPM_MUX("Playback Mux", SND_SOC_NOPM, 1, 0, &dac_mux),
0174 
0175     /* Pins for Simple Card Bindings */
0176     SND_SOC_DAPM_INPUT("MICL"),
0177     SND_SOC_DAPM_INPUT("MICR"),
0178     SND_SOC_DAPM_OUTPUT("HPOL"),
0179     SND_SOC_DAPM_OUTPUT("HPOR"),
0180     SND_SOC_DAPM_OUTPUT("SPKO"),
0181 };
0182 
0183 static const struct snd_soc_dapm_route rk817_dapm_routes[] = {
0184 
0185     /* capture path */
0186     /* left mic */
0187     {"ADC L", NULL, "LDO Regulator"},
0188     {"ADC L", NULL, "IBIAS Block"},
0189     {"ADC L", NULL, "VAvg Buffer"},
0190     {"ADC L", NULL, "PLL Power"},
0191     {"ADC L", NULL, "ADC Clock"},
0192     {"ADC L", NULL, "I2S TX Clock"},
0193     {"ADC L", NULL, "ADC Channel Enable"},
0194     {"ADC L", NULL, "I2S TX Channel Enable"},
0195     {"ADC L", NULL, "I2S TX1 Transfer Start"},
0196     {"MICL", NULL, "MIC Power On"},
0197     {"MICL", NULL, "PGA L Power On"},
0198     {"MICL", NULL, "Mic Boost L1"},
0199     {"MICL", NULL, "Mic Boost L2"},
0200     {"MICL", NULL, "I2S TX3 Transfer Start"},
0201     {"MICL", NULL, "I2S TX3 Right Justified"},
0202     {"ADC L", NULL, "MICL"},
0203 
0204     /* right mic */
0205     {"ADC R", NULL, "LDO Regulator"},
0206     {"ADC R", NULL, "IBIAS Block"},
0207     {"ADC R", NULL, "VAvg Buffer"},
0208     {"ADC R", NULL, "PLL Power"},
0209     {"ADC R", NULL, "ADC Clock"},
0210     {"ADC R", NULL, "I2S TX Clock"},
0211     {"ADC R", NULL, "ADC Channel Enable"},
0212     {"ADC R", NULL, "I2S TX Channel Enable"},
0213     {"ADC R", NULL, "I2S TX1 Transfer Start"},
0214     {"MICR", NULL, "MIC Power On"},
0215     {"MICR", NULL, "PGA R Power On"},
0216     {"MICR", NULL, "Mic Boost R1"},
0217     {"MICR", NULL, "Mic Boost R2"},
0218     {"MICR", NULL, "I2S TX3 Transfer Start"},
0219     {"MICR", NULL, "I2S TX3 Right Justified"},
0220     {"ADC R", NULL, "MICR"},
0221 
0222     /* playback path */
0223     /* speaker path */
0224     {"SPK DAC", NULL, "LDO Regulator"},
0225     {"SPK DAC", NULL, "IBIAS Block"},
0226     {"SPK DAC", NULL, "VAvg Buffer"},
0227     {"SPK DAC", NULL, "PLL Power"},
0228     {"SPK DAC", NULL, "I2S TX1 Transfer Start"},
0229     {"SPK DAC", NULL, "DAC Clock"},
0230     {"SPK DAC", NULL, "I2S RX Clock"},
0231     {"SPK DAC", NULL, "DAC Channel Enable"},
0232     {"SPK DAC", NULL, "I2S RX Channel Enable"},
0233     {"SPK DAC", NULL, "Class D Mode"},
0234     {"SPK DAC", NULL, "DAC Bias"},
0235     {"SPK DAC", NULL, "DAC Mute Off"},
0236     {"SPK DAC", NULL, "Enable Class D"},
0237     {"SPK DAC", NULL, "Disable Class D Mute Ramp"},
0238     {"SPK DAC", NULL, "Class D Mute Rate 1"},
0239     {"SPK DAC", NULL, "Class D Mute Rate 2"},
0240     {"SPK DAC", NULL, "Class D OCPP 2"},
0241     {"SPK DAC", NULL, "Class D OCPP 3"},
0242     {"SPK DAC", NULL, "Class D OCPN 2"},
0243     {"SPK DAC", NULL, "Class D OCPN 3"},
0244     {"SPK DAC", NULL, "High Pass Filter"},
0245 
0246     /* headphone path L */
0247     {"DAC L", NULL, "LDO Regulator"},
0248     {"DAC L", NULL, "IBIAS Block"},
0249     {"DAC L", NULL, "VAvg Buffer"},
0250     {"DAC L", NULL, "PLL Power"},
0251     {"DAC L", NULL, "I2S TX1 Transfer Start"},
0252     {"DAC L", NULL, "DAC Clock"},
0253     {"DAC L", NULL, "I2S RX Clock"},
0254     {"DAC L", NULL, "DAC Channel Enable"},
0255     {"DAC L", NULL, "I2S RX Channel Enable"},
0256     {"DAC L", NULL, "DAC Bias"},
0257     {"DAC L", NULL, "DAC Mute Off"},
0258     {"DAC L", NULL, "Headphone Charge Pump"},
0259     {"DAC L", NULL, "Headphone CP Discharge LDO"},
0260     {"DAC L", NULL, "Headphone OStage"},
0261     {"DAC L", NULL, "Headphone Pre Amp"},
0262 
0263     /* headphone path R */
0264     {"DAC R", NULL, "LDO Regulator"},
0265     {"DAC R", NULL, "IBIAS Block"},
0266     {"DAC R", NULL, "VAvg Buffer"},
0267     {"DAC R", NULL, "PLL Power"},
0268     {"DAC R", NULL, "I2S TX1 Transfer Start"},
0269     {"DAC R", NULL, "DAC Clock"},
0270     {"DAC R", NULL, "I2S RX Clock"},
0271     {"DAC R", NULL, "DAC Channel Enable"},
0272     {"DAC R", NULL, "I2S RX Channel Enable"},
0273     {"DAC R", NULL, "DAC Bias"},
0274     {"DAC R", NULL, "DAC Mute Off"},
0275     {"DAC R", NULL, "Headphone Charge Pump"},
0276     {"DAC R", NULL, "Headphone CP Discharge LDO"},
0277     {"DAC R", NULL, "Headphone OStage"},
0278     {"DAC R", NULL, "Headphone Pre Amp"},
0279 
0280     /* mux path for output selection */
0281     {"Playback Mux", "HP", "DAC L"},
0282     {"Playback Mux", "HP", "DAC R"},
0283     {"Playback Mux", "SPK", "SPK DAC"},
0284     {"SPKO", NULL, "Playback Mux"},
0285     {"HPOL", NULL, "Playback Mux"},
0286     {"HPOR", NULL, "Playback Mux"},
0287 };
0288 
0289 static int rk817_set_dai_sysclk(struct snd_soc_dai *codec_dai,
0290                 int clk_id, unsigned int freq, int dir)
0291 {
0292     struct snd_soc_component *component = codec_dai->component;
0293     struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
0294 
0295     rk817->stereo_sysclk = freq;
0296 
0297     return 0;
0298 }
0299 
0300 static int rk817_set_dai_fmt(struct snd_soc_dai *codec_dai,
0301                  unsigned int fmt)
0302 {
0303     struct snd_soc_component *component = codec_dai->component;
0304     unsigned int i2s_mst = 0;
0305 
0306     switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
0307     case SND_SOC_DAIFMT_CBS_CFS:
0308         i2s_mst |= RK817_I2S_MODE_SLV;
0309         break;
0310     case SND_SOC_DAIFMT_CBM_CFM:
0311         i2s_mst |= RK817_I2S_MODE_MST;
0312         break;
0313     default:
0314         dev_err(component->dev, "%s : set master mask failed!\n", __func__);
0315         return -EINVAL;
0316     }
0317 
0318     snd_soc_component_update_bits(component, RK817_CODEC_DI2S_CKM,
0319                       RK817_I2S_MODE_MASK, i2s_mst);
0320 
0321     return 0;
0322 }
0323 
0324 static int rk817_hw_params(struct snd_pcm_substream *substream,
0325                struct snd_pcm_hw_params *params,
0326                 struct snd_soc_dai *dai)
0327 {
0328     struct snd_soc_component *component = dai->component;
0329 
0330     switch (params_format(params)) {
0331     case SNDRV_PCM_FORMAT_S16_LE:
0332         snd_soc_component_write(component, RK817_CODEC_DI2S_RXCR2,
0333                     VDW_RX_16BITS);
0334         snd_soc_component_write(component, RK817_CODEC_DI2S_TXCR2,
0335                     VDW_TX_16BITS);
0336         break;
0337     case SNDRV_PCM_FORMAT_S24_LE:
0338     case SNDRV_PCM_FORMAT_S32_LE:
0339         snd_soc_component_write(component, RK817_CODEC_DI2S_RXCR2,
0340                     VDW_RX_24BITS);
0341         snd_soc_component_write(component, RK817_CODEC_DI2S_TXCR2,
0342                     VDW_TX_24BITS);
0343         break;
0344     default:
0345         return -EINVAL;
0346     }
0347 
0348     return 0;
0349 }
0350 
0351 static int rk817_digital_mute(struct snd_soc_dai *dai, int mute, int stream)
0352 {
0353     struct snd_soc_component *component = dai->component;
0354 
0355     if (mute)
0356         snd_soc_component_update_bits(component,
0357                           RK817_CODEC_DDAC_MUTE_MIXCTL,
0358                           DACMT_MASK, DACMT_ENABLE);
0359     else
0360         snd_soc_component_update_bits(component,
0361                           RK817_CODEC_DDAC_MUTE_MIXCTL,
0362                           DACMT_MASK, DACMT_DISABLE);
0363 
0364     return 0;
0365 }
0366 
0367 #define RK817_PLAYBACK_RATES (SNDRV_PCM_RATE_8000 |\
0368                   SNDRV_PCM_RATE_16000 |    \
0369                   SNDRV_PCM_RATE_32000 |    \
0370                   SNDRV_PCM_RATE_44100 |    \
0371                   SNDRV_PCM_RATE_48000 |    \
0372                   SNDRV_PCM_RATE_96000)
0373 
0374 #define RK817_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
0375                   SNDRV_PCM_RATE_16000 |    \
0376                   SNDRV_PCM_RATE_32000 |    \
0377                   SNDRV_PCM_RATE_44100 |    \
0378                   SNDRV_PCM_RATE_48000 |    \
0379                   SNDRV_PCM_RATE_96000)
0380 
0381 #define RK817_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
0382             SNDRV_PCM_FMTBIT_S20_3LE |\
0383             SNDRV_PCM_FMTBIT_S24_LE |\
0384             SNDRV_PCM_FMTBIT_S32_LE)
0385 
0386 static const struct snd_soc_dai_ops rk817_dai_ops = {
0387     .hw_params  = rk817_hw_params,
0388     .set_fmt    = rk817_set_dai_fmt,
0389     .set_sysclk = rk817_set_dai_sysclk,
0390     .mute_stream    = rk817_digital_mute,
0391     .no_capture_mute    = 1,
0392 };
0393 
0394 static struct snd_soc_dai_driver rk817_dai[] = {
0395     {
0396         .name = "rk817-hifi",
0397         .playback = {
0398             .stream_name = "Playback",
0399             .channels_min = 2,
0400             .channels_max = 8,
0401             .rates = RK817_PLAYBACK_RATES,
0402             .formats = RK817_FORMATS,
0403         },
0404         .capture = {
0405             .stream_name = "Capture",
0406             .channels_min = 1,
0407             .channels_max = 2,
0408             .rates = RK817_CAPTURE_RATES,
0409             .formats = RK817_FORMATS,
0410         },
0411         .ops = &rk817_dai_ops,
0412     },
0413 };
0414 
0415 static int rk817_probe(struct snd_soc_component *component)
0416 {
0417     struct rk817_codec_priv *rk817 = snd_soc_component_get_drvdata(component);
0418     struct rk808 *rk808 = dev_get_drvdata(component->dev->parent);
0419 
0420     snd_soc_component_init_regmap(component, rk808->regmap);
0421     rk817->component = component;
0422 
0423     snd_soc_component_write(component, RK817_CODEC_DTOP_LPT_SRST, 0x40);
0424 
0425     rk817_init(component);
0426 
0427     /* setting initial pll values so that we can continue to leverage simple-audio-card.
0428      * The values aren't important since no parameters are used.
0429      */
0430 
0431     snd_soc_component_set_pll(component, 0, 0, 0, 0);
0432 
0433     return 0;
0434 }
0435 
0436 static void rk817_remove(struct snd_soc_component *component)
0437 {
0438     snd_soc_component_exit_regmap(component);
0439 }
0440 
0441 static const struct snd_soc_component_driver soc_codec_dev_rk817 = {
0442     .probe = rk817_probe,
0443     .remove = rk817_remove,
0444     .idle_bias_on = 1,
0445     .use_pmdown_time = 1,
0446     .endianness = 1,
0447     .controls = rk817_volume_controls,
0448     .num_controls = ARRAY_SIZE(rk817_volume_controls),
0449     .dapm_routes = rk817_dapm_routes,
0450     .num_dapm_routes = ARRAY_SIZE(rk817_dapm_routes),
0451     .dapm_widgets = rk817_dapm_widgets,
0452     .num_dapm_widgets = ARRAY_SIZE(rk817_dapm_widgets),
0453     .set_pll = rk817_set_component_pll,
0454 };
0455 
0456 static void rk817_codec_parse_dt_property(struct device *dev,
0457                      struct rk817_codec_priv *rk817)
0458 {
0459     struct device_node *node;
0460 
0461     node = of_get_child_by_name(dev->parent->of_node, "codec");
0462     if (!node) {
0463         dev_dbg(dev, "%s() Can not get child: codec\n",
0464             __func__);
0465     }
0466 
0467     rk817->mic_in_differential =
0468             of_property_read_bool(node, "rockchip,mic-in-differential");
0469 
0470     of_node_put(node);
0471 }
0472 
0473 static int rk817_platform_probe(struct platform_device *pdev)
0474 {
0475     struct rk808 *rk808 = dev_get_drvdata(pdev->dev.parent);
0476     struct rk817_codec_priv *rk817_codec_data;
0477     int ret;
0478 
0479     rk817_codec_data = devm_kzalloc(&pdev->dev,
0480                     sizeof(struct rk817_codec_priv),
0481                     GFP_KERNEL);
0482     if (!rk817_codec_data)
0483         return -ENOMEM;
0484 
0485     platform_set_drvdata(pdev, rk817_codec_data);
0486 
0487     rk817_codec_data->rk808 = rk808;
0488 
0489     rk817_codec_parse_dt_property(&pdev->dev, rk817_codec_data);
0490 
0491     rk817_codec_data->mclk = devm_clk_get(pdev->dev.parent, "mclk");
0492     if (IS_ERR(rk817_codec_data->mclk)) {
0493         dev_dbg(&pdev->dev, "Unable to get mclk\n");
0494         ret = -ENXIO;
0495         goto err_;
0496     }
0497 
0498     ret = clk_prepare_enable(rk817_codec_data->mclk);
0499     if (ret < 0) {
0500         dev_err(&pdev->dev, "%s() clock prepare error %d\n",
0501             __func__, ret);
0502         goto err_;
0503     }
0504 
0505     ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_dev_rk817,
0506                           rk817_dai, ARRAY_SIZE(rk817_dai));
0507     if (ret < 0) {
0508         dev_err(&pdev->dev, "%s() register codec error %d\n",
0509             __func__, ret);
0510         goto err_clk;
0511     }
0512 
0513     return 0;
0514 
0515 err_clk:
0516     clk_disable_unprepare(rk817_codec_data->mclk);
0517 err_:
0518     return ret;
0519 }
0520 
0521 static int rk817_platform_remove(struct platform_device *pdev)
0522 {
0523     struct rk817_codec_priv *rk817 = platform_get_drvdata(pdev);
0524 
0525     clk_disable_unprepare(rk817->mclk);
0526 
0527     return 0;
0528 }
0529 
0530 static struct platform_driver rk817_codec_driver = {
0531     .driver = {
0532            .name = "rk817-codec",
0533            },
0534     .probe = rk817_platform_probe,
0535     .remove = rk817_platform_remove,
0536 };
0537 
0538 module_platform_driver(rk817_codec_driver);
0539 
0540 MODULE_DESCRIPTION("ASoC RK817 codec driver");
0541 MODULE_AUTHOR("binyuan <kevan.lan@rock-chips.com>");
0542 MODULE_LICENSE("GPL v2");
0543 MODULE_ALIAS("platform:rk817-codec");