blob: 4b7dbdd2a43833c2553c2b994a28f599e3d6bc46 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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
47struct 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;
Al Viro7686fcf2006-12-08 09:16:49 +000053 struct work_struct change;
Linus Torvalds1da177e2005-04-16 15:20:36 -070054};
55
56
57static const union tas_biquad_t
58tas3001c_eq_unity={
59 .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }
60};
61
62
63static inline unsigned char db_to_regval(short db) {
64 int r=0;
65
66 r=(db+0x59a0) / 0x60;
67
68 if (r < 0x91) return 0x91;
69 if (r > 0xef) return 0xef;
70 return r;
71}
72
73static inline short quantize_db(short db) {
74 return db_to_regval(db) * 0x60 - 0x59a0;
75}
76
77
78static inline int
79register_width(enum tas3001c_reg_t r)
80{
81 switch(r) {
82 case TAS3001C_REG_MCR:
83 case TAS3001C_REG_TREBLE:
84 case TAS3001C_REG_BASS:
85 return 1;
86
87 case TAS3001C_REG_DRC:
88 return 2;
89
90 case TAS3001C_REG_MIXER1:
91 case TAS3001C_REG_MIXER2:
92 return 3;
93
94 case TAS3001C_REG_VOLUME:
95 return 6;
96
97 case TAS3001C_REG_LEFT_BIQUAD0:
98 case TAS3001C_REG_LEFT_BIQUAD1:
99 case TAS3001C_REG_LEFT_BIQUAD2:
100 case TAS3001C_REG_LEFT_BIQUAD3:
101 case TAS3001C_REG_LEFT_BIQUAD4:
102 case TAS3001C_REG_LEFT_BIQUAD5:
103 case TAS3001C_REG_LEFT_BIQUAD6:
104
105 case TAS3001C_REG_RIGHT_BIQUAD0:
106 case TAS3001C_REG_RIGHT_BIQUAD1:
107 case TAS3001C_REG_RIGHT_BIQUAD2:
108 case TAS3001C_REG_RIGHT_BIQUAD3:
109 case TAS3001C_REG_RIGHT_BIQUAD4:
110 case TAS3001C_REG_RIGHT_BIQUAD5:
111 case TAS3001C_REG_RIGHT_BIQUAD6:
112 return 15;
113
114 default:
115 return 0;
116 }
117}
118
119static int
120tas3001c_write_register( struct tas3001c_data_t *self,
121 enum tas3001c_reg_t reg_num,
122 char *data,
123 uint write_mode)
124{
125 if (reg_num==TAS3001C_REG_MCR ||
126 reg_num==TAS3001C_REG_BASS ||
127 reg_num==TAS3001C_REG_TREBLE) {
128 return tas_write_byte_register(&self->super,
129 (uint)reg_num,
130 *data,
131 write_mode);
132 } else {
133 return tas_write_register(&self->super,
134 (uint)reg_num,
135 register_width(reg_num),
136 data,
137 write_mode);
138 }
139}
140
141static int
142tas3001c_sync_register( struct tas3001c_data_t *self,
143 enum tas3001c_reg_t reg_num)
144{
145 if (reg_num==TAS3001C_REG_MCR ||
146 reg_num==TAS3001C_REG_BASS ||
147 reg_num==TAS3001C_REG_TREBLE) {
148 return tas_sync_byte_register(&self->super,
149 (uint)reg_num,
150 register_width(reg_num));
151 } else {
152 return tas_sync_register(&self->super,
153 (uint)reg_num,
154 register_width(reg_num));
155 }
156}
157
158static int
159tas3001c_read_register( struct tas3001c_data_t *self,
160 enum tas3001c_reg_t reg_num,
161 char *data,
162 uint write_mode)
163{
164 return tas_read_register(&self->super,
165 (uint)reg_num,
166 register_width(reg_num),
167 data);
168}
169
170static inline int
171tas3001c_fast_load(struct tas3001c_data_t *self, int fast)
172{
173 if (fast)
174 self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80;
175 else
176 self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f;
177 return tas3001c_sync_register(self,TAS3001C_REG_MCR);
178}
179
180static uint
181tas3001c_supported_mixers(struct tas3001c_data_t *self)
182{
183 return SOUND_MASK_VOLUME |
184 SOUND_MASK_PCM |
185 SOUND_MASK_ALTPCM |
186 SOUND_MASK_TREBLE |
187 SOUND_MASK_BASS;
188}
189
190static int
191tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer)
192{
193 switch(mixer) {
194 case SOUND_MIXER_VOLUME:
195 return 1;
196 default:
197 return 0;
198 }
199}
200
201static uint
202tas3001c_stereo_mixers(struct tas3001c_data_t *self)
203{
204 uint r=tas3001c_supported_mixers(self);
205 uint i;
206
207 for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
208 if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i))
209 r &= ~(1<<i);
210 return r;
211}
212
213static int
214tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level)
215{
216 if (!self)
217 return -1;
218
219 *level=self->super.mixer[mixer];
220
221 return 0;
222}
223
224static int
225tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level)
226{
227 int rc;
228 tas_shadow_t *shadow;
229
230 uint temp;
231 uint offset=0;
232
233 if (!self)
234 return -1;
235
236 shadow=self->super.shadow;
237
238 if (!tas3001c_mixer_is_stereo(self,mixer))
239 level = tas_mono_to_stereo(level);
240
241 switch(mixer) {
242 case SOUND_MIXER_VOLUME:
243 temp = tas3001c_gain.master[level&0xff];
244 shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff;
245 shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8) & 0xff;
246 shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0) & 0xff;
247 temp = tas3001c_gain.master[(level>>8)&0xff];
248 shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff;
249 shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8) & 0xff;
250 shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0) & 0xff;
251 rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
252 break;
253 case SOUND_MIXER_ALTPCM:
254 /* tas3001c_fast_load(self, 1); */
255 level = tas_mono_to_stereo(level);
256 temp = tas3001c_gain.mixer[level&0xff];
257 shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff;
258 shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8) & 0xff;
259 shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0) & 0xff;
260 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
261 /* tas3001c_fast_load(self, 0); */
262 break;
263 case SOUND_MIXER_PCM:
264 /* tas3001c_fast_load(self, 1); */
265 level = tas_mono_to_stereo(level);
266 temp = tas3001c_gain.mixer[level&0xff];
267 shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff;
268 shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8) & 0xff;
269 shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0) & 0xff;
270 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
271 /* tas3001c_fast_load(self, 0); */
272 break;
273 case SOUND_MIXER_TREBLE:
274 temp = tas3001c_gain.treble[level&0xff];
275 shadow[TAS3001C_REG_TREBLE][0]=temp&0xff;
276 rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
277 break;
278 case SOUND_MIXER_BASS:
279 temp = tas3001c_gain.bass[level&0xff];
280 shadow[TAS3001C_REG_BASS][0]=temp&0xff;
281 rc = tas3001c_sync_register(self,TAS3001C_REG_BASS);
282 break;
283 default:
284 rc = -1;
285 break;
286 }
287 if (rc < 0)
288 return rc;
289 self->super.mixer[mixer]=level;
290 return 0;
291}
292
293static int
294tas3001c_leave_sleep(struct tas3001c_data_t *self)
295{
296 unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
297
298 if (!self)
299 return -1;
300
301 /* Make sure something answers on the i2c bus */
302 if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
303 WRITE_NORMAL|FORCE_WRITE) < 0)
304 return -1;
305
306 tas3001c_fast_load(self, 1);
307
308 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
309 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
310 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
311 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
312 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
313 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
314
315 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
316 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
317 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
318 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
319 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
320 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
321
322 tas3001c_fast_load(self, 0);
323
324 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
325 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
326 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
327 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
328 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
329
330 return 0;
331}
332
333static int
334tas3001c_enter_sleep(struct tas3001c_data_t *self)
335{
336 /* Stub for now, but I have the details on low-power mode */
337 if (!self)
338 return -1;
339 return 0;
340}
341
342static int
343tas3001c_sync_biquad( struct tas3001c_data_t *self,
344 u_int channel,
345 u_int filter)
346{
347 enum tas3001c_reg_t reg;
348
349 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
350 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
351
352 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
353
354 return tas3001c_sync_register(self,reg);
355}
356
357static int
358tas3001c_write_biquad_shadow( struct tas3001c_data_t *self,
359 u_int channel,
360 u_int filter,
361 const union tas_biquad_t *biquad)
362{
363 tas_shadow_t *shadow=self->super.shadow;
364 enum tas3001c_reg_t reg;
365
366 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
367 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
368
369 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
370
371 SET_4_20(shadow[reg], 0,biquad->coeff.b0);
372 SET_4_20(shadow[reg], 3,biquad->coeff.b1);
373 SET_4_20(shadow[reg], 6,biquad->coeff.b2);
374 SET_4_20(shadow[reg], 9,biquad->coeff.a1);
375 SET_4_20(shadow[reg],12,biquad->coeff.a2);
376
377 return 0;
378}
379
380static int
381tas3001c_write_biquad( struct tas3001c_data_t *self,
382 u_int channel,
383 u_int filter,
384 const union tas_biquad_t *biquad)
385{
386 int rc;
387
388 rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad);
389 if (rc < 0) return rc;
390
391 return tas3001c_sync_biquad(self, channel, filter);
392}
393
394static int
395tas3001c_write_biquad_list( struct tas3001c_data_t *self,
396 u_int filter_count,
397 u_int flags,
398 struct tas_biquad_ctrl_t *biquads)
399{
400 int i;
401 int rc;
402
403 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
404
405 for (i=0; i<filter_count; i++) {
406 rc=tas3001c_write_biquad(self,
407 biquads[i].channel,
408 biquads[i].filter,
409 &biquads[i].data);
410 if (rc < 0) break;
411 }
412
413 if (flags & TAS_BIQUAD_FAST_LOAD) {
414 tas3001c_fast_load(self,0);
415
416 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
417 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
418 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
419 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
420 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
421 }
422
423 return rc;
424}
425
426static int
427tas3001c_read_biquad( struct tas3001c_data_t *self,
428 u_int channel,
429 u_int filter,
430 union tas_biquad_t *biquad)
431{
432 tas_shadow_t *shadow=self->super.shadow;
433 enum tas3001c_reg_t reg;
434
435 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
436 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
437
438 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
439
440 biquad->coeff.b0=GET_4_20(shadow[reg], 0);
441 biquad->coeff.b1=GET_4_20(shadow[reg], 3);
442 biquad->coeff.b2=GET_4_20(shadow[reg], 6);
443 biquad->coeff.a1=GET_4_20(shadow[reg], 9);
444 biquad->coeff.a2=GET_4_20(shadow[reg],12);
445
446 return 0;
447}
448
449static int
450tas3001c_eq_rw( struct tas3001c_data_t *self,
451 u_int cmd,
452 u_long arg)
453{
454 int rc;
455 struct tas_biquad_ctrl_t biquad;
456 void __user *argp = (void __user *)arg;
457
458 if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
459 return -EFAULT;
460 }
461
462 if (cmd & SIOC_IN) {
463 rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
464 if (rc != 0) return rc;
465 }
466
467 if (cmd & SIOC_OUT) {
468 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
469 if (rc != 0) return rc;
470
471 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
472 return -EFAULT;
473 }
474
475 }
476 return 0;
477}
478
479static int
480tas3001c_eq_list_rw( struct tas3001c_data_t *self,
481 u_int cmd,
482 u_long arg)
483{
484 int rc;
485 int filter_count;
486 int flags;
487 int i,j;
488 char sync_required[2][6];
489 struct tas_biquad_ctrl_t biquad;
490 struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
491
492 memset(sync_required,0,sizeof(sync_required));
493
494 if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
495 return -EFAULT;
496
497 if (copy_from_user(&flags, &argp->flags, sizeof(int)))
498 return -EFAULT;
499
500 if (cmd & SIOC_IN) {
501 }
502
503 for (i=0; i < filter_count; i++) {
504 if (copy_from_user(&biquad, &argp->biquads[i],
505 sizeof(struct tas_biquad_ctrl_t))) {
506 return -EFAULT;
507 }
508
509 if (cmd & SIOC_IN) {
510 sync_required[biquad.channel][biquad.filter]=1;
511 rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
512 if (rc != 0) return rc;
513 }
514
515 if (cmd & SIOC_OUT) {
516 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
517 if (rc != 0) return rc;
518
519 if (copy_to_user(&argp->biquads[i], &biquad,
520 sizeof(struct tas_biquad_ctrl_t))) {
521 return -EFAULT;
522 }
523 }
524 }
525
526 if (cmd & SIOC_IN) {
527 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
528 for (i=0; i<2; i++) {
529 for (j=0; j<6; j++) {
530 if (sync_required[i][j]) {
531 rc=tas3001c_sync_biquad(self, i, j);
532 if (rc < 0) return rc;
533 }
534 }
535 }
536 if (flags & TAS_BIQUAD_FAST_LOAD) {
537 tas3001c_fast_load(self,0);
538 /* now we need to set up the mixers again,
539 because leaving fast mode resets them. */
540 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
541 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
542 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
543 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
544 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
545 }
546 }
547
548 return 0;
549}
550
551static int
552tas3001c_update_drce( struct tas3001c_data_t *self,
553 int flags,
554 struct tas_drce_t *drce)
555{
556 tas_shadow_t *shadow;
557 shadow=self->super.shadow;
558
559 shadow[TAS3001C_REG_DRC][1] = 0xc1;
560
561 if (flags & TAS_DRCE_THRESHOLD) {
562 self->drce_state.threshold=quantize_db(drce->threshold);
563 shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
564 }
565
566 if (flags & TAS_DRCE_ENABLE) {
567 self->drce_state.enable = drce->enable;
568 }
569
570 if (!self->drce_state.enable) {
571 shadow[TAS3001C_REG_DRC][0] = 0xf0;
572 }
573
574#ifdef DEBUG_DRCE
575 printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n",
576 self->drce_state.enable,
577 self->drce_state.threshold);
578
579 printk("DRCE IOCTL: reg [ %02x %02x ]\n",
580 (unsigned char)shadow[TAS3001C_REG_DRC][0],
581 (unsigned char)shadow[TAS3001C_REG_DRC][1]);
582#endif
583
584 return tas3001c_sync_register(self, TAS3001C_REG_DRC);
585}
586
587static int
588tas3001c_drce_rw( struct tas3001c_data_t *self,
589 u_int cmd,
590 u_long arg)
591{
592 int rc;
593 struct tas_drce_ctrl_t drce_ctrl;
594 void __user *argp = (void __user *)arg;
595
596 if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
597 return -EFAULT;
598
599#ifdef DEBUG_DRCE
600 printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n",
601 drce_ctrl.flags,
602 drce_ctrl.data.enable,
603 drce_ctrl.data.threshold);
604#endif
605
606 if (cmd & SIOC_IN) {
607 rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
608 if (rc < 0)
609 return rc;
610 }
611
612 if (cmd & SIOC_OUT) {
613 if (drce_ctrl.flags & TAS_DRCE_ENABLE)
614 drce_ctrl.data.enable = self->drce_state.enable;
615
616 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
617 drce_ctrl.data.threshold = self->drce_state.threshold;
618
619 if (copy_to_user(argp, &drce_ctrl,
620 sizeof(struct tas_drce_ctrl_t))) {
621 return -EFAULT;
622 }
623 }
624
625 return 0;
626}
627
628static void
629tas3001c_update_device_parameters(struct tas3001c_data_t *self)
630{
631 int i,j;
632
633 if (!self) return;
634
635 if (self->output_id == TAS_OUTPUT_HEADPHONES) {
636 tas3001c_fast_load(self, 1);
637
638 for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) {
639 for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) {
640 tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity);
641 }
642 }
643
644 tas3001c_fast_load(self, 0);
645
646 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
647 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
648 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
649 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
650 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
651
652 return;
653 }
654
655 for (i=0; tas3001c_eq_prefs[i]; i++) {
656 struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i];
657
658 if (eq->device_id == self->device_id &&
659 (eq->output_id == 0 || eq->output_id == self->output_id) &&
660 (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
661
662 tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce);
663 tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
664
665 break;
666 }
667 }
668}
669
670static void
Al Viro7686fcf2006-12-08 09:16:49 +0000671tas3001c_device_change_handler(struct work_struct *work)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672{
Al Viro7686fcf2006-12-08 09:16:49 +0000673 struct tas3001c_data_t *self;
674 self = container_of(work, struct tas3001c_data_t, change);
675 tas3001c_update_device_parameters(self);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676}
677
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678static int
679tas3001c_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
Al Viro7686fcf2006-12-08 09:16:49 +0000688 schedule_work(&self->change);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 return 0;
690}
691
692static int
693tas3001c_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
750static int
751tas3001c_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
790static int
791tas3001c_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
803static int
804tas3001c_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
Robert P. J. Day3159f062007-02-14 00:33:16 -0800810 self = kzalloc(sz, GFP_KERNEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 if (!self)
812 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
814 self->super.client = client;
815 self->super.shadow = (tas_shadow_t *)(self+1);
816 self->output_id = TAS_OUTPUT_HEADPHONES;
817
818 dev_set_drvdata(&client->dev, self);
819
820 for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++)
821 for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++)
822 tas3001c_write_biquad_shadow(self, i, j,
823 &tas3001c_eq_unity);
824
Al Viro7686fcf2006-12-08 09:16:49 +0000825 INIT_WORK(&self->change, tas3001c_device_change_handler);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 return 0;
827}
828
829static void
830tas3001c_uninit(struct tas3001c_data_t *self)
831{
832 tas3001c_uninit_mixer(self);
833 kfree(self);
834}
835
836struct tas_driver_hooks_t tas3001c_hooks = {
837 .init = (tas_hook_init_t)tas3001c_init,
838 .post_init = (tas_hook_post_init_t)tas3001c_init_mixer,
839 .uninit = (tas_hook_uninit_t)tas3001c_uninit,
840 .get_mixer_level = (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level,
841 .set_mixer_level = (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level,
842 .enter_sleep = (tas_hook_enter_sleep_t)tas3001c_enter_sleep,
843 .leave_sleep = (tas_hook_leave_sleep_t)tas3001c_leave_sleep,
844 .supported_mixers = (tas_hook_supported_mixers_t)tas3001c_supported_mixers,
845 .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo,
846 .stereo_mixers = (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers,
847 .output_device_change = (tas_hook_output_device_change_t)tas3001c_output_device_change,
848 .device_ioctl = (tas_hook_device_ioctl_t)tas3001c_device_ioctl
849};