28
28
#include <sound/pcm_params.h>
29
29
#include <sound/soc.h>
30
30
#include <sound/tlv.h>
31
+ #include <asm/unaligned.h>
31
32
32
33
#include "tas571x.h"
33
34
@@ -63,6 +64,10 @@ static int tas571x_register_size(struct tas571x_private *priv, unsigned int reg)
63
64
case TAS571X_INPUT_MUX_REG :
64
65
case TAS571X_CH4_SRC_SELECT_REG :
65
66
case TAS571X_PWM_MUX_REG :
67
+ case TAS5717_CH1_RIGHT_CH_MIX_REG :
68
+ case TAS5717_CH1_LEFT_CH_MIX_REG :
69
+ case TAS5717_CH2_LEFT_CH_MIX_REG :
70
+ case TAS5717_CH2_RIGHT_CH_MIX_REG :
66
71
return 4 ;
67
72
default :
68
73
return 1 ;
@@ -135,6 +140,129 @@ static int tas571x_reg_read(void *context, unsigned int reg,
135
140
return 0 ;
136
141
}
137
142
143
+ /*
144
+ * register write for 8- and 20-byte registers
145
+ */
146
+ static int tas571x_reg_write_multiword (struct i2c_client * client ,
147
+ unsigned int reg , const long values [], size_t len )
148
+ {
149
+ size_t i ;
150
+ uint8_t * buf , * p ;
151
+ int ret ;
152
+ size_t send_size = 1 + len * sizeof (uint32_t );
153
+
154
+ buf = kzalloc (send_size , GFP_KERNEL | GFP_DMA );
155
+ if (!buf )
156
+ return - ENOMEM ;
157
+ buf [0 ] = reg ;
158
+
159
+ for (i = 0 , p = buf + 1 ; i < len ; i ++ , p += sizeof (uint32_t ))
160
+ put_unaligned_be32 (values [i ], p );
161
+
162
+ ret = i2c_master_send (client , buf , send_size );
163
+
164
+ kfree (buf );
165
+
166
+ if (ret == send_size )
167
+ return 0 ;
168
+ else if (ret < 0 )
169
+ return ret ;
170
+ else
171
+ return - EIO ;
172
+ }
173
+
174
+ /*
175
+ * register read for 8- and 20-byte registers
176
+ */
177
+ static int tas571x_reg_read_multiword (struct i2c_client * client ,
178
+ unsigned int reg , long values [], size_t len )
179
+ {
180
+ unsigned int i ;
181
+ uint8_t send_buf ;
182
+ uint8_t * recv_buf , * p ;
183
+ struct i2c_msg msgs [2 ];
184
+ unsigned int recv_size = len * sizeof (uint32_t );
185
+ int ret ;
186
+
187
+ recv_buf = kzalloc (recv_size , GFP_KERNEL | GFP_DMA );
188
+ if (!recv_buf )
189
+ return - ENOMEM ;
190
+
191
+ send_buf = reg ;
192
+
193
+ msgs [0 ].addr = client -> addr ;
194
+ msgs [0 ].len = sizeof (send_buf );
195
+ msgs [0 ].buf = & send_buf ;
196
+ msgs [0 ].flags = 0 ;
197
+
198
+ msgs [1 ].addr = client -> addr ;
199
+ msgs [1 ].len = recv_size ;
200
+ msgs [1 ].buf = recv_buf ;
201
+ msgs [1 ].flags = I2C_M_RD ;
202
+
203
+ ret = i2c_transfer (client -> adapter , msgs , ARRAY_SIZE (msgs ));
204
+ if (ret < 0 )
205
+ goto err_ret ;
206
+ else if (ret != ARRAY_SIZE (msgs )) {
207
+ ret = - EIO ;
208
+ goto err_ret ;
209
+ }
210
+
211
+ for (i = 0 , p = recv_buf ; i < len ; i ++ , p += sizeof (uint32_t ))
212
+ values [i ] = get_unaligned_be32 (p );
213
+
214
+ err_ret :
215
+ kfree (recv_buf );
216
+ return ret ;
217
+ }
218
+
219
+ /*
220
+ * Integer array controls for setting biquad, mixer, DRC coefficients.
221
+ * According to the datasheet each coefficient is effectively 26bits,
222
+ * i.e. stored as 32bits, where bits [31:26] are ignored.
223
+ * TI's TAS57xx Graphical Development Environment tool however produces
224
+ * coefficients with more than 26 bits. For this reason we allow values
225
+ * in the full 32-bits reange.
226
+ * The coefficients are ordered as given in the TAS571x data sheet:
227
+ * b0, b1, b2, a1, a2
228
+ */
229
+
230
+ static int tas571x_coefficient_info (struct snd_kcontrol * kcontrol ,
231
+ struct snd_ctl_elem_info * uinfo )
232
+ {
233
+ int numcoef = kcontrol -> private_value >> 16 ;
234
+
235
+ uinfo -> type = SNDRV_CTL_ELEM_TYPE_INTEGER ;
236
+ uinfo -> count = numcoef ;
237
+ uinfo -> value .integer .min = 0 ;
238
+ uinfo -> value .integer .max = 0xffffffff ;
239
+ return 0 ;
240
+ }
241
+
242
+ static int tas571x_coefficient_get (struct snd_kcontrol * kcontrol ,
243
+ struct snd_ctl_elem_value * ucontrol )
244
+ {
245
+ struct snd_soc_codec * codec = snd_soc_kcontrol_codec (kcontrol );
246
+ struct i2c_client * i2c = to_i2c_client (codec -> dev );
247
+ int numcoef = kcontrol -> private_value >> 16 ;
248
+ int index = kcontrol -> private_value & 0xffff ;
249
+
250
+ return tas571x_reg_read_multiword (i2c , index ,
251
+ ucontrol -> value .integer .value , numcoef );
252
+ }
253
+
254
+ static int tas571x_coefficient_put (struct snd_kcontrol * kcontrol ,
255
+ struct snd_ctl_elem_value * ucontrol )
256
+ {
257
+ struct snd_soc_codec * codec = snd_soc_kcontrol_codec (kcontrol );
258
+ struct i2c_client * i2c = to_i2c_client (codec -> dev );
259
+ int numcoef = kcontrol -> private_value >> 16 ;
260
+ int index = kcontrol -> private_value & 0xffff ;
261
+
262
+ return tas571x_reg_write_multiword (i2c , index ,
263
+ ucontrol -> value .integer .value , numcoef );
264
+ }
265
+
138
266
static int tas571x_set_dai_fmt (struct snd_soc_dai * dai , unsigned int format )
139
267
{
140
268
struct tas571x_private * priv = snd_soc_codec_get_drvdata (dai -> codec );
@@ -241,6 +369,15 @@ static const struct snd_soc_dai_ops tas571x_dai_ops = {
241
369
.digital_mute = tas571x_mute ,
242
370
};
243
371
372
+
373
+ #define BIQUAD_COEFS (xname , reg ) \
374
+ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
375
+ .info = tas571x_coefficient_info, \
376
+ .get = tas571x_coefficient_get,\
377
+ .put = tas571x_coefficient_put, \
378
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
379
+ .private_value = reg | (5 << 16) }
380
+
244
381
static const char * const tas5711_supply_names [] = {
245
382
"AVDD" ,
246
383
"DVDD" ,
@@ -264,6 +401,16 @@ static const struct snd_kcontrol_new tas5711_controls[] = {
264
401
TAS571X_SOFT_MUTE_REG ,
265
402
TAS571X_SOFT_MUTE_CH1_SHIFT , TAS571X_SOFT_MUTE_CH2_SHIFT ,
266
403
1 , 1 ),
404
+
405
+ SOC_DOUBLE_R_RANGE ("CH1 Mixer Volume" ,
406
+ TAS5717_CH1_LEFT_CH_MIX_REG ,
407
+ TAS5717_CH1_RIGHT_CH_MIX_REG ,
408
+ 16 , 0 , 0x80 , 0 ),
409
+
410
+ SOC_DOUBLE_R_RANGE ("CH2 Mixer Volume" ,
411
+ TAS5717_CH2_LEFT_CH_MIX_REG ,
412
+ TAS5717_CH2_RIGHT_CH_MIX_REG ,
413
+ 16 , 0 , 0x80 , 0 ),
267
414
};
268
415
269
416
static const struct regmap_range tas571x_readonly_regs_range [] = {
@@ -340,6 +487,43 @@ static const struct snd_kcontrol_new tas5717_controls[] = {
340
487
TAS571X_SOFT_MUTE_REG ,
341
488
TAS571X_SOFT_MUTE_CH1_SHIFT , TAS571X_SOFT_MUTE_CH2_SHIFT ,
342
489
1 , 1 ),
490
+
491
+ /*
492
+ * The biquads are named according to the register names.
493
+ * Please note that TI's TAS57xx Graphical Development Environment
494
+ * tool names them different.
495
+ */
496
+ BIQUAD_COEFS ("CH1 - Biquad 0" , TAS5717_CH1_BQ0_REG ),
497
+ BIQUAD_COEFS ("CH1 - Biquad 1" , TAS5717_CH1_BQ1_REG ),
498
+ BIQUAD_COEFS ("CH1 - Biquad 2" , TAS5717_CH1_BQ2_REG ),
499
+ BIQUAD_COEFS ("CH1 - Biquad 3" , TAS5717_CH1_BQ3_REG ),
500
+ BIQUAD_COEFS ("CH1 - Biquad 4" , TAS5717_CH1_BQ4_REG ),
501
+ BIQUAD_COEFS ("CH1 - Biquad 5" , TAS5717_CH1_BQ5_REG ),
502
+ BIQUAD_COEFS ("CH1 - Biquad 6" , TAS5717_CH1_BQ6_REG ),
503
+ BIQUAD_COEFS ("CH1 - Biquad 7" , TAS5717_CH1_BQ7_REG ),
504
+ BIQUAD_COEFS ("CH1 - Biquad 8" , TAS5717_CH1_BQ8_REG ),
505
+ BIQUAD_COEFS ("CH1 - Biquad 9" , TAS5717_CH1_BQ9_REG ),
506
+ BIQUAD_COEFS ("CH1 - Biquad 10" , TAS5717_CH1_BQ10_REG ),
507
+ BIQUAD_COEFS ("CH1 - Biquad 11" , TAS5717_CH1_BQ11_REG ),
508
+
509
+ BIQUAD_COEFS ("CH2 - Biquad 0" , TAS5717_CH2_BQ0_REG ),
510
+ BIQUAD_COEFS ("CH2 - Biquad 1" , TAS5717_CH2_BQ1_REG ),
511
+ BIQUAD_COEFS ("CH2 - Biquad 2" , TAS5717_CH2_BQ2_REG ),
512
+ BIQUAD_COEFS ("CH2 - Biquad 3" , TAS5717_CH2_BQ3_REG ),
513
+ BIQUAD_COEFS ("CH2 - Biquad 4" , TAS5717_CH2_BQ4_REG ),
514
+ BIQUAD_COEFS ("CH2 - Biquad 5" , TAS5717_CH2_BQ5_REG ),
515
+ BIQUAD_COEFS ("CH2 - Biquad 6" , TAS5717_CH2_BQ6_REG ),
516
+ BIQUAD_COEFS ("CH2 - Biquad 7" , TAS5717_CH2_BQ7_REG ),
517
+ BIQUAD_COEFS ("CH2 - Biquad 8" , TAS5717_CH2_BQ8_REG ),
518
+ BIQUAD_COEFS ("CH2 - Biquad 9" , TAS5717_CH2_BQ9_REG ),
519
+ BIQUAD_COEFS ("CH2 - Biquad 10" , TAS5717_CH2_BQ10_REG ),
520
+ BIQUAD_COEFS ("CH2 - Biquad 11" , TAS5717_CH2_BQ11_REG ),
521
+
522
+ BIQUAD_COEFS ("CH3 - Biquad 0" , TAS5717_CH3_BQ0_REG ),
523
+ BIQUAD_COEFS ("CH3 - Biquad 1" , TAS5717_CH3_BQ1_REG ),
524
+
525
+ BIQUAD_COEFS ("CH4 - Biquad 0" , TAS5717_CH4_BQ0_REG ),
526
+ BIQUAD_COEFS ("CH4 - Biquad 1" , TAS5717_CH4_BQ1_REG ),
343
527
};
344
528
345
529
static const struct reg_default tas5717_reg_defaults [] = {
@@ -350,6 +534,10 @@ static const struct reg_default tas5717_reg_defaults[] = {
350
534
{ 0x08 , 0x00c0 },
351
535
{ 0x09 , 0x00c0 },
352
536
{ 0x1b , 0x82 },
537
+ { TAS5717_CH1_RIGHT_CH_MIX_REG , 0x0 },
538
+ { TAS5717_CH1_LEFT_CH_MIX_REG , 0x800000 },
539
+ { TAS5717_CH2_LEFT_CH_MIX_REG , 0x0 },
540
+ { TAS5717_CH2_RIGHT_CH_MIX_REG , 0x800000 },
353
541
};
354
542
355
543
static const struct regmap_config tas5717_regmap_config = {
0 commit comments