]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - sound/oss/dmasound/tas3001c.c
Linux-2.6.12-rc2
[mirror_ubuntu-zesty-kernel.git] / sound / oss / dmasound / tas3001c.c
1 /*
2 * Driver for the i2c/i2s based TA3004 sound chip used
3 * on some Apple hardware. Also known as "snapper".
4 *
5 * Tobias Sargeant <tobias.sargeant@bigpond.com>
6 * Based upon, tas3001c.c by Christopher C. Chimelis <chris@debian.org>:
7 *
8 * TODO:
9 * -----
10 * * Enable control over input line 2 (is this connected?)
11 * * Implement sleep support (at least mute everything and
12 * * set gains to minimum during sleep)
13 * * Look into some of Darwin's tweaks regarding the mute
14 * * lines (delays & different behaviour on some HW)
15 *
16 */
17
18 #include <linux/module.h>
19 #include <linux/slab.h>
20 #include <linux/proc_fs.h>
21 #include <linux/ioport.h>
22 #include <linux/sysctl.h>
23 #include <linux/types.h>
24 #include <linux/i2c.h>
25 #include <linux/init.h>
26 #include <linux/soundcard.h>
27 #include <linux/workqueue.h>
28 #include <asm/uaccess.h>
29 #include <asm/errno.h>
30 #include <asm/io.h>
31 #include <asm/prom.h>
32
33 #include "dmasound.h"
34 #include "tas_common.h"
35 #include "tas3001c.h"
36
37 #include "tas_ioctl.h"
38
39 #define TAS3001C_BIQUAD_FILTER_COUNT 6
40 #define TAS3001C_BIQUAD_CHANNEL_COUNT 2
41
42 #define VOL_DEFAULT (100 * 4 / 5)
43 #define INPUT_DEFAULT (100 * 4 / 5)
44 #define BASS_DEFAULT (100 / 2)
45 #define TREBLE_DEFAULT (100 / 2)
46
47 struct tas3001c_data_t {
48 struct tas_data_t super;
49 int device_id;
50 int output_id;
51 int speaker_id;
52 struct tas_drce_t drce_state;
53 };
54
55
56 static const union tas_biquad_t
57 tas3001c_eq_unity={
58 .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }
59 };
60
61
62 static inline unsigned char db_to_regval(short db) {
63 int r=0;
64
65 r=(db+0x59a0) / 0x60;
66
67 if (r < 0x91) return 0x91;
68 if (r > 0xef) return 0xef;
69 return r;
70 }
71
72 static inline short quantize_db(short db) {
73 return db_to_regval(db) * 0x60 - 0x59a0;
74 }
75
76
77 static inline int
78 register_width(enum tas3001c_reg_t r)
79 {
80 switch(r) {
81 case TAS3001C_REG_MCR:
82 case TAS3001C_REG_TREBLE:
83 case TAS3001C_REG_BASS:
84 return 1;
85
86 case TAS3001C_REG_DRC:
87 return 2;
88
89 case TAS3001C_REG_MIXER1:
90 case TAS3001C_REG_MIXER2:
91 return 3;
92
93 case TAS3001C_REG_VOLUME:
94 return 6;
95
96 case TAS3001C_REG_LEFT_BIQUAD0:
97 case TAS3001C_REG_LEFT_BIQUAD1:
98 case TAS3001C_REG_LEFT_BIQUAD2:
99 case TAS3001C_REG_LEFT_BIQUAD3:
100 case TAS3001C_REG_LEFT_BIQUAD4:
101 case TAS3001C_REG_LEFT_BIQUAD5:
102 case TAS3001C_REG_LEFT_BIQUAD6:
103
104 case TAS3001C_REG_RIGHT_BIQUAD0:
105 case TAS3001C_REG_RIGHT_BIQUAD1:
106 case TAS3001C_REG_RIGHT_BIQUAD2:
107 case TAS3001C_REG_RIGHT_BIQUAD3:
108 case TAS3001C_REG_RIGHT_BIQUAD4:
109 case TAS3001C_REG_RIGHT_BIQUAD5:
110 case TAS3001C_REG_RIGHT_BIQUAD6:
111 return 15;
112
113 default:
114 return 0;
115 }
116 }
117
118 static int
119 tas3001c_write_register( struct tas3001c_data_t *self,
120 enum tas3001c_reg_t reg_num,
121 char *data,
122 uint write_mode)
123 {
124 if (reg_num==TAS3001C_REG_MCR ||
125 reg_num==TAS3001C_REG_BASS ||
126 reg_num==TAS3001C_REG_TREBLE) {
127 return tas_write_byte_register(&self->super,
128 (uint)reg_num,
129 *data,
130 write_mode);
131 } else {
132 return tas_write_register(&self->super,
133 (uint)reg_num,
134 register_width(reg_num),
135 data,
136 write_mode);
137 }
138 }
139
140 static int
141 tas3001c_sync_register( struct tas3001c_data_t *self,
142 enum tas3001c_reg_t reg_num)
143 {
144 if (reg_num==TAS3001C_REG_MCR ||
145 reg_num==TAS3001C_REG_BASS ||
146 reg_num==TAS3001C_REG_TREBLE) {
147 return tas_sync_byte_register(&self->super,
148 (uint)reg_num,
149 register_width(reg_num));
150 } else {
151 return tas_sync_register(&self->super,
152 (uint)reg_num,
153 register_width(reg_num));
154 }
155 }
156
157 static int
158 tas3001c_read_register( struct tas3001c_data_t *self,
159 enum tas3001c_reg_t reg_num,
160 char *data,
161 uint write_mode)
162 {
163 return tas_read_register(&self->super,
164 (uint)reg_num,
165 register_width(reg_num),
166 data);
167 }
168
169 static inline int
170 tas3001c_fast_load(struct tas3001c_data_t *self, int fast)
171 {
172 if (fast)
173 self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80;
174 else
175 self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f;
176 return tas3001c_sync_register(self,TAS3001C_REG_MCR);
177 }
178
179 static uint
180 tas3001c_supported_mixers(struct tas3001c_data_t *self)
181 {
182 return SOUND_MASK_VOLUME |
183 SOUND_MASK_PCM |
184 SOUND_MASK_ALTPCM |
185 SOUND_MASK_TREBLE |
186 SOUND_MASK_BASS;
187 }
188
189 static int
190 tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer)
191 {
192 switch(mixer) {
193 case SOUND_MIXER_VOLUME:
194 return 1;
195 default:
196 return 0;
197 }
198 }
199
200 static uint
201 tas3001c_stereo_mixers(struct tas3001c_data_t *self)
202 {
203 uint r=tas3001c_supported_mixers(self);
204 uint i;
205
206 for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
207 if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i))
208 r &= ~(1<<i);
209 return r;
210 }
211
212 static int
213 tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level)
214 {
215 if (!self)
216 return -1;
217
218 *level=self->super.mixer[mixer];
219
220 return 0;
221 }
222
223 static int
224 tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level)
225 {
226 int rc;
227 tas_shadow_t *shadow;
228
229 uint temp;
230 uint offset=0;
231
232 if (!self)
233 return -1;
234
235 shadow=self->super.shadow;
236
237 if (!tas3001c_mixer_is_stereo(self,mixer))
238 level = tas_mono_to_stereo(level);
239
240 switch(mixer) {
241 case SOUND_MIXER_VOLUME:
242 temp = tas3001c_gain.master[level&0xff];
243 shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff;
244 shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8) & 0xff;
245 shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0) & 0xff;
246 temp = tas3001c_gain.master[(level>>8)&0xff];
247 shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff;
248 shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8) & 0xff;
249 shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0) & 0xff;
250 rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
251 break;
252 case SOUND_MIXER_ALTPCM:
253 /* tas3001c_fast_load(self, 1); */
254 level = tas_mono_to_stereo(level);
255 temp = tas3001c_gain.mixer[level&0xff];
256 shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff;
257 shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8) & 0xff;
258 shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0) & 0xff;
259 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
260 /* tas3001c_fast_load(self, 0); */
261 break;
262 case SOUND_MIXER_PCM:
263 /* tas3001c_fast_load(self, 1); */
264 level = tas_mono_to_stereo(level);
265 temp = tas3001c_gain.mixer[level&0xff];
266 shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff;
267 shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8) & 0xff;
268 shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0) & 0xff;
269 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
270 /* tas3001c_fast_load(self, 0); */
271 break;
272 case SOUND_MIXER_TREBLE:
273 temp = tas3001c_gain.treble[level&0xff];
274 shadow[TAS3001C_REG_TREBLE][0]=temp&0xff;
275 rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
276 break;
277 case SOUND_MIXER_BASS:
278 temp = tas3001c_gain.bass[level&0xff];
279 shadow[TAS3001C_REG_BASS][0]=temp&0xff;
280 rc = tas3001c_sync_register(self,TAS3001C_REG_BASS);
281 break;
282 default:
283 rc = -1;
284 break;
285 }
286 if (rc < 0)
287 return rc;
288 self->super.mixer[mixer]=level;
289 return 0;
290 }
291
292 static int
293 tas3001c_leave_sleep(struct tas3001c_data_t *self)
294 {
295 unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
296
297 if (!self)
298 return -1;
299
300 /* Make sure something answers on the i2c bus */
301 if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
302 WRITE_NORMAL|FORCE_WRITE) < 0)
303 return -1;
304
305 tas3001c_fast_load(self, 1);
306
307 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
308 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
309 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
310 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
311 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
312 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
313
314 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
315 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
316 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
317 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
318 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
319 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
320
321 tas3001c_fast_load(self, 0);
322
323 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
324 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
325 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
326 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
327 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
328
329 return 0;
330 }
331
332 static int
333 tas3001c_enter_sleep(struct tas3001c_data_t *self)
334 {
335 /* Stub for now, but I have the details on low-power mode */
336 if (!self)
337 return -1;
338 return 0;
339 }
340
341 static int
342 tas3001c_sync_biquad( struct tas3001c_data_t *self,
343 u_int channel,
344 u_int filter)
345 {
346 enum tas3001c_reg_t reg;
347
348 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
349 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
350
351 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
352
353 return tas3001c_sync_register(self,reg);
354 }
355
356 static int
357 tas3001c_write_biquad_shadow( struct tas3001c_data_t *self,
358 u_int channel,
359 u_int filter,
360 const union tas_biquad_t *biquad)
361 {
362 tas_shadow_t *shadow=self->super.shadow;
363 enum tas3001c_reg_t reg;
364
365 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
366 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
367
368 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
369
370 SET_4_20(shadow[reg], 0,biquad->coeff.b0);
371 SET_4_20(shadow[reg], 3,biquad->coeff.b1);
372 SET_4_20(shadow[reg], 6,biquad->coeff.b2);
373 SET_4_20(shadow[reg], 9,biquad->coeff.a1);
374 SET_4_20(shadow[reg],12,biquad->coeff.a2);
375
376 return 0;
377 }
378
379 static int
380 tas3001c_write_biquad( struct tas3001c_data_t *self,
381 u_int channel,
382 u_int filter,
383 const union tas_biquad_t *biquad)
384 {
385 int rc;
386
387 rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad);
388 if (rc < 0) return rc;
389
390 return tas3001c_sync_biquad(self, channel, filter);
391 }
392
393 static int
394 tas3001c_write_biquad_list( struct tas3001c_data_t *self,
395 u_int filter_count,
396 u_int flags,
397 struct tas_biquad_ctrl_t *biquads)
398 {
399 int i;
400 int rc;
401
402 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
403
404 for (i=0; i<filter_count; i++) {
405 rc=tas3001c_write_biquad(self,
406 biquads[i].channel,
407 biquads[i].filter,
408 &biquads[i].data);
409 if (rc < 0) break;
410 }
411
412 if (flags & TAS_BIQUAD_FAST_LOAD) {
413 tas3001c_fast_load(self,0);
414
415 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
416 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
417 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
418 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
419 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
420 }
421
422 return rc;
423 }
424
425 static int
426 tas3001c_read_biquad( struct tas3001c_data_t *self,
427 u_int channel,
428 u_int filter,
429 union tas_biquad_t *biquad)
430 {
431 tas_shadow_t *shadow=self->super.shadow;
432 enum tas3001c_reg_t reg;
433
434 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
435 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
436
437 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
438
439 biquad->coeff.b0=GET_4_20(shadow[reg], 0);
440 biquad->coeff.b1=GET_4_20(shadow[reg], 3);
441 biquad->coeff.b2=GET_4_20(shadow[reg], 6);
442 biquad->coeff.a1=GET_4_20(shadow[reg], 9);
443 biquad->coeff.a2=GET_4_20(shadow[reg],12);
444
445 return 0;
446 }
447
448 static int
449 tas3001c_eq_rw( struct tas3001c_data_t *self,
450 u_int cmd,
451 u_long arg)
452 {
453 int rc;
454 struct tas_biquad_ctrl_t biquad;
455 void __user *argp = (void __user *)arg;
456
457 if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
458 return -EFAULT;
459 }
460
461 if (cmd & SIOC_IN) {
462 rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
463 if (rc != 0) return rc;
464 }
465
466 if (cmd & SIOC_OUT) {
467 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
468 if (rc != 0) return rc;
469
470 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
471 return -EFAULT;
472 }
473
474 }
475 return 0;
476 }
477
478 static int
479 tas3001c_eq_list_rw( struct tas3001c_data_t *self,
480 u_int cmd,
481 u_long arg)
482 {
483 int rc;
484 int filter_count;
485 int flags;
486 int i,j;
487 char sync_required[2][6];
488 struct tas_biquad_ctrl_t biquad;
489 struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
490
491 memset(sync_required,0,sizeof(sync_required));
492
493 if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
494 return -EFAULT;
495
496 if (copy_from_user(&flags, &argp->flags, sizeof(int)))
497 return -EFAULT;
498
499 if (cmd & SIOC_IN) {
500 }
501
502 for (i=0; i < filter_count; i++) {
503 if (copy_from_user(&biquad, &argp->biquads[i],
504 sizeof(struct tas_biquad_ctrl_t))) {
505 return -EFAULT;
506 }
507
508 if (cmd & SIOC_IN) {
509 sync_required[biquad.channel][biquad.filter]=1;
510 rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
511 if (rc != 0) return rc;
512 }
513
514 if (cmd & SIOC_OUT) {
515 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
516 if (rc != 0) return rc;
517
518 if (copy_to_user(&argp->biquads[i], &biquad,
519 sizeof(struct tas_biquad_ctrl_t))) {
520 return -EFAULT;
521 }
522 }
523 }
524
525 if (cmd & SIOC_IN) {
526 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
527 for (i=0; i<2; i++) {
528 for (j=0; j<6; j++) {
529 if (sync_required[i][j]) {
530 rc=tas3001c_sync_biquad(self, i, j);
531 if (rc < 0) return rc;
532 }
533 }
534 }
535 if (flags & TAS_BIQUAD_FAST_LOAD) {
536 tas3001c_fast_load(self,0);
537 /* now we need to set up the mixers again,
538 because leaving fast mode resets them. */
539 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
540 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
541 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
542 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
543 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
544 }
545 }
546
547 return 0;
548 }
549
550 static int
551 tas3001c_update_drce( struct tas3001c_data_t *self,
552 int flags,
553 struct tas_drce_t *drce)
554 {
555 tas_shadow_t *shadow;
556 shadow=self->super.shadow;
557
558 shadow[TAS3001C_REG_DRC][1] = 0xc1;
559
560 if (flags & TAS_DRCE_THRESHOLD) {
561 self->drce_state.threshold=quantize_db(drce->threshold);
562 shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
563 }
564
565 if (flags & TAS_DRCE_ENABLE) {
566 self->drce_state.enable = drce->enable;
567 }
568
569 if (!self->drce_state.enable) {
570 shadow[TAS3001C_REG_DRC][0] = 0xf0;
571 }
572
573 #ifdef DEBUG_DRCE
574 printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n",
575 self->drce_state.enable,
576 self->drce_state.threshold);
577
578 printk("DRCE IOCTL: reg [ %02x %02x ]\n",
579 (unsigned char)shadow[TAS3001C_REG_DRC][0],
580 (unsigned char)shadow[TAS3001C_REG_DRC][1]);
581 #endif
582
583 return tas3001c_sync_register(self, TAS3001C_REG_DRC);
584 }
585
586 static int
587 tas3001c_drce_rw( struct tas3001c_data_t *self,
588 u_int cmd,
589 u_long arg)
590 {
591 int rc;
592 struct tas_drce_ctrl_t drce_ctrl;
593 void __user *argp = (void __user *)arg;
594
595 if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
596 return -EFAULT;
597
598 #ifdef DEBUG_DRCE
599 printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n",
600 drce_ctrl.flags,
601 drce_ctrl.data.enable,
602 drce_ctrl.data.threshold);
603 #endif
604
605 if (cmd & SIOC_IN) {
606 rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
607 if (rc < 0)
608 return rc;
609 }
610
611 if (cmd & SIOC_OUT) {
612 if (drce_ctrl.flags & TAS_DRCE_ENABLE)
613 drce_ctrl.data.enable = self->drce_state.enable;
614
615 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
616 drce_ctrl.data.threshold = self->drce_state.threshold;
617
618 if (copy_to_user(argp, &drce_ctrl,
619 sizeof(struct tas_drce_ctrl_t))) {
620 return -EFAULT;
621 }
622 }
623
624 return 0;
625 }
626
627 static void
628 tas3001c_update_device_parameters(struct tas3001c_data_t *self)
629 {
630 int i,j;
631
632 if (!self) return;
633
634 if (self->output_id == TAS_OUTPUT_HEADPHONES) {
635 tas3001c_fast_load(self, 1);
636
637 for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) {
638 for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) {
639 tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity);
640 }
641 }
642
643 tas3001c_fast_load(self, 0);
644
645 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
646 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
647 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
648 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
649 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
650
651 return;
652 }
653
654 for (i=0; tas3001c_eq_prefs[i]; i++) {
655 struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i];
656
657 if (eq->device_id == self->device_id &&
658 (eq->output_id == 0 || eq->output_id == self->output_id) &&
659 (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
660
661 tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce);
662 tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
663
664 break;
665 }
666 }
667 }
668
669 static void
670 tas3001c_device_change_handler(void *self)
671 {
672 if (self)
673 tas3001c_update_device_parameters(self);
674 }
675
676 static struct work_struct device_change;
677
678 static int
679 tas3001c_output_device_change( struct tas3001c_data_t *self,
680 int device_id,
681 int output_id,
682 int speaker_id)
683 {
684 self->device_id=device_id;
685 self->output_id=output_id;
686 self->speaker_id=speaker_id;
687
688 schedule_work(&device_change);
689 return 0;
690 }
691
692 static int
693 tas3001c_device_ioctl( struct tas3001c_data_t *self,
694 u_int cmd,
695 u_long arg)
696 {
697 uint __user *argp = (void __user *)arg;
698 switch (cmd) {
699 case TAS_READ_EQ:
700 case TAS_WRITE_EQ:
701 return tas3001c_eq_rw(self, cmd, arg);
702
703 case TAS_READ_EQ_LIST:
704 case TAS_WRITE_EQ_LIST:
705 return tas3001c_eq_list_rw(self, cmd, arg);
706
707 case TAS_READ_EQ_FILTER_COUNT:
708 put_user(TAS3001C_BIQUAD_FILTER_COUNT, argp);
709 return 0;
710
711 case TAS_READ_EQ_CHANNEL_COUNT:
712 put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, argp);
713 return 0;
714
715 case TAS_READ_DRCE:
716 case TAS_WRITE_DRCE:
717 return tas3001c_drce_rw(self, cmd, arg);
718
719 case TAS_READ_DRCE_CAPS:
720 put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, argp);
721 return 0;
722
723 case TAS_READ_DRCE_MIN:
724 case TAS_READ_DRCE_MAX: {
725 struct tas_drce_ctrl_t drce_ctrl;
726
727 if (copy_from_user(&drce_ctrl, argp,
728 sizeof(struct tas_drce_ctrl_t))) {
729 return -EFAULT;
730 }
731
732 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) {
733 if (cmd == TAS_READ_DRCE_MIN) {
734 drce_ctrl.data.threshold=-36<<8;
735 } else {
736 drce_ctrl.data.threshold=-6<<8;
737 }
738 }
739
740 if (copy_to_user(argp, &drce_ctrl,
741 sizeof(struct tas_drce_ctrl_t))) {
742 return -EFAULT;
743 }
744 }
745 }
746
747 return -EINVAL;
748 }
749
750 static int
751 tas3001c_init_mixer(struct tas3001c_data_t *self)
752 {
753 unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
754
755 /* Make sure something answers on the i2c bus */
756 if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
757 WRITE_NORMAL|FORCE_WRITE) < 0)
758 return -1;
759
760 tas3001c_fast_load(self, 1);
761
762 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
763 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
764 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
765 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
766 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
767 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
768 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6);
769
770 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
771 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
772 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
773 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
774 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
775 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
776 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6);
777
778 tas3001c_fast_load(self, 0);
779
780 tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT);
781 tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT);
782 tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
783
784 tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT);
785 tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT);
786
787 return 0;
788 }
789
790 static int
791 tas3001c_uninit_mixer(struct tas3001c_data_t *self)
792 {
793 tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0);
794 tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, 0);
795 tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
796
797 tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, 0);
798 tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0);
799
800 return 0;
801 }
802
803 static int
804 tas3001c_init(struct i2c_client *client)
805 {
806 struct tas3001c_data_t *self;
807 size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t));
808 int i, j;
809
810 self = kmalloc(sz, GFP_KERNEL);
811 if (!self)
812 return -ENOMEM;
813 memset(self, 0, sz);
814
815 self->super.client = client;
816 self->super.shadow = (tas_shadow_t *)(self+1);
817 self->output_id = TAS_OUTPUT_HEADPHONES;
818
819 dev_set_drvdata(&client->dev, self);
820
821 for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++)
822 for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++)
823 tas3001c_write_biquad_shadow(self, i, j,
824 &tas3001c_eq_unity);
825
826 INIT_WORK(&device_change, tas3001c_device_change_handler, self);
827 return 0;
828 }
829
830 static void
831 tas3001c_uninit(struct tas3001c_data_t *self)
832 {
833 tas3001c_uninit_mixer(self);
834 kfree(self);
835 }
836
837 struct tas_driver_hooks_t tas3001c_hooks = {
838 .init = (tas_hook_init_t)tas3001c_init,
839 .post_init = (tas_hook_post_init_t)tas3001c_init_mixer,
840 .uninit = (tas_hook_uninit_t)tas3001c_uninit,
841 .get_mixer_level = (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level,
842 .set_mixer_level = (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level,
843 .enter_sleep = (tas_hook_enter_sleep_t)tas3001c_enter_sleep,
844 .leave_sleep = (tas_hook_leave_sleep_t)tas3001c_leave_sleep,
845 .supported_mixers = (tas_hook_supported_mixers_t)tas3001c_supported_mixers,
846 .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo,
847 .stereo_mixers = (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers,
848 .output_device_change = (tas_hook_output_device_change_t)tas3001c_output_device_change,
849 .device_ioctl = (tas_hook_device_ioctl_t)tas3001c_device_ioctl
850 };