ASoC: tas571x: add biquads for TAS5717/19
[deliverable/linux.git] / sound / soc / codecs / tas571x.c
CommitLineData
3fd6e7d9
KC
1/*
2 * TAS571x amplifier audio driver
3 *
4 * Copyright (C) 2015 Google, Inc.
5 * Copyright (c) 2013 Daniel Mack <zonque@gmail.com>
6 *
23a282c4
PK
7 * TAS5721 support:
8 * Copyright (C) 2016 Petr Kulhavy, Barix AG <petr@barix.com>
9 *
3fd6e7d9
KC
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 */
15
16#include <linux/clk.h>
17#include <linux/delay.h>
18#include <linux/device.h>
19#include <linux/gpio/consumer.h>
20#include <linux/i2c.h>
21#include <linux/init.h>
22#include <linux/kernel.h>
23#include <linux/module.h>
24#include <linux/of_device.h>
25#include <linux/regmap.h>
26#include <linux/regulator/consumer.h>
27#include <linux/stddef.h>
28#include <sound/pcm_params.h>
29#include <sound/soc.h>
30#include <sound/tlv.h>
4b9e385b 31#include <asm/unaligned.h>
3fd6e7d9
KC
32
33#include "tas571x.h"
34
35#define TAS571X_MAX_SUPPLIES 6
36
37struct tas571x_chip {
38 const char *const *supply_names;
39 int num_supply_names;
40 const struct snd_kcontrol_new *controls;
41 int num_controls;
42 const struct regmap_config *regmap_config;
43 int vol_reg_size;
44};
45
46struct tas571x_private {
47 const struct tas571x_chip *chip;
48 struct regmap *regmap;
49 struct regulator_bulk_data supplies[TAS571X_MAX_SUPPLIES];
50 struct clk *mclk;
51 unsigned int format;
52 struct gpio_desc *reset_gpio;
53 struct gpio_desc *pdn_gpio;
54 struct snd_soc_codec_driver codec_driver;
55};
56
57static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)
58{
59 switch (reg) {
60 case TAS571X_MVOL_REG:
61 case TAS571X_CH1_VOL_REG:
62 case TAS571X_CH2_VOL_REG:
63 return priv->chip->vol_reg_size;
a593ed09
PK
64 case TAS571X_INPUT_MUX_REG:
65 case TAS571X_CH4_SRC_SELECT_REG:
66 case TAS571X_PWM_MUX_REG:
67 return 4;
3fd6e7d9
KC
68 default:
69 return 1;
70 }
71}
72
73static int tas571x_reg_write(void *context, unsigned int reg,
74 unsigned int value)
75{
76 struct i2c_client *client = context;
77 struct tas571x_private *priv = i2c_get_clientdata(client);
78 unsigned int i, size;
79 uint8_t buf[5];
80 int ret;
81
82 size = tas571x_register_size(priv, reg);
83 buf[0] = reg;
84
85 for (i = size; i >= 1; --i) {
86 buf[i] = value;
87 value >>= 8;
88 }
89
90 ret = i2c_master_send(client, buf, size + 1);
91 if (ret == size + 1)
92 return 0;
93 else if (ret < 0)
94 return ret;
95 else
96 return -EIO;
97}
98
99static int tas571x_reg_read(void *context, unsigned int reg,
100 unsigned int *value)
101{
102 struct i2c_client *client = context;
103 struct tas571x_private *priv = i2c_get_clientdata(client);
104 uint8_t send_buf, recv_buf[4];
105 struct i2c_msg msgs[2];
106 unsigned int size;
107 unsigned int i;
108 int ret;
109
110 size = tas571x_register_size(priv, reg);
111 send_buf = reg;
112
113 msgs[0].addr = client->addr;
114 msgs[0].len = sizeof(send_buf);
115 msgs[0].buf = &send_buf;
116 msgs[0].flags = 0;
117
118 msgs[1].addr = client->addr;
119 msgs[1].len = size;
120 msgs[1].buf = recv_buf;
121 msgs[1].flags = I2C_M_RD;
122
123 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
124 if (ret < 0)
125 return ret;
126 else if (ret != ARRAY_SIZE(msgs))
127 return -EIO;
128
129 *value = 0;
130
131 for (i = 0; i < size; i++) {
132 *value <<= 8;
133 *value |= recv_buf[i];
134 }
135
136 return 0;
137}
138
4b9e385b
PK
139/*
140 * register write for 8- and 20-byte registers
141 */
142static int tas571x_reg_write_multiword(struct i2c_client *client,
143 unsigned int reg, const long values[], size_t len)
144{
145 size_t i;
146 uint8_t *buf, *p;
147 int ret;
148 size_t send_size = 1 + len * sizeof(uint32_t);
149
150 buf = kzalloc(send_size, GFP_KERNEL | GFP_DMA);
151 if (!buf)
152 return -ENOMEM;
153 buf[0] = reg;
154
155 for (i = 0, p = buf + 1; i < len; i++, p += sizeof(uint32_t))
156 put_unaligned_be32(values[i], p);
157
158 ret = i2c_master_send(client, buf, send_size);
159
160 kfree(buf);
161
162 if (ret == send_size)
163 return 0;
164 else if (ret < 0)
165 return ret;
166 else
167 return -EIO;
168}
169
170/*
171 * register read for 8- and 20-byte registers
172 */
173static int tas571x_reg_read_multiword(struct i2c_client *client,
174 unsigned int reg, long values[], size_t len)
175{
176 unsigned int i;
177 uint8_t send_buf;
178 uint8_t *recv_buf, *p;
179 struct i2c_msg msgs[2];
180 unsigned int recv_size = len * sizeof(uint32_t);
181 int ret;
182
183 recv_buf = kzalloc(recv_size, GFP_KERNEL | GFP_DMA);
184 if (!recv_buf)
185 return -ENOMEM;
186
187 send_buf = reg;
188
189 msgs[0].addr = client->addr;
190 msgs[0].len = sizeof(send_buf);
191 msgs[0].buf = &send_buf;
192 msgs[0].flags = 0;
193
194 msgs[1].addr = client->addr;
195 msgs[1].len = recv_size;
196 msgs[1].buf = recv_buf;
197 msgs[1].flags = I2C_M_RD;
198
199 ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
200 if (ret < 0)
201 goto err_ret;
202 else if (ret != ARRAY_SIZE(msgs)) {
203 ret = -EIO;
204 goto err_ret;
205 }
206
207 for (i = 0, p = recv_buf; i < len; i++, p += sizeof(uint32_t))
208 values[i] = get_unaligned_be32(p);
209
210err_ret:
211 kfree(recv_buf);
212 return ret;
213}
214
215/*
216 * Integer array controls for setting biquad, mixer, DRC coefficients.
217 * According to the datasheet each coefficient is effectively 26bits,
218 * i.e. stored as 32bits, where bits [31:26] are ignored.
219 * TI's TAS57xx Graphical Development Environment tool however produces
220 * coefficients with more than 26 bits. For this reason we allow values
221 * in the full 32-bits reange.
222 * The coefficients are ordered as given in the TAS571x data sheet:
223 * b0, b1, b2, a1, a2
224 */
225
226static int tas571x_coefficient_info(struct snd_kcontrol *kcontrol,
227 struct snd_ctl_elem_info *uinfo)
228{
229 int numcoef = kcontrol->private_value >> 16;
230
231 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
232 uinfo->count = numcoef;
233 uinfo->value.integer.min = 0;
234 uinfo->value.integer.max = 0xffffffff;
235 return 0;
236}
237
238static int tas571x_coefficient_get(struct snd_kcontrol *kcontrol,
239 struct snd_ctl_elem_value *ucontrol)
240{
241 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
242 struct i2c_client *i2c = to_i2c_client(codec->dev);
243 int numcoef = kcontrol->private_value >> 16;
244 int index = kcontrol->private_value & 0xffff;
245
246 return tas571x_reg_read_multiword(i2c, index,
247 ucontrol->value.integer.value, numcoef);
248}
249
250static int tas571x_coefficient_put(struct snd_kcontrol *kcontrol,
251 struct snd_ctl_elem_value *ucontrol)
252{
253 struct snd_soc_codec *codec = snd_soc_kcontrol_codec(kcontrol);
254 struct i2c_client *i2c = to_i2c_client(codec->dev);
255 int numcoef = kcontrol->private_value >> 16;
256 int index = kcontrol->private_value & 0xffff;
257
258 return tas571x_reg_write_multiword(i2c, index,
259 ucontrol->value.integer.value, numcoef);
260}
261
3fd6e7d9
KC
262static int tas571x_set_dai_fmt(struct snd_soc_dai *dai, unsigned int format)
263{
264 struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec);
265
266 priv->format = format;
267
268 return 0;
269}
270
271static int tas571x_hw_params(struct snd_pcm_substream *substream,
272 struct snd_pcm_hw_params *params,
273 struct snd_soc_dai *dai)
274{
275 struct tas571x_private *priv = snd_soc_codec_get_drvdata(dai->codec);
276 u32 val;
277
278 switch (priv->format & SND_SOC_DAIFMT_FORMAT_MASK) {
279 case SND_SOC_DAIFMT_RIGHT_J:
280 val = 0x00;
281 break;
282 case SND_SOC_DAIFMT_I2S:
283 val = 0x03;
284 break;
285 case SND_SOC_DAIFMT_LEFT_J:
286 val = 0x06;
287 break;
288 default:
289 return -EINVAL;
290 }
291
292 if (params_width(params) >= 24)
293 val += 2;
294 else if (params_width(params) >= 20)
295 val += 1;
296
297 return regmap_update_bits(priv->regmap, TAS571X_SDI_REG,
298 TAS571X_SDI_FMT_MASK, val);
299}
300
04004850
PK
301static int tas571x_mute(struct snd_soc_dai *dai, int mute)
302{
303 struct snd_soc_codec *codec = dai->codec;
304 u8 sysctl2;
305 int ret;
306
307 sysctl2 = mute ? TAS571X_SYS_CTRL_2_SDN_MASK : 0;
308
309 ret = snd_soc_update_bits(codec,
310 TAS571X_SYS_CTRL_2_REG,
311 TAS571X_SYS_CTRL_2_SDN_MASK,
312 sysctl2);
313 usleep_range(1000, 2000);
314
315 return ret;
316}
317
3fd6e7d9
KC
318static int tas571x_set_bias_level(struct snd_soc_codec *codec,
319 enum snd_soc_bias_level level)
320{
321 struct tas571x_private *priv = snd_soc_codec_get_drvdata(codec);
322 int ret;
323
324 switch (level) {
325 case SND_SOC_BIAS_ON:
326 break;
327 case SND_SOC_BIAS_PREPARE:
328 break;
329 case SND_SOC_BIAS_STANDBY:
8f218fa9 330 if (snd_soc_codec_get_bias_level(codec) == SND_SOC_BIAS_OFF) {
3fd6e7d9
KC
331 if (!IS_ERR(priv->mclk)) {
332 ret = clk_prepare_enable(priv->mclk);
333 if (ret) {
334 dev_err(codec->dev,
335 "Failed to enable master clock: %d\n",
336 ret);
337 return ret;
338 }
339 }
340
341 gpiod_set_value(priv->pdn_gpio, 0);
342 usleep_range(5000, 6000);
343
344 regcache_cache_only(priv->regmap, false);
345 ret = regcache_sync(priv->regmap);
346 if (ret)
347 return ret;
348 }
349 break;
350 case SND_SOC_BIAS_OFF:
351 regcache_cache_only(priv->regmap, true);
352 gpiod_set_value(priv->pdn_gpio, 1);
353
354 if (!IS_ERR(priv->mclk))
355 clk_disable_unprepare(priv->mclk);
356 break;
357 }
358
3fd6e7d9
KC
359 return 0;
360}
361
362static const struct snd_soc_dai_ops tas571x_dai_ops = {
363 .set_fmt = tas571x_set_dai_fmt,
364 .hw_params = tas571x_hw_params,
04004850 365 .digital_mute = tas571x_mute,
3fd6e7d9
KC
366};
367
4b9e385b
PK
368
369#define BIQUAD_COEFS(xname, reg) \
370{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
371 .info = tas571x_coefficient_info, \
372 .get = tas571x_coefficient_get,\
373 .put = tas571x_coefficient_put, \
374 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
375 .private_value = reg | (5 << 16) }
376
3fd6e7d9
KC
377static const char *const tas5711_supply_names[] = {
378 "AVDD",
379 "DVDD",
380 "PVDD_A",
381 "PVDD_B",
382 "PVDD_C",
383 "PVDD_D",
384};
385
386static const DECLARE_TLV_DB_SCALE(tas5711_volume_tlv, -10350, 50, 1);
387
388static const struct snd_kcontrol_new tas5711_controls[] = {
389 SOC_SINGLE_TLV("Master Volume",
390 TAS571X_MVOL_REG,
391 0, 0xff, 1, tas5711_volume_tlv),
392 SOC_DOUBLE_R_TLV("Speaker Volume",
393 TAS571X_CH1_VOL_REG,
394 TAS571X_CH2_VOL_REG,
395 0, 0xff, 1, tas5711_volume_tlv),
396 SOC_DOUBLE("Speaker Switch",
397 TAS571X_SOFT_MUTE_REG,
398 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
399 1, 1),
400};
401
a593ed09
PK
402static const struct regmap_range tas571x_readonly_regs_range[] = {
403 regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_DEV_ID_REG),
404};
405
406static const struct regmap_range tas571x_volatile_regs_range[] = {
407 regmap_reg_range(TAS571X_CLK_CTRL_REG, TAS571X_ERR_STATUS_REG),
408 regmap_reg_range(TAS571X_OSC_TRIM_REG, TAS571X_OSC_TRIM_REG),
409};
410
411static const struct regmap_access_table tas571x_write_regs = {
412 .no_ranges = tas571x_readonly_regs_range,
413 .n_no_ranges = ARRAY_SIZE(tas571x_readonly_regs_range),
414};
415
416static const struct regmap_access_table tas571x_volatile_regs = {
417 .yes_ranges = tas571x_volatile_regs_range,
418 .n_yes_ranges = ARRAY_SIZE(tas571x_volatile_regs_range),
419
420};
421
3fd6e7d9
KC
422static const struct reg_default tas5711_reg_defaults[] = {
423 { 0x04, 0x05 },
424 { 0x05, 0x40 },
425 { 0x06, 0x00 },
426 { 0x07, 0xff },
427 { 0x08, 0x30 },
428 { 0x09, 0x30 },
429 { 0x1b, 0x82 },
430};
431
432static const struct regmap_config tas5711_regmap_config = {
433 .reg_bits = 8,
434 .val_bits = 32,
435 .max_register = 0xff,
436 .reg_read = tas571x_reg_read,
437 .reg_write = tas571x_reg_write,
438 .reg_defaults = tas5711_reg_defaults,
439 .num_reg_defaults = ARRAY_SIZE(tas5711_reg_defaults),
440 .cache_type = REGCACHE_RBTREE,
a593ed09
PK
441 .wr_table = &tas571x_write_regs,
442 .volatile_table = &tas571x_volatile_regs,
3fd6e7d9
KC
443};
444
445static const struct tas571x_chip tas5711_chip = {
446 .supply_names = tas5711_supply_names,
447 .num_supply_names = ARRAY_SIZE(tas5711_supply_names),
448 .controls = tas5711_controls,
449 .num_controls = ARRAY_SIZE(tas5711_controls),
450 .regmap_config = &tas5711_regmap_config,
451 .vol_reg_size = 1,
452};
453
454static const char *const tas5717_supply_names[] = {
455 "AVDD",
456 "DVDD",
457 "HPVDD",
458 "PVDD_AB",
459 "PVDD_CD",
460};
461
462static const DECLARE_TLV_DB_SCALE(tas5717_volume_tlv, -10375, 25, 0);
463
464static const struct snd_kcontrol_new tas5717_controls[] = {
465 /* MVOL LSB is ignored - see comments in tas571x_i2c_probe() */
466 SOC_SINGLE_TLV("Master Volume",
467 TAS571X_MVOL_REG, 1, 0x1ff, 1,
468 tas5717_volume_tlv),
469 SOC_DOUBLE_R_TLV("Speaker Volume",
470 TAS571X_CH1_VOL_REG, TAS571X_CH2_VOL_REG,
471 1, 0x1ff, 1, tas5717_volume_tlv),
472 SOC_DOUBLE("Speaker Switch",
473 TAS571X_SOFT_MUTE_REG,
474 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
475 1, 1),
4b9e385b
PK
476
477 /*
478 * The biquads are named according to the register names.
479 * Please note that TI's TAS57xx Graphical Development Environment
480 * tool names them different.
481 */
482 BIQUAD_COEFS("CH1 - Biquad 0", TAS5717_CH1_BQ0_REG),
483 BIQUAD_COEFS("CH1 - Biquad 1", TAS5717_CH1_BQ1_REG),
484 BIQUAD_COEFS("CH1 - Biquad 2", TAS5717_CH1_BQ2_REG),
485 BIQUAD_COEFS("CH1 - Biquad 3", TAS5717_CH1_BQ3_REG),
486 BIQUAD_COEFS("CH1 - Biquad 4", TAS5717_CH1_BQ4_REG),
487 BIQUAD_COEFS("CH1 - Biquad 5", TAS5717_CH1_BQ5_REG),
488 BIQUAD_COEFS("CH1 - Biquad 6", TAS5717_CH1_BQ6_REG),
489 BIQUAD_COEFS("CH1 - Biquad 7", TAS5717_CH1_BQ7_REG),
490 BIQUAD_COEFS("CH1 - Biquad 8", TAS5717_CH1_BQ8_REG),
491 BIQUAD_COEFS("CH1 - Biquad 9", TAS5717_CH1_BQ9_REG),
492 BIQUAD_COEFS("CH1 - Biquad 10", TAS5717_CH1_BQ10_REG),
493 BIQUAD_COEFS("CH1 - Biquad 11", TAS5717_CH1_BQ11_REG),
494
495 BIQUAD_COEFS("CH2 - Biquad 0", TAS5717_CH2_BQ0_REG),
496 BIQUAD_COEFS("CH2 - Biquad 1", TAS5717_CH2_BQ1_REG),
497 BIQUAD_COEFS("CH2 - Biquad 2", TAS5717_CH2_BQ2_REG),
498 BIQUAD_COEFS("CH2 - Biquad 3", TAS5717_CH2_BQ3_REG),
499 BIQUAD_COEFS("CH2 - Biquad 4", TAS5717_CH2_BQ4_REG),
500 BIQUAD_COEFS("CH2 - Biquad 5", TAS5717_CH2_BQ5_REG),
501 BIQUAD_COEFS("CH2 - Biquad 6", TAS5717_CH2_BQ6_REG),
502 BIQUAD_COEFS("CH2 - Biquad 7", TAS5717_CH2_BQ7_REG),
503 BIQUAD_COEFS("CH2 - Biquad 8", TAS5717_CH2_BQ8_REG),
504 BIQUAD_COEFS("CH2 - Biquad 9", TAS5717_CH2_BQ9_REG),
505 BIQUAD_COEFS("CH2 - Biquad 10", TAS5717_CH2_BQ10_REG),
506 BIQUAD_COEFS("CH2 - Biquad 11", TAS5717_CH2_BQ11_REG),
507
508 BIQUAD_COEFS("CH3 - Biquad 0", TAS5717_CH3_BQ0_REG),
509 BIQUAD_COEFS("CH3 - Biquad 1", TAS5717_CH3_BQ1_REG),
510
511 BIQUAD_COEFS("CH4 - Biquad 0", TAS5717_CH4_BQ0_REG),
512 BIQUAD_COEFS("CH4 - Biquad 1", TAS5717_CH4_BQ1_REG),
3fd6e7d9
KC
513};
514
515static const struct reg_default tas5717_reg_defaults[] = {
516 { 0x04, 0x05 },
517 { 0x05, 0x40 },
518 { 0x06, 0x00 },
519 { 0x07, 0x03ff },
520 { 0x08, 0x00c0 },
521 { 0x09, 0x00c0 },
522 { 0x1b, 0x82 },
523};
524
525static const struct regmap_config tas5717_regmap_config = {
526 .reg_bits = 8,
527 .val_bits = 32,
528 .max_register = 0xff,
529 .reg_read = tas571x_reg_read,
530 .reg_write = tas571x_reg_write,
531 .reg_defaults = tas5717_reg_defaults,
532 .num_reg_defaults = ARRAY_SIZE(tas5717_reg_defaults),
533 .cache_type = REGCACHE_RBTREE,
a593ed09
PK
534 .wr_table = &tas571x_write_regs,
535 .volatile_table = &tas571x_volatile_regs,
3fd6e7d9
KC
536};
537
538/* This entry is reused for tas5719 as the software interface is identical. */
539static const struct tas571x_chip tas5717_chip = {
540 .supply_names = tas5717_supply_names,
541 .num_supply_names = ARRAY_SIZE(tas5717_supply_names),
542 .controls = tas5717_controls,
543 .num_controls = ARRAY_SIZE(tas5717_controls),
544 .regmap_config = &tas5717_regmap_config,
545 .vol_reg_size = 2,
546};
547
23a282c4
PK
548static const char *const tas5721_supply_names[] = {
549 "AVDD",
550 "DVDD",
551 "DRVDD",
552 "PVDD",
553};
554
555static const struct snd_kcontrol_new tas5721_controls[] = {
556 SOC_SINGLE_TLV("Master Volume",
557 TAS571X_MVOL_REG,
558 0, 0xff, 1, tas5711_volume_tlv),
559 SOC_DOUBLE_R_TLV("Speaker Volume",
560 TAS571X_CH1_VOL_REG,
561 TAS571X_CH2_VOL_REG,
562 0, 0xff, 1, tas5711_volume_tlv),
563 SOC_DOUBLE("Speaker Switch",
564 TAS571X_SOFT_MUTE_REG,
565 TAS571X_SOFT_MUTE_CH1_SHIFT, TAS571X_SOFT_MUTE_CH2_SHIFT,
566 1, 1),
567};
568
569static const struct reg_default tas5721_reg_defaults[] = {
570 {TAS571X_CLK_CTRL_REG, 0x6c},
571 {TAS571X_DEV_ID_REG, 0x00},
572 {TAS571X_ERR_STATUS_REG, 0x00},
573 {TAS571X_SYS_CTRL_1_REG, 0xa0},
574 {TAS571X_SDI_REG, 0x05},
575 {TAS571X_SYS_CTRL_2_REG, 0x40},
576 {TAS571X_SOFT_MUTE_REG, 0x00},
577 {TAS571X_MVOL_REG, 0xff},
578 {TAS571X_CH1_VOL_REG, 0x30},
579 {TAS571X_CH2_VOL_REG, 0x30},
580 {TAS571X_CH3_VOL_REG, 0x30},
581 {TAS571X_VOL_CFG_REG, 0x91},
582 {TAS571X_MODULATION_LIMIT_REG, 0x02},
583 {TAS571X_IC_DELAY_CH1_REG, 0xac},
584 {TAS571X_IC_DELAY_CH2_REG, 0x54},
585 {TAS571X_IC_DELAY_CH3_REG, 0xac},
586 {TAS571X_IC_DELAY_CH4_REG, 0x54},
587 {TAS571X_PWM_CH_SDN_GROUP_REG, 0x30},
588 {TAS571X_START_STOP_PERIOD_REG, 0x0f},
589 {TAS571X_OSC_TRIM_REG, 0x82},
590 {TAS571X_BKND_ERR_REG, 0x02},
591 {TAS571X_INPUT_MUX_REG, 0x17772},
592 {TAS571X_CH4_SRC_SELECT_REG, 0x4303},
593 {TAS571X_PWM_MUX_REG, 0x1021345},
594};
595
596static const struct regmap_config tas5721_regmap_config = {
597 .reg_bits = 8,
598 .val_bits = 32,
599 .max_register = 0xff,
600 .reg_read = tas571x_reg_read,
601 .reg_write = tas571x_reg_write,
602 .reg_defaults = tas5721_reg_defaults,
603 .num_reg_defaults = ARRAY_SIZE(tas5721_reg_defaults),
604 .cache_type = REGCACHE_RBTREE,
605 .wr_table = &tas571x_write_regs,
606 .volatile_table = &tas571x_volatile_regs,
607};
608
609
610static const struct tas571x_chip tas5721_chip = {
611 .supply_names = tas5721_supply_names,
612 .num_supply_names = ARRAY_SIZE(tas5721_supply_names),
613 .controls = tas5711_controls,
614 .num_controls = ARRAY_SIZE(tas5711_controls),
615 .regmap_config = &tas5721_regmap_config,
616 .vol_reg_size = 1,
617};
618
3fd6e7d9
KC
619static const struct snd_soc_dapm_widget tas571x_dapm_widgets[] = {
620 SND_SOC_DAPM_DAC("DACL", NULL, SND_SOC_NOPM, 0, 0),
621 SND_SOC_DAPM_DAC("DACR", NULL, SND_SOC_NOPM, 0, 0),
622
623 SND_SOC_DAPM_OUTPUT("OUT_A"),
624 SND_SOC_DAPM_OUTPUT("OUT_B"),
625 SND_SOC_DAPM_OUTPUT("OUT_C"),
626 SND_SOC_DAPM_OUTPUT("OUT_D"),
627};
628
629static const struct snd_soc_dapm_route tas571x_dapm_routes[] = {
630 { "DACL", NULL, "Playback" },
631 { "DACR", NULL, "Playback" },
632
633 { "OUT_A", NULL, "DACL" },
634 { "OUT_B", NULL, "DACL" },
635 { "OUT_C", NULL, "DACR" },
636 { "OUT_D", NULL, "DACR" },
637};
638
639static const struct snd_soc_codec_driver tas571x_codec = {
640 .set_bias_level = tas571x_set_bias_level,
641 .idle_bias_off = true,
642
643 .dapm_widgets = tas571x_dapm_widgets,
644 .num_dapm_widgets = ARRAY_SIZE(tas571x_dapm_widgets),
645 .dapm_routes = tas571x_dapm_routes,
646 .num_dapm_routes = ARRAY_SIZE(tas571x_dapm_routes),
647};
648
649static struct snd_soc_dai_driver tas571x_dai = {
650 .name = "tas571x-hifi",
651 .playback = {
652 .stream_name = "Playback",
653 .channels_min = 2,
654 .channels_max = 2,
655 .rates = SNDRV_PCM_RATE_8000_48000,
656 .formats = SNDRV_PCM_FMTBIT_S32_LE |
657 SNDRV_PCM_FMTBIT_S24_LE |
658 SNDRV_PCM_FMTBIT_S16_LE,
659 },
660 .ops = &tas571x_dai_ops,
661};
662
663static const struct of_device_id tas571x_of_match[];
664
665static int tas571x_i2c_probe(struct i2c_client *client,
666 const struct i2c_device_id *id)
667{
668 struct tas571x_private *priv;
669 struct device *dev = &client->dev;
97fceb4d 670 const struct of_device_id *of_id;
3fd6e7d9
KC
671 int i, ret;
672
673 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
674 if (!priv)
675 return -ENOMEM;
676 i2c_set_clientdata(client, priv);
677
97fceb4d 678 of_id = of_match_device(tas571x_of_match, dev);
630e413d
PK
679 if (of_id)
680 priv->chip = of_id->data;
681 else
682 priv->chip = (void *) id->driver_data;
3fd6e7d9
KC
683
684 priv->mclk = devm_clk_get(dev, "mclk");
685 if (IS_ERR(priv->mclk) && PTR_ERR(priv->mclk) != -ENOENT) {
686 dev_err(dev, "Failed to request mclk: %ld\n",
687 PTR_ERR(priv->mclk));
688 return PTR_ERR(priv->mclk);
689 }
690
691 BUG_ON(priv->chip->num_supply_names > TAS571X_MAX_SUPPLIES);
692 for (i = 0; i < priv->chip->num_supply_names; i++)
693 priv->supplies[i].supply = priv->chip->supply_names[i];
694
695 ret = devm_regulator_bulk_get(dev, priv->chip->num_supply_names,
696 priv->supplies);
697 if (ret) {
698 dev_err(dev, "Failed to get supplies: %d\n", ret);
699 return ret;
700 }
701 ret = regulator_bulk_enable(priv->chip->num_supply_names,
702 priv->supplies);
703 if (ret) {
704 dev_err(dev, "Failed to enable supplies: %d\n", ret);
705 return ret;
706 }
707
708 priv->regmap = devm_regmap_init(dev, NULL, client,
709 priv->chip->regmap_config);
710 if (IS_ERR(priv->regmap))
711 return PTR_ERR(priv->regmap);
712
713 priv->pdn_gpio = devm_gpiod_get_optional(dev, "pdn", GPIOD_OUT_LOW);
714 if (IS_ERR(priv->pdn_gpio)) {
715 dev_err(dev, "error requesting pdn_gpio: %ld\n",
716 PTR_ERR(priv->pdn_gpio));
717 return PTR_ERR(priv->pdn_gpio);
718 }
719
720 priv->reset_gpio = devm_gpiod_get_optional(dev, "reset",
721 GPIOD_OUT_HIGH);
722 if (IS_ERR(priv->reset_gpio)) {
723 dev_err(dev, "error requesting reset_gpio: %ld\n",
724 PTR_ERR(priv->reset_gpio));
725 return PTR_ERR(priv->reset_gpio);
726 } else if (priv->reset_gpio) {
727 /* pulse the active low reset line for ~100us */
728 usleep_range(100, 200);
729 gpiod_set_value(priv->reset_gpio, 0);
730 usleep_range(12000, 20000);
731 }
732
733 ret = regmap_write(priv->regmap, TAS571X_OSC_TRIM_REG, 0);
734 if (ret)
735 return ret;
736
3fd6e7d9
KC
737
738 memcpy(&priv->codec_driver, &tas571x_codec, sizeof(priv->codec_driver));
739 priv->codec_driver.controls = priv->chip->controls;
740 priv->codec_driver.num_controls = priv->chip->num_controls;
741
742 if (priv->chip->vol_reg_size == 2) {
743 /*
744 * The master volume defaults to 0x3ff (mute), but we ignore
745 * (zero) the LSB because the hardware step size is 0.125 dB
746 * and TLV_DB_SCALE_ITEM has a resolution of 0.01 dB.
747 */
748 ret = regmap_update_bits(priv->regmap, TAS571X_MVOL_REG, 1, 0);
749 if (ret)
750 return ret;
751 }
752
753 regcache_cache_only(priv->regmap, true);
754 gpiod_set_value(priv->pdn_gpio, 1);
755
756 return snd_soc_register_codec(&client->dev, &priv->codec_driver,
757 &tas571x_dai, 1);
758}
759
760static int tas571x_i2c_remove(struct i2c_client *client)
761{
762 struct tas571x_private *priv = i2c_get_clientdata(client);
763
764 snd_soc_unregister_codec(&client->dev);
765 regulator_bulk_disable(priv->chip->num_supply_names, priv->supplies);
766
767 return 0;
768}
769
770static const struct of_device_id tas571x_of_match[] = {
771 { .compatible = "ti,tas5711", .data = &tas5711_chip, },
772 { .compatible = "ti,tas5717", .data = &tas5717_chip, },
773 { .compatible = "ti,tas5719", .data = &tas5717_chip, },
23a282c4 774 { .compatible = "ti,tas5721", .data = &tas5721_chip, },
3fd6e7d9
KC
775 { }
776};
777MODULE_DEVICE_TABLE(of, tas571x_of_match);
778
779static const struct i2c_device_id tas571x_i2c_id[] = {
630e413d
PK
780 { "tas5711", (kernel_ulong_t) &tas5711_chip },
781 { "tas5717", (kernel_ulong_t) &tas5717_chip },
782 { "tas5719", (kernel_ulong_t) &tas5717_chip },
23a282c4 783 { "tas5721", (kernel_ulong_t) &tas5721_chip },
3fd6e7d9
KC
784 { }
785};
786MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id);
787
788static struct i2c_driver tas571x_i2c_driver = {
789 .driver = {
790 .name = "tas571x",
791 .of_match_table = of_match_ptr(tas571x_of_match),
792 },
793 .probe = tas571x_i2c_probe,
794 .remove = tas571x_i2c_remove,
795 .id_table = tas571x_i2c_id,
796};
797module_i2c_driver(tas571x_i2c_driver);
798
799MODULE_DESCRIPTION("ASoC TAS571x driver");
800MODULE_AUTHOR("Kevin Cernekee <cernekee@chromium.org>");
801MODULE_LICENSE("GPL");
This page took 0.088707 seconds and 5 git commands to generate.