22dbd89a8be0798178f5ac24eff83fbc20a13f78
[openwrt/staging/luka.git] /
1 From a1344150b31e3b9592f76df8f453a15565a8390a Mon Sep 17 00:00:00 2001
2 From: Daniel Matuschek <info@crazy-audio.com>
3 Date: Mon, 4 Aug 2014 11:09:58 +0200
4 Subject: [PATCH 069/806] Added driver for HiFiBerry Amp amplifier add-on board
5
6 The driver contains a low-level hardware driver for the TAS5713 and the
7 drivers for the Raspberry Pi I2S subsystem.
8
9 TAS5713: return error if initialisation fails
10
11 Existing TAS5713 driver logs errors during initialisation, but does not return
12 an error code. Therefore even if initialisation fails, the driver will still be
13 loaded, but won't work. This patch fixes this. I2C communication error will now
14 reported correctly by a non-zero return code.
15
16 HiFiBerry Amp: fix device-tree problems
17
18 Some code to load the driver based on device-tree-overlays was missing. This is added by this patch.
19 ---
20 sound/soc/codecs/Kconfig | 4 +
21 sound/soc/codecs/Makefile | 2 +
22 sound/soc/codecs/tas5713.c | 366 +++++++++++++++++++++++++++++++++++++
23 sound/soc/codecs/tas5713.h | 210 +++++++++++++++++++++
24 4 files changed, 582 insertions(+)
25 create mode 100644 sound/soc/codecs/tas5713.c
26 create mode 100644 sound/soc/codecs/tas5713.h
27
28 --- a/sound/soc/codecs/Kconfig
29 +++ b/sound/soc/codecs/Kconfig
30 @@ -167,6 +167,7 @@ config SND_SOC_ALL_CODECS
31 select SND_SOC_TFA9879 if I2C
32 select SND_SOC_TLV320AIC23_I2C if I2C
33 select SND_SOC_TLV320AIC23_SPI if SPI_MASTER
34 + select SND_SOC_TAS5713 if I2C
35 select SND_SOC_TLV320AIC26 if SPI_MASTER
36 select SND_SOC_TLV320AIC31XX if I2C
37 select SND_SOC_TLV320AIC32X4_I2C if I2C
38 @@ -997,6 +998,9 @@ config SND_SOC_TFA9879
39 tristate "NXP Semiconductors TFA9879 amplifier"
40 depends on I2C
41
42 +config SND_SOC_TAS5713
43 + tristate
44 +
45 config SND_SOC_TLV320AIC23
46 tristate
47
48 --- a/sound/soc/codecs/Makefile
49 +++ b/sound/soc/codecs/Makefile
50 @@ -176,6 +176,7 @@ snd-soc-tas5720-objs := tas5720.o
51 snd-soc-tas6424-objs := tas6424.o
52 snd-soc-tda7419-objs := tda7419.o
53 snd-soc-tfa9879-objs := tfa9879.o
54 +snd-soc-tas5713-objs := tas5713.o
55 snd-soc-tlv320aic23-objs := tlv320aic23.o
56 snd-soc-tlv320aic23-i2c-objs := tlv320aic23-i2c.o
57 snd-soc-tlv320aic23-spi-objs := tlv320aic23-spi.o
58 @@ -436,6 +437,7 @@ obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc
59 obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
60 obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
61 obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
62 +obj-$(CONFIG_SND_SOC_TAS5713) += snd-soc-tas5713.o
63 obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
64 obj-$(CONFIG_SND_SOC_TLV320AIC23_I2C) += snd-soc-tlv320aic23-i2c.o
65 obj-$(CONFIG_SND_SOC_TLV320AIC23_SPI) += snd-soc-tlv320aic23-spi.o
66 --- /dev/null
67 +++ b/sound/soc/codecs/tas5713.c
68 @@ -0,0 +1,366 @@
69 +/*
70 + * ASoC Driver for TAS5713
71 + *
72 + * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
73 + * Copyright 2014
74 + *
75 + * This program is free software; you can redistribute it and/or
76 + * modify it under the terms of the GNU General Public License
77 + * version 2 as published by the Free Software Foundation.
78 + *
79 + * This program is distributed in the hope that it will be useful, but
80 + * WITHOUT ANY WARRANTY; without even the implied warranty of
81 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
82 + * General Public License for more details.
83 + */
84 +
85 +#include <linux/module.h>
86 +#include <linux/moduleparam.h>
87 +#include <linux/init.h>
88 +#include <linux/delay.h>
89 +#include <linux/pm.h>
90 +#include <linux/i2c.h>
91 +#include <linux/of_device.h>
92 +#include <linux/spi/spi.h>
93 +#include <linux/regmap.h>
94 +#include <linux/regulator/consumer.h>
95 +#include <linux/slab.h>
96 +#include <sound/core.h>
97 +#include <sound/pcm.h>
98 +#include <sound/pcm_params.h>
99 +#include <sound/soc.h>
100 +#include <sound/initval.h>
101 +#include <sound/tlv.h>
102 +
103 +#include <linux/kernel.h>
104 +#include <linux/string.h>
105 +#include <linux/fs.h>
106 +#include <asm/uaccess.h>
107 +
108 +#include "tas5713.h"
109 +
110 +
111 +static struct i2c_client *i2c;
112 +
113 +struct tas5713_priv {
114 + struct regmap *regmap;
115 + int mclk_div;
116 + struct snd_soc_component *component;
117 +};
118 +
119 +static struct tas5713_priv *priv_data;
120 +
121 +
122 +
123 +
124 +/*
125 + * _ _ ___ _ ___ _ _
126 + * /_\ | | / __| /_\ / __|___ _ _| |_ _ _ ___| |___
127 + * / _ \| |__\__ \/ _ \ | (__/ _ \ ' \ _| '_/ _ \ (_-<
128 + * /_/ \_\____|___/_/ \_\ \___\___/_||_\__|_| \___/_/__/
129 + *
130 + */
131 +
132 +static const DECLARE_TLV_DB_SCALE(tas5713_vol_tlv, -10000, 50, 1);
133 +
134 +
135 +static const struct snd_kcontrol_new tas5713_snd_controls[] = {
136 + SOC_SINGLE_TLV ("Master" , TAS5713_VOL_MASTER, 0, 248, 1, tas5713_vol_tlv),
137 + SOC_DOUBLE_R_TLV("Channels" , TAS5713_VOL_CH1, TAS5713_VOL_CH2, 0, 248, 1, tas5713_vol_tlv)
138 +};
139 +
140 +
141 +
142 +
143 +/*
144 + * __ __ _ _ ___ _
145 + * | \/ |__ _ __| |_ (_)_ _ ___ | \ _ _(_)_ _____ _ _
146 + * | |\/| / _` / _| ' \| | ' \/ -_) | |) | '_| \ V / -_) '_|
147 + * |_| |_\__,_\__|_||_|_|_||_\___| |___/|_| |_|\_/\___|_|
148 + *
149 + */
150 +
151 +static int tas5713_hw_params(struct snd_pcm_substream *substream,
152 + struct snd_pcm_hw_params *params,
153 + struct snd_soc_dai *dai)
154 +{
155 + u16 blen = 0x00;
156 +
157 + struct snd_soc_component *component = dai->component;
158 + priv_data->component = component;
159 +
160 + switch (params_format(params)) {
161 + case SNDRV_PCM_FORMAT_S16_LE:
162 + blen = 0x03;
163 + break;
164 + case SNDRV_PCM_FORMAT_S20_3LE:
165 + blen = 0x1;
166 + break;
167 + case SNDRV_PCM_FORMAT_S24_LE:
168 + blen = 0x04;
169 + break;
170 + case SNDRV_PCM_FORMAT_S32_LE:
171 + blen = 0x05;
172 + break;
173 + default:
174 + dev_err(dai->dev, "Unsupported word length: %u\n",
175 + params_format(params));
176 + return -EINVAL;
177 + }
178 +
179 + // set word length
180 + snd_soc_component_update_bits(component, TAS5713_SERIAL_DATA_INTERFACE, 0x7, blen);
181 +
182 + return 0;
183 +}
184 +
185 +
186 +static int tas5713_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
187 +{
188 + unsigned int val = 0;
189 +
190 + struct tas5713_priv *tas5713;
191 + struct snd_soc_component *component = dai->component;
192 + tas5713 = snd_soc_component_get_drvdata(component);
193 +
194 + if (mute) {
195 + val = TAS5713_SOFT_MUTE_ALL;
196 + }
197 +
198 + return regmap_write(tas5713->regmap, TAS5713_SOFT_MUTE, val);
199 +}
200 +
201 +
202 +static const struct snd_soc_dai_ops tas5713_dai_ops = {
203 + .hw_params = tas5713_hw_params,
204 + .mute_stream = tas5713_mute_stream,
205 +};
206 +
207 +
208 +static struct snd_soc_dai_driver tas5713_dai = {
209 + .name = "tas5713-hifi",
210 + .playback = {
211 + .stream_name = "Playback",
212 + .channels_min = 2,
213 + .channels_max = 2,
214 + .rates = SNDRV_PCM_RATE_8000_48000,
215 + .formats = (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE ),
216 + },
217 + .ops = &tas5713_dai_ops,
218 +};
219 +
220 +
221 +
222 +
223 +/*
224 + * ___ _ ___ _
225 + * / __|___ __| |___ __ | \ _ _(_)_ _____ _ _
226 + * | (__/ _ \/ _` / -_) _| | |) | '_| \ V / -_) '_|
227 + * \___\___/\__,_\___\__| |___/|_| |_|\_/\___|_|
228 + *
229 + */
230 +
231 +static void tas5713_remove(struct snd_soc_component *component)
232 +{
233 + struct tas5713_priv *tas5713;
234 +
235 + tas5713 = snd_soc_component_get_drvdata(component);
236 +}
237 +
238 +
239 +static int tas5713_probe(struct snd_soc_component *component)
240 +{
241 + struct tas5713_priv *tas5713;
242 + int i, ret;
243 +
244 + i2c = container_of(component->dev, struct i2c_client, dev);
245 +
246 + tas5713 = snd_soc_component_get_drvdata(component);
247 +
248 + // Reset error
249 + ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
250 + if (ret < 0) return ret;
251 +
252 + // Trim oscillator
253 + ret = snd_soc_component_write(component, TAS5713_OSC_TRIM, 0x00);
254 + if (ret < 0) return ret;
255 + msleep(1000);
256 +
257 + // Reset error
258 + ret = snd_soc_component_write(component, TAS5713_ERROR_STATUS, 0x00);
259 + if (ret < 0) return ret;
260 +
261 + // Clock mode: 44/48kHz, MCLK=64xfs
262 + ret = snd_soc_component_write(component, TAS5713_CLOCK_CTRL, 0x60);
263 + if (ret < 0) return ret;
264 +
265 + // I2S 24bit
266 + ret = snd_soc_component_write(component, TAS5713_SERIAL_DATA_INTERFACE, 0x05);
267 + if (ret < 0) return ret;
268 +
269 + // Unmute
270 + ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
271 + if (ret < 0) return ret;
272 + ret = snd_soc_component_write(component, TAS5713_SOFT_MUTE, 0x00);
273 + if (ret < 0) return ret;
274 +
275 + // Set volume to 0db
276 + ret = snd_soc_component_write(component, TAS5713_VOL_MASTER, 0x00);
277 + if (ret < 0) return ret;
278 +
279 + // Now start programming the default initialization sequence
280 + for (i = 0; i < ARRAY_SIZE(tas5713_init_sequence); ++i) {
281 + ret = i2c_master_send(i2c,
282 + tas5713_init_sequence[i].data,
283 + tas5713_init_sequence[i].size);
284 + if (ret < 0) {
285 + printk(KERN_INFO "TAS5713 CODEC PROBE: InitSeq returns: %d\n", ret);
286 + }
287 + }
288 +
289 + // Unmute
290 + ret = snd_soc_component_write(component, TAS5713_SYSTEM_CTRL2, 0x00);
291 + if (ret < 0) return ret;
292 +
293 + return 0;
294 +}
295 +
296 +
297 +static struct snd_soc_component_driver soc_codec_dev_tas5713 = {
298 + .probe = tas5713_probe,
299 + .remove = tas5713_remove,
300 + .controls = tas5713_snd_controls,
301 + .num_controls = ARRAY_SIZE(tas5713_snd_controls),
302 +};
303 +
304 +
305 +
306 +
307 +/*
308 + * ___ ___ ___ ___ _
309 + * |_ _|_ ) __| | \ _ _(_)_ _____ _ _
310 + * | | / / (__ | |) | '_| \ V / -_) '_|
311 + * |___/___\___| |___/|_| |_|\_/\___|_|
312 + *
313 + */
314 +
315 +static const struct reg_default tas5713_reg_defaults[] = {
316 + { 0x07 ,0x80 }, // R7 - VOL_MASTER - -40dB
317 + { 0x08 , 30 }, // R8 - VOL_CH1 - 0dB
318 + { 0x09 , 30 }, // R9 - VOL_CH2 - 0dB
319 + { 0x0A ,0x80 }, // R10 - VOL_HEADPHONE - -40dB
320 +};
321 +
322 +
323 +static bool tas5713_reg_volatile(struct device *dev, unsigned int reg)
324 +{
325 + switch (reg) {
326 + case TAS5713_DEVICE_ID:
327 + case TAS5713_ERROR_STATUS:
328 + return true;
329 + default:
330 + return false;
331 + }
332 +}
333 +
334 +
335 +static const struct of_device_id tas5713_of_match[] = {
336 + { .compatible = "ti,tas5713", },
337 + { }
338 +};
339 +MODULE_DEVICE_TABLE(of, tas5713_of_match);
340 +
341 +
342 +static struct regmap_config tas5713_regmap_config = {
343 + .reg_bits = 8,
344 + .val_bits = 8,
345 +
346 + .max_register = TAS5713_MAX_REGISTER,
347 + .volatile_reg = tas5713_reg_volatile,
348 +
349 + .cache_type = REGCACHE_RBTREE,
350 + .reg_defaults = tas5713_reg_defaults,
351 + .num_reg_defaults = ARRAY_SIZE(tas5713_reg_defaults),
352 +};
353 +
354 +
355 +static int tas5713_i2c_probe(struct i2c_client *i2c,
356 + const struct i2c_device_id *id)
357 +{
358 + int ret;
359 +
360 + priv_data = devm_kzalloc(&i2c->dev, sizeof *priv_data, GFP_KERNEL);
361 + if (!priv_data)
362 + return -ENOMEM;
363 +
364 + priv_data->regmap = devm_regmap_init_i2c(i2c, &tas5713_regmap_config);
365 + if (IS_ERR(priv_data->regmap)) {
366 + ret = PTR_ERR(priv_data->regmap);
367 + return ret;
368 + }
369 +
370 + i2c_set_clientdata(i2c, priv_data);
371 +
372 + ret = snd_soc_register_component(&i2c->dev,
373 + &soc_codec_dev_tas5713, &tas5713_dai, 1);
374 +
375 + return ret;
376 +}
377 +
378 +
379 +static int tas5713_i2c_remove(struct i2c_client *i2c)
380 +{
381 + snd_soc_unregister_component(&i2c->dev);
382 + i2c_set_clientdata(i2c, NULL);
383 +
384 + kfree(priv_data);
385 +
386 + return 0;
387 +}
388 +
389 +
390 +static const struct i2c_device_id tas5713_i2c_id[] = {
391 + { "tas5713", 0 },
392 + { }
393 +};
394 +
395 +MODULE_DEVICE_TABLE(i2c, tas5713_i2c_id);
396 +
397 +
398 +static struct i2c_driver tas5713_i2c_driver = {
399 + .driver = {
400 + .name = "tas5713",
401 + .owner = THIS_MODULE,
402 + .of_match_table = tas5713_of_match,
403 + },
404 + .probe = tas5713_i2c_probe,
405 + .remove = tas5713_i2c_remove,
406 + .id_table = tas5713_i2c_id
407 +};
408 +
409 +
410 +static int __init tas5713_modinit(void)
411 +{
412 + int ret = 0;
413 +
414 + ret = i2c_add_driver(&tas5713_i2c_driver);
415 + if (ret) {
416 + printk(KERN_ERR "Failed to register tas5713 I2C driver: %d\n",
417 + ret);
418 + }
419 +
420 + return ret;
421 +}
422 +module_init(tas5713_modinit);
423 +
424 +
425 +static void __exit tas5713_exit(void)
426 +{
427 + i2c_del_driver(&tas5713_i2c_driver);
428 +}
429 +module_exit(tas5713_exit);
430 +
431 +
432 +MODULE_AUTHOR("Sebastian Eickhoff <basti.eickhoff@googlemail.com>");
433 +MODULE_DESCRIPTION("ASoC driver for TAS5713");
434 +MODULE_LICENSE("GPL v2");
435 --- /dev/null
436 +++ b/sound/soc/codecs/tas5713.h
437 @@ -0,0 +1,210 @@
438 +/*
439 + * ASoC Driver for TAS5713
440 + *
441 + * Author: Sebastian Eickhoff <basti.eickhoff@googlemail.com>
442 + * Copyright 2014
443 + *
444 + * This program is free software; you can redistribute it and/or
445 + * modify it under the terms of the GNU General Public License
446 + * version 2 as published by the Free Software Foundation.
447 + *
448 + * This program is distributed in the hope that it will be useful, but
449 + * WITHOUT ANY WARRANTY; without even the implied warranty of
450 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
451 + * General Public License for more details.
452 + */
453 +
454 +#ifndef _TAS5713_H
455 +#define _TAS5713_H
456 +
457 +
458 +// TAS5713 I2C-bus register addresses
459 +
460 +#define TAS5713_CLOCK_CTRL 0x00
461 +#define TAS5713_DEVICE_ID 0x01
462 +#define TAS5713_ERROR_STATUS 0x02
463 +#define TAS5713_SYSTEM_CTRL1 0x03
464 +#define TAS5713_SERIAL_DATA_INTERFACE 0x04
465 +#define TAS5713_SYSTEM_CTRL2 0x05
466 +#define TAS5713_SOFT_MUTE 0x06
467 +#define TAS5713_VOL_MASTER 0x07
468 +#define TAS5713_VOL_CH1 0x08
469 +#define TAS5713_VOL_CH2 0x09
470 +#define TAS5713_VOL_HEADPHONE 0x0A
471 +#define TAS5713_VOL_CONFIG 0x0E
472 +#define TAS5713_MODULATION_LIMIT 0x10
473 +#define TAS5713_IC_DLY_CH1 0x11
474 +#define TAS5713_IC_DLY_CH2 0x12
475 +#define TAS5713_IC_DLY_CH3 0x13
476 +#define TAS5713_IC_DLY_CH4 0x14
477 +
478 +#define TAS5713_START_STOP_PERIOD 0x1A
479 +#define TAS5713_OSC_TRIM 0x1B
480 +#define TAS5713_BKND_ERR 0x1C
481 +
482 +#define TAS5713_INPUT_MUX 0x20
483 +#define TAS5713_SRC_SELECT_CH4 0x21
484 +#define TAS5713_PWM_MUX 0x25
485 +
486 +#define TAS5713_CH1_BQ0 0x29
487 +#define TAS5713_CH1_BQ1 0x2A
488 +#define TAS5713_CH1_BQ2 0x2B
489 +#define TAS5713_CH1_BQ3 0x2C
490 +#define TAS5713_CH1_BQ4 0x2D
491 +#define TAS5713_CH1_BQ5 0x2E
492 +#define TAS5713_CH1_BQ6 0x2F
493 +#define TAS5713_CH1_BQ7 0x58
494 +#define TAS5713_CH1_BQ8 0x59
495 +
496 +#define TAS5713_CH2_BQ0 0x30
497 +#define TAS5713_CH2_BQ1 0x31
498 +#define TAS5713_CH2_BQ2 0x32
499 +#define TAS5713_CH2_BQ3 0x33
500 +#define TAS5713_CH2_BQ4 0x34
501 +#define TAS5713_CH2_BQ5 0x35
502 +#define TAS5713_CH2_BQ6 0x36
503 +#define TAS5713_CH2_BQ7 0x5C
504 +#define TAS5713_CH2_BQ8 0x5D
505 +
506 +#define TAS5713_CH4_BQ0 0x5A
507 +#define TAS5713_CH4_BQ1 0x5B
508 +#define TAS5713_CH3_BQ0 0x5E
509 +#define TAS5713_CH3_BQ1 0x5F
510 +
511 +#define TAS5713_DRC1_SOFTENING_FILTER_ALPHA_OMEGA 0x3B
512 +#define TAS5713_DRC1_ATTACK_RELEASE_RATE 0x3C
513 +#define TAS5713_DRC2_SOFTENING_FILTER_ALPHA_OMEGA 0x3E
514 +#define TAS5713_DRC2_ATTACK_RELEASE_RATE 0x3F
515 +#define TAS5713_DRC1_ATTACK_RELEASE_THRES 0x40
516 +#define TAS5713_DRC2_ATTACK_RELEASE_THRES 0x43
517 +#define TAS5713_DRC_CTRL 0x46
518 +
519 +#define TAS5713_BANK_SW_CTRL 0x50
520 +#define TAS5713_CH1_OUTPUT_MIXER 0x51
521 +#define TAS5713_CH2_OUTPUT_MIXER 0x52
522 +#define TAS5713_CH1_INPUT_MIXER 0x53
523 +#define TAS5713_CH2_INPUT_MIXER 0x54
524 +#define TAS5713_OUTPUT_POST_SCALE 0x56
525 +#define TAS5713_OUTPUT_PRESCALE 0x57
526 +
527 +#define TAS5713_IDF_POST_SCALE 0x62
528 +
529 +#define TAS5713_CH1_INLINE_MIXER 0x70
530 +#define TAS5713_CH1_INLINE_DRC_EN_MIXER 0x71
531 +#define TAS5713_CH1_R_CHANNEL_MIXER 0x72
532 +#define TAS5713_CH1_L_CHANNEL_MIXER 0x73
533 +#define TAS5713_CH2_INLINE_MIXER 0x74
534 +#define TAS5713_CH2_INLINE_DRC_EN_MIXER 0x75
535 +#define TAS5713_CH2_L_CHANNEL_MIXER 0x76
536 +#define TAS5713_CH2_R_CHANNEL_MIXER 0x77
537 +
538 +#define TAS5713_UPDATE_DEV_ADDR_KEY 0xF8
539 +#define TAS5713_UPDATE_DEV_ADDR_REG 0xF9
540 +
541 +#define TAS5713_REGISTER_COUNT 0x46
542 +#define TAS5713_MAX_REGISTER 0xF9
543 +
544 +
545 +// Bitmasks for registers
546 +#define TAS5713_SOFT_MUTE_ALL 0x07
547 +
548 +
549 +
550 +struct tas5713_init_command {
551 + const int size;
552 + const char *const data;
553 +};
554 +
555 +static const struct tas5713_init_command tas5713_init_sequence[] = {
556 +
557 + // Trim oscillator
558 + { .size = 2, .data = "\x1B\x00" },
559 + // System control register 1 (0x03): block DC
560 + { .size = 2, .data = "\x03\x80" },
561 + // Mute everything
562 + { .size = 2, .data = "\x05\x40" },
563 + // Modulation limit register (0x10): 97.7%
564 + { .size = 2, .data = "\x10\x02" },
565 + // Interchannel delay registers
566 + // (0x11, 0x12, 0x13, and 0x14): BD mode
567 + { .size = 2, .data = "\x11\xB8" },
568 + { .size = 2, .data = "\x12\x60" },
569 + { .size = 2, .data = "\x13\xA0" },
570 + { .size = 2, .data = "\x14\x48" },
571 + // PWM shutdown group register (0x19): no shutdown
572 + { .size = 2, .data = "\x19\x00" },
573 + // Input multiplexer register (0x20): BD mode
574 + { .size = 2, .data = "\x20\x00\x89\x77\x72" },
575 + // PWM output mux register (0x25)
576 + // Channel 1 --> OUTA, channel 1 neg --> OUTB
577 + // Channel 2 --> OUTC, channel 2 neg --> OUTD
578 + { .size = 5, .data = "\x25\x01\x02\x13\x45" },
579 + // DRC control (0x46): DRC off
580 + { .size = 5, .data = "\x46\x00\x00\x00\x00" },
581 + // BKND_ERR register (0x1C): 299ms reset period
582 + { .size = 2, .data = "\x1C\x07" },
583 + // Mute channel 3
584 + { .size = 2, .data = "\x0A\xFF" },
585 + // Volume configuration register (0x0E): volume slew 512 steps
586 + { .size = 2, .data = "\x0E\x90" },
587 + // Clock control register (0x00): 44/48kHz, MCLK=64xfs
588 + { .size = 2, .data = "\x00\x60" },
589 + // Bank switch and eq control (0x50): no bank switching
590 + { .size = 5, .data = "\x50\x00\x00\x00\x00" },
591 + // Volume registers (0x07, 0x08, 0x09, 0x0A)
592 + { .size = 2, .data = "\x07\x20" },
593 + { .size = 2, .data = "\x08\x30" },
594 + { .size = 2, .data = "\x09\x30" },
595 + { .size = 2, .data = "\x0A\xFF" },
596 + // 0x72, 0x73, 0x76, 0x77 input mixer:
597 + // no intermix between channels
598 + { .size = 5, .data = "\x72\x00\x00\x00\x00" },
599 + { .size = 5, .data = "\x73\x00\x80\x00\x00" },
600 + { .size = 5, .data = "\x76\x00\x00\x00\x00" },
601 + { .size = 5, .data = "\x77\x00\x80\x00\x00" },
602 + // 0x70, 0x71, 0x74, 0x75 inline DRC mixer:
603 + // no inline DRC inmix
604 + { .size = 5, .data = "\x70\x00\x80\x00\x00" },
605 + { .size = 5, .data = "\x71\x00\x00\x00\x00" },
606 + { .size = 5, .data = "\x74\x00\x80\x00\x00" },
607 + { .size = 5, .data = "\x75\x00\x00\x00\x00" },
608 + // 0x56, 0x57 Output scale
609 + { .size = 5, .data = "\x56\x00\x80\x00\x00" },
610 + { .size = 5, .data = "\x57\x00\x02\x00\x00" },
611 + // 0x3B, 0x3c
612 + { .size = 9, .data = "\x3B\x00\x08\x00\x00\x00\x78\x00\x00" },
613 + { .size = 9, .data = "\x3C\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
614 + { .size = 9, .data = "\x3E\x00\x08\x00\x00\x00\x78\x00\x00" },
615 + { .size = 9, .data = "\x3F\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
616 + { .size = 9, .data = "\x40\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
617 + { .size = 9, .data = "\x43\x00\x00\x01\x00\xFF\xFF\xFF\x00" },
618 + // 0x51, 0x52: output mixer
619 + { .size = 9, .data = "\x51\x00\x80\x00\x00\x00\x00\x00\x00" },
620 + { .size = 9, .data = "\x52\x00\x80\x00\x00\x00\x00\x00\x00" },
621 + // PEQ defaults
622 + { .size = 21, .data = "\x29\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
623 + { .size = 21, .data = "\x2A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
624 + { .size = 21, .data = "\x2B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
625 + { .size = 21, .data = "\x2C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
626 + { .size = 21, .data = "\x2D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
627 + { .size = 21, .data = "\x2E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
628 + { .size = 21, .data = "\x2F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
629 + { .size = 21, .data = "\x30\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
630 + { .size = 21, .data = "\x31\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
631 + { .size = 21, .data = "\x32\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
632 + { .size = 21, .data = "\x33\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
633 + { .size = 21, .data = "\x34\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
634 + { .size = 21, .data = "\x35\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
635 + { .size = 21, .data = "\x36\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
636 + { .size = 21, .data = "\x58\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
637 + { .size = 21, .data = "\x59\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
638 + { .size = 21, .data = "\x5C\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
639 + { .size = 21, .data = "\x5D\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
640 + { .size = 21, .data = "\x5E\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
641 + { .size = 21, .data = "\x5F\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
642 + { .size = 21, .data = "\x5A\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
643 + { .size = 21, .data = "\x5B\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" },
644 +};
645 +
646 +
647 +#endif /* _TAS5713_H */