1873e65bcSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2d808fe9fSTomoya MORINAGA /* 3d808fe9fSTomoya MORINAGA * Copyright (C) 2011 LAPIS Semiconductor Co., Ltd. 4d808fe9fSTomoya MORINAGA */ 5d808fe9fSTomoya MORINAGA 6d808fe9fSTomoya MORINAGA #include <linux/module.h> 7d808fe9fSTomoya MORINAGA #include <linux/moduleparam.h> 8d808fe9fSTomoya MORINAGA #include <linux/init.h> 9d808fe9fSTomoya MORINAGA #include <linux/delay.h> 10d808fe9fSTomoya MORINAGA #include <linux/pm.h> 11d808fe9fSTomoya MORINAGA #include <linux/i2c.h> 12d808fe9fSTomoya MORINAGA #include <linux/slab.h> 13d808fe9fSTomoya MORINAGA #include <linux/platform_device.h> 14d808fe9fSTomoya MORINAGA #include <linux/regmap.h> 15d808fe9fSTomoya MORINAGA #include <sound/core.h> 16d808fe9fSTomoya MORINAGA #include <sound/pcm.h> 17d808fe9fSTomoya MORINAGA #include <sound/pcm_params.h> 18d808fe9fSTomoya MORINAGA #include <sound/soc.h> 19d808fe9fSTomoya MORINAGA #include <sound/tlv.h> 20d808fe9fSTomoya MORINAGA #include "ml26124.h" 21d808fe9fSTomoya MORINAGA 22d808fe9fSTomoya MORINAGA #define DVOL_CTL_DVMUTE_ON BIT(4) /* Digital volume MUTE On */ 23d808fe9fSTomoya MORINAGA #define DVOL_CTL_DVMUTE_OFF 0 /* Digital volume MUTE Off */ 24d808fe9fSTomoya MORINAGA #define ML26124_SAI_NO_DELAY BIT(1) 25d808fe9fSTomoya MORINAGA #define ML26124_SAI_FRAME_SYNC (BIT(5) | BIT(0)) /* For mono (Telecodec) */ 26d808fe9fSTomoya MORINAGA #define ML26134_CACHESIZE 212 27d808fe9fSTomoya MORINAGA #define ML26124_VMID BIT(1) 28d808fe9fSTomoya MORINAGA #define ML26124_RATES (SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_32000 |\ 29d808fe9fSTomoya MORINAGA SNDRV_PCM_RATE_48000) 30d808fe9fSTomoya MORINAGA #define ML26124_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |\ 31d808fe9fSTomoya MORINAGA SNDRV_PCM_FMTBIT_S32_LE) 32d808fe9fSTomoya MORINAGA #define ML26124_NUM_REGISTER ML26134_CACHESIZE 33d808fe9fSTomoya MORINAGA 34d808fe9fSTomoya MORINAGA struct ml26124_priv { 35d808fe9fSTomoya MORINAGA u32 mclk; 36d808fe9fSTomoya MORINAGA u32 rate; 37d808fe9fSTomoya MORINAGA struct regmap *regmap; 38d808fe9fSTomoya MORINAGA int clk_in; 39d808fe9fSTomoya MORINAGA struct snd_pcm_substream *substream; 40d808fe9fSTomoya MORINAGA }; 41d808fe9fSTomoya MORINAGA 42d808fe9fSTomoya MORINAGA struct clk_coeff { 43d808fe9fSTomoya MORINAGA u32 mclk; 44d808fe9fSTomoya MORINAGA u32 rate; 45d808fe9fSTomoya MORINAGA u8 pllnl; 46d808fe9fSTomoya MORINAGA u8 pllnh; 47d808fe9fSTomoya MORINAGA u8 pllml; 48d808fe9fSTomoya MORINAGA u8 pllmh; 49d808fe9fSTomoya MORINAGA u8 plldiv; 50d808fe9fSTomoya MORINAGA }; 51d808fe9fSTomoya MORINAGA 52d808fe9fSTomoya MORINAGA /* ML26124 configuration */ 53d808fe9fSTomoya MORINAGA static const DECLARE_TLV_DB_SCALE(digital_tlv, -7150, 50, 0); 54d808fe9fSTomoya MORINAGA 55d808fe9fSTomoya MORINAGA static const DECLARE_TLV_DB_SCALE(alclvl, -2250, 150, 0); 56d808fe9fSTomoya MORINAGA static const DECLARE_TLV_DB_SCALE(mingain, -1200, 600, 0); 57d808fe9fSTomoya MORINAGA static const DECLARE_TLV_DB_SCALE(maxgain, -675, 600, 0); 58d808fe9fSTomoya MORINAGA static const DECLARE_TLV_DB_SCALE(boost_vol, -1200, 75, 0); 59d808fe9fSTomoya MORINAGA 60d808fe9fSTomoya MORINAGA static const char * const ml26124_companding[] = {"16bit PCM", "u-law", 61d808fe9fSTomoya MORINAGA "A-law"}; 62d808fe9fSTomoya MORINAGA 63c3518d1bSTakashi Iwai static SOC_ENUM_SINGLE_DECL(ml26124_adc_companding_enum, 64c3518d1bSTakashi Iwai ML26124_SAI_TRANS_CTL, 6, ml26124_companding); 65d808fe9fSTomoya MORINAGA 66c3518d1bSTakashi Iwai static SOC_ENUM_SINGLE_DECL(ml26124_dac_companding_enum, 67c3518d1bSTakashi Iwai ML26124_SAI_RCV_CTL, 6, ml26124_companding); 68d808fe9fSTomoya MORINAGA 69d808fe9fSTomoya MORINAGA static const struct snd_kcontrol_new ml26124_snd_controls[] = { 70d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("Capture Digital Volume", ML26124_RECORD_DIG_VOL, 0, 71d808fe9fSTomoya MORINAGA 0xff, 1, digital_tlv), 72d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("Playback Digital Volume", ML26124_PLBAK_DIG_VOL, 0, 73d808fe9fSTomoya MORINAGA 0xff, 1, digital_tlv), 74d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("Digital Boost Volume", ML26124_DIGI_BOOST_VOL, 0, 75d808fe9fSTomoya MORINAGA 0x3f, 0, boost_vol), 76d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("EQ Band0 Volume", ML26124_EQ_GAIN_BRAND0, 0, 77d808fe9fSTomoya MORINAGA 0xff, 1, digital_tlv), 78d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("EQ Band1 Volume", ML26124_EQ_GAIN_BRAND1, 0, 79d808fe9fSTomoya MORINAGA 0xff, 1, digital_tlv), 80d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("EQ Band2 Volume", ML26124_EQ_GAIN_BRAND2, 0, 81d808fe9fSTomoya MORINAGA 0xff, 1, digital_tlv), 82d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("EQ Band3 Volume", ML26124_EQ_GAIN_BRAND3, 0, 83d808fe9fSTomoya MORINAGA 0xff, 1, digital_tlv), 84d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("EQ Band4 Volume", ML26124_EQ_GAIN_BRAND4, 0, 85d808fe9fSTomoya MORINAGA 0xff, 1, digital_tlv), 86d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("ALC Target Level", ML26124_ALC_TARGET_LEV, 0, 87d808fe9fSTomoya MORINAGA 0xf, 1, alclvl), 88d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("ALC Min Input Volume", ML26124_ALC_MAXMIN_GAIN, 0, 89d808fe9fSTomoya MORINAGA 7, 0, mingain), 90d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("ALC Max Input Volume", ML26124_ALC_MAXMIN_GAIN, 4, 91d808fe9fSTomoya MORINAGA 7, 1, maxgain), 92d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("Playback Limiter Min Input Volume", 93d808fe9fSTomoya MORINAGA ML26124_PL_MAXMIN_GAIN, 0, 7, 0, mingain), 94d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("Playback Limiter Max Input Volume", 95d808fe9fSTomoya MORINAGA ML26124_PL_MAXMIN_GAIN, 4, 7, 1, maxgain), 96d808fe9fSTomoya MORINAGA SOC_SINGLE_TLV("Playback Boost Volume", ML26124_PLYBAK_BOST_VOL, 0, 97d808fe9fSTomoya MORINAGA 0x3f, 0, boost_vol), 98d808fe9fSTomoya MORINAGA SOC_SINGLE("DC High Pass Filter Switch", ML26124_FILTER_EN, 0, 1, 0), 99d808fe9fSTomoya MORINAGA SOC_SINGLE("Noise High Pass Filter Switch", ML26124_FILTER_EN, 1, 1, 0), 100d808fe9fSTomoya MORINAGA SOC_SINGLE("ZC Switch", ML26124_PW_ZCCMP_PW_MNG, 1, 101d808fe9fSTomoya MORINAGA 1, 0), 102d808fe9fSTomoya MORINAGA SOC_SINGLE("EQ Band0 Switch", ML26124_FILTER_EN, 2, 1, 0), 103d808fe9fSTomoya MORINAGA SOC_SINGLE("EQ Band1 Switch", ML26124_FILTER_EN, 3, 1, 0), 104d808fe9fSTomoya MORINAGA SOC_SINGLE("EQ Band2 Switch", ML26124_FILTER_EN, 4, 1, 0), 105d808fe9fSTomoya MORINAGA SOC_SINGLE("EQ Band3 Switch", ML26124_FILTER_EN, 5, 1, 0), 106d808fe9fSTomoya MORINAGA SOC_SINGLE("EQ Band4 Switch", ML26124_FILTER_EN, 6, 1, 0), 107d808fe9fSTomoya MORINAGA SOC_SINGLE("Play Limiter", ML26124_DVOL_CTL, 0, 1, 0), 108d808fe9fSTomoya MORINAGA SOC_SINGLE("Capture Limiter", ML26124_DVOL_CTL, 1, 1, 0), 109d808fe9fSTomoya MORINAGA SOC_SINGLE("Digital Volume Fade Switch", ML26124_DVOL_CTL, 3, 1, 0), 110d808fe9fSTomoya MORINAGA SOC_SINGLE("Digital Switch", ML26124_DVOL_CTL, 4, 1, 0), 111d808fe9fSTomoya MORINAGA SOC_ENUM("DAC Companding", ml26124_dac_companding_enum), 112d808fe9fSTomoya MORINAGA SOC_ENUM("ADC Companding", ml26124_adc_companding_enum), 113d808fe9fSTomoya MORINAGA }; 114d808fe9fSTomoya MORINAGA 115d808fe9fSTomoya MORINAGA static const struct snd_kcontrol_new ml26124_output_mixer_controls[] = { 116d808fe9fSTomoya MORINAGA SOC_DAPM_SINGLE("DAC Switch", ML26124_SPK_AMP_OUT, 1, 1, 0), 117d808fe9fSTomoya MORINAGA SOC_DAPM_SINGLE("Line in loopback Switch", ML26124_SPK_AMP_OUT, 3, 1, 118d808fe9fSTomoya MORINAGA 0), 119d808fe9fSTomoya MORINAGA SOC_DAPM_SINGLE("PGA Switch", ML26124_SPK_AMP_OUT, 5, 1, 0), 120d808fe9fSTomoya MORINAGA }; 121d808fe9fSTomoya MORINAGA 122d808fe9fSTomoya MORINAGA /* Input mux */ 123d808fe9fSTomoya MORINAGA static const char * const ml26124_input_select[] = {"Analog MIC SingleEnded in", 124d808fe9fSTomoya MORINAGA "Digital MIC in", "Analog MIC Differential in"}; 125d808fe9fSTomoya MORINAGA 126c3518d1bSTakashi Iwai static SOC_ENUM_SINGLE_DECL(ml26124_insel_enum, 127c3518d1bSTakashi Iwai ML26124_MIC_IF_CTL, 0, ml26124_input_select); 128d808fe9fSTomoya MORINAGA 129d808fe9fSTomoya MORINAGA static const struct snd_kcontrol_new ml26124_input_mux_controls = 130d808fe9fSTomoya MORINAGA SOC_DAPM_ENUM("Input Select", ml26124_insel_enum); 131d808fe9fSTomoya MORINAGA 132d808fe9fSTomoya MORINAGA static const struct snd_kcontrol_new ml26124_line_control = 133d808fe9fSTomoya MORINAGA SOC_DAPM_SINGLE("Switch", ML26124_PW_LOUT_PW_MNG, 1, 1, 0); 134d808fe9fSTomoya MORINAGA 135d808fe9fSTomoya MORINAGA static const struct snd_soc_dapm_widget ml26124_dapm_widgets[] = { 136d808fe9fSTomoya MORINAGA SND_SOC_DAPM_SUPPLY("MCLKEN", ML26124_CLK_EN, 0, 0, NULL, 0), 137d808fe9fSTomoya MORINAGA SND_SOC_DAPM_SUPPLY("PLLEN", ML26124_CLK_EN, 1, 0, NULL, 0), 138d808fe9fSTomoya MORINAGA SND_SOC_DAPM_SUPPLY("PLLOE", ML26124_CLK_EN, 2, 0, NULL, 0), 139d808fe9fSTomoya MORINAGA SND_SOC_DAPM_SUPPLY("MICBIAS", ML26124_PW_REF_PW_MNG, 2, 0, NULL, 0), 140d808fe9fSTomoya MORINAGA SND_SOC_DAPM_MIXER("Output Mixer", SND_SOC_NOPM, 0, 0, 141d808fe9fSTomoya MORINAGA &ml26124_output_mixer_controls[0], 142d808fe9fSTomoya MORINAGA ARRAY_SIZE(ml26124_output_mixer_controls)), 143d808fe9fSTomoya MORINAGA SND_SOC_DAPM_DAC("DAC", "Playback", ML26124_PW_DAC_PW_MNG, 1, 0), 144d808fe9fSTomoya MORINAGA SND_SOC_DAPM_ADC("ADC", "Capture", ML26124_PW_IN_PW_MNG, 1, 0), 145d808fe9fSTomoya MORINAGA SND_SOC_DAPM_PGA("PGA", ML26124_PW_IN_PW_MNG, 3, 0, NULL, 0), 146d808fe9fSTomoya MORINAGA SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, 147d808fe9fSTomoya MORINAGA &ml26124_input_mux_controls), 148d808fe9fSTomoya MORINAGA SND_SOC_DAPM_SWITCH("Line Out Enable", SND_SOC_NOPM, 0, 0, 149d808fe9fSTomoya MORINAGA &ml26124_line_control), 150d808fe9fSTomoya MORINAGA SND_SOC_DAPM_INPUT("MDIN"), 151d808fe9fSTomoya MORINAGA SND_SOC_DAPM_INPUT("MIN"), 152d808fe9fSTomoya MORINAGA SND_SOC_DAPM_INPUT("LIN"), 153d808fe9fSTomoya MORINAGA SND_SOC_DAPM_OUTPUT("SPOUT"), 154d808fe9fSTomoya MORINAGA SND_SOC_DAPM_OUTPUT("LOUT"), 155d808fe9fSTomoya MORINAGA }; 156d808fe9fSTomoya MORINAGA 157d808fe9fSTomoya MORINAGA static const struct snd_soc_dapm_route ml26124_intercon[] = { 158d808fe9fSTomoya MORINAGA /* Supply */ 159d808fe9fSTomoya MORINAGA {"DAC", NULL, "MCLKEN"}, 160d808fe9fSTomoya MORINAGA {"ADC", NULL, "MCLKEN"}, 161d808fe9fSTomoya MORINAGA {"DAC", NULL, "PLLEN"}, 162d808fe9fSTomoya MORINAGA {"ADC", NULL, "PLLEN"}, 163d808fe9fSTomoya MORINAGA {"DAC", NULL, "PLLOE"}, 164d808fe9fSTomoya MORINAGA {"ADC", NULL, "PLLOE"}, 165d808fe9fSTomoya MORINAGA 166d808fe9fSTomoya MORINAGA /* output mixer */ 167d808fe9fSTomoya MORINAGA {"Output Mixer", "DAC Switch", "DAC"}, 168d808fe9fSTomoya MORINAGA {"Output Mixer", "Line in loopback Switch", "LIN"}, 169d808fe9fSTomoya MORINAGA 170d808fe9fSTomoya MORINAGA /* outputs */ 171d808fe9fSTomoya MORINAGA {"LOUT", NULL, "Output Mixer"}, 172d808fe9fSTomoya MORINAGA {"SPOUT", NULL, "Output Mixer"}, 173d808fe9fSTomoya MORINAGA {"Line Out Enable", NULL, "LOUT"}, 174d808fe9fSTomoya MORINAGA 175d808fe9fSTomoya MORINAGA /* input */ 176d808fe9fSTomoya MORINAGA {"ADC", NULL, "Input Mux"}, 177d808fe9fSTomoya MORINAGA {"Input Mux", "Analog MIC SingleEnded in", "PGA"}, 178d808fe9fSTomoya MORINAGA {"Input Mux", "Analog MIC Differential in", "PGA"}, 179d808fe9fSTomoya MORINAGA {"PGA", NULL, "MIN"}, 180d808fe9fSTomoya MORINAGA }; 181d808fe9fSTomoya MORINAGA 182d808fe9fSTomoya MORINAGA /* PLLOutputFreq(Hz) = InputMclkFreq(Hz) * PLLM / (PLLN * PLLDIV) */ 183d808fe9fSTomoya MORINAGA static const struct clk_coeff coeff_div[] = { 184d808fe9fSTomoya MORINAGA {12288000, 16000, 0xc, 0x0, 0x20, 0x0, 0x4}, 185d808fe9fSTomoya MORINAGA {12288000, 32000, 0xc, 0x0, 0x20, 0x0, 0x4}, 186d808fe9fSTomoya MORINAGA {12288000, 48000, 0xc, 0x0, 0x30, 0x0, 0x4}, 187d808fe9fSTomoya MORINAGA }; 188d808fe9fSTomoya MORINAGA 189c418a84aSAxel Lin static const struct reg_default ml26124_reg[] = { 190d808fe9fSTomoya MORINAGA /* CLOCK control Register */ 191d808fe9fSTomoya MORINAGA {0x00, 0x00 }, /* Sampling Rate */ 192d808fe9fSTomoya MORINAGA {0x02, 0x00}, /* PLL NL */ 193d808fe9fSTomoya MORINAGA {0x04, 0x00}, /* PLLNH */ 194d808fe9fSTomoya MORINAGA {0x06, 0x00}, /* PLLML */ 195d808fe9fSTomoya MORINAGA {0x08, 0x00}, /* MLLMH */ 196d808fe9fSTomoya MORINAGA {0x0a, 0x00}, /* PLLDIV */ 197d808fe9fSTomoya MORINAGA {0x0c, 0x00}, /* Clock Enable */ 198d808fe9fSTomoya MORINAGA {0x0e, 0x00}, /* CLK Input/Output Control */ 199d808fe9fSTomoya MORINAGA 200d808fe9fSTomoya MORINAGA /* System Control Register */ 201d808fe9fSTomoya MORINAGA {0x10, 0x00}, /* Software RESET */ 202d808fe9fSTomoya MORINAGA {0x12, 0x00}, /* Record/Playback Run */ 203d808fe9fSTomoya MORINAGA {0x14, 0x00}, /* Mic Input/Output control */ 204d808fe9fSTomoya MORINAGA 205d808fe9fSTomoya MORINAGA /* Power Management Register */ 206d808fe9fSTomoya MORINAGA {0x20, 0x00}, /* Reference Power Management */ 207d808fe9fSTomoya MORINAGA {0x22, 0x00}, /* Input Power Management */ 208d808fe9fSTomoya MORINAGA {0x24, 0x00}, /* DAC Power Management */ 209d808fe9fSTomoya MORINAGA {0x26, 0x00}, /* SP-AMP Power Management */ 210d808fe9fSTomoya MORINAGA {0x28, 0x00}, /* LINEOUT Power Management */ 211d808fe9fSTomoya MORINAGA {0x2a, 0x00}, /* VIDEO Power Management */ 212d808fe9fSTomoya MORINAGA {0x2e, 0x00}, /* AC-CMP Power Management */ 213d808fe9fSTomoya MORINAGA 214d808fe9fSTomoya MORINAGA /* Analog reference Control Register */ 215d808fe9fSTomoya MORINAGA {0x30, 0x04}, /* MICBIAS Voltage Control */ 216d808fe9fSTomoya MORINAGA 217d808fe9fSTomoya MORINAGA /* Input/Output Amplifier Control Register */ 218d808fe9fSTomoya MORINAGA {0x32, 0x10}, /* MIC Input Volume */ 219d808fe9fSTomoya MORINAGA {0x38, 0x00}, /* Mic Boost Volume */ 220d808fe9fSTomoya MORINAGA {0x3a, 0x33}, /* Speaker AMP Volume */ 221d808fe9fSTomoya MORINAGA {0x48, 0x00}, /* AMP Volume Control Function Enable */ 222d808fe9fSTomoya MORINAGA {0x4a, 0x00}, /* Amplifier Volume Fader Control */ 223d808fe9fSTomoya MORINAGA 224d808fe9fSTomoya MORINAGA /* Analog Path Control Register */ 225d808fe9fSTomoya MORINAGA {0x54, 0x00}, /* Speaker AMP Output Control */ 226d808fe9fSTomoya MORINAGA {0x5a, 0x00}, /* Mic IF Control */ 227d808fe9fSTomoya MORINAGA {0xe8, 0x01}, /* Mic Select Control */ 228d808fe9fSTomoya MORINAGA 229d808fe9fSTomoya MORINAGA /* Audio Interface Control Register */ 230d808fe9fSTomoya MORINAGA {0x60, 0x00}, /* SAI-Trans Control */ 231d808fe9fSTomoya MORINAGA {0x62, 0x00}, /* SAI-Receive Control */ 232d808fe9fSTomoya MORINAGA {0x64, 0x00}, /* SAI Mode select */ 233d808fe9fSTomoya MORINAGA 234d808fe9fSTomoya MORINAGA /* DSP Control Register */ 235d808fe9fSTomoya MORINAGA {0x66, 0x01}, /* Filter Func Enable */ 236d808fe9fSTomoya MORINAGA {0x68, 0x00}, /* Volume Control Func Enable */ 237d808fe9fSTomoya MORINAGA {0x6A, 0x00}, /* Mixer & Volume Control*/ 238d808fe9fSTomoya MORINAGA {0x6C, 0xff}, /* Record Digital Volume */ 239d808fe9fSTomoya MORINAGA {0x70, 0xff}, /* Playback Digital Volume */ 240d808fe9fSTomoya MORINAGA {0x72, 0x10}, /* Digital Boost Volume */ 241d808fe9fSTomoya MORINAGA {0x74, 0xe7}, /* EQ gain Band0 */ 242d808fe9fSTomoya MORINAGA {0x76, 0xe7}, /* EQ gain Band1 */ 243d808fe9fSTomoya MORINAGA {0x78, 0xe7}, /* EQ gain Band2 */ 244d808fe9fSTomoya MORINAGA {0x7A, 0xe7}, /* EQ gain Band3 */ 245d808fe9fSTomoya MORINAGA {0x7C, 0xe7}, /* EQ gain Band4 */ 246d808fe9fSTomoya MORINAGA {0x7E, 0x00}, /* HPF2 CutOff*/ 247d808fe9fSTomoya MORINAGA {0x80, 0x00}, /* EQ Band0 Coef0L */ 248d808fe9fSTomoya MORINAGA {0x82, 0x00}, /* EQ Band0 Coef0H */ 249d808fe9fSTomoya MORINAGA {0x84, 0x00}, /* EQ Band0 Coef0L */ 250d808fe9fSTomoya MORINAGA {0x86, 0x00}, /* EQ Band0 Coef0H */ 251d808fe9fSTomoya MORINAGA {0x88, 0x00}, /* EQ Band1 Coef0L */ 252d808fe9fSTomoya MORINAGA {0x8A, 0x00}, /* EQ Band1 Coef0H */ 253d808fe9fSTomoya MORINAGA {0x8C, 0x00}, /* EQ Band1 Coef0L */ 254d808fe9fSTomoya MORINAGA {0x8E, 0x00}, /* EQ Band1 Coef0H */ 255d808fe9fSTomoya MORINAGA {0x90, 0x00}, /* EQ Band2 Coef0L */ 256d808fe9fSTomoya MORINAGA {0x92, 0x00}, /* EQ Band2 Coef0H */ 257d808fe9fSTomoya MORINAGA {0x94, 0x00}, /* EQ Band2 Coef0L */ 258d808fe9fSTomoya MORINAGA {0x96, 0x00}, /* EQ Band2 Coef0H */ 259d808fe9fSTomoya MORINAGA {0x98, 0x00}, /* EQ Band3 Coef0L */ 260d808fe9fSTomoya MORINAGA {0x9A, 0x00}, /* EQ Band3 Coef0H */ 261d808fe9fSTomoya MORINAGA {0x9C, 0x00}, /* EQ Band3 Coef0L */ 262d808fe9fSTomoya MORINAGA {0x9E, 0x00}, /* EQ Band3 Coef0H */ 263d808fe9fSTomoya MORINAGA {0xA0, 0x00}, /* EQ Band4 Coef0L */ 264d808fe9fSTomoya MORINAGA {0xA2, 0x00}, /* EQ Band4 Coef0H */ 265d808fe9fSTomoya MORINAGA {0xA4, 0x00}, /* EQ Band4 Coef0L */ 266d808fe9fSTomoya MORINAGA {0xA6, 0x00}, /* EQ Band4 Coef0H */ 267d808fe9fSTomoya MORINAGA 268d808fe9fSTomoya MORINAGA /* ALC Control Register */ 269d808fe9fSTomoya MORINAGA {0xb0, 0x00}, /* ALC Mode */ 270d808fe9fSTomoya MORINAGA {0xb2, 0x02}, /* ALC Attack Time */ 271d808fe9fSTomoya MORINAGA {0xb4, 0x03}, /* ALC Decay Time */ 272d808fe9fSTomoya MORINAGA {0xb6, 0x00}, /* ALC Hold Time */ 273d808fe9fSTomoya MORINAGA {0xb8, 0x0b}, /* ALC Target Level */ 274d808fe9fSTomoya MORINAGA {0xba, 0x70}, /* ALC Max/Min Gain */ 275d808fe9fSTomoya MORINAGA {0xbc, 0x00}, /* Noise Gate Threshold */ 276d808fe9fSTomoya MORINAGA {0xbe, 0x00}, /* ALC ZeroCross TimeOut */ 277d808fe9fSTomoya MORINAGA 278d808fe9fSTomoya MORINAGA /* Playback Limiter Control Register */ 279d808fe9fSTomoya MORINAGA {0xc0, 0x04}, /* PL Attack Time */ 280d808fe9fSTomoya MORINAGA {0xc2, 0x05}, /* PL Decay Time */ 281d808fe9fSTomoya MORINAGA {0xc4, 0x0d}, /* PL Target Level */ 282d808fe9fSTomoya MORINAGA {0xc6, 0x70}, /* PL Max/Min Gain */ 283d808fe9fSTomoya MORINAGA {0xc8, 0x10}, /* Playback Boost Volume */ 284d808fe9fSTomoya MORINAGA {0xca, 0x00}, /* PL ZeroCross TimeOut */ 285d808fe9fSTomoya MORINAGA 286d808fe9fSTomoya MORINAGA /* Video Amplifier Control Register */ 287d808fe9fSTomoya MORINAGA {0xd0, 0x01}, /* VIDEO AMP Gain Control */ 288d808fe9fSTomoya MORINAGA {0xd2, 0x01}, /* VIDEO AMP Setup 1 */ 289d808fe9fSTomoya MORINAGA {0xd4, 0x01}, /* VIDEO AMP Control2 */ 290d808fe9fSTomoya MORINAGA }; 291d808fe9fSTomoya MORINAGA 292d808fe9fSTomoya MORINAGA /* Get sampling rate value of sampling rate setting register (0x0) */ 293d808fe9fSTomoya MORINAGA static inline int get_srate(int rate) 294d808fe9fSTomoya MORINAGA { 295d808fe9fSTomoya MORINAGA int srate; 296d808fe9fSTomoya MORINAGA 297d808fe9fSTomoya MORINAGA switch (rate) { 298d808fe9fSTomoya MORINAGA case 16000: 299d808fe9fSTomoya MORINAGA srate = 3; 300d808fe9fSTomoya MORINAGA break; 301d808fe9fSTomoya MORINAGA case 32000: 302d808fe9fSTomoya MORINAGA srate = 6; 303d808fe9fSTomoya MORINAGA break; 304d808fe9fSTomoya MORINAGA case 48000: 305d808fe9fSTomoya MORINAGA srate = 8; 306d808fe9fSTomoya MORINAGA break; 307d808fe9fSTomoya MORINAGA default: 308d808fe9fSTomoya MORINAGA return -EINVAL; 309d808fe9fSTomoya MORINAGA } 310d808fe9fSTomoya MORINAGA return srate; 311d808fe9fSTomoya MORINAGA } 312d808fe9fSTomoya MORINAGA 313d808fe9fSTomoya MORINAGA static inline int get_coeff(int mclk, int rate) 314d808fe9fSTomoya MORINAGA { 315d808fe9fSTomoya MORINAGA int i; 316d808fe9fSTomoya MORINAGA 317d808fe9fSTomoya MORINAGA for (i = 0; i < ARRAY_SIZE(coeff_div); i++) { 318d808fe9fSTomoya MORINAGA if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) 319d808fe9fSTomoya MORINAGA return i; 320d808fe9fSTomoya MORINAGA } 321d808fe9fSTomoya MORINAGA return -EINVAL; 322d808fe9fSTomoya MORINAGA } 323d808fe9fSTomoya MORINAGA 324d808fe9fSTomoya MORINAGA static int ml26124_hw_params(struct snd_pcm_substream *substream, 325d808fe9fSTomoya MORINAGA struct snd_pcm_hw_params *hw_params, 326d808fe9fSTomoya MORINAGA struct snd_soc_dai *dai) 327d808fe9fSTomoya MORINAGA { 328a9886cd0SKuninori Morimoto struct snd_soc_component *component = dai->component; 329a9886cd0SKuninori Morimoto struct ml26124_priv *priv = snd_soc_component_get_drvdata(component); 330d808fe9fSTomoya MORINAGA int i = get_coeff(priv->mclk, params_rate(hw_params)); 331b43fccf4SAxel Lin int srate; 332d808fe9fSTomoya MORINAGA 3338b4b3036STakashi Iwai if (i < 0) 3348b4b3036STakashi Iwai return i; 335d808fe9fSTomoya MORINAGA priv->substream = substream; 336d808fe9fSTomoya MORINAGA priv->rate = params_rate(hw_params); 337d808fe9fSTomoya MORINAGA 338d808fe9fSTomoya MORINAGA if (priv->clk_in) { 339d808fe9fSTomoya MORINAGA switch (priv->mclk / params_rate(hw_params)) { 340d808fe9fSTomoya MORINAGA case 256: 341a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_CLK_CTL, 342d808fe9fSTomoya MORINAGA BIT(0) | BIT(1), 1); 343d808fe9fSTomoya MORINAGA break; 344d808fe9fSTomoya MORINAGA case 512: 345a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_CLK_CTL, 346d808fe9fSTomoya MORINAGA BIT(0) | BIT(1), 2); 347d808fe9fSTomoya MORINAGA break; 348d808fe9fSTomoya MORINAGA case 1024: 349a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_CLK_CTL, 350d808fe9fSTomoya MORINAGA BIT(0) | BIT(1), 3); 351d808fe9fSTomoya MORINAGA break; 352d808fe9fSTomoya MORINAGA default: 353a9886cd0SKuninori Morimoto dev_err(component->dev, "Unsupported MCLKI\n"); 354d808fe9fSTomoya MORINAGA break; 355d808fe9fSTomoya MORINAGA } 356d808fe9fSTomoya MORINAGA } else { 357a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_CLK_CTL, 358d808fe9fSTomoya MORINAGA BIT(0) | BIT(1), 0); 359d808fe9fSTomoya MORINAGA } 360d808fe9fSTomoya MORINAGA 361b43fccf4SAxel Lin srate = get_srate(params_rate(hw_params)); 362b43fccf4SAxel Lin if (srate < 0) 363b43fccf4SAxel Lin return srate; 364b43fccf4SAxel Lin 365a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_SMPLING_RATE, 0xf, srate); 366a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PLLNL, 0xff, coeff_div[i].pllnl); 367a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PLLNH, 0x1, coeff_div[i].pllnh); 368a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PLLML, 0xff, coeff_div[i].pllml); 369a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PLLMH, 0x3f, coeff_div[i].pllmh); 370a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PLLDIV, 0x1f, coeff_div[i].plldiv); 371d808fe9fSTomoya MORINAGA 372d808fe9fSTomoya MORINAGA return 0; 373d808fe9fSTomoya MORINAGA } 374d808fe9fSTomoya MORINAGA 37554b59270SKuninori Morimoto static int ml26124_mute(struct snd_soc_dai *dai, int mute, int direction) 376d808fe9fSTomoya MORINAGA { 377a9886cd0SKuninori Morimoto struct snd_soc_component *component = dai->component; 378a9886cd0SKuninori Morimoto struct ml26124_priv *priv = snd_soc_component_get_drvdata(component); 379d808fe9fSTomoya MORINAGA 380d808fe9fSTomoya MORINAGA switch (priv->substream->stream) { 381d808fe9fSTomoya MORINAGA case SNDRV_PCM_STREAM_CAPTURE: 382a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_REC_PLYBAK_RUN, BIT(0), 1); 383d808fe9fSTomoya MORINAGA break; 384d808fe9fSTomoya MORINAGA case SNDRV_PCM_STREAM_PLAYBACK: 385a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_REC_PLYBAK_RUN, BIT(1), 2); 386d808fe9fSTomoya MORINAGA break; 387d808fe9fSTomoya MORINAGA } 388d808fe9fSTomoya MORINAGA 389d808fe9fSTomoya MORINAGA if (mute) 390a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_DVOL_CTL, BIT(4), 391d808fe9fSTomoya MORINAGA DVOL_CTL_DVMUTE_ON); 392d808fe9fSTomoya MORINAGA else 393a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_DVOL_CTL, BIT(4), 394d808fe9fSTomoya MORINAGA DVOL_CTL_DVMUTE_OFF); 395d808fe9fSTomoya MORINAGA 396d808fe9fSTomoya MORINAGA return 0; 397d808fe9fSTomoya MORINAGA } 398d808fe9fSTomoya MORINAGA 399d808fe9fSTomoya MORINAGA static int ml26124_set_dai_fmt(struct snd_soc_dai *codec_dai, 400d808fe9fSTomoya MORINAGA unsigned int fmt) 401d808fe9fSTomoya MORINAGA { 402d808fe9fSTomoya MORINAGA unsigned char mode; 403a9886cd0SKuninori Morimoto struct snd_soc_component *component = codec_dai->component; 404d808fe9fSTomoya MORINAGA 405ca7176f6SMark Brown switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) { 406ca7176f6SMark Brown case SND_SOC_DAIFMT_CBP_CFP: 407d808fe9fSTomoya MORINAGA mode = 1; 408d808fe9fSTomoya MORINAGA break; 409ca7176f6SMark Brown case SND_SOC_DAIFMT_CBC_CFC: 410d808fe9fSTomoya MORINAGA mode = 0; 411d808fe9fSTomoya MORINAGA break; 412d808fe9fSTomoya MORINAGA default: 413d808fe9fSTomoya MORINAGA return -EINVAL; 414d808fe9fSTomoya MORINAGA } 415a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_SAI_MODE_SEL, BIT(0), mode); 416d808fe9fSTomoya MORINAGA 417d808fe9fSTomoya MORINAGA /* interface format */ 418d808fe9fSTomoya MORINAGA switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { 419d808fe9fSTomoya MORINAGA case SND_SOC_DAIFMT_I2S: 420d808fe9fSTomoya MORINAGA break; 421d808fe9fSTomoya MORINAGA default: 422d808fe9fSTomoya MORINAGA return -EINVAL; 423d808fe9fSTomoya MORINAGA } 424d808fe9fSTomoya MORINAGA 425d808fe9fSTomoya MORINAGA /* clock inversion */ 426d808fe9fSTomoya MORINAGA switch (fmt & SND_SOC_DAIFMT_INV_MASK) { 427d808fe9fSTomoya MORINAGA case SND_SOC_DAIFMT_NB_NF: 428d808fe9fSTomoya MORINAGA break; 429d808fe9fSTomoya MORINAGA default: 430d808fe9fSTomoya MORINAGA return -EINVAL; 431d808fe9fSTomoya MORINAGA } 432d808fe9fSTomoya MORINAGA 433d808fe9fSTomoya MORINAGA return 0; 434d808fe9fSTomoya MORINAGA } 435d808fe9fSTomoya MORINAGA 436d808fe9fSTomoya MORINAGA static int ml26124_set_dai_sysclk(struct snd_soc_dai *codec_dai, 437d808fe9fSTomoya MORINAGA int clk_id, unsigned int freq, int dir) 438d808fe9fSTomoya MORINAGA { 439a9886cd0SKuninori Morimoto struct snd_soc_component *component = codec_dai->component; 440a9886cd0SKuninori Morimoto struct ml26124_priv *priv = snd_soc_component_get_drvdata(component); 441d808fe9fSTomoya MORINAGA 442d808fe9fSTomoya MORINAGA switch (clk_id) { 443d808fe9fSTomoya MORINAGA case ML26124_USE_PLLOUT: 444d808fe9fSTomoya MORINAGA priv->clk_in = ML26124_USE_PLLOUT; 445d808fe9fSTomoya MORINAGA break; 446d808fe9fSTomoya MORINAGA case ML26124_USE_MCLKI: 447d808fe9fSTomoya MORINAGA priv->clk_in = ML26124_USE_MCLKI; 448d808fe9fSTomoya MORINAGA break; 449d808fe9fSTomoya MORINAGA default: 450d808fe9fSTomoya MORINAGA return -EINVAL; 451d808fe9fSTomoya MORINAGA } 452d808fe9fSTomoya MORINAGA 453d808fe9fSTomoya MORINAGA priv->mclk = freq; 454d808fe9fSTomoya MORINAGA 455d808fe9fSTomoya MORINAGA return 0; 456d808fe9fSTomoya MORINAGA } 457d808fe9fSTomoya MORINAGA 458a9886cd0SKuninori Morimoto static int ml26124_set_bias_level(struct snd_soc_component *component, 459d808fe9fSTomoya MORINAGA enum snd_soc_bias_level level) 460d808fe9fSTomoya MORINAGA { 461a9886cd0SKuninori Morimoto struct ml26124_priv *priv = snd_soc_component_get_drvdata(component); 462d808fe9fSTomoya MORINAGA 463d808fe9fSTomoya MORINAGA switch (level) { 464d808fe9fSTomoya MORINAGA case SND_SOC_BIAS_ON: 465a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PW_SPAMP_PW_MNG, 466d808fe9fSTomoya MORINAGA ML26124_R26_MASK, ML26124_BLT_PREAMP_ON); 467d808fe9fSTomoya MORINAGA msleep(100); 468a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PW_SPAMP_PW_MNG, 469d808fe9fSTomoya MORINAGA ML26124_R26_MASK, 470d808fe9fSTomoya MORINAGA ML26124_MICBEN_ON | ML26124_BLT_ALL_ON); 471d808fe9fSTomoya MORINAGA break; 472d808fe9fSTomoya MORINAGA case SND_SOC_BIAS_PREPARE: 473d808fe9fSTomoya MORINAGA break; 474d808fe9fSTomoya MORINAGA case SND_SOC_BIAS_STANDBY: 475d808fe9fSTomoya MORINAGA /* VMID ON */ 476a9886cd0SKuninori Morimoto if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { 477a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PW_REF_PW_MNG, 478d808fe9fSTomoya MORINAGA ML26124_VMID, ML26124_VMID); 479d808fe9fSTomoya MORINAGA msleep(500); 480d808fe9fSTomoya MORINAGA regcache_sync(priv->regmap); 481d808fe9fSTomoya MORINAGA } 482d808fe9fSTomoya MORINAGA break; 483d808fe9fSTomoya MORINAGA case SND_SOC_BIAS_OFF: 484d808fe9fSTomoya MORINAGA /* VMID OFF */ 485a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_PW_REF_PW_MNG, 486d808fe9fSTomoya MORINAGA ML26124_VMID, 0); 487d808fe9fSTomoya MORINAGA break; 488d808fe9fSTomoya MORINAGA } 489d808fe9fSTomoya MORINAGA return 0; 490d808fe9fSTomoya MORINAGA } 491d808fe9fSTomoya MORINAGA 492d808fe9fSTomoya MORINAGA static const struct snd_soc_dai_ops ml26124_dai_ops = { 493d808fe9fSTomoya MORINAGA .hw_params = ml26124_hw_params, 49454b59270SKuninori Morimoto .mute_stream = ml26124_mute, 495d808fe9fSTomoya MORINAGA .set_fmt = ml26124_set_dai_fmt, 496d808fe9fSTomoya MORINAGA .set_sysclk = ml26124_set_dai_sysclk, 49754b59270SKuninori Morimoto .no_capture_mute = 1, 498d808fe9fSTomoya MORINAGA }; 499d808fe9fSTomoya MORINAGA 500d808fe9fSTomoya MORINAGA static struct snd_soc_dai_driver ml26124_dai = { 501d808fe9fSTomoya MORINAGA .name = "ml26124-hifi", 502d808fe9fSTomoya MORINAGA .playback = { 503d808fe9fSTomoya MORINAGA .stream_name = "Playback", 504d808fe9fSTomoya MORINAGA .channels_min = 1, 505d808fe9fSTomoya MORINAGA .channels_max = 2, 506d808fe9fSTomoya MORINAGA .rates = ML26124_RATES, 507d808fe9fSTomoya MORINAGA .formats = ML26124_FORMATS,}, 508d808fe9fSTomoya MORINAGA .capture = { 509d808fe9fSTomoya MORINAGA .stream_name = "Capture", 510d808fe9fSTomoya MORINAGA .channels_min = 1, 511d808fe9fSTomoya MORINAGA .channels_max = 2, 512d808fe9fSTomoya MORINAGA .rates = ML26124_RATES, 513d808fe9fSTomoya MORINAGA .formats = ML26124_FORMATS,}, 514d808fe9fSTomoya MORINAGA .ops = &ml26124_dai_ops, 5156944db0aSKuninori Morimoto .symmetric_rate = 1, 516d808fe9fSTomoya MORINAGA }; 517d808fe9fSTomoya MORINAGA 518a9886cd0SKuninori Morimoto static int ml26124_probe(struct snd_soc_component *component) 519d808fe9fSTomoya MORINAGA { 520d808fe9fSTomoya MORINAGA /* Software Reset */ 521a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_SW_RST, 0x01, 1); 522a9886cd0SKuninori Morimoto snd_soc_component_update_bits(component, ML26124_SW_RST, 0x01, 0); 523d808fe9fSTomoya MORINAGA 524d808fe9fSTomoya MORINAGA return 0; 525d808fe9fSTomoya MORINAGA } 526d808fe9fSTomoya MORINAGA 527a9886cd0SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_ml26124 = { 528d808fe9fSTomoya MORINAGA .probe = ml26124_probe, 529d808fe9fSTomoya MORINAGA .set_bias_level = ml26124_set_bias_level, 530e21413caSKuninori Morimoto .controls = ml26124_snd_controls, 531e21413caSKuninori Morimoto .num_controls = ARRAY_SIZE(ml26124_snd_controls), 532d808fe9fSTomoya MORINAGA .dapm_widgets = ml26124_dapm_widgets, 533d808fe9fSTomoya MORINAGA .num_dapm_widgets = ARRAY_SIZE(ml26124_dapm_widgets), 534d808fe9fSTomoya MORINAGA .dapm_routes = ml26124_intercon, 535d808fe9fSTomoya MORINAGA .num_dapm_routes = ARRAY_SIZE(ml26124_intercon), 536a9886cd0SKuninori Morimoto .suspend_bias_off = 1, 537a9886cd0SKuninori Morimoto .idle_bias_on = 1, 538a9886cd0SKuninori Morimoto .use_pmdown_time = 1, 539a9886cd0SKuninori Morimoto .endianness = 1, 540a9886cd0SKuninori Morimoto .non_legacy_dai_naming = 1, 541d808fe9fSTomoya MORINAGA }; 542d808fe9fSTomoya MORINAGA 543d808fe9fSTomoya MORINAGA static const struct regmap_config ml26124_i2c_regmap = { 544d808fe9fSTomoya MORINAGA .val_bits = 8, 545d808fe9fSTomoya MORINAGA .reg_bits = 8, 546d808fe9fSTomoya MORINAGA .max_register = ML26124_NUM_REGISTER, 547d808fe9fSTomoya MORINAGA .reg_defaults = ml26124_reg, 548d808fe9fSTomoya MORINAGA .num_reg_defaults = ARRAY_SIZE(ml26124_reg), 549d808fe9fSTomoya MORINAGA .cache_type = REGCACHE_RBTREE, 550d808fe9fSTomoya MORINAGA .write_flag_mask = 0x01, 551d808fe9fSTomoya MORINAGA }; 552d808fe9fSTomoya MORINAGA 553*f7537e3aSStephen Kitt static int ml26124_i2c_probe(struct i2c_client *i2c) 554d808fe9fSTomoya MORINAGA { 555d808fe9fSTomoya MORINAGA struct ml26124_priv *priv; 556d808fe9fSTomoya MORINAGA int ret; 557d808fe9fSTomoya MORINAGA 558d808fe9fSTomoya MORINAGA priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); 559d808fe9fSTomoya MORINAGA if (!priv) 560d808fe9fSTomoya MORINAGA return -ENOMEM; 561d808fe9fSTomoya MORINAGA 562d808fe9fSTomoya MORINAGA i2c_set_clientdata(i2c, priv); 563d808fe9fSTomoya MORINAGA 5648994a5e1SAxel Lin priv->regmap = devm_regmap_init_i2c(i2c, &ml26124_i2c_regmap); 565d808fe9fSTomoya MORINAGA if (IS_ERR(priv->regmap)) { 566d808fe9fSTomoya MORINAGA ret = PTR_ERR(priv->regmap); 567d808fe9fSTomoya MORINAGA dev_err(&i2c->dev, "regmap_init_i2c() failed: %d\n", ret); 568d808fe9fSTomoya MORINAGA return ret; 569d808fe9fSTomoya MORINAGA } 570d808fe9fSTomoya MORINAGA 571a9886cd0SKuninori Morimoto return devm_snd_soc_register_component(&i2c->dev, 572a9886cd0SKuninori Morimoto &soc_component_dev_ml26124, &ml26124_dai, 1); 573d808fe9fSTomoya MORINAGA } 574d808fe9fSTomoya MORINAGA 575d808fe9fSTomoya MORINAGA static const struct i2c_device_id ml26124_i2c_id[] = { 576d808fe9fSTomoya MORINAGA { "ml26124", 0 }, 577d808fe9fSTomoya MORINAGA { } 578d808fe9fSTomoya MORINAGA }; 579d808fe9fSTomoya MORINAGA MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id); 580d808fe9fSTomoya MORINAGA 581d808fe9fSTomoya MORINAGA static struct i2c_driver ml26124_i2c_driver = { 582d808fe9fSTomoya MORINAGA .driver = { 583d808fe9fSTomoya MORINAGA .name = "ml26124", 584d808fe9fSTomoya MORINAGA }, 585*f7537e3aSStephen Kitt .probe_new = ml26124_i2c_probe, 586d808fe9fSTomoya MORINAGA .id_table = ml26124_i2c_id, 587d808fe9fSTomoya MORINAGA }; 588d808fe9fSTomoya MORINAGA 589d808fe9fSTomoya MORINAGA module_i2c_driver(ml26124_i2c_driver); 590d808fe9fSTomoya MORINAGA 591d808fe9fSTomoya MORINAGA MODULE_AUTHOR("Tomoya MORINAGA <tomoya.rohm@gmail.com>"); 592d808fe9fSTomoya MORINAGA MODULE_DESCRIPTION("LAPIS Semiconductor ML26124 ALSA SoC codec driver"); 593d808fe9fSTomoya MORINAGA MODULE_LICENSE("GPL"); 594