1c942fddfSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
24fa89346SDaniel Mack /*
34fa89346SDaniel Mack * TAS5086 ASoC codec driver
44fa89346SDaniel Mack *
54fa89346SDaniel Mack * Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
64fa89346SDaniel Mack *
74fa89346SDaniel Mack * TODO:
84fa89346SDaniel Mack * - implement DAPM and input muxing
94fa89346SDaniel Mack * - implement modulation limit
104fa89346SDaniel Mack * - implement non-default PWM start
114fa89346SDaniel Mack *
124fa89346SDaniel Mack * Note that this chip has a very unusual register layout, specifically
134fa89346SDaniel Mack * because the registers are of unequal size, and multi-byte registers
144fa89346SDaniel Mack * require bulk writes to take effect. Regmap does not support that kind
154fa89346SDaniel Mack * of devices.
164fa89346SDaniel Mack *
174fa89346SDaniel Mack * Currently, the driver does not touch any of the registers >= 0x20, so
184fa89346SDaniel Mack * it doesn't matter because the entire map can be accessed as 8-bit
194fa89346SDaniel Mack * array. In case more features will be added in the future
204fa89346SDaniel Mack * that require access to higher registers, the entire regmap H/W I/O
214fa89346SDaniel Mack * routines have to be open-coded.
224fa89346SDaniel Mack */
234fa89346SDaniel Mack
244fa89346SDaniel Mack #include <linux/module.h>
254fa89346SDaniel Mack #include <linux/slab.h>
264fa89346SDaniel Mack #include <linux/delay.h>
274fa89346SDaniel Mack #include <linux/gpio.h>
284fa89346SDaniel Mack #include <linux/i2c.h>
294fa89346SDaniel Mack #include <linux/regmap.h>
30c46af312SDaniel Mack #include <linux/regulator/consumer.h>
314fa89346SDaniel Mack #include <linux/spi/spi.h>
32285d00c1SSachin Kamat #include <linux/of.h>
334fa89346SDaniel Mack #include <linux/of_device.h>
344fa89346SDaniel Mack #include <linux/of_gpio.h>
354fa89346SDaniel Mack #include <sound/pcm.h>
364fa89346SDaniel Mack #include <sound/pcm_params.h>
374fa89346SDaniel Mack #include <sound/soc.h>
384fa89346SDaniel Mack #include <sound/tlv.h>
394fa89346SDaniel Mack #include <sound/tas5086.h>
404fa89346SDaniel Mack
414fa89346SDaniel Mack #define TAS5086_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
424fa89346SDaniel Mack SNDRV_PCM_FMTBIT_S20_3LE | \
434fa89346SDaniel Mack SNDRV_PCM_FMTBIT_S24_3LE)
444fa89346SDaniel Mack
454fa89346SDaniel Mack #define TAS5086_PCM_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
464fa89346SDaniel Mack SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | \
474fa89346SDaniel Mack SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 | \
484fa89346SDaniel Mack SNDRV_PCM_RATE_192000)
494fa89346SDaniel Mack
504fa89346SDaniel Mack /*
514fa89346SDaniel Mack * TAS5086 registers
524fa89346SDaniel Mack */
534fa89346SDaniel Mack #define TAS5086_CLOCK_CONTROL 0x00 /* Clock control register */
544fa89346SDaniel Mack #define TAS5086_CLOCK_RATE(val) (val << 5)
554fa89346SDaniel Mack #define TAS5086_CLOCK_RATE_MASK (0x7 << 5)
564fa89346SDaniel Mack #define TAS5086_CLOCK_RATIO(val) (val << 2)
574fa89346SDaniel Mack #define TAS5086_CLOCK_RATIO_MASK (0x7 << 2)
584fa89346SDaniel Mack #define TAS5086_CLOCK_SCLK_RATIO_48 (1 << 1)
594fa89346SDaniel Mack #define TAS5086_CLOCK_VALID (1 << 0)
604fa89346SDaniel Mack
614fa89346SDaniel Mack #define TAS5086_DEEMPH_MASK 0x03
624fa89346SDaniel Mack #define TAS5086_SOFT_MUTE_ALL 0x3f
634fa89346SDaniel Mack
644fa89346SDaniel Mack #define TAS5086_DEV_ID 0x01 /* Device ID register */
654fa89346SDaniel Mack #define TAS5086_ERROR_STATUS 0x02 /* Error status register */
664fa89346SDaniel Mack #define TAS5086_SYS_CONTROL_1 0x03 /* System control register 1 */
674fa89346SDaniel Mack #define TAS5086_SERIAL_DATA_IF 0x04 /* Serial data interface register */
684fa89346SDaniel Mack #define TAS5086_SYS_CONTROL_2 0x05 /* System control register 2 */
694fa89346SDaniel Mack #define TAS5086_SOFT_MUTE 0x06 /* Soft mute register */
704fa89346SDaniel Mack #define TAS5086_MASTER_VOL 0x07 /* Master volume */
714fa89346SDaniel Mack #define TAS5086_CHANNEL_VOL(X) (0x08 + (X)) /* Channel 1-6 volume */
724fa89346SDaniel Mack #define TAS5086_VOLUME_CONTROL 0x09 /* Volume control register */
734fa89346SDaniel Mack #define TAS5086_MOD_LIMIT 0x10 /* Modulation limit register */
744fa89346SDaniel Mack #define TAS5086_PWM_START 0x18 /* PWM start register */
754fa89346SDaniel Mack #define TAS5086_SURROUND 0x19 /* Surround register */
764fa89346SDaniel Mack #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */
774fa89346SDaniel Mack #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */
784fa89346SDaniel Mack #define TAS5086_BKNDERR 0x1c
798892d479SDaniel Mack #define TAS5086_INPUT_MUX 0x20
808892d479SDaniel Mack #define TAS5086_PWM_OUTPUT_MUX 0x25
818892d479SDaniel Mack
828892d479SDaniel Mack #define TAS5086_MAX_REGISTER TAS5086_PWM_OUTPUT_MUX
834fa89346SDaniel Mack
8479b23b56SDaniel Mack #define TAS5086_PWM_START_MIDZ_FOR_START_1 (1 << 7)
8579b23b56SDaniel Mack #define TAS5086_PWM_START_MIDZ_FOR_START_2 (1 << 6)
8679b23b56SDaniel Mack #define TAS5086_PWM_START_CHANNEL_MASK (0x3f)
8779b23b56SDaniel Mack
884fa89346SDaniel Mack /*
894fa89346SDaniel Mack * Default TAS5086 power-up configuration
904fa89346SDaniel Mack */
914fa89346SDaniel Mack static const struct reg_default tas5086_reg_defaults[] = {
924fa89346SDaniel Mack { 0x00, 0x6c },
934fa89346SDaniel Mack { 0x01, 0x03 },
944fa89346SDaniel Mack { 0x02, 0x00 },
954fa89346SDaniel Mack { 0x03, 0xa0 },
964fa89346SDaniel Mack { 0x04, 0x05 },
974fa89346SDaniel Mack { 0x05, 0x60 },
984fa89346SDaniel Mack { 0x06, 0x00 },
994fa89346SDaniel Mack { 0x07, 0xff },
1004fa89346SDaniel Mack { 0x08, 0x30 },
1014fa89346SDaniel Mack { 0x09, 0x30 },
1024fa89346SDaniel Mack { 0x0a, 0x30 },
1034fa89346SDaniel Mack { 0x0b, 0x30 },
1044fa89346SDaniel Mack { 0x0c, 0x30 },
1054fa89346SDaniel Mack { 0x0d, 0x30 },
1064fa89346SDaniel Mack { 0x0e, 0xb1 },
1074fa89346SDaniel Mack { 0x0f, 0x00 },
1084fa89346SDaniel Mack { 0x10, 0x02 },
1094fa89346SDaniel Mack { 0x11, 0x00 },
1104fa89346SDaniel Mack { 0x12, 0x00 },
1114fa89346SDaniel Mack { 0x13, 0x00 },
1124fa89346SDaniel Mack { 0x14, 0x00 },
1134fa89346SDaniel Mack { 0x15, 0x00 },
1144fa89346SDaniel Mack { 0x16, 0x00 },
1154fa89346SDaniel Mack { 0x17, 0x00 },
1164fa89346SDaniel Mack { 0x18, 0x3f },
1174fa89346SDaniel Mack { 0x19, 0x00 },
1184fa89346SDaniel Mack { 0x1a, 0x18 },
1194fa89346SDaniel Mack { 0x1b, 0x82 },
1204fa89346SDaniel Mack { 0x1c, 0x05 },
1214fa89346SDaniel Mack };
1224fa89346SDaniel Mack
tas5086_register_size(struct device * dev,unsigned int reg)1236b36d370SDaniel Mack static int tas5086_register_size(struct device *dev, unsigned int reg)
1246b36d370SDaniel Mack {
1256b36d370SDaniel Mack switch (reg) {
1269f24dc87SDaniel Mack case TAS5086_CLOCK_CONTROL ... TAS5086_BKNDERR:
1276b36d370SDaniel Mack return 1;
1288892d479SDaniel Mack case TAS5086_INPUT_MUX:
1298892d479SDaniel Mack case TAS5086_PWM_OUTPUT_MUX:
1308892d479SDaniel Mack return 4;
1316b36d370SDaniel Mack }
1326b36d370SDaniel Mack
1336b36d370SDaniel Mack dev_err(dev, "Unsupported register address: %d\n", reg);
1346b36d370SDaniel Mack return 0;
1356b36d370SDaniel Mack }
1366b36d370SDaniel Mack
tas5086_accessible_reg(struct device * dev,unsigned int reg)1374fa89346SDaniel Mack static bool tas5086_accessible_reg(struct device *dev, unsigned int reg)
1384fa89346SDaniel Mack {
1398892d479SDaniel Mack switch (reg) {
1408892d479SDaniel Mack case 0x0f:
1418892d479SDaniel Mack case 0x11 ... 0x17:
1428892d479SDaniel Mack case 0x1d ... 0x1f:
1438892d479SDaniel Mack return false;
1448892d479SDaniel Mack default:
1458892d479SDaniel Mack return true;
1468892d479SDaniel Mack }
1474fa89346SDaniel Mack }
1484fa89346SDaniel Mack
tas5086_volatile_reg(struct device * dev,unsigned int reg)1494fa89346SDaniel Mack static bool tas5086_volatile_reg(struct device *dev, unsigned int reg)
1504fa89346SDaniel Mack {
1514fa89346SDaniel Mack switch (reg) {
1524fa89346SDaniel Mack case TAS5086_DEV_ID:
1534fa89346SDaniel Mack case TAS5086_ERROR_STATUS:
1544fa89346SDaniel Mack return true;
1554fa89346SDaniel Mack }
1564fa89346SDaniel Mack
1574fa89346SDaniel Mack return false;
1584fa89346SDaniel Mack }
1594fa89346SDaniel Mack
tas5086_writeable_reg(struct device * dev,unsigned int reg)1604fa89346SDaniel Mack static bool tas5086_writeable_reg(struct device *dev, unsigned int reg)
1614fa89346SDaniel Mack {
1624fa89346SDaniel Mack return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID);
1634fa89346SDaniel Mack }
1644fa89346SDaniel Mack
tas5086_reg_write(void * context,unsigned int reg,unsigned int value)1656b36d370SDaniel Mack static int tas5086_reg_write(void *context, unsigned int reg,
1666b36d370SDaniel Mack unsigned int value)
1676b36d370SDaniel Mack {
1686b36d370SDaniel Mack struct i2c_client *client = context;
1696b36d370SDaniel Mack unsigned int i, size;
1706b36d370SDaniel Mack uint8_t buf[5];
1716b36d370SDaniel Mack int ret;
1726b36d370SDaniel Mack
1736b36d370SDaniel Mack size = tas5086_register_size(&client->dev, reg);
1746b36d370SDaniel Mack if (size == 0)
1756b36d370SDaniel Mack return -EINVAL;
1766b36d370SDaniel Mack
1776b36d370SDaniel Mack buf[0] = reg;
1786b36d370SDaniel Mack
1796b36d370SDaniel Mack for (i = size; i >= 1; --i) {
1806b36d370SDaniel Mack buf[i] = value;
1816b36d370SDaniel Mack value >>= 8;
1826b36d370SDaniel Mack }
1836b36d370SDaniel Mack
1846b36d370SDaniel Mack ret = i2c_master_send(client, buf, size + 1);
1856b36d370SDaniel Mack if (ret == size + 1)
1866b36d370SDaniel Mack return 0;
1876b36d370SDaniel Mack else if (ret < 0)
1886b36d370SDaniel Mack return ret;
1896b36d370SDaniel Mack else
1906b36d370SDaniel Mack return -EIO;
1916b36d370SDaniel Mack }
1926b36d370SDaniel Mack
tas5086_reg_read(void * context,unsigned int reg,unsigned int * value)1936b36d370SDaniel Mack static int tas5086_reg_read(void *context, unsigned int reg,
1946b36d370SDaniel Mack unsigned int *value)
1956b36d370SDaniel Mack {
1966b36d370SDaniel Mack struct i2c_client *client = context;
1976b36d370SDaniel Mack uint8_t send_buf, recv_buf[4];
1986b36d370SDaniel Mack struct i2c_msg msgs[2];
1996b36d370SDaniel Mack unsigned int size;
2006b36d370SDaniel Mack unsigned int i;
2016b36d370SDaniel Mack int ret;
2026b36d370SDaniel Mack
2036b36d370SDaniel Mack size = tas5086_register_size(&client->dev, reg);
2046b36d370SDaniel Mack if (size == 0)
2056b36d370SDaniel Mack return -EINVAL;
2066b36d370SDaniel Mack
2076b36d370SDaniel Mack send_buf = reg;
2086b36d370SDaniel Mack
2096b36d370SDaniel Mack msgs[0].addr = client->addr;
2106b36d370SDaniel Mack msgs[0].len = sizeof(send_buf);
2116b36d370SDaniel Mack msgs[0].buf = &send_buf;
2126b36d370SDaniel Mack msgs[0].flags = 0;
2136b36d370SDaniel Mack
2146b36d370SDaniel Mack msgs[1].addr = client->addr;
2156b36d370SDaniel Mack msgs[1].len = size;
2166b36d370SDaniel Mack msgs[1].buf = recv_buf;
2176b36d370SDaniel Mack msgs[1].flags = I2C_M_RD;
2186b36d370SDaniel Mack
2196b36d370SDaniel Mack ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
2206b36d370SDaniel Mack if (ret < 0)
2216b36d370SDaniel Mack return ret;
2226b36d370SDaniel Mack else if (ret != ARRAY_SIZE(msgs))
2236b36d370SDaniel Mack return -EIO;
2246b36d370SDaniel Mack
2256b36d370SDaniel Mack *value = 0;
2266b36d370SDaniel Mack
2276b36d370SDaniel Mack for (i = 0; i < size; i++) {
2286b36d370SDaniel Mack *value <<= 8;
2296b36d370SDaniel Mack *value |= recv_buf[i];
2306b36d370SDaniel Mack }
2316b36d370SDaniel Mack
2326b36d370SDaniel Mack return 0;
2336b36d370SDaniel Mack }
2346b36d370SDaniel Mack
235c46af312SDaniel Mack static const char * const supply_names[] = {
236c46af312SDaniel Mack "dvdd", "avdd"
237c46af312SDaniel Mack };
238c46af312SDaniel Mack
2394fa89346SDaniel Mack struct tas5086_private {
2404fa89346SDaniel Mack struct regmap *regmap;
2414fa89346SDaniel Mack unsigned int mclk, sclk;
2424fa89346SDaniel Mack unsigned int format;
2434fa89346SDaniel Mack bool deemph;
244648c5382SDaniel Mack unsigned int charge_period;
245648c5382SDaniel Mack unsigned int pwm_start_mid_z;
2464fa89346SDaniel Mack /* Current sample rate for de-emphasis control */
2474fa89346SDaniel Mack int rate;
2484fa89346SDaniel Mack /* GPIO driving Reset pin, if any */
2494fa89346SDaniel Mack int gpio_nreset;
250c46af312SDaniel Mack struct regulator_bulk_data supplies[ARRAY_SIZE(supply_names)];
2514fa89346SDaniel Mack };
2524fa89346SDaniel Mack
2534fa89346SDaniel Mack static int tas5086_deemph[] = { 0, 32000, 44100, 48000 };
2544fa89346SDaniel Mack
tas5086_set_deemph(struct snd_soc_component * component)255459bc024SKuninori Morimoto static int tas5086_set_deemph(struct snd_soc_component *component)
2564fa89346SDaniel Mack {
257459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
2584fa89346SDaniel Mack int i, val = 0;
2594fa89346SDaniel Mack
2609425e9d8SAxel Lin if (priv->deemph) {
2619425e9d8SAxel Lin for (i = 0; i < ARRAY_SIZE(tas5086_deemph); i++) {
2629425e9d8SAxel Lin if (tas5086_deemph[i] == priv->rate) {
2634fa89346SDaniel Mack val = i;
2649425e9d8SAxel Lin break;
2659425e9d8SAxel Lin }
2669425e9d8SAxel Lin }
2679425e9d8SAxel Lin }
2684fa89346SDaniel Mack
2694fa89346SDaniel Mack return regmap_update_bits(priv->regmap, TAS5086_SYS_CONTROL_1,
2704fa89346SDaniel Mack TAS5086_DEEMPH_MASK, val);
2714fa89346SDaniel Mack }
2724fa89346SDaniel Mack
tas5086_get_deemph(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2734fa89346SDaniel Mack static int tas5086_get_deemph(struct snd_kcontrol *kcontrol,
2744fa89346SDaniel Mack struct snd_ctl_elem_value *ucontrol)
2754fa89346SDaniel Mack {
276459bc024SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
277459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
2784fa89346SDaniel Mack
2794c523ef6STakashi Iwai ucontrol->value.integer.value[0] = priv->deemph;
2804fa89346SDaniel Mack
2814fa89346SDaniel Mack return 0;
2824fa89346SDaniel Mack }
2834fa89346SDaniel Mack
tas5086_put_deemph(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)2844fa89346SDaniel Mack static int tas5086_put_deemph(struct snd_kcontrol *kcontrol,
2854fa89346SDaniel Mack struct snd_ctl_elem_value *ucontrol)
2864fa89346SDaniel Mack {
287459bc024SKuninori Morimoto struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol);
288459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
2894fa89346SDaniel Mack
2904c523ef6STakashi Iwai priv->deemph = ucontrol->value.integer.value[0];
2914fa89346SDaniel Mack
292459bc024SKuninori Morimoto return tas5086_set_deemph(component);
2934fa89346SDaniel Mack }
2944fa89346SDaniel Mack
2954fa89346SDaniel Mack
tas5086_set_dai_sysclk(struct snd_soc_dai * codec_dai,int clk_id,unsigned int freq,int dir)2964fa89346SDaniel Mack static int tas5086_set_dai_sysclk(struct snd_soc_dai *codec_dai,
2974fa89346SDaniel Mack int clk_id, unsigned int freq, int dir)
2984fa89346SDaniel Mack {
299459bc024SKuninori Morimoto struct snd_soc_component *component = codec_dai->component;
300459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
3014fa89346SDaniel Mack
3024fa89346SDaniel Mack switch (clk_id) {
3034fa89346SDaniel Mack case TAS5086_CLK_IDX_MCLK:
3044fa89346SDaniel Mack priv->mclk = freq;
3054fa89346SDaniel Mack break;
3064fa89346SDaniel Mack case TAS5086_CLK_IDX_SCLK:
3074fa89346SDaniel Mack priv->sclk = freq;
3084fa89346SDaniel Mack break;
3094fa89346SDaniel Mack }
3104fa89346SDaniel Mack
3114fa89346SDaniel Mack return 0;
3124fa89346SDaniel Mack }
3134fa89346SDaniel Mack
tas5086_set_dai_fmt(struct snd_soc_dai * codec_dai,unsigned int format)3144fa89346SDaniel Mack static int tas5086_set_dai_fmt(struct snd_soc_dai *codec_dai,
3154fa89346SDaniel Mack unsigned int format)
3164fa89346SDaniel Mack {
317459bc024SKuninori Morimoto struct snd_soc_component *component = codec_dai->component;
318459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
3194fa89346SDaniel Mack
3204fa89346SDaniel Mack /* The TAS5086 can only be slave to all clocks */
3217c5c399fSMark Brown if ((format & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) != SND_SOC_DAIFMT_CBC_CFC) {
322459bc024SKuninori Morimoto dev_err(component->dev, "Invalid clocking mode\n");
3234fa89346SDaniel Mack return -EINVAL;
3244fa89346SDaniel Mack }
3254fa89346SDaniel Mack
3264fa89346SDaniel Mack /* we need to refer to the data format from hw_params() */
3274fa89346SDaniel Mack priv->format = format;
3284fa89346SDaniel Mack
3294fa89346SDaniel Mack return 0;
3304fa89346SDaniel Mack }
3314fa89346SDaniel Mack
3324fa89346SDaniel Mack static const int tas5086_sample_rates[] = {
3334fa89346SDaniel Mack 32000, 38000, 44100, 48000, 88200, 96000, 176400, 192000
3344fa89346SDaniel Mack };
3354fa89346SDaniel Mack
3364fa89346SDaniel Mack static const int tas5086_ratios[] = {
3374fa89346SDaniel Mack 64, 128, 192, 256, 384, 512
3384fa89346SDaniel Mack };
3394fa89346SDaniel Mack
index_in_array(const int * array,int len,int needle)3404fa89346SDaniel Mack static int index_in_array(const int *array, int len, int needle)
3414fa89346SDaniel Mack {
3424fa89346SDaniel Mack int i;
3434fa89346SDaniel Mack
3444fa89346SDaniel Mack for (i = 0; i < len; i++)
3454fa89346SDaniel Mack if (array[i] == needle)
3464fa89346SDaniel Mack return i;
3474fa89346SDaniel Mack
3484fa89346SDaniel Mack return -ENOENT;
3494fa89346SDaniel Mack }
3504fa89346SDaniel Mack
tas5086_hw_params(struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct snd_soc_dai * dai)3514fa89346SDaniel Mack static int tas5086_hw_params(struct snd_pcm_substream *substream,
3524fa89346SDaniel Mack struct snd_pcm_hw_params *params,
3534fa89346SDaniel Mack struct snd_soc_dai *dai)
3544fa89346SDaniel Mack {
355459bc024SKuninori Morimoto struct snd_soc_component *component = dai->component;
356459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
35728dbd161SDan Carpenter int val;
3584fa89346SDaniel Mack int ret;
3594fa89346SDaniel Mack
3604fa89346SDaniel Mack priv->rate = params_rate(params);
3614fa89346SDaniel Mack
3624fa89346SDaniel Mack /* Look up the sample rate and refer to the offset in the list */
3634fa89346SDaniel Mack val = index_in_array(tas5086_sample_rates,
3644fa89346SDaniel Mack ARRAY_SIZE(tas5086_sample_rates), priv->rate);
3654fa89346SDaniel Mack
3664fa89346SDaniel Mack if (val < 0) {
367459bc024SKuninori Morimoto dev_err(component->dev, "Invalid sample rate\n");
3684fa89346SDaniel Mack return -EINVAL;
3694fa89346SDaniel Mack }
3704fa89346SDaniel Mack
3714fa89346SDaniel Mack ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
3724fa89346SDaniel Mack TAS5086_CLOCK_RATE_MASK,
3734fa89346SDaniel Mack TAS5086_CLOCK_RATE(val));
3744fa89346SDaniel Mack if (ret < 0)
3754fa89346SDaniel Mack return ret;
3764fa89346SDaniel Mack
3774fa89346SDaniel Mack /* MCLK / Fs ratio */
3784fa89346SDaniel Mack val = index_in_array(tas5086_ratios, ARRAY_SIZE(tas5086_ratios),
3794fa89346SDaniel Mack priv->mclk / priv->rate);
3804fa89346SDaniel Mack if (val < 0) {
381459bc024SKuninori Morimoto dev_err(component->dev, "Invalid MCLK / Fs ratio\n");
3824fa89346SDaniel Mack return -EINVAL;
3834fa89346SDaniel Mack }
3844fa89346SDaniel Mack
3854fa89346SDaniel Mack ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
3864fa89346SDaniel Mack TAS5086_CLOCK_RATIO_MASK,
3874fa89346SDaniel Mack TAS5086_CLOCK_RATIO(val));
3884fa89346SDaniel Mack if (ret < 0)
3894fa89346SDaniel Mack return ret;
3904fa89346SDaniel Mack
3914fa89346SDaniel Mack
3924fa89346SDaniel Mack ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
3934fa89346SDaniel Mack TAS5086_CLOCK_SCLK_RATIO_48,
3944fa89346SDaniel Mack (priv->sclk == 48 * priv->rate) ?
3954fa89346SDaniel Mack TAS5086_CLOCK_SCLK_RATIO_48 : 0);
3964fa89346SDaniel Mack if (ret < 0)
3974fa89346SDaniel Mack return ret;
3984fa89346SDaniel Mack
3994fa89346SDaniel Mack /*
4004fa89346SDaniel Mack * The chip has a very unituitive register mapping and muxes information
4014fa89346SDaniel Mack * about data format and sample depth into the same register, but not on
4024fa89346SDaniel Mack * a logical bit-boundary. Hence, we have to refer to the format passed
4034fa89346SDaniel Mack * in the set_dai_fmt() callback and set up everything from here.
4044fa89346SDaniel Mack *
4054fa89346SDaniel Mack * First, determine the 'base' value, using the format ...
4064fa89346SDaniel Mack */
4074fa89346SDaniel Mack switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
4084fa89346SDaniel Mack case SND_SOC_DAIFMT_RIGHT_J:
4094fa89346SDaniel Mack val = 0x00;
4104fa89346SDaniel Mack break;
4114fa89346SDaniel Mack case SND_SOC_DAIFMT_I2S:
4124fa89346SDaniel Mack val = 0x03;
4134fa89346SDaniel Mack break;
4144fa89346SDaniel Mack case SND_SOC_DAIFMT_LEFT_J:
4154fa89346SDaniel Mack val = 0x06;
4164fa89346SDaniel Mack break;
4174fa89346SDaniel Mack default:
418459bc024SKuninori Morimoto dev_err(component->dev, "Invalid DAI format\n");
4194fa89346SDaniel Mack return -EINVAL;
4204fa89346SDaniel Mack }
4214fa89346SDaniel Mack
4224fa89346SDaniel Mack /* ... then add the offset for the sample bit depth. */
423c665330cSMark Brown switch (params_width(params)) {
424c665330cSMark Brown case 16:
4254fa89346SDaniel Mack val += 0;
4264fa89346SDaniel Mack break;
427c665330cSMark Brown case 20:
4284fa89346SDaniel Mack val += 1;
4294fa89346SDaniel Mack break;
430c665330cSMark Brown case 24:
4314fa89346SDaniel Mack val += 2;
4324fa89346SDaniel Mack break;
4334fa89346SDaniel Mack default:
434459bc024SKuninori Morimoto dev_err(component->dev, "Invalid bit width\n");
4354fa89346SDaniel Mack return -EINVAL;
4361d198f26SJoe Perches }
4374fa89346SDaniel Mack
4384fa89346SDaniel Mack ret = regmap_write(priv->regmap, TAS5086_SERIAL_DATA_IF, val);
4394fa89346SDaniel Mack if (ret < 0)
4404fa89346SDaniel Mack return ret;
4414fa89346SDaniel Mack
4424fa89346SDaniel Mack /* clock is considered valid now */
4434fa89346SDaniel Mack ret = regmap_update_bits(priv->regmap, TAS5086_CLOCK_CONTROL,
4444fa89346SDaniel Mack TAS5086_CLOCK_VALID, TAS5086_CLOCK_VALID);
4454fa89346SDaniel Mack if (ret < 0)
4464fa89346SDaniel Mack return ret;
4474fa89346SDaniel Mack
448459bc024SKuninori Morimoto return tas5086_set_deemph(component);
4494fa89346SDaniel Mack }
4504fa89346SDaniel Mack
tas5086_mute_stream(struct snd_soc_dai * dai,int mute,int stream)4514fa89346SDaniel Mack static int tas5086_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
4524fa89346SDaniel Mack {
453459bc024SKuninori Morimoto struct snd_soc_component *component = dai->component;
454459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
4554fa89346SDaniel Mack unsigned int val = 0;
4564fa89346SDaniel Mack
4574fa89346SDaniel Mack if (mute)
4584fa89346SDaniel Mack val = TAS5086_SOFT_MUTE_ALL;
4594fa89346SDaniel Mack
4604fa89346SDaniel Mack return regmap_write(priv->regmap, TAS5086_SOFT_MUTE, val);
4614fa89346SDaniel Mack }
4624fa89346SDaniel Mack
tas5086_reset(struct tas5086_private * priv)463d5fd3cccSDaniel Mack static void tas5086_reset(struct tas5086_private *priv)
464d5fd3cccSDaniel Mack {
465d5fd3cccSDaniel Mack if (gpio_is_valid(priv->gpio_nreset)) {
466d5fd3cccSDaniel Mack /* Reset codec - minimum assertion time is 400ns */
467d5fd3cccSDaniel Mack gpio_direction_output(priv->gpio_nreset, 0);
468d5fd3cccSDaniel Mack udelay(1);
469d5fd3cccSDaniel Mack gpio_set_value(priv->gpio_nreset, 1);
470d5fd3cccSDaniel Mack
471d5fd3cccSDaniel Mack /* Codec needs ~15ms to wake up */
472d5fd3cccSDaniel Mack msleep(15);
473d5fd3cccSDaniel Mack }
474d5fd3cccSDaniel Mack }
475d5fd3cccSDaniel Mack
476d5fd3cccSDaniel Mack /* charge period values in microseconds */
477d5fd3cccSDaniel Mack static const int tas5086_charge_period[] = {
478d5fd3cccSDaniel Mack 13000, 16900, 23400, 31200, 41600, 54600, 72800, 96200,
479d5fd3cccSDaniel Mack 130000, 156000, 234000, 312000, 416000, 546000, 728000, 962000,
480d5fd3cccSDaniel Mack 1300000, 169000, 2340000, 3120000, 4160000, 5460000, 7280000, 9620000,
481d5fd3cccSDaniel Mack };
482d5fd3cccSDaniel Mack
tas5086_init(struct device * dev,struct tas5086_private * priv)483d5fd3cccSDaniel Mack static int tas5086_init(struct device *dev, struct tas5086_private *priv)
484d5fd3cccSDaniel Mack {
485d5fd3cccSDaniel Mack int ret, i;
486d5fd3cccSDaniel Mack
487d5fd3cccSDaniel Mack /*
488d5fd3cccSDaniel Mack * If any of the channels is configured to start in Mid-Z mode,
489d5fd3cccSDaniel Mack * configure 'part 1' of the PWM starts to use Mid-Z, and tell
49085131d94SRandy Dunlap * all configured mid-z channels to start under 'part 1'.
491d5fd3cccSDaniel Mack */
492d5fd3cccSDaniel Mack if (priv->pwm_start_mid_z)
493d5fd3cccSDaniel Mack regmap_write(priv->regmap, TAS5086_PWM_START,
494d5fd3cccSDaniel Mack TAS5086_PWM_START_MIDZ_FOR_START_1 |
495d5fd3cccSDaniel Mack priv->pwm_start_mid_z);
496d5fd3cccSDaniel Mack
497d5fd3cccSDaniel Mack /* lookup and set split-capacitor charge period */
498d5fd3cccSDaniel Mack if (priv->charge_period == 0) {
499d5fd3cccSDaniel Mack regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0);
500d5fd3cccSDaniel Mack } else {
501d5fd3cccSDaniel Mack i = index_in_array(tas5086_charge_period,
502d5fd3cccSDaniel Mack ARRAY_SIZE(tas5086_charge_period),
503d5fd3cccSDaniel Mack priv->charge_period);
504d5fd3cccSDaniel Mack if (i >= 0)
505d5fd3cccSDaniel Mack regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE,
506d5fd3cccSDaniel Mack i + 0x08);
507d5fd3cccSDaniel Mack else
508d5fd3cccSDaniel Mack dev_warn(dev,
509d5fd3cccSDaniel Mack "Invalid split-cap charge period of %d ns.\n",
510d5fd3cccSDaniel Mack priv->charge_period);
511d5fd3cccSDaniel Mack }
512d5fd3cccSDaniel Mack
513d5fd3cccSDaniel Mack /* enable factory trim */
514d5fd3cccSDaniel Mack ret = regmap_write(priv->regmap, TAS5086_OSC_TRIM, 0x00);
515d5fd3cccSDaniel Mack if (ret < 0)
516d5fd3cccSDaniel Mack return ret;
517d5fd3cccSDaniel Mack
518d5fd3cccSDaniel Mack /* start all channels */
519d5fd3cccSDaniel Mack ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x20);
520d5fd3cccSDaniel Mack if (ret < 0)
521d5fd3cccSDaniel Mack return ret;
522d5fd3cccSDaniel Mack
523d5fd3cccSDaniel Mack /* mute all channels for now */
524d5fd3cccSDaniel Mack ret = regmap_write(priv->regmap, TAS5086_SOFT_MUTE,
525d5fd3cccSDaniel Mack TAS5086_SOFT_MUTE_ALL);
526d5fd3cccSDaniel Mack if (ret < 0)
527d5fd3cccSDaniel Mack return ret;
528d5fd3cccSDaniel Mack
529d5fd3cccSDaniel Mack return 0;
530d5fd3cccSDaniel Mack }
531d5fd3cccSDaniel Mack
5324fa89346SDaniel Mack /* TAS5086 controls */
5334fa89346SDaniel Mack static const DECLARE_TLV_DB_SCALE(tas5086_dac_tlv, -10350, 50, 1);
5344fa89346SDaniel Mack
5354fa89346SDaniel Mack static const struct snd_kcontrol_new tas5086_controls[] = {
5364fa89346SDaniel Mack SOC_SINGLE_TLV("Master Playback Volume", TAS5086_MASTER_VOL,
5374fa89346SDaniel Mack 0, 0xff, 1, tas5086_dac_tlv),
5384fa89346SDaniel Mack SOC_DOUBLE_R_TLV("Channel 1/2 Playback Volume",
5394fa89346SDaniel Mack TAS5086_CHANNEL_VOL(0), TAS5086_CHANNEL_VOL(1),
5404fa89346SDaniel Mack 0, 0xff, 1, tas5086_dac_tlv),
5414fa89346SDaniel Mack SOC_DOUBLE_R_TLV("Channel 3/4 Playback Volume",
5424fa89346SDaniel Mack TAS5086_CHANNEL_VOL(2), TAS5086_CHANNEL_VOL(3),
5434fa89346SDaniel Mack 0, 0xff, 1, tas5086_dac_tlv),
5444fa89346SDaniel Mack SOC_DOUBLE_R_TLV("Channel 5/6 Playback Volume",
5454fa89346SDaniel Mack TAS5086_CHANNEL_VOL(4), TAS5086_CHANNEL_VOL(5),
5464fa89346SDaniel Mack 0, 0xff, 1, tas5086_dac_tlv),
5474fa89346SDaniel Mack SOC_SINGLE_BOOL_EXT("De-emphasis Switch", 0,
5484fa89346SDaniel Mack tas5086_get_deemph, tas5086_put_deemph),
5494fa89346SDaniel Mack };
5504fa89346SDaniel Mack
55118710acdSDaniel Mack /* Input mux controls */
55218710acdSDaniel Mack static const char *tas5086_dapm_sdin_texts[] =
55318710acdSDaniel Mack {
55418710acdSDaniel Mack "SDIN1-L", "SDIN1-R", "SDIN2-L", "SDIN2-R",
55518710acdSDaniel Mack "SDIN3-L", "SDIN3-R", "Ground (0)", "nc"
55618710acdSDaniel Mack };
55718710acdSDaniel Mack
55818710acdSDaniel Mack static const struct soc_enum tas5086_dapm_input_mux_enum[] = {
55918710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 20, 8, tas5086_dapm_sdin_texts),
56018710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 16, 8, tas5086_dapm_sdin_texts),
56118710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 12, 8, tas5086_dapm_sdin_texts),
56218710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 8, 8, tas5086_dapm_sdin_texts),
56318710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 4, 8, tas5086_dapm_sdin_texts),
56418710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 0, 8, tas5086_dapm_sdin_texts),
56518710acdSDaniel Mack };
56618710acdSDaniel Mack
56718710acdSDaniel Mack static const struct snd_kcontrol_new tas5086_dapm_input_mux_controls[] = {
56818710acdSDaniel Mack SOC_DAPM_ENUM("Channel 1 input", tas5086_dapm_input_mux_enum[0]),
56918710acdSDaniel Mack SOC_DAPM_ENUM("Channel 2 input", tas5086_dapm_input_mux_enum[1]),
57018710acdSDaniel Mack SOC_DAPM_ENUM("Channel 3 input", tas5086_dapm_input_mux_enum[2]),
57118710acdSDaniel Mack SOC_DAPM_ENUM("Channel 4 input", tas5086_dapm_input_mux_enum[3]),
57218710acdSDaniel Mack SOC_DAPM_ENUM("Channel 5 input", tas5086_dapm_input_mux_enum[4]),
57318710acdSDaniel Mack SOC_DAPM_ENUM("Channel 6 input", tas5086_dapm_input_mux_enum[5]),
57418710acdSDaniel Mack };
57518710acdSDaniel Mack
57618710acdSDaniel Mack /* Output mux controls */
57718710acdSDaniel Mack static const char *tas5086_dapm_channel_texts[] =
57818710acdSDaniel Mack { "Channel 1 Mux", "Channel 2 Mux", "Channel 3 Mux",
57918710acdSDaniel Mack "Channel 4 Mux", "Channel 5 Mux", "Channel 6 Mux" };
58018710acdSDaniel Mack
58118710acdSDaniel Mack static const struct soc_enum tas5086_dapm_output_mux_enum[] = {
58218710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 20, 6, tas5086_dapm_channel_texts),
58318710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 16, 6, tas5086_dapm_channel_texts),
58418710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 12, 6, tas5086_dapm_channel_texts),
58518710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 8, 6, tas5086_dapm_channel_texts),
58618710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 4, 6, tas5086_dapm_channel_texts),
58718710acdSDaniel Mack SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 0, 6, tas5086_dapm_channel_texts),
58818710acdSDaniel Mack };
58918710acdSDaniel Mack
59018710acdSDaniel Mack static const struct snd_kcontrol_new tas5086_dapm_output_mux_controls[] = {
59118710acdSDaniel Mack SOC_DAPM_ENUM("PWM1 Output", tas5086_dapm_output_mux_enum[0]),
59218710acdSDaniel Mack SOC_DAPM_ENUM("PWM2 Output", tas5086_dapm_output_mux_enum[1]),
59318710acdSDaniel Mack SOC_DAPM_ENUM("PWM3 Output", tas5086_dapm_output_mux_enum[2]),
59418710acdSDaniel Mack SOC_DAPM_ENUM("PWM4 Output", tas5086_dapm_output_mux_enum[3]),
59518710acdSDaniel Mack SOC_DAPM_ENUM("PWM5 Output", tas5086_dapm_output_mux_enum[4]),
59618710acdSDaniel Mack SOC_DAPM_ENUM("PWM6 Output", tas5086_dapm_output_mux_enum[5]),
59718710acdSDaniel Mack };
59818710acdSDaniel Mack
59918710acdSDaniel Mack static const struct snd_soc_dapm_widget tas5086_dapm_widgets[] = {
60018710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN1-L"),
60118710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN1-R"),
60218710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN2-L"),
60318710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN2-R"),
60418710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN3-L"),
60518710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN3-R"),
60618710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN4-L"),
60718710acdSDaniel Mack SND_SOC_DAPM_INPUT("SDIN4-R"),
60818710acdSDaniel Mack
60918710acdSDaniel Mack SND_SOC_DAPM_OUTPUT("PWM1"),
61018710acdSDaniel Mack SND_SOC_DAPM_OUTPUT("PWM2"),
61118710acdSDaniel Mack SND_SOC_DAPM_OUTPUT("PWM3"),
61218710acdSDaniel Mack SND_SOC_DAPM_OUTPUT("PWM4"),
61318710acdSDaniel Mack SND_SOC_DAPM_OUTPUT("PWM5"),
61418710acdSDaniel Mack SND_SOC_DAPM_OUTPUT("PWM6"),
61518710acdSDaniel Mack
61618710acdSDaniel Mack SND_SOC_DAPM_MUX("Channel 1 Mux", SND_SOC_NOPM, 0, 0,
61718710acdSDaniel Mack &tas5086_dapm_input_mux_controls[0]),
61818710acdSDaniel Mack SND_SOC_DAPM_MUX("Channel 2 Mux", SND_SOC_NOPM, 0, 0,
61918710acdSDaniel Mack &tas5086_dapm_input_mux_controls[1]),
62018710acdSDaniel Mack SND_SOC_DAPM_MUX("Channel 3 Mux", SND_SOC_NOPM, 0, 0,
62118710acdSDaniel Mack &tas5086_dapm_input_mux_controls[2]),
62218710acdSDaniel Mack SND_SOC_DAPM_MUX("Channel 4 Mux", SND_SOC_NOPM, 0, 0,
62318710acdSDaniel Mack &tas5086_dapm_input_mux_controls[3]),
62418710acdSDaniel Mack SND_SOC_DAPM_MUX("Channel 5 Mux", SND_SOC_NOPM, 0, 0,
62518710acdSDaniel Mack &tas5086_dapm_input_mux_controls[4]),
62618710acdSDaniel Mack SND_SOC_DAPM_MUX("Channel 6 Mux", SND_SOC_NOPM, 0, 0,
62718710acdSDaniel Mack &tas5086_dapm_input_mux_controls[5]),
62818710acdSDaniel Mack
62918710acdSDaniel Mack SND_SOC_DAPM_MUX("PWM1 Mux", SND_SOC_NOPM, 0, 0,
63018710acdSDaniel Mack &tas5086_dapm_output_mux_controls[0]),
63118710acdSDaniel Mack SND_SOC_DAPM_MUX("PWM2 Mux", SND_SOC_NOPM, 0, 0,
63218710acdSDaniel Mack &tas5086_dapm_output_mux_controls[1]),
63318710acdSDaniel Mack SND_SOC_DAPM_MUX("PWM3 Mux", SND_SOC_NOPM, 0, 0,
63418710acdSDaniel Mack &tas5086_dapm_output_mux_controls[2]),
63518710acdSDaniel Mack SND_SOC_DAPM_MUX("PWM4 Mux", SND_SOC_NOPM, 0, 0,
63618710acdSDaniel Mack &tas5086_dapm_output_mux_controls[3]),
63718710acdSDaniel Mack SND_SOC_DAPM_MUX("PWM5 Mux", SND_SOC_NOPM, 0, 0,
63818710acdSDaniel Mack &tas5086_dapm_output_mux_controls[4]),
63918710acdSDaniel Mack SND_SOC_DAPM_MUX("PWM6 Mux", SND_SOC_NOPM, 0, 0,
64018710acdSDaniel Mack &tas5086_dapm_output_mux_controls[5]),
64118710acdSDaniel Mack };
64218710acdSDaniel Mack
64318710acdSDaniel Mack static const struct snd_soc_dapm_route tas5086_dapm_routes[] = {
64418710acdSDaniel Mack /* SDIN inputs -> channel muxes */
64518710acdSDaniel Mack { "Channel 1 Mux", "SDIN1-L", "SDIN1-L" },
64618710acdSDaniel Mack { "Channel 1 Mux", "SDIN1-R", "SDIN1-R" },
64718710acdSDaniel Mack { "Channel 1 Mux", "SDIN2-L", "SDIN2-L" },
64818710acdSDaniel Mack { "Channel 1 Mux", "SDIN2-R", "SDIN2-R" },
64918710acdSDaniel Mack { "Channel 1 Mux", "SDIN3-L", "SDIN3-L" },
65018710acdSDaniel Mack { "Channel 1 Mux", "SDIN3-R", "SDIN3-R" },
65118710acdSDaniel Mack
65218710acdSDaniel Mack { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" },
65318710acdSDaniel Mack { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" },
65418710acdSDaniel Mack { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" },
65518710acdSDaniel Mack { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" },
65618710acdSDaniel Mack { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" },
65718710acdSDaniel Mack { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" },
65818710acdSDaniel Mack
65918710acdSDaniel Mack { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" },
66018710acdSDaniel Mack { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" },
66118710acdSDaniel Mack { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" },
66218710acdSDaniel Mack { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" },
66318710acdSDaniel Mack { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" },
66418710acdSDaniel Mack { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" },
66518710acdSDaniel Mack
66618710acdSDaniel Mack { "Channel 3 Mux", "SDIN1-L", "SDIN1-L" },
66718710acdSDaniel Mack { "Channel 3 Mux", "SDIN1-R", "SDIN1-R" },
66818710acdSDaniel Mack { "Channel 3 Mux", "SDIN2-L", "SDIN2-L" },
66918710acdSDaniel Mack { "Channel 3 Mux", "SDIN2-R", "SDIN2-R" },
67018710acdSDaniel Mack { "Channel 3 Mux", "SDIN3-L", "SDIN3-L" },
67118710acdSDaniel Mack { "Channel 3 Mux", "SDIN3-R", "SDIN3-R" },
67218710acdSDaniel Mack
67318710acdSDaniel Mack { "Channel 4 Mux", "SDIN1-L", "SDIN1-L" },
67418710acdSDaniel Mack { "Channel 4 Mux", "SDIN1-R", "SDIN1-R" },
67518710acdSDaniel Mack { "Channel 4 Mux", "SDIN2-L", "SDIN2-L" },
67618710acdSDaniel Mack { "Channel 4 Mux", "SDIN2-R", "SDIN2-R" },
67718710acdSDaniel Mack { "Channel 4 Mux", "SDIN3-L", "SDIN3-L" },
67818710acdSDaniel Mack { "Channel 4 Mux", "SDIN3-R", "SDIN3-R" },
67918710acdSDaniel Mack
68018710acdSDaniel Mack { "Channel 5 Mux", "SDIN1-L", "SDIN1-L" },
68118710acdSDaniel Mack { "Channel 5 Mux", "SDIN1-R", "SDIN1-R" },
68218710acdSDaniel Mack { "Channel 5 Mux", "SDIN2-L", "SDIN2-L" },
68318710acdSDaniel Mack { "Channel 5 Mux", "SDIN2-R", "SDIN2-R" },
68418710acdSDaniel Mack { "Channel 5 Mux", "SDIN3-L", "SDIN3-L" },
68518710acdSDaniel Mack { "Channel 5 Mux", "SDIN3-R", "SDIN3-R" },
68618710acdSDaniel Mack
68718710acdSDaniel Mack { "Channel 6 Mux", "SDIN1-L", "SDIN1-L" },
68818710acdSDaniel Mack { "Channel 6 Mux", "SDIN1-R", "SDIN1-R" },
68918710acdSDaniel Mack { "Channel 6 Mux", "SDIN2-L", "SDIN2-L" },
69018710acdSDaniel Mack { "Channel 6 Mux", "SDIN2-R", "SDIN2-R" },
69118710acdSDaniel Mack { "Channel 6 Mux", "SDIN3-L", "SDIN3-L" },
69218710acdSDaniel Mack { "Channel 6 Mux", "SDIN3-R", "SDIN3-R" },
69318710acdSDaniel Mack
69418710acdSDaniel Mack /* Channel muxes -> PWM muxes */
69518710acdSDaniel Mack { "PWM1 Mux", "Channel 1 Mux", "Channel 1 Mux" },
69618710acdSDaniel Mack { "PWM2 Mux", "Channel 1 Mux", "Channel 1 Mux" },
69718710acdSDaniel Mack { "PWM3 Mux", "Channel 1 Mux", "Channel 1 Mux" },
69818710acdSDaniel Mack { "PWM4 Mux", "Channel 1 Mux", "Channel 1 Mux" },
69918710acdSDaniel Mack { "PWM5 Mux", "Channel 1 Mux", "Channel 1 Mux" },
70018710acdSDaniel Mack { "PWM6 Mux", "Channel 1 Mux", "Channel 1 Mux" },
70118710acdSDaniel Mack
70218710acdSDaniel Mack { "PWM1 Mux", "Channel 2 Mux", "Channel 2 Mux" },
70318710acdSDaniel Mack { "PWM2 Mux", "Channel 2 Mux", "Channel 2 Mux" },
70418710acdSDaniel Mack { "PWM3 Mux", "Channel 2 Mux", "Channel 2 Mux" },
70518710acdSDaniel Mack { "PWM4 Mux", "Channel 2 Mux", "Channel 2 Mux" },
70618710acdSDaniel Mack { "PWM5 Mux", "Channel 2 Mux", "Channel 2 Mux" },
70718710acdSDaniel Mack { "PWM6 Mux", "Channel 2 Mux", "Channel 2 Mux" },
70818710acdSDaniel Mack
70918710acdSDaniel Mack { "PWM1 Mux", "Channel 3 Mux", "Channel 3 Mux" },
71018710acdSDaniel Mack { "PWM2 Mux", "Channel 3 Mux", "Channel 3 Mux" },
71118710acdSDaniel Mack { "PWM3 Mux", "Channel 3 Mux", "Channel 3 Mux" },
71218710acdSDaniel Mack { "PWM4 Mux", "Channel 3 Mux", "Channel 3 Mux" },
71318710acdSDaniel Mack { "PWM5 Mux", "Channel 3 Mux", "Channel 3 Mux" },
71418710acdSDaniel Mack { "PWM6 Mux", "Channel 3 Mux", "Channel 3 Mux" },
71518710acdSDaniel Mack
71618710acdSDaniel Mack { "PWM1 Mux", "Channel 4 Mux", "Channel 4 Mux" },
71718710acdSDaniel Mack { "PWM2 Mux", "Channel 4 Mux", "Channel 4 Mux" },
71818710acdSDaniel Mack { "PWM3 Mux", "Channel 4 Mux", "Channel 4 Mux" },
71918710acdSDaniel Mack { "PWM4 Mux", "Channel 4 Mux", "Channel 4 Mux" },
72018710acdSDaniel Mack { "PWM5 Mux", "Channel 4 Mux", "Channel 4 Mux" },
72118710acdSDaniel Mack { "PWM6 Mux", "Channel 4 Mux", "Channel 4 Mux" },
72218710acdSDaniel Mack
72318710acdSDaniel Mack { "PWM1 Mux", "Channel 5 Mux", "Channel 5 Mux" },
72418710acdSDaniel Mack { "PWM2 Mux", "Channel 5 Mux", "Channel 5 Mux" },
72518710acdSDaniel Mack { "PWM3 Mux", "Channel 5 Mux", "Channel 5 Mux" },
72618710acdSDaniel Mack { "PWM4 Mux", "Channel 5 Mux", "Channel 5 Mux" },
72718710acdSDaniel Mack { "PWM5 Mux", "Channel 5 Mux", "Channel 5 Mux" },
72818710acdSDaniel Mack { "PWM6 Mux", "Channel 5 Mux", "Channel 5 Mux" },
72918710acdSDaniel Mack
73018710acdSDaniel Mack { "PWM1 Mux", "Channel 6 Mux", "Channel 6 Mux" },
73118710acdSDaniel Mack { "PWM2 Mux", "Channel 6 Mux", "Channel 6 Mux" },
73218710acdSDaniel Mack { "PWM3 Mux", "Channel 6 Mux", "Channel 6 Mux" },
73318710acdSDaniel Mack { "PWM4 Mux", "Channel 6 Mux", "Channel 6 Mux" },
73418710acdSDaniel Mack { "PWM5 Mux", "Channel 6 Mux", "Channel 6 Mux" },
73518710acdSDaniel Mack { "PWM6 Mux", "Channel 6 Mux", "Channel 6 Mux" },
73618710acdSDaniel Mack
73718710acdSDaniel Mack /* The PWM muxes are directly connected to the PWM outputs */
73818710acdSDaniel Mack { "PWM1", NULL, "PWM1 Mux" },
73918710acdSDaniel Mack { "PWM2", NULL, "PWM2 Mux" },
74018710acdSDaniel Mack { "PWM3", NULL, "PWM3 Mux" },
74118710acdSDaniel Mack { "PWM4", NULL, "PWM4 Mux" },
74218710acdSDaniel Mack { "PWM5", NULL, "PWM5 Mux" },
74318710acdSDaniel Mack { "PWM6", NULL, "PWM6 Mux" },
74418710acdSDaniel Mack
74518710acdSDaniel Mack };
74618710acdSDaniel Mack
7474fa89346SDaniel Mack static const struct snd_soc_dai_ops tas5086_dai_ops = {
7484fa89346SDaniel Mack .hw_params = tas5086_hw_params,
7494fa89346SDaniel Mack .set_sysclk = tas5086_set_dai_sysclk,
7504fa89346SDaniel Mack .set_fmt = tas5086_set_dai_fmt,
7514fa89346SDaniel Mack .mute_stream = tas5086_mute_stream,
7524fa89346SDaniel Mack };
7534fa89346SDaniel Mack
7544fa89346SDaniel Mack static struct snd_soc_dai_driver tas5086_dai = {
7554fa89346SDaniel Mack .name = "tas5086-hifi",
7564fa89346SDaniel Mack .playback = {
7574fa89346SDaniel Mack .stream_name = "Playback",
7584fa89346SDaniel Mack .channels_min = 2,
7594fa89346SDaniel Mack .channels_max = 6,
7604fa89346SDaniel Mack .rates = TAS5086_PCM_RATES,
7614fa89346SDaniel Mack .formats = TAS5086_PCM_FORMATS,
7624fa89346SDaniel Mack },
7634fa89346SDaniel Mack .ops = &tas5086_dai_ops,
7644fa89346SDaniel Mack };
7654fa89346SDaniel Mack
7664fa89346SDaniel Mack #ifdef CONFIG_PM
tas5086_soc_suspend(struct snd_soc_component * component)767459bc024SKuninori Morimoto static int tas5086_soc_suspend(struct snd_soc_component *component)
76825c84cc1SDaniel Mack {
769459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
77025c84cc1SDaniel Mack int ret;
77125c84cc1SDaniel Mack
77225c84cc1SDaniel Mack /* Shut down all channels */
77325c84cc1SDaniel Mack ret = regmap_write(priv->regmap, TAS5086_SYS_CONTROL_2, 0x60);
77425c84cc1SDaniel Mack if (ret < 0)
77525c84cc1SDaniel Mack return ret;
77625c84cc1SDaniel Mack
777c46af312SDaniel Mack regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
778c46af312SDaniel Mack
77925c84cc1SDaniel Mack return 0;
78025c84cc1SDaniel Mack }
78125c84cc1SDaniel Mack
tas5086_soc_resume(struct snd_soc_component * component)782459bc024SKuninori Morimoto static int tas5086_soc_resume(struct snd_soc_component *component)
7834fa89346SDaniel Mack {
784459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
78525c84cc1SDaniel Mack int ret;
7864fa89346SDaniel Mack
787c46af312SDaniel Mack ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
788c46af312SDaniel Mack if (ret < 0)
789c46af312SDaniel Mack return ret;
790c46af312SDaniel Mack
79125c84cc1SDaniel Mack tas5086_reset(priv);
79225c84cc1SDaniel Mack regcache_mark_dirty(priv->regmap);
79325c84cc1SDaniel Mack
794459bc024SKuninori Morimoto ret = tas5086_init(component->dev, priv);
79525c84cc1SDaniel Mack if (ret < 0)
79625c84cc1SDaniel Mack return ret;
79725c84cc1SDaniel Mack
79825c84cc1SDaniel Mack ret = regcache_sync(priv->regmap);
79925c84cc1SDaniel Mack if (ret < 0)
80025c84cc1SDaniel Mack return ret;
80125c84cc1SDaniel Mack
80225c84cc1SDaniel Mack return 0;
8034fa89346SDaniel Mack }
8044fa89346SDaniel Mack #else
80525c84cc1SDaniel Mack #define tas5086_soc_suspend NULL
8064fa89346SDaniel Mack #define tas5086_soc_resume NULL
8074fa89346SDaniel Mack #endif /* CONFIG_PM */
8084fa89346SDaniel Mack
8094fa89346SDaniel Mack #ifdef CONFIG_OF
8104fa89346SDaniel Mack static const struct of_device_id tas5086_dt_ids[] = {
8114fa89346SDaniel Mack { .compatible = "ti,tas5086", },
8124fa89346SDaniel Mack { }
8134fa89346SDaniel Mack };
8144fa89346SDaniel Mack MODULE_DEVICE_TABLE(of, tas5086_dt_ids);
8154fa89346SDaniel Mack #endif
8164fa89346SDaniel Mack
tas5086_probe(struct snd_soc_component * component)817459bc024SKuninori Morimoto static int tas5086_probe(struct snd_soc_component *component)
8184fa89346SDaniel Mack {
819459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
8204fa89346SDaniel Mack int i, ret;
8214fa89346SDaniel Mack
822c46af312SDaniel Mack ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
823c46af312SDaniel Mack if (ret < 0) {
824459bc024SKuninori Morimoto dev_err(component->dev, "Failed to enable regulators: %d\n", ret);
825c46af312SDaniel Mack return ret;
826c46af312SDaniel Mack }
827c46af312SDaniel Mack
828648c5382SDaniel Mack priv->pwm_start_mid_z = 0;
829648c5382SDaniel Mack priv->charge_period = 1300000; /* hardware default is 1300 ms */
830648c5382SDaniel Mack
831459bc024SKuninori Morimoto if (of_match_device(of_match_ptr(tas5086_dt_ids), component->dev)) {
832459bc024SKuninori Morimoto struct device_node *of_node = component->dev->of_node;
833d5fd3cccSDaniel Mack
834648c5382SDaniel Mack of_property_read_u32(of_node, "ti,charge-period",
835648c5382SDaniel Mack &priv->charge_period);
83679b23b56SDaniel Mack
83779b23b56SDaniel Mack for (i = 0; i < 6; i++) {
83879b23b56SDaniel Mack char name[25];
83979b23b56SDaniel Mack
84079b23b56SDaniel Mack snprintf(name, sizeof(name),
84179b23b56SDaniel Mack "ti,mid-z-channel-%d", i + 1);
84279b23b56SDaniel Mack
843*2d2998b8SRob Herring if (of_property_read_bool(of_node, name))
844648c5382SDaniel Mack priv->pwm_start_mid_z |= 1 << i;
8454fa89346SDaniel Mack }
84679b23b56SDaniel Mack }
84779b23b56SDaniel Mack
848c46af312SDaniel Mack tas5086_reset(priv);
849459bc024SKuninori Morimoto ret = tas5086_init(component->dev, priv);
8504fa89346SDaniel Mack if (ret < 0)
851c46af312SDaniel Mack goto exit_disable_regulators;
8524fa89346SDaniel Mack
8534fa89346SDaniel Mack /* set master volume to 0 dB */
8544fa89346SDaniel Mack ret = regmap_write(priv->regmap, TAS5086_MASTER_VOL, 0x30);
8554fa89346SDaniel Mack if (ret < 0)
856c46af312SDaniel Mack goto exit_disable_regulators;
8574fa89346SDaniel Mack
8584fa89346SDaniel Mack return 0;
859c46af312SDaniel Mack
860c46af312SDaniel Mack exit_disable_regulators:
861c46af312SDaniel Mack regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
862c46af312SDaniel Mack
863c46af312SDaniel Mack return ret;
8644fa89346SDaniel Mack }
8654fa89346SDaniel Mack
tas5086_remove(struct snd_soc_component * component)866459bc024SKuninori Morimoto static void tas5086_remove(struct snd_soc_component *component)
8674fa89346SDaniel Mack {
868459bc024SKuninori Morimoto struct tas5086_private *priv = snd_soc_component_get_drvdata(component);
8694fa89346SDaniel Mack
8704fa89346SDaniel Mack if (gpio_is_valid(priv->gpio_nreset))
8714fa89346SDaniel Mack /* Set codec to the reset state */
8724fa89346SDaniel Mack gpio_set_value(priv->gpio_nreset, 0);
8734fa89346SDaniel Mack
874c46af312SDaniel Mack regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
8754fa89346SDaniel Mack };
8764fa89346SDaniel Mack
877459bc024SKuninori Morimoto static const struct snd_soc_component_driver soc_component_dev_tas5086 = {
8784fa89346SDaniel Mack .probe = tas5086_probe,
8794fa89346SDaniel Mack .remove = tas5086_remove,
88025c84cc1SDaniel Mack .suspend = tas5086_soc_suspend,
8814fa89346SDaniel Mack .resume = tas5086_soc_resume,
8824fa89346SDaniel Mack .controls = tas5086_controls,
8834fa89346SDaniel Mack .num_controls = ARRAY_SIZE(tas5086_controls),
88418710acdSDaniel Mack .dapm_widgets = tas5086_dapm_widgets,
88518710acdSDaniel Mack .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets),
88618710acdSDaniel Mack .dapm_routes = tas5086_dapm_routes,
88718710acdSDaniel Mack .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes),
888459bc024SKuninori Morimoto .idle_bias_on = 1,
889459bc024SKuninori Morimoto .use_pmdown_time = 1,
890459bc024SKuninori Morimoto .endianness = 1,
8914fa89346SDaniel Mack };
8924fa89346SDaniel Mack
8934fa89346SDaniel Mack static const struct i2c_device_id tas5086_i2c_id[] = {
8944fa89346SDaniel Mack { "tas5086", 0 },
8954fa89346SDaniel Mack { }
8964fa89346SDaniel Mack };
8974fa89346SDaniel Mack MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id);
8984fa89346SDaniel Mack
8994fa89346SDaniel Mack static const struct regmap_config tas5086_regmap = {
9004fa89346SDaniel Mack .reg_bits = 8,
9018892d479SDaniel Mack .val_bits = 32,
9028892d479SDaniel Mack .max_register = TAS5086_MAX_REGISTER,
9034fa89346SDaniel Mack .reg_defaults = tas5086_reg_defaults,
9044fa89346SDaniel Mack .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults),
9054fa89346SDaniel Mack .cache_type = REGCACHE_RBTREE,
9064fa89346SDaniel Mack .volatile_reg = tas5086_volatile_reg,
9074fa89346SDaniel Mack .writeable_reg = tas5086_writeable_reg,
9084fa89346SDaniel Mack .readable_reg = tas5086_accessible_reg,
9096b36d370SDaniel Mack .reg_read = tas5086_reg_read,
9106b36d370SDaniel Mack .reg_write = tas5086_reg_write,
9114fa89346SDaniel Mack };
9124fa89346SDaniel Mack
tas5086_i2c_probe(struct i2c_client * i2c)913ad11678fSStephen Kitt static int tas5086_i2c_probe(struct i2c_client *i2c)
9144fa89346SDaniel Mack {
9154fa89346SDaniel Mack struct tas5086_private *priv;
9164fa89346SDaniel Mack struct device *dev = &i2c->dev;
9174fa89346SDaniel Mack int gpio_nreset = -EINVAL;
9184fa89346SDaniel Mack int i, ret;
9194fa89346SDaniel Mack
9204fa89346SDaniel Mack priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
9214fa89346SDaniel Mack if (!priv)
9224fa89346SDaniel Mack return -ENOMEM;
9234fa89346SDaniel Mack
924c46af312SDaniel Mack for (i = 0; i < ARRAY_SIZE(supply_names); i++)
925c46af312SDaniel Mack priv->supplies[i].supply = supply_names[i];
926c46af312SDaniel Mack
927c46af312SDaniel Mack ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(priv->supplies),
928c46af312SDaniel Mack priv->supplies);
929c46af312SDaniel Mack if (ret < 0) {
930c46af312SDaniel Mack dev_err(dev, "Failed to get regulators: %d\n", ret);
931c46af312SDaniel Mack return ret;
932c46af312SDaniel Mack }
933c46af312SDaniel Mack
9346b36d370SDaniel Mack priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap);
9354fa89346SDaniel Mack if (IS_ERR(priv->regmap)) {
9364fa89346SDaniel Mack ret = PTR_ERR(priv->regmap);
9374fa89346SDaniel Mack dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret);
9384fa89346SDaniel Mack return ret;
9394fa89346SDaniel Mack }
9404fa89346SDaniel Mack
9414fa89346SDaniel Mack i2c_set_clientdata(i2c, priv);
9424fa89346SDaniel Mack
9434fa89346SDaniel Mack if (of_match_device(of_match_ptr(tas5086_dt_ids), dev)) {
9444fa89346SDaniel Mack struct device_node *of_node = dev->of_node;
9454fa89346SDaniel Mack gpio_nreset = of_get_named_gpio(of_node, "reset-gpio", 0);
9464fa89346SDaniel Mack }
9474fa89346SDaniel Mack
9484fa89346SDaniel Mack if (gpio_is_valid(gpio_nreset))
9494fa89346SDaniel Mack if (devm_gpio_request(dev, gpio_nreset, "TAS5086 Reset"))
9504fa89346SDaniel Mack gpio_nreset = -EINVAL;
9514fa89346SDaniel Mack
9524fa89346SDaniel Mack priv->gpio_nreset = gpio_nreset;
953c46af312SDaniel Mack
954c46af312SDaniel Mack ret = regulator_bulk_enable(ARRAY_SIZE(priv->supplies), priv->supplies);
955c46af312SDaniel Mack if (ret < 0) {
956c46af312SDaniel Mack dev_err(dev, "Failed to enable regulators: %d\n", ret);
957c46af312SDaniel Mack return ret;
958c46af312SDaniel Mack }
959c46af312SDaniel Mack
960d5fd3cccSDaniel Mack tas5086_reset(priv);
9614fa89346SDaniel Mack
9624fa89346SDaniel Mack /* The TAS5086 always returns 0x03 in its TAS5086_DEV_ID register */
9634fa89346SDaniel Mack ret = regmap_read(priv->regmap, TAS5086_DEV_ID, &i);
964c46af312SDaniel Mack if (ret == 0 && i != 0x3) {
9654fa89346SDaniel Mack dev_err(dev,
9664fa89346SDaniel Mack "Failed to identify TAS5086 codec (got %02x)\n", i);
967c46af312SDaniel Mack ret = -ENODEV;
9684fa89346SDaniel Mack }
9694fa89346SDaniel Mack
970c46af312SDaniel Mack /*
971c46af312SDaniel Mack * The chip has been identified, so we can turn off the power
972c46af312SDaniel Mack * again until the dai link is set up.
973c46af312SDaniel Mack */
974c46af312SDaniel Mack regulator_bulk_disable(ARRAY_SIZE(priv->supplies), priv->supplies);
975c46af312SDaniel Mack
976c46af312SDaniel Mack if (ret == 0)
977459bc024SKuninori Morimoto ret = devm_snd_soc_register_component(&i2c->dev,
978459bc024SKuninori Morimoto &soc_component_dev_tas5086,
9794fa89346SDaniel Mack &tas5086_dai, 1);
980c46af312SDaniel Mack
981c46af312SDaniel Mack return ret;
9824fa89346SDaniel Mack }
9834fa89346SDaniel Mack
tas5086_i2c_remove(struct i2c_client * i2c)984ed5c2f5fSUwe Kleine-König static void tas5086_i2c_remove(struct i2c_client *i2c)
985ed5c2f5fSUwe Kleine-König {}
9864fa89346SDaniel Mack
9874fa89346SDaniel Mack static struct i2c_driver tas5086_i2c_driver = {
9884fa89346SDaniel Mack .driver = {
9894fa89346SDaniel Mack .name = "tas5086",
9904fa89346SDaniel Mack .of_match_table = of_match_ptr(tas5086_dt_ids),
9914fa89346SDaniel Mack },
9924fa89346SDaniel Mack .id_table = tas5086_i2c_id,
993ad11678fSStephen Kitt .probe = tas5086_i2c_probe,
9944fa89346SDaniel Mack .remove = tas5086_i2c_remove,
9954fa89346SDaniel Mack };
9964fa89346SDaniel Mack
997c300d6deSWei Yongjun module_i2c_driver(tas5086_i2c_driver);
9984fa89346SDaniel Mack
9994fa89346SDaniel Mack MODULE_AUTHOR("Daniel Mack <zonque@gmail.com>");
10004fa89346SDaniel Mack MODULE_DESCRIPTION("Texas Instruments TAS5086 ALSA SoC Codec Driver");
10014fa89346SDaniel Mack MODULE_LICENSE("GPL");
1002