2 * ASoC Driver for TAS5713
4 * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * version 2 as published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/init.h>
20 #include <linux/delay.h>
22 #include <linux/i2c.h>
23 #include <linux/of_device.h>
24 #include <linux/spi/spi.h>
25 #include <linux/regmap.h>
26 #include <linux/regulator/consumer.h>
27 #include <linux/slab.h>
28 #include <sound/core.h>
29 #include <sound/pcm.h>
30 #include <sound/pcm_params.h>
31 #include <sound/soc.h>
32 #include <sound/initval.h>
33 #include <sound/tlv.h>
35 #include <linux/kernel.h>
36 #include <linux/string.h>
38 #include <asm/uaccess.h>
43 static struct i2c_client *i2c;
46 struct regmap *regmap;
48 struct snd_soc_component *component;
51 static struct tas5713_priv *priv_data;
58 * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___
59 * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-<
60 * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/
64 static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1);
67 static const struct snd_kcontrol_new tas5713_snd_controls[] = {
68 SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv),
69 SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv)
77 * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _
78 * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_|
79 * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_|
83 static int tas5713_hw_params(struct snd_pcm_substream *substream,
84 struct snd_pcm_hw_params *params,
85 struct snd_soc_dai *dai)
89 struct snd_soc_component *component = dai->component;
90 priv_data->component = component;
92 switch (params_format(params)) {
93 case SNDRV_PCM_FORMAT_S16_LE:
96 case SNDRV_PCM_FORMAT_S20_3LE:
99 case SNDRV_PCM_FORMAT_S24_LE:
102 case SNDRV_PCM_FORMAT_S32_LE:
106 dev_err(dai->dev, "Unsupported word length: %u\n",
107 params_format(params));
112 snd_soc_component_update_bits(component, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen);
118 static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
120 unsigned int val = 0;
122 struct tas5713_priv *tas5713;
123 struct snd_soc_component *component = dai->component;
124 tas5713 = snd_soc_component_get_drvdata(component);
127 val = TAS5713_SOFT_MUTE_ALL;
130 return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val);
134 static const struct snd_soc_dai_ops tas5713_dai_ops = {
135 .hw_params = tas5713_hw_params,
136 .mute_stream = tas5713_mute_stream,
140 static struct snd_soc_dai_driver tas5713_dai = {
141 .name = "tas5713-hifi",
143 .stream_name = "Playback",
146 .rates = SNDRV_PCM_RATE_8000_48000,
147 .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ),
149 .ops = &tas5713_dai_ops,
157 * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _
158 * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_|
159 * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_|
163 static void tas5713_remove(struct snd_soc_component *component)
165 struct tas5713_priv *tas5713;
167 tas5713 = snd_soc_component_get_drvdata(component);
171 static int tas5713_probe(struct snd_soc_component *component)
173 struct tas5713_priv *tas5713;
176 i2c = container_of(component->dev, struct i2c_client, dev);
178 tas5713 = snd_soc_component_get_drvdata(component);
181 ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
182 if (ret < 0) return ret;
185 ret = snd_soc_component_write(component, TAS5713_OSC_TRIM, 0x00);
186 if (ret < 0) return ret;
190 ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
191 if (ret < 0) return ret;
194 ret = snd_soc_component_write(component, TAS5713_SERIAL_DATA_INTERFACE, 0x05);
195 if (ret < 0) return ret;
198 ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
199 if (ret < 0) return ret;
200 ret = snd_soc_component_write(component, TAS5713_SOFT_MUTE, 0x00);
201 if (ret < 0) return ret;
204 ret = snd_soc_component_write(component, TAS5713_VOL_MASTER, 0x00);
205 if (ret < 0) return ret;
207 // Now start programming the default initialization sequence
208 for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) {
209 ret = i2c_master_send(i2c,
210 tas5713_init_sequence[i].data,
211 tas5713_init_sequence[i].size);
213 printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret);
218 ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
219 if (ret < 0) return ret;
225 static struct snd_soc_component_driver soc_codec_dev_tas5713 = {
226 .probe = tas5713_probe,
227 .remove = tas5713_remove,
228 .controls = tas5713_snd_controls,
229 .num_controls = ARRAY_SIZE(tas5713_snd_controls),
237 * |_ _|_ ) __| | \ _ _(_)_ _____ _ _
238 * | | / / (__ | |) | '_| \ V / -_) '_|
239 * |___/___\___| |___/|_| |_|\_/\___|_|
243 static const struct reg_default tas5713_reg_defaults[] = {
244 { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB
245 { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB
246 { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB
247 { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB
251 static bool tas5713_reg_volatile(struct device *dev, unsigned int reg)
254 case TAS5713_DEVICE_ID:
255 case TAS5713_ERROR_STATUS:
256 case TAS5713_CLOCK_CTRL:
264 static const struct of_device_id tas5713_of_match[] = {
265 { .compatible = "ti,tas5713", },
268 MODULE_DEVICE_TABLE(of, tas5713_of_match);
271 static struct regmap_config tas5713_regmap_config = {
275 .max_register = TAS5713_MAX_REGISTER,
276 .volatile_reg = tas5713_reg_volatile,
278 .cache_type = REGCACHE_RBTREE,
279 .reg_defaults = tas5713_reg_defaults,
280 .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults),
284 static int tas5713_i2c_probe(struct i2c_client *i2c,
285 const struct i2c_device_id *id)
289 priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL);
293 priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config);
294 if (IS_ERR(priv_data->regmap)) {
295 ret = PTR_ERR(priv_data->regmap);
299 i2c_set_clientdata(i2c, priv_data);
301 ret = snd_soc_register_component(&i2c->dev,
302 &soc_codec_dev_tas5713, &tas5713_dai, 1);
308 static int tas5713_i2c_remove(struct i2c_client *i2c)
310 snd_soc_unregister_component(&i2c->dev);
311 i2c_set_clientdata(i2c, NULL);
319 static const struct i2c_device_id tas5713_i2c_id[] = {
324 MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id);
327 static struct i2c_driver tas5713_i2c_driver = {
330 .owner = THIS_MODULE,
331 .of_match_table = tas5713_of_match,
333 .probe = tas5713_i2c_probe,
334 .remove = tas5713_i2c_remove,
335 .id_table = tas5713_i2c_id
339 static int __init tas5713_modinit(void)
343 ret = i2c_add_driver(&tas5713_i2c_driver);
345 printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n",
351 module_init(tas5713_modinit);
354 static void __exit tas5713_exit(void)
356 i2c_del_driver(&tas5713_i2c_driver);
358 module_exit(tas5713_exit);
361 MODULE_AUTHOR("Sebastian Eickhoff <basti.eickhoff@googlemail.com>");
362 MODULE_DESCRIPTION("ASoC driver for TAS5713");
363 MODULE_LICENSE("GPL v2");