diff options
Diffstat (limited to 'sound/soc/codecs/tlv320aic23.c')
| -rw-r--r-- | sound/soc/codecs/tlv320aic23.c | 338 |
1 files changed, 96 insertions, 242 deletions
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c index e8652b1ae32..686b8b85b95 100644 --- a/sound/soc/codecs/tlv320aic23.c +++ b/sound/soc/codecs/tlv320aic23.c @@ -23,101 +23,57 @@ #include <linux/init.h> #include <linux/delay.h> #include <linux/pm.h> -#include <linux/i2c.h> -#include <linux/platform_device.h> +#include <linux/regmap.h> #include <linux/slab.h> #include <sound/core.h> #include <sound/pcm.h> #include <sound/pcm_params.h> #include <sound/soc.h> -#include <sound/soc-dapm.h> #include <sound/tlv.h> #include <sound/initval.h> #include "tlv320aic23.h" -#define AIC23_VERSION "0.1" - /* * AIC23 register cache */ -static const u16 tlv320aic23_reg[] = { - 0x0097, 0x0097, 0x00F9, 0x00F9, /* 0 */ - 0x001A, 0x0004, 0x0007, 0x0001, /* 4 */ - 0x0020, 0x0000, 0x0000, 0x0000, /* 8 */ - 0x0000, 0x0000, 0x0000, 0x0000, /* 12 */ +static const struct reg_default tlv320aic23_reg[] = { + { 0, 0x0097 }, + { 1, 0x0097 }, + { 2, 0x00F9 }, + { 3, 0x00F9 }, + { 4, 0x001A }, + { 5, 0x0004 }, + { 6, 0x0007 }, + { 7, 0x0001 }, + { 8, 0x0020 }, + { 9, 0x0000 }, }; -/* - * read tlv320aic23 register cache - */ -static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec - *codec, unsigned int reg) -{ - u16 *cache = codec->reg_cache; - if (reg >= ARRAY_SIZE(tlv320aic23_reg)) - return -1; - return cache[reg]; -} - -/* - * write tlv320aic23 register cache - */ -static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec, - u8 reg, u16 value) -{ - u16 *cache = codec->reg_cache; - if (reg >= ARRAY_SIZE(tlv320aic23_reg)) - return; - cache[reg] = value; -} - -/* - * write to the tlv320aic23 register space - */ -static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg, - unsigned int value) -{ +const struct regmap_config tlv320aic23_regmap = { + .reg_bits = 7, + .val_bits = 9, - u8 data[2]; - - /* TLV320AIC23 has 7 bit address and 9 bits of data - * so we need to switch one data bit into reg and rest - * of data into val - */ - - if (reg > 9 && reg != 15) { - printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg); - return -1; - } - - data[0] = (reg << 1) | (value >> 8 & 0x01); - data[1] = value & 0xff; - - tlv320aic23_write_reg_cache(codec, reg, value); - - if (codec->hw_write(codec->control_data, data, 2) == 2) - return 0; - - printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__, - value, reg); - - return -EIO; -} + .max_register = TLV320AIC23_RESET, + .reg_defaults = tlv320aic23_reg, + .num_reg_defaults = ARRAY_SIZE(tlv320aic23_reg), + .cache_type = REGCACHE_RBTREE, +}; +EXPORT_SYMBOL(tlv320aic23_regmap); static const char *rec_src_text[] = { "Line", "Mic" }; static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"}; -static const struct soc_enum rec_src_enum = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(rec_src_enum, + TLV320AIC23_ANLG, 2, rec_src_text); static const struct snd_kcontrol_new tlv320aic23_rec_src_mux_controls = SOC_DAPM_ENUM("Input Select", rec_src_enum); -static const struct soc_enum tlv320aic23_rec_src = - SOC_ENUM_SINGLE(TLV320AIC23_ANLG, 2, 2, rec_src_text); -static const struct soc_enum tlv320aic23_deemph = - SOC_ENUM_SINGLE(TLV320AIC23_DIGT, 1, 4, deemph_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_rec_src, + TLV320AIC23_ANLG, 2, rec_src_text); +static SOC_ENUM_SINGLE_DECL(tlv320aic23_deemph, + TLV320AIC23_DIGT, 1, deemph_text); static const DECLARE_TLV_DB_SCALE(out_gain_tlv, -12100, 100, 0); static const DECLARE_TLV_DB_SCALE(input_gain_tlv, -1725, 75, 0); @@ -126,7 +82,7 @@ static const DECLARE_TLV_DB_SCALE(sidetone_vol_tlv, -1800, 300, 0); static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); u16 val, reg; val = (ucontrol->value.integer.value[0] & 0x07); @@ -140,8 +96,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, */ val = (val >= 4) ? 4 : (3 - val); - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0); - tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6)); + reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0); + snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6)); return 0; } @@ -149,10 +105,10 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol, static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { - struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); u16 val; - val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0); + val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0); val = val >> 6; val = (val >= 4) ? 4 : (3 - val); ucontrol->value.integer.value[0] = val; @@ -160,15 +116,6 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol, } -#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ - SNDRV_CTL_ELEM_ACCESS_READWRITE,\ - .tlv.p = (tlv_array), \ - .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\ - .put = snd_soc_tlv320aic23_put_volsw, \ - .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } - static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL, TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv), @@ -179,8 +126,9 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = { TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv), SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1), SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0), - SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG, - 6, 4, 0, sidetone_vol_tlv), + SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0, + snd_soc_tlv320aic23_get_volsw, + snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv), SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph), }; @@ -213,7 +161,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = { SND_SOC_DAPM_INPUT("MICIN"), }; -static const struct snd_soc_dapm_route intercon[] = { +static const struct snd_soc_dapm_route tlv320aic23_intercon[] = { /* Output Mixer */ {"Output Mixer", "Line Bypass Switch", "Line Input"}, {"Output Mixer", "Playback Switch", "DAC"}, @@ -240,8 +188,7 @@ static const struct snd_soc_dapm_route intercon[] = { /* AIC23 driver data */ struct aic23 { - enum snd_soc_control_type control_type; - void *control_data; + struct regmap *regmap; int mclk; int requested_adc; int requested_dac; @@ -353,7 +300,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac) static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk, u32 *sample_rate_adc, u32 *sample_rate_dac) { - int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE); + int src = snd_soc_read(codec, TLV320AIC23_SRATE); int sr = (src >> 2) & 0x0f; int val = (mclk / bosr_usb_divisor_table[src & 3]); int adc = (val * sr_adc_mult_table[sr]) / SR_MULT; @@ -377,7 +324,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk, __func__, sample_rate_adc, sample_rate_dac); return -EINVAL; } - tlv320aic23_write(codec, TLV320AIC23_SRATE, data); + snd_soc_write(codec, TLV320AIC23_SRATE, data); #ifdef DEBUG { u32 adc, dac; @@ -389,23 +336,11 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk, return 0; } -static int tlv320aic23_add_widgets(struct snd_soc_codec *codec) -{ - snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets, - ARRAY_SIZE(tlv320aic23_dapm_widgets)); - - /* set up audio path interconnects */ - snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); - - return 0; -} - static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; u16 iface_reg; int ret; struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); @@ -427,9 +362,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, if (ret < 0) return ret; - iface_reg = - tlv320aic23_read_reg_cache(codec, - TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); + iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2); + switch (params_format(params)) { case SNDRV_PCM_FORMAT_S16_LE: break; @@ -443,7 +377,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, iface_reg |= (0x03 << 2); break; } - tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); + snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); return 0; } @@ -451,11 +385,10 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream, static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; /* set active */ - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001); return 0; } @@ -463,14 +396,13 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream, static void tlv320aic23_shutdown(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { - struct snd_soc_pcm_runtime *rtd = substream->private_data; - struct snd_soc_codec *codec = rtd->codec; + struct snd_soc_codec *codec = dai->codec; struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); /* deactivate */ - if (!codec->active) { + if (!snd_soc_codec_is_active(codec)) { udelay(50); - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); } if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) aic23->requested_dac = 0; @@ -483,14 +415,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute) struct snd_soc_codec *codec = dai->codec; u16 reg; - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT); + reg = snd_soc_read(codec, TLV320AIC23_DIGT); if (mute) reg |= TLV320AIC23_DACM_MUTE; else reg &= ~TLV320AIC23_DACM_MUTE; - tlv320aic23_write(codec, TLV320AIC23_DIGT, reg); + snd_soc_write(codec, TLV320AIC23_DIGT, reg); return 0; } @@ -501,8 +433,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, struct snd_soc_codec *codec = codec_dai->codec; u16 iface_reg; - iface_reg = - tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03); + iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03); /* set master/slave audio interface */ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -510,6 +441,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, iface_reg |= TLV320AIC23_MS_MASTER; break; case SND_SOC_DAIFMT_CBS_CFS: + iface_reg &= ~TLV320AIC23_MS_MASTER; break; default: return -EINVAL; @@ -536,7 +468,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai, } - tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); + snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg); return 0; } @@ -552,29 +484,29 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai, static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, enum snd_soc_bias_level level) { - u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f; + u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0x17f; switch (level) { case SND_SOC_BIAS_ON: /* vref/mid, osc on, dac unmute */ reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \ TLV320AIC23_DAC_OFF); - tlv320aic23_write(codec, TLV320AIC23_PWR, reg); + snd_soc_write(codec, TLV320AIC23_PWR, reg); break; case SND_SOC_BIAS_PREPARE: break; case SND_SOC_BIAS_STANDBY: /* everything off except vref/vmid, */ - tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \ - TLV320AIC23_CLK_OFF); + snd_soc_write(codec, TLV320AIC23_PWR, + reg | TLV320AIC23_CLK_OFF); break; case SND_SOC_BIAS_OFF: /* everything off, dac mute, inactive */ - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0); - tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0); + snd_soc_write(codec, TLV320AIC23_PWR, 0x1ff); break; } - codec->bias_level = level; + codec->dapm.bias_level = level; return 0; } @@ -582,7 +514,7 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec, #define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE) -static struct snd_soc_dai_ops tlv320aic23_dai_ops = { +static const struct snd_soc_dai_ops tlv320aic23_dai_ops = { .prepare = tlv320aic23_pcm_prepare, .hw_params = tlv320aic23_hw_params, .shutdown = tlv320aic23_shutdown, @@ -608,8 +540,7 @@ static struct snd_soc_dai_driver tlv320aic23_dai = { .ops = &tlv320aic23_dai_ops, }; -static int tlv320aic23_suspend(struct snd_soc_codec *codec, - pm_message_t state) +static int tlv320aic23_suspend(struct snd_soc_codec *codec) { tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF); @@ -618,65 +549,42 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec, static int tlv320aic23_resume(struct snd_soc_codec *codec) { - u16 reg; - - /* Sync reg_cache with the hardware */ - for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) { - u16 val = tlv320aic23_read_reg_cache(codec, reg); - tlv320aic23_write(codec, reg, val); - } + struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); + regcache_mark_dirty(aic23->regmap); + regcache_sync(aic23->regmap); tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; } -static int tlv320aic23_probe(struct snd_soc_codec *codec) +static int tlv320aic23_codec_probe(struct snd_soc_codec *codec) { - struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec); - int reg; - - printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION); - codec->control_data = aic23->control_data; - codec->hw_write = (hw_write_t)i2c_master_send; - codec->hw_read = NULL; - /* Reset codec */ - tlv320aic23_write(codec, TLV320AIC23_RESET, 0); + snd_soc_write(codec, TLV320AIC23_RESET, 0); /* power on device */ tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY); - tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); + snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K); /* Unmute input */ - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL); - tlv320aic23_write(codec, TLV320AIC23_LINVOL, - (reg & (~TLV320AIC23_LIM_MUTED)) | - (TLV320AIC23_LRS_ENABLED)); + snd_soc_update_bits(codec, TLV320AIC23_LINVOL, + TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED); - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL); - tlv320aic23_write(codec, TLV320AIC23_RINVOL, - (reg & (~TLV320AIC23_LIM_MUTED)) | - TLV320AIC23_LRS_ENABLED); + snd_soc_update_bits(codec, TLV320AIC23_RINVOL, + TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED); - reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG); - tlv320aic23_write(codec, TLV320AIC23_ANLG, - (reg) & (~TLV320AIC23_BYPASS_ON) & - (~TLV320AIC23_MICM_MUTED)); + snd_soc_update_bits(codec, TLV320AIC23_ANLG, + TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED, + 0); /* Default output volume */ - tlv320aic23_write(codec, TLV320AIC23_LCHNVOL, - TLV320AIC23_DEFAULT_OUT_VOL & - TLV320AIC23_OUT_VOL_MASK); - tlv320aic23_write(codec, TLV320AIC23_RCHNVOL, - TLV320AIC23_DEFAULT_OUT_VOL & - TLV320AIC23_OUT_VOL_MASK); - - tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1); + snd_soc_write(codec, TLV320AIC23_LCHNVOL, + TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK); + snd_soc_write(codec, TLV320AIC23_RCHNVOL, + TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK); - snd_soc_add_controls(codec, tlv320aic23_snd_controls, - ARRAY_SIZE(tlv320aic23_snd_controls)); - tlv320aic23_add_widgets(codec); + snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1); return 0; } @@ -688,92 +596,38 @@ static int tlv320aic23_remove(struct snd_soc_codec *codec) } static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = { - .reg_cache_size = ARRAY_SIZE(tlv320aic23_reg), - .reg_word_size = sizeof(u16), - .reg_cache_default = tlv320aic23_reg, - .probe = tlv320aic23_probe, + .probe = tlv320aic23_codec_probe, .remove = tlv320aic23_remove, .suspend = tlv320aic23_suspend, .resume = tlv320aic23_resume, - .read = tlv320aic23_read_reg_cache, - .write = tlv320aic23_write, .set_bias_level = tlv320aic23_set_bias_level, + .controls = tlv320aic23_snd_controls, + .num_controls = ARRAY_SIZE(tlv320aic23_snd_controls), + .dapm_widgets = tlv320aic23_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets), + .dapm_routes = tlv320aic23_intercon, + .num_dapm_routes = ARRAY_SIZE(tlv320aic23_intercon), }; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int tlv320aic23_codec_probe(struct i2c_client *i2c, - const struct i2c_device_id *i2c_id) +int tlv320aic23_probe(struct device *dev, struct regmap *regmap) { struct aic23 *aic23; - int ret; - if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EINVAL; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); - aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL); + aic23 = devm_kzalloc(dev, sizeof(struct aic23), GFP_KERNEL); if (aic23 == NULL) return -ENOMEM; - i2c_set_clientdata(i2c, aic23); - aic23->control_data = i2c; - aic23->control_type = SND_SOC_I2C; + aic23->regmap = regmap; - ret = snd_soc_register_codec(&i2c->dev, - &soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1); - if (ret < 0) - kfree(aic23); - return ret; -} -static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c) -{ - snd_soc_unregister_codec(&i2c->dev); - kfree(i2c_get_clientdata(i2c)); - return 0; -} - -static const struct i2c_device_id tlv320aic23_id[] = { - {"tlv320aic23", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, tlv320aic23_id); - -static struct i2c_driver tlv320aic23_i2c_driver = { - .driver = { - .name = "tlv320aic23-codec", - }, - .probe = tlv320aic23_codec_probe, - .remove = __exit_p(tlv320aic23_i2c_remove), - .id_table = tlv320aic23_id, -}; - -#endif + dev_set_drvdata(dev, aic23); -static int __init tlv320aic23_modinit(void) -{ - int ret; -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - ret = i2c_add_driver(&tlv320aic23_i2c_driver); - if (ret != 0) { - printk(KERN_ERR "Failed to register TLV320AIC23 I2C driver: %d\n", - ret); - } -#endif - return ret; -} -module_init(tlv320aic23_modinit); - -static void __exit tlv320aic23_exit(void) -{ -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) - i2c_del_driver(&tlv320aic23_i2c_driver); -#endif + return snd_soc_register_codec(dev, &soc_codec_dev_tlv320aic23, + &tlv320aic23_dai, 1); } -module_exit(tlv320aic23_exit); +EXPORT_SYMBOL(tlv320aic23_probe); MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver"); MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>"); |
