Linux Audio

Check our new training course

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