Merge tag 'v5.15.57' into rpi-5.15.y
[platform/kernel/linux-rpi.git] / sound / soc / codecs / tas5713.c
1 /*
2  * ASoC Driver for TAS5713
3  *
4  * Author:      Sebastian Eickhoff <basti.eickhoff@googlemail.com>
5  *              Copyright 2014
6  *
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.
10  *
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.
15  */
16
17 #include <linux/module.h>
18 #include <linux/moduleparam.h>
19 #include <linux/init.h>
20 #include <linux/delay.h>
21 #include <linux/pm.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>
34
35 #include <linux/kernel.h>
36 #include <linux/string.h>
37 #include <linux/fs.h>
38 #include <asm/uaccess.h>
39
40 #include "tas5713.h"
41
42
43 static struct i2c_client *i2c;
44
45 struct tas5713_priv {
46         struct regmap *regmap;
47         int mclk_div;
48         struct snd_soc_component *component;
49 };
50
51 static struct tas5713_priv *priv_data;
52
53
54
55
56 /*
57  *    _   _    ___   _      ___         _           _
58  *   /_\ | |  / __| /_\    / __|___ _ _| |_ _ _ ___| |___
59  *  / _ \| |__\__ \/ _ \  | (__/ _ \ ' \  _| '_/ _ \ (_-<
60  * /_/ \_\____|___/_/ \_\  \___\___/_||_\__|_| \___/_/__/
61  *
62  */
63
64 static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1);
65
66
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)
70 };
71
72
73
74
75 /*
76  *  __  __         _    _            ___      _
77  * |  \/  |__ _ __| |_ (_)_ _  ___  |   \ _ _(_)_ _____ _ _
78  * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_|
79  * |_|  |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_|
80  *
81  */
82
83 static int tas5713_hw_params(struct snd_pcm_substream *substream,
84                             struct snd_pcm_hw_params *params,
85                             struct snd_soc_dai *dai)
86 {
87         u16 blen = 0x00;
88
89         struct snd_soc_component *component = dai->component;
90         priv_data->component = component;
91
92         switch (params_format(params)) {
93         case SNDRV_PCM_FORMAT_S16_LE:
94                 blen = 0x03;
95                 break;
96         case SNDRV_PCM_FORMAT_S20_3LE:
97                 blen = 0x1;
98                 break;
99         case SNDRV_PCM_FORMAT_S24_LE:
100                 blen = 0x04;
101                 break;
102         case SNDRV_PCM_FORMAT_S32_LE:
103                 blen = 0x05;
104                 break;
105         default:
106                 dev_err(dai->dev, "Unsupported word length: %u\n",
107                         params_format(params));
108                 return -EINVAL;
109         }
110
111         // set word length
112         snd_soc_component_update_bits(component, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen);
113
114         return 0;
115 }
116
117
118 static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
119 {
120         unsigned int val = 0;
121
122         struct tas5713_priv *tas5713;
123         struct snd_soc_component *component = dai->component;
124         tas5713 = snd_soc_component_get_drvdata(component);
125
126         if (mute) {
127                 val = TAS5713_SOFT_MUTE_ALL;
128         }
129
130         return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val);
131 }
132
133
134 static const struct snd_soc_dai_ops tas5713_dai_ops = {
135         .hw_params              = tas5713_hw_params,
136         .mute_stream    = tas5713_mute_stream,
137 };
138
139
140 static struct snd_soc_dai_driver tas5713_dai = {
141         .name           = "tas5713-hifi",
142         .playback       = {
143                 .stream_name    = "Playback",
144                 .channels_min   = 2,
145                 .channels_max   = 2,
146                 .rates              = SNDRV_PCM_RATE_8000_48000,
147                 .formats            = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ),
148         },
149         .ops        = &tas5713_dai_ops,
150 };
151
152
153
154
155 /*
156  *   ___         _          ___      _
157  *  / __|___  __| |___ __  |   \ _ _(_)_ _____ _ _
158  * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_|
159  *  \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_|
160  *
161  */
162
163 static void tas5713_remove(struct snd_soc_component *component)
164 {
165         struct tas5713_priv *tas5713;
166
167         tas5713 = snd_soc_component_get_drvdata(component);
168 }
169
170
171 static int tas5713_probe(struct snd_soc_component *component)
172 {
173         struct tas5713_priv *tas5713;
174         int i, ret;
175
176         i2c = container_of(component->dev, struct i2c_client, dev);
177
178         tas5713 = snd_soc_component_get_drvdata(component);
179
180         // Reset error
181         ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
182         if (ret < 0) return ret;
183
184         // Trim oscillator
185         ret = snd_soc_component_write(component, TAS5713_OSC_TRIM, 0x00);
186         if (ret < 0) return ret;
187         msleep(1000);
188
189         // Reset error
190         ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
191         if (ret < 0) return ret;
192
193         // I2S 24bit
194         ret = snd_soc_component_write(component, TAS5713_SERIAL_DATA_INTERFACE, 0x05);
195         if (ret < 0) return ret;
196
197         // Unmute
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;
202
203         // Set volume to 0db
204         ret = snd_soc_component_write(component, TAS5713_VOL_MASTER, 0x00);
205         if (ret < 0) return ret;
206
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);
212                 if (ret < 0) {
213                         printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret);
214                 }
215         }
216
217         // Unmute
218         ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
219         if (ret < 0) return ret;
220
221         return 0;
222 }
223
224
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),
230 };
231
232
233
234
235 /*
236  *   ___ ___ ___   ___      _
237  *  |_ _|_  ) __| |   \ _ _(_)_ _____ _ _
238  *   | | / / (__  | |) | '_| \ V / -_) '_|
239  *  |___/___\___| |___/|_| |_|\_/\___|_|
240  *
241  */
242
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
248 };
249
250
251 static bool tas5713_reg_volatile(struct device *dev, unsigned int reg)
252 {
253         switch (reg) {
254                 case TAS5713_DEVICE_ID:
255                 case TAS5713_ERROR_STATUS:
256                 case TAS5713_CLOCK_CTRL:
257                         return true;
258         default:
259                         return false;
260         }
261 }
262
263
264 static const struct of_device_id tas5713_of_match[] = {
265         { .compatible = "ti,tas5713", },
266         { }
267 };
268 MODULE_DEVICE_TABLE(of, tas5713_of_match);
269
270
271 static struct regmap_config tas5713_regmap_config = {
272         .reg_bits = 8,
273         .val_bits = 8,
274
275         .max_register = TAS5713_MAX_REGISTER,
276         .volatile_reg = tas5713_reg_volatile,
277
278         .cache_type = REGCACHE_RBTREE,
279         .reg_defaults = tas5713_reg_defaults,
280         .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults),
281 };
282
283
284 static int tas5713_i2c_probe(struct i2c_client *i2c,
285                             const struct i2c_device_id *id)
286 {
287         int ret;
288
289         priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL);
290         if (!priv_data)
291                 return -ENOMEM;
292
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);
296                 return ret;
297         }
298
299         i2c_set_clientdata(i2c, priv_data);
300
301         ret = snd_soc_register_component(&i2c->dev,
302                                      &soc_codec_dev_tas5713, &tas5713_dai, 1);
303
304         return ret;
305 }
306
307
308 static int tas5713_i2c_remove(struct i2c_client *i2c)
309 {
310         snd_soc_unregister_component(&i2c->dev);
311         i2c_set_clientdata(i2c, NULL);
312
313         kfree(priv_data);
314
315         return 0;
316 }
317
318
319 static const struct i2c_device_id tas5713_i2c_id[] = {
320         { "tas5713", 0 },
321         { }
322 };
323
324 MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id);
325
326
327 static struct i2c_driver tas5713_i2c_driver = {
328         .driver = {
329                 .name = "tas5713",
330                 .owner = THIS_MODULE,
331                 .of_match_table = tas5713_of_match,
332         },
333         .probe = tas5713_i2c_probe,
334         .remove = tas5713_i2c_remove,
335         .id_table = tas5713_i2c_id
336 };
337
338
339 static int __init tas5713_modinit(void)
340 {
341         int ret = 0;
342
343         ret = i2c_add_driver(&tas5713_i2c_driver);
344         if (ret) {
345                 printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n",
346                        ret);
347         }
348
349         return ret;
350 }
351 module_init(tas5713_modinit);
352
353
354 static void __exit tas5713_exit(void)
355 {
356         i2c_del_driver(&tas5713_i2c_driver);
357 }
358 module_exit(tas5713_exit);
359
360
361 MODULE_AUTHOR("Sebastian Eickhoff <basti.eickhoff@googlemail.com>");
362 MODULE_DESCRIPTION("ASoC driver for TAS5713");
363 MODULE_LICENSE("GPL v2");