/* * ark1668ed_audio_codec.c -- ARK SoC audio driver */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ark1668ed_i2s.h" //#define ARK_CODEC_DEBUG #define ARKADAC_RATES \ (SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \ SNDRV_PCM_RATE_64000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | \ SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 | SNDRV_PCM_RATE_8000) #define ARKADAC_FORMATS (SNDRV_PCM_FMTBIT_S16_LE) static struct snd_soc_component *ark_codec_component; struct regval_list { unsigned int addr; unsigned int data; }; static struct regval_list ark_codec_init_regs[] = { //{0x00, 0x00}, /**/ //{0x00, 0x03}, /*Reset ADC/DAC*/ //{0x15, 0x00}, {0x47, 0x00}, {0xF3, 0xc0}, //{0x15, 0x0b}, /*mic-bias:active*/ {0x16, 0x0f}, /*LADC/RADC LPGA/RPGA:active*/ {0x18, 0xf3}, /*LDAC/RDAC,LHeadset/RHeadset,Lline/Rline:active*/ {0x19, 0x04}, /*Differential-line:active*/ {0x1d, 0x00}, /*Recording/Input PGA volume control 0:un-mute 1:mute*/ {0x1f, 0x00}, /*Playback/Headset/Line volume control 0:un-mute 1:mute*/ {0x21, 0x00}, /*Line volume control 0:un-mute 1:mute*/ {0x24, 0xbfbf}, /*Recording digital master volume control(left/right channel)*/ {0x26, 0x1212}, /*Input PGA volume control(left/right channel)*/ {0x34, 0xe7e7}, /*Digital playback master volume control(left/right channel)*/ {0x38, 0x0d0d}, /*Headset analog volume control(left/right channel)*/ {0x47, 0x0101}, /*PGA input selection((single ended)-ainl1p/ainr1n)*/ {0x59, 0x0101}, /*Playback path channel analog mixer input selection*/ {0x5d, 0x0101}, /*Playback path channel analog mixer input selection*/ {0x7b, 0x00}, /*Record digital mixer selection*/ {0x7c, 0x00}, /*Playback digital mixer selection*/ {0x7d, 0x00}, /*ASRC1 digital mixer selection*/ {0x80, 0x0000}, /**/ {0x88, 0x3f3f}, /**/ {0x82, 0x3f3f}, /**/ {0x8a, 0x0000}, /**/ {0x01, 0x05}, /*Set external clock clk_ext(mclk)=12288kHz*/ {0xDC, 0x00}, {0xFB, 0x09}, {0x13, 0x00}, {0xA2, 0x00}, {0x03, 0x01}, {0x04, 0x40}, /*master_mode_valid:play_lrclk_div 0x7d(fs=48k clk_ext(mclk)=12MHz) 0x40(12.288M)*/ {0x05, 0x04}, /*master_mode_valid:play_sclk_div 0x2(fs=48k clk_ext(mclk)=12MHz) 0x4(12.288M)*/ {0x06, 0x40}, /*master_mode_valid:rec_lrclk_div 0x7d(fs=48k clk_ext(mclk)=12MHz) 0x40(12.288M)*/ {0x07, 0x04}, /*master_mode_valid:rec_sclk_div 0x2(fs=48k clk_ext(mclk)=12MHz) 0x4(12.288M)*/ //{0x00, 0x00}, /**/ //{0x00, 0x03}, /*Reset ADC/DAC*/ //{0x15, 0x01}, {0x03, 0x31}, /*set i2s data_format,mode,data_len,bit[2:0]:0x1:i2s bit[3]:0:slave/1:master bit[5:4]:0x11:16bit*/ }; struct ark_codec_priv { struct regmap *regmap; struct snd_soc_component *component; struct clk *mclk; struct i2c_client *i2c; void __iomem *sys_base; int master; unsigned int sample_rate; unsigned int volume_left; unsigned int volume_right; unsigned int mic_volume_left; unsigned int mic_volume_right; bool mute_left; bool mute_right; //bool mute; }; #ifdef ARK_CODEC_DEBUG #define arkdbgprt printk #else #define arkdbgprt(format, arg...) do {} while (0) #endif static const char *const ark_input_sel[] = { "Mic" }; //static SOC_ENUM_SINGLE_DECL(ark_input_enum, ADC_CODEC_REG_CTRL1, 0, ark_input_sel); static unsigned int arkcodec_register_size(struct device *dev, unsigned int reg) { switch (reg) { case CODEC_REG_RECVOL: case CODEC_REG_PGA1VOL: case CODEC_REG_LMVOL: case CODEC_REG_HS1VOL: case CODEC_REG_PGA1SEL: case CODEC_REG_LDR1SEL: case CODEC_REG_LDR2SEL: case CODEC_REG_RECPBVOL: case CODEC_REG_RECI2S1VOL: case CODEC_REG_I2S1PBVOL: case CODEC_REG_I2S1I2S1VOL: return 2; default: return 1; } dev_err(dev, "Unsupported register address: %d\n", reg); return 0; } static int codec_reg_write(struct i2c_client *client, unsigned int reg, unsigned int value) { unsigned int data_len; int ret; uint8_t buf[3]; unsigned int pos = 0; data_len = arkcodec_register_size(&client->dev, reg); buf[pos++] = reg & 0xFF; if (data_len == 1) { buf[pos++] = value & 0xFF; } else { buf[pos++] = (value >> 8) & 0xFF; buf[pos++] = value & 0xFF; } ret = i2c_master_send(client, buf, pos); if (ret < 0) { dev_err(&client->dev, "I2C write error: %d\n", ret); return ret; } else if (ret != pos) { dev_err(&client->dev, "I2C write: short transfer (%d)\n", ret); return -EIO; } else return 0; } static int codec_reg_read(struct i2c_client *client, unsigned int reg, unsigned int *value) { int ret; //unsigned int i; unsigned int data_len, reg_len; uint8_t addr_buf[2] = {0}, data_buf[2] = {0}; struct i2c_msg msgs[2]; data_len = arkcodec_register_size(&client->dev, reg); if (data_len == 0) return -EINVAL; addr_buf[0] = reg & 0xFF; reg_len = 1; msgs[0].addr = client->addr; msgs[0].len = reg_len; msgs[0].buf = addr_buf; msgs[0].flags = 0; msgs[1].addr = client->addr; msgs[1].len = data_len; msgs[1].buf = data_buf; msgs[1].flags = I2C_M_RD; ret = i2c_transfer(client->adapter, msgs, 2); if (ret < 0) return ret; else if (ret != 2) return -EIO; if (data_len == 2) { *value = (data_buf[0] << 8) | data_buf[1]; } else { *value = data_buf[0]; } return 0; } static int ark_dac_l_playback_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = arkcodec->volume_left; return 0; } static int ark_dac_l_playback_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); unsigned int val = ucontrol->value.integer.value[0]; int change = 0; if (arkcodec->volume_left != val) { arkcodec->volume_left = val; //printk("[set:val = 0x%04x\n",(arkcodec->volume_left << 8) | arkcodec->volume_right); codec_reg_write(arkcodec->i2c, CODEC_REG_LMVOL, (arkcodec->volume_left << 8) | arkcodec->volume_right); change = 1; } return change; } static int ark_dac_r_playback_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = arkcodec->volume_right; return 0; } static int ark_dac_r_playback_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); unsigned int val = ucontrol->value.integer.value[0]; int change = 0; if (arkcodec->volume_right != val) { arkcodec->volume_right = val; //printk("[set:val = 0x%04x\n",(arkcodec->volume_left << 8) | arkcodec->volume_right); codec_reg_write(arkcodec->i2c, CODEC_REG_LMVOL, (arkcodec->volume_left << 8) | arkcodec->volume_right); change = 1; } return change; } static int ark_adc_l_capture_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = arkcodec->mic_volume_left; return 0; } static int ark_adc_l_capture_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); unsigned int val = ucontrol->value.integer.value[0]; int change = 0; if (arkcodec->mic_volume_left != val) { arkcodec->mic_volume_left = val; //printk("[set:val = 0x%04x\n",(arkcodec->mic_volume_left << 8) | arkcodec->mic_volume_right); codec_reg_write(arkcodec->i2c, CODEC_REG_RECVOL, (arkcodec->mic_volume_left << 8) | arkcodec->mic_volume_right); change = 1; } return change; } static int ark_adc_r_capture_volume_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = arkcodec->mic_volume_right; return 0; } static int ark_adc_r_capture_volume_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); unsigned int val = ucontrol->value.integer.value[0]; int change = 0; if (arkcodec->mic_volume_right != val) { arkcodec->mic_volume_right = val; //printk("[set:val = 0x%04x\n",(arkcodec->mic_volume_left << 8) | arkcodec->mic_volume_right); codec_reg_write(arkcodec->i2c, CODEC_REG_RECVOL, (arkcodec->mic_volume_left << 8) | arkcodec->mic_volume_right); change = 1; } return change; } static int ark_dac_mute_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); ucontrol->value.integer.value[0] = arkcodec->mute_left; ucontrol->value.integer.value[1] = arkcodec->mute_right; return 0; } static int ark_dac_mute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct ark_codec_priv *arkcodec = snd_soc_component_get_drvdata(component); unsigned int left = ucontrol->value.integer.value[0]; unsigned int right = ucontrol->value.integer.value[1]; unsigned int mute_val = 0; int change = 0; if (arkcodec->mute_left != left || arkcodec->mute_right != right) { arkcodec->mute_left = left; arkcodec->mute_right = right; if (left) mute_val |= MUTE_BIT_LEFT; if (right) mute_val |= MUTE_BIT_RIGHT; //printk("[set:mute_val = %d\n",mute_val); regmap_update_bits(arkcodec->regmap, CODEC_REG_PLAYBACK_MUTE, 0x3, mute_val); change = 1; } return change; } static const DECLARE_TLV_DB_SCALE(ark_dac_vol_tlv, -11550, 50, 0);/*\D2\F4\C1\BF\B7\B6Χ:[-115.5dB-12dB],\B2\BD\B3\A4 :0.5dB*/ static const DECLARE_TLV_DB_SCALE(ark_mic_vol_tlv, -9550, 50, 0);/*\D2\F4\C1\BF\B7\B6Χ:[-95.5dB-12dB], \B2\BD\B3\A4 :0.5dB*/ static const struct snd_kcontrol_new ark_codec_controls[] = { SOC_SINGLE_EXT("DAC Left Playback Volume", 0, 0, 255, 0, ark_dac_l_playback_volume_get, ark_dac_l_playback_volume_put), SOC_SINGLE_EXT("DAC Right Playback Volume", 0, 0, 255, 0, ark_dac_r_playback_volume_get, ark_dac_r_playback_volume_put), SOC_SINGLE_EXT("ADC Left Capture Volume", 0, 0, 255, 0, ark_adc_l_capture_volume_get, ark_adc_l_capture_volume_put), SOC_SINGLE_EXT("ADC Right Capture Volume", 0, 0, 255, 0, ark_adc_r_capture_volume_get, ark_adc_r_capture_volume_put), SOC_DOUBLE_EXT("Playback Switch", CODEC_REG_PLAYBACK_MUTE, 0, 1, 1, 1, ark_dac_mute_get, ark_dac_mute_put), }; static const struct snd_soc_dapm_widget dwc_audio_dapm_widgets[] = { SND_SOC_DAPM_DAC("DAC", "Playback", CODEC_REG_DAC_RESET_CTRL, 0, 0), SND_SOC_DAPM_ADC("ADC", "Capture", CODEC_REG_ADC_RESET_CTRL, 1, 0), }; static const struct snd_soc_dapm_route dwc_audio_dapm_routes[] = { {"DAC", NULL, "Playback"}, {"ADC", NULL, "Capture"}, }; static int ark_codec_init_reg(struct snd_soc_component *component) { arkdbgprt("[ARK_CODEC] %s(%d)\n", __func__, __LINE__); struct ark_codec_priv *priv = snd_soc_component_get_drvdata(component); unsigned int val; int i; /*reset codec*/ regmap_write(priv->regmap, CODEC_REG_ADC_DAC_RESET, 0); mdelay(2); regmap_write(priv->regmap, CODEC_REG_ADC_DAC_RESET, 0x3); /*init-regs*/ for (i = 0; i < ARRAY_SIZE(ark_codec_init_regs); i++) { codec_reg_write(priv->i2c, ark_codec_init_regs[i].addr, ark_codec_init_regs[i].data); //printk("[write:reg=0x%02x,val=0x%04x]\n",ark_codec_init_regs[i].addr,ark_codec_init_regs[i].data); } #if 0 for (i = 0; i < ARRAY_SIZE(ark_codec_init_regs); i++) { codec_reg_read(priv->i2c, ark_codec_init_regs[i].addr, &val); printk("[read:reg=0x%02x,val=0x%04x]\n", ark_codec_init_regs[i], val); } #endif /*Mic_Bias power-down*/ regmap_write(priv->regmap, CODEC_REG_POWER_DOWN, 0); mdelay(2); regmap_write(priv->regmap, CODEC_REG_POWER_DOWN, 0xb); codec_reg_read(priv->i2c, CODEC_REG_LMVOL, &val); priv->volume_left = (val >> 8) & 0xFF; priv->volume_right = val & 0xFF; codec_reg_read(priv->i2c, CODEC_REG_RECVOL, &val); priv->mic_volume_left = (val >> 8) & 0xFF; priv->mic_volume_right = val & 0xFF; priv->mute_left = false; priv->mute_right = false; return 0; } //static unsigned int ark_codec_read(struct snd_soc_component *component, // unsigned int reg) //{ // int val; // val = snd_soc_component_read(component,reg); // return val; //} //static int ark_codec_write(struct snd_soc_component *component, // unsigned int reg, unsigned int value) //{ // int ret; // ret = snd_soc_component_write(component, reg, value); // return ret; //} static int ark_codec_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { return 0; } static void ark_codec_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { } static int ark_codec_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { struct ark_codec_priv *priv = snd_soc_component_get_drvdata(dai->component); //int regval = 0; unsigned int clk_div, bclk_div; arkdbgprt("[ARK_CODEC] %s(%d)\n", __func__, __LINE__); priv->sample_rate = params_rate(params); switch (priv->sample_rate) { case 8000: case 16000: case 32000: clk_div = 3; break; case 44100: case 88200: clk_div = 2; break; case 48000: case 96000: clk_div = 1; break; default: return -EINVAL; } switch (params_width(params)) { case 16: bclk_div = 0; break; case 24: bclk_div = 1; break; case 32: bclk_div = 2; break; default: return -EINVAL; } /*set rate*/ // switch (params_rate(params)) { // case 48000: // regval = CTRL1_SAMPLE_RATE_48K; // break; // default: // dev_err(dai->dev, "Unsupported sample rate: %d\n", params_rate(params)); // return -EINVAL; // } //regmap_update_bits(priv->regmap, ADC_CODEC_REG_CTRL1, 0xF0, regval); return 0; } static int ark_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai, int clk_id, unsigned int freq, int dir) { arkdbgprt("[ARK_CODEC] %s(%d)\n", __func__, __LINE__); return 0; } static int ark_codec_mute(struct snd_soc_dai *dai, int mute, int direction) { //struct snd_soc_component *component = dai->component; //struct ark_codec_priv *priv = snd_soc_component_get_drvdata(component); //unsigned int val = mute ? CODEC_REG_DAC_SOFT_MUTE : CODEC_REG_DAC_SOFT_UNMUTE; int ret = 0; #if 0 printk("#####%s,%d:mute = %d\n", __func__, __LINE__, mute); if (mute) { regmap_update_bits(priv->regmap, CODEC_REG_PLAYBACK_MUTE, 0x3, 0x3); priv->mute_left = true; priv->mute_right = true; } else { regmap_update_bits(priv->regmap, CODEC_REG_PLAYBACK_MUTE, 0x3, 0x0); priv->mute_left = false; priv->mute_right = false; } #endif return ret; } static int ark_codec_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) { //struct snd_soc_component *component = codec_dai->component; struct ark_codec_priv *priv = snd_soc_dai_get_drvdata(codec_dai); arkdbgprt("[ARK_CODEC] %s(%d),codec_dai->id = %d\n", __func__, __LINE__, codec_dai->id); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBM_CFM: printk("###ark audio codec master###\n"); //priv->master= 1; regmap_update_bits(priv->regmap, CODEC_REG_I2S1_CONFIG_0, CODEC_REG_I2S1_MODE_SEL, 0x1); break; case SND_SOC_DAIFMT_CBS_CFS: printk("###ark audio codec slave###\n"); //priv->master = 0; regmap_update_bits(priv->regmap, CODEC_REG_I2S1_CONFIG_0, CODEC_REG_I2S1_MODE_SEL, 0x0); break; default: return -EINVAL; } return 0; } static const struct snd_soc_dai_ops ark_codec_dai_ops = { .startup = ark_codec_startup, .shutdown = ark_codec_shutdown, .hw_params = ark_codec_hw_params, .set_fmt = ark_codec_set_dai_fmt, .set_sysclk = ark_codec_set_dai_sysclk, .mute_stream = ark_codec_mute, }; static struct snd_soc_dai_driver ark_codec_dai = { .name = "ark-codec-dai", .playback = { .stream_name = "Playback", .channels_min = 1, .channels_max = 2, .rates = ARKADAC_RATES, .formats = ARKADAC_FORMATS, }, .capture = { .stream_name = "Capture", .channels_min = 1, .channels_max = 4, .rates = ARKADAC_RATES, .formats = ARKADAC_FORMATS, }, .ops = &ark_codec_dai_ops, .symmetric_rate = 1, }; static int ark_codec_probe(struct snd_soc_component *component) { struct ark_codec_priv *priv = snd_soc_component_get_drvdata(component); ark_codec_component = component; priv->component = component; arkdbgprt("[ARK_CODEC] %s(%d)\n", __func__, __LINE__); ark_codec_init_reg(component); return 0; } static void ark_codec_remove(struct snd_soc_component *component) { //struct ark_codec_priv *priv = snd_soc_component_get_drvdata(component); arkdbgprt("[ARK_CODEC] %s(%d)\n", __func__, __LINE__); //regmap_write(priv->regmap, ADC_CODEC_REG_POWER_CTRL, 0); } static const struct snd_soc_component_driver ark_codec_component_driver = { .probe = ark_codec_probe, .remove = ark_codec_remove, .controls = ark_codec_controls, .num_controls = ARRAY_SIZE(ark_codec_controls), .dapm_widgets = dwc_audio_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(dwc_audio_dapm_widgets), // .dapm_routes = dwc_audio_dapm_routes, // .num_dapm_routes = ARRAY_SIZE(dwc_audio_dapm_routes), }; static const struct regmap_config ark_codec_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = CODEC_REG_RESERVED_3, }; static ssize_t ark_codec_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int val = 0, flag = 0; u8 i = 0, reg, num, value_w; int value_r; struct ark_codec_priv *priv = dev_get_drvdata(dev); val = simple_strtol(buf, NULL, 16); flag = (val >> 16) & 0xFFF; if (flag) { reg = (val >> 8) & 0xFF; value_w = val & 0xFF; printk("\nWrite: start REG:0x%04x,val:0x%04x,count:0x%04x\n", reg, value_w, flag); while (flag--) { //ark_codec_write(ark_codec_component,reg, value_w); codec_reg_write(priv->i2c, reg, value_w); printk("Write 0x%04x to REG:0x%04x\n", value_w, reg); reg++; } } else { reg = (val >> 8) & 0xFF; num = val & 0xFF; printk("\nRead: start REG:0x%04x,count:0x%04x\n", reg, num); do { //value_r = 0; //value_r = ark_codec_read(ark_codec_component,reg); codec_reg_read(priv->i2c, reg, &value_r); printk("REG[0x%04x]: 0x%04x; ", reg, value_r); reg++; i++; if ((i == num) || (i%4 == 0)) printk("\n"); } while (i < num); } return count; } static ssize_t ark_codec_show(struct device *dev, struct device_attribute *attr, char *buf) { printk("echo flag|reg|val > ark_codec\n"); printk("eg read star addres=0x06,count 0x10:echo 0610 >ark_codec\n"); printk("eg write star addres=0x90,value=0x3c,count=4:echo 4903c >ark_codec\n"); //printk("eg write value:0xfe to address:0x06 :echo 106fe > es7243\n"); return 0; } static DEVICE_ATTR(ark_codec, 0644, ark_codec_show, ark_codec_store); static struct attribute *ark_codec_debug_attrs[] = { &dev_attr_ark_codec.attr, NULL, }; static struct attribute_group ark_codec_debug_attr_group = { .name = "ark_codec_debug", .attrs = ark_codec_debug_attrs, }; static int ark_codec_i2c_probe(struct i2c_client *i2c) { struct ark_codec_priv *priv; int ret; priv = devm_kzalloc(&i2c->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; priv->regmap = devm_regmap_init_i2c(i2c, &ark_codec_regmap_config); if (IS_ERR(priv->regmap)) return PTR_ERR(priv->regmap); i2c_set_clientdata(i2c, priv); priv->i2c = i2c; ret = devm_snd_soc_register_component(&i2c->dev, &ark_codec_component_driver, &ark_codec_dai, 1); if (ret) dev_err(&i2c->dev, "Failed to register component: %d\n", ret); #if 1 ret = sysfs_create_group(&i2c->dev.kobj, &ark_codec_debug_attr_group); if (ret) { pr_err("failed to create attr group\n"); } #endif return ret; } static void ark_codec_i2c_remove(struct i2c_client *client) { } static void ark_codec_i2c_shutdown(struct i2c_client *client) { //struct ark_codec_priv *codec = i2c_get_clientdata(client); } static const struct i2c_device_id ark_codec_i2c_id[] = { { "ark-codec", 0 }, { } }; MODULE_DEVICE_TABLE(i2c, ark_codec_i2c_id); static const struct of_device_id ark_codec_of_match[] = { { .compatible = "arkmicro,ark-audio-codec" }, { } }; MODULE_DEVICE_TABLE(of, adc_codec_of_match); static struct i2c_driver ark_codec_i2c_driver = { .driver = { .name = "ark-codec", .of_match_table = ark_codec_of_match, }, .probe = ark_codec_i2c_probe, .remove = ark_codec_i2c_remove, .shutdown = ark_codec_i2c_shutdown, .id_table = ark_codec_i2c_id, }; module_i2c_driver(ark_codec_i2c_driver); MODULE_DESCRIPTION("ARK Codec I2C Driver"); MODULE_AUTHOR("ARK"); MODULE_LICENSE("GPL");