Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/i2c/tea6330t.c
26378 views
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 <[email protected]>
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
15
MODULE_AUTHOR("Jaroslav Kysela <[email protected]>");
16
MODULE_DESCRIPTION("Routines for control of the TEA6330T circuit via i2c bus");
17
MODULE_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
33
struct 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
45
int 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
56
static 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
68
static 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
78
static 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
90
static 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
130
static 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
142
static 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
173
static 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
185
static 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
194
static 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
221
static 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
233
static 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
242
static 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
264
static const struct snd_kcontrol_new snd_tea6330t_controls[] = {
265
TEA6330T_MASTER_SWITCH("Master Playback Switch", 0),
266
TEA6330T_MASTER_VOLUME("Master Playback Volume", 0),
267
TEA6330T_BASS("Tone Control - Bass", 0),
268
TEA6330T_TREBLE("Tone Control - Treble", 0)
269
};
270
271
static void snd_tea6330_free(struct snd_i2c_device *device)
272
{
273
kfree(device->private_data);
274
}
275
276
int 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
359
EXPORT_SYMBOL(snd_tea6330t_detect);
360
EXPORT_SYMBOL(snd_tea6330t_update_mixer);
361
362