diff --git a/MAINTAINERS b/MAINTAINERS index 5207f08cd39e..56602280b8ba 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14759,11 +14759,6 @@ F: drivers/amlogic/media/common/canvas/canvas_mgr.c F: drivers/amlogic/media/common/vfm/vfm.c F: include/linux/amlogic/media/camera/* -AMLOGIC MESON TL1 PANEL DTS -M: Evoke Zhang -F: arch/arm/boot/dts/amlogic/mesontl1_skt-panel.dtsi -F: arch/arm/boot/dts/amlogic/mesontl1_x301-panel.dtsi - AMLOGIC multimedia M: Pengcheng Chen F: drivers/amlogic/media/common/ge2d/ge2d_dmabuf.c diff --git a/sound/soc/codecs/amlogic/tas5782m.c b/sound/soc/codecs/amlogic/tas5782m.c new file mode 100644 index 000000000000..4befae22451a --- /dev/null +++ b/sound/soc/codecs/amlogic/tas5782m.c @@ -0,0 +1,762 @@ +/* + * sound/soc/codecs/amlogic/tas5782m.c + * + * Copyright (C) 2019 Amlogic, Inc. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tas5782m.h" + +#define DEV_NAME "tas5782m" + +#ifdef CONFIG_HAS_EARLYSUSPEND +#include +static void tas5782m_early_suspend(struct early_suspend *h); +static void tas5782m_late_resume(struct early_suspend *h); +#endif + +#define tas5782m_RATES (SNDRV_PCM_RATE_8000 | \ + SNDRV_PCM_RATE_11025 | \ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_22050 | \ + SNDRV_PCM_RATE_32000 | \ + SNDRV_PCM_RATE_44100 | \ + SNDRV_PCM_RATE_48000) + +#define tas5782m_FORMATS \ + (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \ + SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S20_3BE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \ + SNDRV_PCM_FMTBIT_S32_LE) + +#define TAS5782M_REG_00 (0x00) +#define TAS5782M_REG_7F (0x7F) +#define TAS5782M_REG_28 (0x28) +#define TAS5782M_REG_29 (0x29) +#define TAS5782M_REG_3D (0x3D) +#define TAS5782M_REG_3E (0x3E) + + + +enum BITSIZE_MODE { + BITSIZE_MODE_16BITS = 0, + BITSIZE_MODE_20BITS = 1, + BITSIZE_MODE_24BITS = 2, + BITSIZE_MODE_32BITS = 3, +}; + +/* codec private data */ +struct tas5782m_priv { + struct i2c_client *i2c; + struct regmap *regmap; + struct snd_soc_codec *codec; + struct tas57xx_platform_data *pdata; + struct work_struct work; + + unsigned int work_mode; + unsigned int chip_offset; + + /*Platform provided EQ configuration */ + int num_eq_conf_texts; + const char **eq_conf_texts; + int eq_cfg; + struct soc_enum eq_conf_enum; + unsigned char Ch1_vol; + unsigned char Ch2_vol; + unsigned char master_vol; + unsigned int mclk; + unsigned int EQ_enum_value; + unsigned int DRC_enum_value; +#ifdef CONFIG_HAS_EARLYSUSPEND + struct early_suspend early_suspend; +#endif +}; + +static int g_sample_bitsize = 32; + +static int tas5782m_ch1_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xff; + uinfo->value.integer.step = 1; + + return 0; +} + +static int tas5782m_ch2_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->access = SNDRV_CTL_ELEM_ACCESS_TLV_READ + | SNDRV_CTL_ELEM_ACCESS_READWRITE; + uinfo->count = 1; + + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0xff; + uinfo->value.integer.step = 1; + + return 0; +} + + +static int tas5782m_ch1_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch1_vol; + + return 0; +} + +static int tas5782m_ch2_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + ucontrol->value.integer.value[0] = tas5782m->Ch2_vol; + + return 0; +} + + +static void tas5782m_set_volume(struct snd_soc_codec *codec, + int value, int ch_num) +{ + unsigned char buf[2]; + int write_count = 0; + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + if (value < 0) + value = 0; + if (value > 255) + value = 255; + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = (ch_num == 0) ? TAS5782M_REG_3D : TAS5782M_REG_3E; + buf[1] = value; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + +} + +static int tas5782m_ch1_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch1_vol = value; + tas5782m_set_volume(codec, value, 0); + + return 0; +} + +static int tas5782m_ch2_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol); + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int value; + + value = ucontrol->value.integer.value[0]; + tas5782m->Ch2_vol = value; + tas5782m_set_volume(codec, value, 1); + + return 0; +} + + +static const struct snd_kcontrol_new tas5782m_snd_controls[] = { + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch1 Volume", + .info = tas5782m_ch1_vol_info, + .get = tas5782m_ch1_vol_get, + .put = tas5782m_ch1_vol_put, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Ch2 Volume", + .info = tas5782m_ch2_vol_info, + .get = tas5782m_ch2_vol_get, + .put = tas5782m_ch2_vol_put, + } +}; + +static int tas5782m_set_dai_sysclk(struct snd_soc_dai *codec_dai, + int clk_id, unsigned int freq, int dir) +{ + return 0; +} + +static int tas5782m_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) +{ + + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { + case SND_SOC_DAIFMT_CBS_CFS: + break; + default: + return 0;//-EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + case SND_SOC_DAIFMT_RIGHT_J: + case SND_SOC_DAIFMT_LEFT_J: + break; + default: + return 0;//-EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_NB_IF: + break; + default: + return 0;//-EINVAL; + } + + return 0; +} + +static int tas5782m_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + unsigned int rate; + + rate = params_rate(params); + + pr_debug("rate: %u\n", rate); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S24_LE: + case SNDRV_PCM_FORMAT_S24_BE: + pr_debug("24bit\n"); + /* fall through */ + case SNDRV_PCM_FORMAT_S32_LE: + case SNDRV_PCM_FORMAT_S20_3LE: + case SNDRV_PCM_FORMAT_S20_3BE: + pr_debug("20bit\n"); + + break; + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: + pr_debug("16bit\n"); + + break; + default: + return -EINVAL; + } + + return 0; +} + +static int tas5782m_set_bias_level(struct snd_soc_codec *codec, + enum snd_soc_bias_level level) +{ + pr_debug("level = %d\n", level); + + switch (level) { + case SND_SOC_BIAS_ON: + break; + + case SND_SOC_BIAS_PREPARE: + /* Full power on */ + break; + + case SND_SOC_BIAS_STANDBY: + break; + + case SND_SOC_BIAS_OFF: + /* The chip runs through the power down sequence for us. */ + break; + } + codec->component.dapm.bias_level = level; + + return 0; +} + +static const struct snd_soc_dai_ops tas5782m_dai_ops = { + .hw_params = tas5782m_hw_params, + .set_sysclk = tas5782m_set_dai_sysclk, + .set_fmt = tas5782m_set_dai_fmt, +}; + +static struct snd_soc_dai_driver tas5782m_dai = { + .name = DEV_NAME, + .playback = { + .stream_name = "HIFI Playback", + .channels_min = 2, + .channels_max = 8, + .rates = tas5782m_RATES, + .formats = tas5782m_FORMATS, + }, + .ops = &tas5782m_dai_ops, +}; + + +static int reset_tas5782m_GPIO(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + struct tas57xx_platform_data *pdata = tas5782m->pdata; + int ret = 0; + + if (pdata->reset_pin < 0) + return 0; + + ret = devm_gpio_request_one(codec->dev, pdata->reset_pin, + GPIOF_OUT_INIT_LOW, "tas5782m-reset-pin"); + + if (ret < 0) { + pr_err("failed!!! devm_gpio_request_one = %d!\n", ret); + return -1; + } + + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + udelay(1000); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_LOW); + udelay(1000); + gpio_direction_output(pdata->reset_pin, GPIOF_OUT_INIT_HIGH); + msleep(20); + + return 0; +} + +static int tas5782m_init_i2s_tdm_mode(struct snd_soc_codec *codec, int bit_size) +{ + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + int work_mod = tas5782m->work_mode; + + int tdm_aofs = 0; + unsigned char buf[8] = {0}; + int write_count = 0; + enum BITSIZE_MODE bit_value = BITSIZE_MODE_32BITS; + + write_count = 2; + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + if (bit_size == 16) + bit_value = BITSIZE_MODE_16BITS; + else if (bit_size == 20) + bit_value = BITSIZE_MODE_20BITS; + else if (bit_size == 24) + bit_value = BITSIZE_MODE_24BITS; + else if (bit_size == 32) + bit_value = BITSIZE_MODE_32BITS; + + buf[0] = TAS5782M_REG_28, buf[1] = (work_mod << 4) | bit_value; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + } else { + pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x data:0x%x\n", + __func__, __LINE__, tas5782m->i2c->addr, + tas5782m->chip_offset, buf[0], buf[1]); + } + + if (work_mod == WORK_MODE_TDM) { + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_7F, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + buf[0] = TAS5782M_REG_00, buf[1] = 0x00; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + + tdm_aofs = bit_size * 2 * (tas5782m->chip_offset - 1); + + buf[0] = TAS5782M_REG_29, buf[1] = tdm_aofs; + write_count = 2; + if (write_count != i2c_master_send(tas5782m->i2c, buf, + write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + } else { + pr_debug("%s %d reg:0x%x, chip_offset:%d reg_off:0x%x", + __func__, __LINE__, tas5782m->i2c->addr, + tas5782m->chip_offset, buf[0]); + pr_debug("tdm_aofs:0x%x SCLKS\n", tdm_aofs); + } + } + + return 0; +} + +static void tas5782m_init_func(struct work_struct *p_work) +{ + struct tas5782m_priv *tas5782m; + struct snd_soc_codec *codec; + struct i2c_client *i2c; + int i = 0, j = 0, k = 0; + int value_count; + unsigned char buf[64] = {0}; + int write_count = 0; + int data_row = 0; + + tas5782m = container_of( + p_work, struct tas5782m_priv, work); + + codec = tas5782m->codec; + + reset_tas5782m_GPIO(codec); + + //init register + tas5782m = snd_soc_codec_get_drvdata(codec); + dev_info(codec->dev, "tas5782m_init id=%d\n", tas5782m->chip_offset); + + i2c = tas5782m->i2c; + value_count = ARRAY_SIZE(tas5782m_reg_defaults); + for (i = 0; i < value_count;) { + if (tas5782m_reg_defaults[i].reg == CFG_META_BURST) { + if (tas5782m_reg_defaults[i].def == 2) { + data_row = 1; + write_count = + tas5782m_reg_defaults[i].def; + } else { + data_row = + (tas5782m_reg_defaults[i].def + + 2) >> 1; + write_count = + tas5782m_reg_defaults[i].def + + 1; + } + i++; + + j = 0, k = 0; + for (k = 0; k < data_row; k++) { + buf[j++] = + tas5782m_reg_defaults[i+k].reg; + buf[j++] = + tas5782m_reg_defaults[i+k].def; + } + + i += data_row; + + //dump_buf(buf, k); + if (write_count != + i2c_master_send(i2c, buf, + write_count)) { + pr_err("%s %d !!!!! i2c_master_send error !!!!!\n", + __func__, __LINE__); + break; + } + } else { + i++; + pr_info("%s %d warning: register value error!\n", + __func__, __LINE__); + } + } + + tas5782m_init_i2s_tdm_mode(codec, g_sample_bitsize); +} + +static int tas5782m_probe(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m; + +#ifdef CONFIG_HAS_EARLYSUSPEND + tas5782m->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN; + tas5782m->early_suspend.suspend = tas5782m_early_suspend; + tas5782m->early_suspend.resume = tas5782m_late_resume; + tas5782m->early_suspend.param = codec; + register_early_suspend(&(tas5782m->early_suspend)); +#endif + + tas5782m = snd_soc_codec_get_drvdata(codec); + tas5782m->codec = codec; + + INIT_WORK(&tas5782m->work, tas5782m_init_func); + schedule_work(&tas5782m->work); + + return 0; +} + +static int tas5782m_remove(struct snd_soc_codec *codec) +{ + struct tas5782m_priv *tas5782m; + +#ifdef CONFIG_HAS_EARLYSUSPEND + struct tas5782m_priv *tas5782m = snd_soc_codec_get_drvdata(codec); + + unregister_early_suspend(&(tas5782m->early_suspend)); +#endif + tas5782m = snd_soc_codec_get_drvdata(codec); + + cancel_work_sync(&tas5782m->work); + + return 0; +} + +#ifdef CONFIG_PM +static int tas5782m_suspend(struct snd_soc_codec *codec) +{ + struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev); + + dev_info(codec->dev, "tas5782m_suspend!\n"); + + if (pdata && pdata->suspend_func) + pdata->suspend_func(); + + return 0; +} + +static int tas5782m_resume(struct snd_soc_codec *codec) +{ + struct tas57xx_platform_data *pdata = dev_get_platdata(codec->dev); + struct tas5782m_priv *tas5782m; + + dev_info(codec->dev, "tas5782m_resume!\n"); + + if (pdata && pdata->resume_func) + pdata->resume_func(); + + tas5782m = snd_soc_codec_get_drvdata(codec); + tas5782m->codec = codec; + + INIT_WORK(&tas5782m->work, tas5782m_init_func); + schedule_work(&tas5782m->work); + + + return 0; +} +#endif + +#ifdef CONFIG_HAS_EARLYSUSPEND +static void tas5782m_early_suspend(struct early_suspend *h) +{ +} + +static void tas5782m_late_resume(struct early_suspend *h) +{ +} +#endif + +static const struct snd_soc_dapm_widget tas5782m_dapm_widgets[] = { + SND_SOC_DAPM_DAC("DAC", "HIFI Playback", SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_codec_driver soc_codec_dev_tas5782m = { + .probe = tas5782m_probe, + .remove = tas5782m_remove, +#ifdef CONFIG_PM + .suspend = tas5782m_suspend, + .resume = tas5782m_resume, +#endif + .set_bias_level = tas5782m_set_bias_level, + .component_driver = { + .controls = tas5782m_snd_controls, + .num_controls = ARRAY_SIZE(tas5782m_snd_controls), + .dapm_widgets = tas5782m_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(tas5782m_dapm_widgets), + } +}; + +/* + *static const struct regmap_config tas5782m_regmap = { + * .reg_bits = 8, + * .val_bits = 8, + * + * .max_register = tas5782m_REGISTER_COUNT, + * .reg_defaults = tas5782m_reg_defaults, + * .num_reg_defaults = + * sizeof(tas5782m_reg_defaults)/sizeof(tas5782m_reg_defaults[0]), + * .cache_type = REGCACHE_RBTREE, + *}; + */ + +static int tas5782m_parse_dts(struct tas5782m_priv *tas5782m, + struct device_node *np) +{ + int ret = 0; + int reset_pin = -1; + + reset_pin = of_get_named_gpio(np, "reset_pin", 0); + if (reset_pin < 0) { + pr_err("%s fail to get reset pin from dts!\n", __func__); + ret = -1; + } else { + pr_debug("%s pdata->reset_pin = %d!\n", __func__, reset_pin); + } + tas5782m->pdata->reset_pin = reset_pin; + + ret = of_property_read_u32(np, "work_mode", &tas5782m->work_mode); + pr_debug("tas5782m->work_mode:%d(%s)!\n", tas5782m->work_mode, + (tas5782m->work_mode == WORK_MODE_I2S)?"i2s":"tdm"); + + ret = of_property_read_u32(np, "chip_offset", &tas5782m->chip_offset); + pr_debug("tas5782m->chip_offset:%d!\n", tas5782m->chip_offset); + + return ret; +} + +static int tas5782m_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct tas5782m_priv *tas5782m; + struct tas57xx_platform_data *pdata; + int ret; + const char *codec_name = NULL; + + pr_debug("i2c->addr=0x%x\n", i2c->addr); + + tas5782m = devm_kzalloc(&i2c->dev, + sizeof(struct tas5782m_priv), GFP_KERNEL); + if (!tas5782m) + return -ENOMEM; + + + tas5782m->i2c = i2c; + /* + * tas5782m->regmap = devm_regmap_init_i2c(i2c, &tas5782m_regmap); + * if (IS_ERR(tas5782m->regmap)) { + * ret = PTR_ERR(tas5782m->regmap); + * dev_err(&i2c->dev, + * "Failed to allocate register map: %d\n", ret); + * return ret; + * } + */ + pdata = devm_kzalloc(&i2c->dev, + sizeof(struct tas57xx_platform_data), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + tas5782m->pdata = pdata; + + tas5782m_parse_dts(tas5782m, i2c->dev.of_node); + + if (of_property_read_string(i2c->dev.of_node, + "codec_name", &codec_name)) { + pr_info("no codec name\n"); + ret = -1; + } + pr_debug("aux name = %s\n", codec_name); + if (codec_name) + dev_set_name(&i2c->dev, "%s", codec_name); + + i2c_set_clientdata(i2c, tas5782m); + + ret = snd_soc_register_codec(&i2c->dev, + &soc_codec_dev_tas5782m, &tas5782m_dai, 1); + if (ret != 0) + dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret); + + return ret; +} + +static int tas5782m_i2c_remove(struct i2c_client *client) +{ + snd_soc_unregister_codec(&client->dev); + + return 0; +} + +static const struct i2c_device_id tas5782m_i2c_id[] = { + { "tas5782m", 0 }, + {} +}; + +static const struct of_device_id tas5782m_of_id[] = { + {.compatible = "ti, tas5782m",}, + { /* senitel */ } +}; +MODULE_DEVICE_TABLE(of, tas5782m_of_id); + +static struct i2c_driver tas5782m_i2c_driver = { + .driver = { + .name = DEV_NAME, + .of_match_table = tas5782m_of_id, + .owner = THIS_MODULE, + }, + .probe = tas5782m_i2c_probe, + .remove = tas5782m_i2c_remove, + .id_table = tas5782m_i2c_id, +}; + +module_i2c_driver(tas5782m_i2c_driver); + + +MODULE_DESCRIPTION("ASoC tas5782m driver"); +MODULE_AUTHOR("AML MM team"); +MODULE_LICENSE("GPL");