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
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;
53	struct work_struct change;
54};
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
671tas3001c_device_change_handler(struct work_struct *work)
672{
673	struct tas3001c_data_t *self;
674	self = container_of(work, struct tas3001c_data_t, change);
675	tas3001c_update_device_parameters(self);
676}
677
678static 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
688	schedule_work(&self->change);
689	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
810	self = kzalloc(sz, GFP_KERNEL);
811	if (!self)
812		return -ENOMEM;
813
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
825	INIT_WORK(&self->change, tas3001c_device_change_handler);
826	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};
850