xref: /OK3568_Linux_fs/kernel/sound/i2c/tea6330t.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  *  Routines for control of the TEA6330T circuit via i2c bus
4*4882a593Smuzhiyun  *  Sound fader control circuit for car radios by Philips Semiconductors
5*4882a593Smuzhiyun  *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/init.h>
9*4882a593Smuzhiyun #include <linux/slab.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <sound/core.h>
12*4882a593Smuzhiyun #include <sound/control.h>
13*4882a593Smuzhiyun #include <sound/tea6330t.h>
14*4882a593Smuzhiyun 
15*4882a593Smuzhiyun MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
16*4882a593Smuzhiyun MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus");
17*4882a593Smuzhiyun MODULE_LICENSE("GPL");
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun #define TEA6330T_ADDR			(0x80>>1) /* fixed address */
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define TEA6330T_SADDR_VOLUME_LEFT	0x00	/* volume left */
22*4882a593Smuzhiyun #define TEA6330T_SADDR_VOLUME_RIGHT	0x01	/* volume right */
23*4882a593Smuzhiyun #define TEA6330T_SADDR_BASS		0x02	/* bass control */
24*4882a593Smuzhiyun #define TEA6330T_SADDR_TREBLE		0x03	/* treble control */
25*4882a593Smuzhiyun #define TEA6330T_SADDR_FADER		0x04	/* fader control */
26*4882a593Smuzhiyun #define   TEA6330T_MFN			0x20	/* mute control for selected channels */
27*4882a593Smuzhiyun #define   TEA6330T_FCH			0x10	/* select fader channels - front or rear */
28*4882a593Smuzhiyun #define TEA6330T_SADDR_AUDIO_SWITCH	0x05	/* audio switch */
29*4882a593Smuzhiyun #define   TEA6330T_GMU			0x80	/* mute control, general mute */
30*4882a593Smuzhiyun #define   TEA6330T_EQN			0x40	/* equalizer switchover (0=equalizer-on) */
31*4882a593Smuzhiyun 
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun struct tea6330t {
34*4882a593Smuzhiyun 	struct snd_i2c_device *device;
35*4882a593Smuzhiyun 	struct snd_i2c_bus *bus;
36*4882a593Smuzhiyun 	int equalizer;
37*4882a593Smuzhiyun 	int fader;
38*4882a593Smuzhiyun 	unsigned char regs[8];
39*4882a593Smuzhiyun 	unsigned char mleft, mright;
40*4882a593Smuzhiyun 	unsigned char bass, treble;
41*4882a593Smuzhiyun 	unsigned char max_bass, max_treble;
42*4882a593Smuzhiyun };
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 
snd_tea6330t_detect(struct snd_i2c_bus * bus,int equalizer)45*4882a593Smuzhiyun int snd_tea6330t_detect(struct snd_i2c_bus *bus, int equalizer)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	int res;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	snd_i2c_lock(bus);
50*4882a593Smuzhiyun 	res = snd_i2c_probeaddr(bus, TEA6330T_ADDR);
51*4882a593Smuzhiyun 	snd_i2c_unlock(bus);
52*4882a593Smuzhiyun 	return res;
53*4882a593Smuzhiyun }
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun #if 0
56*4882a593Smuzhiyun static void snd_tea6330t_set(struct tea6330t *tea,
57*4882a593Smuzhiyun 			     unsigned char addr, unsigned char value)
58*4882a593Smuzhiyun {
59*4882a593Smuzhiyun #if 0
60*4882a593Smuzhiyun 	printk(KERN_DEBUG "set - 0x%x/0x%x\n", addr, value);
61*4882a593Smuzhiyun #endif
62*4882a593Smuzhiyun 	snd_i2c_write(tea->bus, TEA6330T_ADDR, addr, value, 1);
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun #endif
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #define TEA6330T_MASTER_VOLUME(xname, xindex) \
67*4882a593Smuzhiyun { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
68*4882a593Smuzhiyun   .info = snd_tea6330t_info_master_volume, \
69*4882a593Smuzhiyun   .get = snd_tea6330t_get_master_volume, .put = snd_tea6330t_put_master_volume }
70*4882a593Smuzhiyun 
snd_tea6330t_info_master_volume(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)71*4882a593Smuzhiyun static int snd_tea6330t_info_master_volume(struct snd_kcontrol *kcontrol,
72*4882a593Smuzhiyun 					   struct snd_ctl_elem_info *uinfo)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
75*4882a593Smuzhiyun 	uinfo->count = 2;
76*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
77*4882a593Smuzhiyun 	uinfo->value.integer.max = 43;
78*4882a593Smuzhiyun 	return 0;
79*4882a593Smuzhiyun }
80*4882a593Smuzhiyun 
snd_tea6330t_get_master_volume(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)81*4882a593Smuzhiyun static int snd_tea6330t_get_master_volume(struct snd_kcontrol *kcontrol,
82*4882a593Smuzhiyun 					  struct snd_ctl_elem_value *ucontrol)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	snd_i2c_lock(tea->bus);
87*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = tea->mleft - 0x14;
88*4882a593Smuzhiyun 	ucontrol->value.integer.value[1] = tea->mright - 0x14;
89*4882a593Smuzhiyun 	snd_i2c_unlock(tea->bus);
90*4882a593Smuzhiyun 	return 0;
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun 
snd_tea6330t_put_master_volume(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)93*4882a593Smuzhiyun static int snd_tea6330t_put_master_volume(struct snd_kcontrol *kcontrol,
94*4882a593Smuzhiyun 					  struct snd_ctl_elem_value *ucontrol)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
97*4882a593Smuzhiyun 	int change, count, err;
98*4882a593Smuzhiyun 	unsigned char bytes[3];
99*4882a593Smuzhiyun 	unsigned char val1, val2;
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun 	val1 = (ucontrol->value.integer.value[0] % 44) + 0x14;
102*4882a593Smuzhiyun 	val2 = (ucontrol->value.integer.value[1] % 44) + 0x14;
103*4882a593Smuzhiyun 	snd_i2c_lock(tea->bus);
104*4882a593Smuzhiyun 	change = val1 != tea->mleft || val2 != tea->mright;
105*4882a593Smuzhiyun 	tea->mleft = val1;
106*4882a593Smuzhiyun 	tea->mright = val2;
107*4882a593Smuzhiyun 	count = 0;
108*4882a593Smuzhiyun 	if (tea->regs[TEA6330T_SADDR_VOLUME_LEFT] != 0) {
109*4882a593Smuzhiyun 		bytes[count++] = TEA6330T_SADDR_VOLUME_LEFT;
110*4882a593Smuzhiyun 		bytes[count++] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT] = tea->mleft;
111*4882a593Smuzhiyun 	}
112*4882a593Smuzhiyun 	if (tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] != 0) {
113*4882a593Smuzhiyun 		if (count == 0)
114*4882a593Smuzhiyun 			bytes[count++] = TEA6330T_SADDR_VOLUME_RIGHT;
115*4882a593Smuzhiyun 		bytes[count++] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] = tea->mright;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun 	if (count > 0) {
118*4882a593Smuzhiyun 		if ((err = snd_i2c_sendbytes(tea->device, bytes, count)) < 0)
119*4882a593Smuzhiyun 			change = err;
120*4882a593Smuzhiyun 	}
121*4882a593Smuzhiyun 	snd_i2c_unlock(tea->bus);
122*4882a593Smuzhiyun 	return change;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun #define TEA6330T_MASTER_SWITCH(xname, xindex) \
126*4882a593Smuzhiyun { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
127*4882a593Smuzhiyun   .info = snd_tea6330t_info_master_switch, \
128*4882a593Smuzhiyun   .get = snd_tea6330t_get_master_switch, .put = snd_tea6330t_put_master_switch }
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun #define snd_tea6330t_info_master_switch		snd_ctl_boolean_stereo_info
131*4882a593Smuzhiyun 
snd_tea6330t_get_master_switch(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)132*4882a593Smuzhiyun static int snd_tea6330t_get_master_switch(struct snd_kcontrol *kcontrol,
133*4882a593Smuzhiyun 					  struct snd_ctl_elem_value *ucontrol)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	snd_i2c_lock(tea->bus);
138*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT] == 0 ? 0 : 1;
139*4882a593Smuzhiyun 	ucontrol->value.integer.value[1] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] == 0 ? 0 : 1;
140*4882a593Smuzhiyun 	snd_i2c_unlock(tea->bus);
141*4882a593Smuzhiyun 	return 0;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun 
snd_tea6330t_put_master_switch(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)144*4882a593Smuzhiyun static int snd_tea6330t_put_master_switch(struct snd_kcontrol *kcontrol,
145*4882a593Smuzhiyun 					  struct snd_ctl_elem_value *ucontrol)
146*4882a593Smuzhiyun {
147*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
148*4882a593Smuzhiyun 	int change, err;
149*4882a593Smuzhiyun 	unsigned char bytes[3];
150*4882a593Smuzhiyun 	unsigned char oval1, oval2, val1, val2;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	val1 = ucontrol->value.integer.value[0] & 1;
153*4882a593Smuzhiyun 	val2 = ucontrol->value.integer.value[1] & 1;
154*4882a593Smuzhiyun 	snd_i2c_lock(tea->bus);
155*4882a593Smuzhiyun 	oval1 = tea->regs[TEA6330T_SADDR_VOLUME_LEFT] == 0 ? 0 : 1;
156*4882a593Smuzhiyun 	oval2 = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] == 0 ? 0 : 1;
157*4882a593Smuzhiyun 	change = val1 != oval1 || val2 != oval2;
158*4882a593Smuzhiyun 	tea->regs[TEA6330T_SADDR_VOLUME_LEFT] = val1 ? tea->mleft : 0;
159*4882a593Smuzhiyun 	tea->regs[TEA6330T_SADDR_VOLUME_RIGHT] = val2 ? tea->mright : 0;
160*4882a593Smuzhiyun 	bytes[0] = TEA6330T_SADDR_VOLUME_LEFT;
161*4882a593Smuzhiyun 	bytes[1] = tea->regs[TEA6330T_SADDR_VOLUME_LEFT];
162*4882a593Smuzhiyun 	bytes[2] = tea->regs[TEA6330T_SADDR_VOLUME_RIGHT];
163*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(tea->device, bytes, 3)) < 0)
164*4882a593Smuzhiyun 		change = err;
165*4882a593Smuzhiyun 	snd_i2c_unlock(tea->bus);
166*4882a593Smuzhiyun 	return change;
167*4882a593Smuzhiyun }
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun #define TEA6330T_BASS(xname, xindex) \
170*4882a593Smuzhiyun { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
171*4882a593Smuzhiyun   .info = snd_tea6330t_info_bass, \
172*4882a593Smuzhiyun   .get = snd_tea6330t_get_bass, .put = snd_tea6330t_put_bass }
173*4882a593Smuzhiyun 
snd_tea6330t_info_bass(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)174*4882a593Smuzhiyun static int snd_tea6330t_info_bass(struct snd_kcontrol *kcontrol,
175*4882a593Smuzhiyun 				  struct snd_ctl_elem_info *uinfo)
176*4882a593Smuzhiyun {
177*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
180*4882a593Smuzhiyun 	uinfo->count = 1;
181*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
182*4882a593Smuzhiyun 	uinfo->value.integer.max = tea->max_bass;
183*4882a593Smuzhiyun 	return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
snd_tea6330t_get_bass(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)186*4882a593Smuzhiyun static int snd_tea6330t_get_bass(struct snd_kcontrol *kcontrol,
187*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = tea->bass;
192*4882a593Smuzhiyun 	return 0;
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun 
snd_tea6330t_put_bass(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)195*4882a593Smuzhiyun static int snd_tea6330t_put_bass(struct snd_kcontrol *kcontrol,
196*4882a593Smuzhiyun 				 struct snd_ctl_elem_value *ucontrol)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
199*4882a593Smuzhiyun 	int change, err;
200*4882a593Smuzhiyun 	unsigned char bytes[2];
201*4882a593Smuzhiyun 	unsigned char val1;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	val1 = ucontrol->value.integer.value[0] % (tea->max_bass + 1);
204*4882a593Smuzhiyun 	snd_i2c_lock(tea->bus);
205*4882a593Smuzhiyun 	tea->bass = val1;
206*4882a593Smuzhiyun 	val1 += tea->equalizer ? 7 : 3;
207*4882a593Smuzhiyun 	change = tea->regs[TEA6330T_SADDR_BASS] != val1;
208*4882a593Smuzhiyun 	bytes[0] = TEA6330T_SADDR_BASS;
209*4882a593Smuzhiyun 	bytes[1] = tea->regs[TEA6330T_SADDR_BASS] = val1;
210*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(tea->device, bytes, 2)) < 0)
211*4882a593Smuzhiyun 		change = err;
212*4882a593Smuzhiyun 	snd_i2c_unlock(tea->bus);
213*4882a593Smuzhiyun 	return change;
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun #define TEA6330T_TREBLE(xname, xindex) \
217*4882a593Smuzhiyun { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
218*4882a593Smuzhiyun   .info = snd_tea6330t_info_treble, \
219*4882a593Smuzhiyun   .get = snd_tea6330t_get_treble, .put = snd_tea6330t_put_treble }
220*4882a593Smuzhiyun 
snd_tea6330t_info_treble(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_info * uinfo)221*4882a593Smuzhiyun static int snd_tea6330t_info_treble(struct snd_kcontrol *kcontrol,
222*4882a593Smuzhiyun 				    struct snd_ctl_elem_info *uinfo)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
225*4882a593Smuzhiyun 
226*4882a593Smuzhiyun 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
227*4882a593Smuzhiyun 	uinfo->count = 1;
228*4882a593Smuzhiyun 	uinfo->value.integer.min = 0;
229*4882a593Smuzhiyun 	uinfo->value.integer.max = tea->max_treble;
230*4882a593Smuzhiyun 	return 0;
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
snd_tea6330t_get_treble(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)233*4882a593Smuzhiyun static int snd_tea6330t_get_treble(struct snd_kcontrol *kcontrol,
234*4882a593Smuzhiyun 				   struct snd_ctl_elem_value *ucontrol)
235*4882a593Smuzhiyun {
236*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun 	ucontrol->value.integer.value[0] = tea->treble;
239*4882a593Smuzhiyun 	return 0;
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun 
snd_tea6330t_put_treble(struct snd_kcontrol * kcontrol,struct snd_ctl_elem_value * ucontrol)242*4882a593Smuzhiyun static int snd_tea6330t_put_treble(struct snd_kcontrol *kcontrol,
243*4882a593Smuzhiyun 				   struct snd_ctl_elem_value *ucontrol)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	struct tea6330t *tea = snd_kcontrol_chip(kcontrol);
246*4882a593Smuzhiyun 	int change, err;
247*4882a593Smuzhiyun 	unsigned char bytes[2];
248*4882a593Smuzhiyun 	unsigned char val1;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	val1 = ucontrol->value.integer.value[0] % (tea->max_treble + 1);
251*4882a593Smuzhiyun 	snd_i2c_lock(tea->bus);
252*4882a593Smuzhiyun 	tea->treble = val1;
253*4882a593Smuzhiyun 	val1 += 3;
254*4882a593Smuzhiyun 	change = tea->regs[TEA6330T_SADDR_TREBLE] != val1;
255*4882a593Smuzhiyun 	bytes[0] = TEA6330T_SADDR_TREBLE;
256*4882a593Smuzhiyun 	bytes[1] = tea->regs[TEA6330T_SADDR_TREBLE] = val1;
257*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(tea->device, bytes, 2)) < 0)
258*4882a593Smuzhiyun 		change = err;
259*4882a593Smuzhiyun 	snd_i2c_unlock(tea->bus);
260*4882a593Smuzhiyun 	return change;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun static const struct snd_kcontrol_new snd_tea6330t_controls[] = {
264*4882a593Smuzhiyun TEA6330T_MASTER_SWITCH("Master Playback Switch", 0),
265*4882a593Smuzhiyun TEA6330T_MASTER_VOLUME("Master Playback Volume", 0),
266*4882a593Smuzhiyun TEA6330T_BASS("Tone Control - Bass", 0),
267*4882a593Smuzhiyun TEA6330T_TREBLE("Tone Control - Treble", 0)
268*4882a593Smuzhiyun };
269*4882a593Smuzhiyun 
snd_tea6330_free(struct snd_i2c_device * device)270*4882a593Smuzhiyun static void snd_tea6330_free(struct snd_i2c_device *device)
271*4882a593Smuzhiyun {
272*4882a593Smuzhiyun 	kfree(device->private_data);
273*4882a593Smuzhiyun }
274*4882a593Smuzhiyun 
snd_tea6330t_update_mixer(struct snd_card * card,struct snd_i2c_bus * bus,int equalizer,int fader)275*4882a593Smuzhiyun int snd_tea6330t_update_mixer(struct snd_card *card,
276*4882a593Smuzhiyun 			      struct snd_i2c_bus *bus,
277*4882a593Smuzhiyun 			      int equalizer, int fader)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun 	struct snd_i2c_device *device;
280*4882a593Smuzhiyun 	struct tea6330t *tea;
281*4882a593Smuzhiyun 	const struct snd_kcontrol_new *knew;
282*4882a593Smuzhiyun 	unsigned int idx;
283*4882a593Smuzhiyun 	int err = -ENOMEM;
284*4882a593Smuzhiyun 	u8 default_treble, default_bass;
285*4882a593Smuzhiyun 	unsigned char bytes[7];
286*4882a593Smuzhiyun 
287*4882a593Smuzhiyun 	tea = kzalloc(sizeof(*tea), GFP_KERNEL);
288*4882a593Smuzhiyun 	if (tea == NULL)
289*4882a593Smuzhiyun 		return -ENOMEM;
290*4882a593Smuzhiyun 	if ((err = snd_i2c_device_create(bus, "TEA6330T", TEA6330T_ADDR, &device)) < 0) {
291*4882a593Smuzhiyun 		kfree(tea);
292*4882a593Smuzhiyun 		return err;
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 	tea->device = device;
295*4882a593Smuzhiyun 	tea->bus = bus;
296*4882a593Smuzhiyun 	tea->equalizer = equalizer;
297*4882a593Smuzhiyun 	tea->fader = fader;
298*4882a593Smuzhiyun 	device->private_data = tea;
299*4882a593Smuzhiyun 	device->private_free = snd_tea6330_free;
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun 	snd_i2c_lock(bus);
302*4882a593Smuzhiyun 
303*4882a593Smuzhiyun 	/* turn fader off and handle equalizer */
304*4882a593Smuzhiyun 	tea->regs[TEA6330T_SADDR_FADER] = 0x3f;
305*4882a593Smuzhiyun 	tea->regs[TEA6330T_SADDR_AUDIO_SWITCH] = equalizer ? 0 : TEA6330T_EQN;
306*4882a593Smuzhiyun 	/* initialize mixer */
307*4882a593Smuzhiyun 	if (!tea->equalizer) {
308*4882a593Smuzhiyun 		tea->max_bass = 9;
309*4882a593Smuzhiyun 		tea->max_treble = 8;
310*4882a593Smuzhiyun 		default_bass = 3 + 4;
311*4882a593Smuzhiyun 		tea->bass = 4;
312*4882a593Smuzhiyun 		default_treble = 3 + 4;
313*4882a593Smuzhiyun 		tea->treble = 4;
314*4882a593Smuzhiyun 	} else {
315*4882a593Smuzhiyun 		tea->max_bass = 5;
316*4882a593Smuzhiyun 		tea->max_treble = 0;
317*4882a593Smuzhiyun 		default_bass = 7 + 4;
318*4882a593Smuzhiyun 		tea->bass = 4;
319*4882a593Smuzhiyun 		default_treble = 3;
320*4882a593Smuzhiyun 		tea->treble = 0;
321*4882a593Smuzhiyun 	}
322*4882a593Smuzhiyun 	tea->mleft = tea->mright = 0x14;
323*4882a593Smuzhiyun 	tea->regs[TEA6330T_SADDR_BASS] = default_bass;
324*4882a593Smuzhiyun 	tea->regs[TEA6330T_SADDR_TREBLE] = default_treble;
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	/* compose I2C message and put the hardware to initial state */
327*4882a593Smuzhiyun 	bytes[0] = TEA6330T_SADDR_VOLUME_LEFT;
328*4882a593Smuzhiyun 	for (idx = 0; idx < 6; idx++)
329*4882a593Smuzhiyun 		bytes[idx+1] = tea->regs[idx];
330*4882a593Smuzhiyun 	if ((err = snd_i2c_sendbytes(device, bytes, 7)) < 0)
331*4882a593Smuzhiyun 		goto __error;
332*4882a593Smuzhiyun 
333*4882a593Smuzhiyun 	strcat(card->mixername, ",TEA6330T");
334*4882a593Smuzhiyun 	if ((err = snd_component_add(card, "TEA6330T")) < 0)
335*4882a593Smuzhiyun 		goto __error;
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	for (idx = 0; idx < ARRAY_SIZE(snd_tea6330t_controls); idx++) {
338*4882a593Smuzhiyun 		knew = &snd_tea6330t_controls[idx];
339*4882a593Smuzhiyun 		if (tea->treble == 0 && !strcmp(knew->name, "Tone Control - Treble"))
340*4882a593Smuzhiyun 			continue;
341*4882a593Smuzhiyun 		if ((err = snd_ctl_add(card, snd_ctl_new1(knew, tea))) < 0)
342*4882a593Smuzhiyun 			goto __error;
343*4882a593Smuzhiyun 	}
344*4882a593Smuzhiyun 
345*4882a593Smuzhiyun 	snd_i2c_unlock(bus);
346*4882a593Smuzhiyun 	return 0;
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun       __error:
349*4882a593Smuzhiyun       	snd_i2c_unlock(bus);
350*4882a593Smuzhiyun       	snd_i2c_device_free(device);
351*4882a593Smuzhiyun       	return err;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun EXPORT_SYMBOL(snd_tea6330t_detect);
355*4882a593Smuzhiyun EXPORT_SYMBOL(snd_tea6330t_update_mixer);
356