1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * For the STS-Thompson TDA7432 audio processor chip |
4 | * |
5 | * Handles audio functions: volume, balance, tone, loudness |
6 | * This driver will not complain if used with any |
7 | * other i2c device with the same address. |
8 | * |
9 | * Muting and tone control by Jonathan Isom <jisom@ematic.com> |
10 | * |
11 | * Copyright (c) 2000 Eric Sandeen <eric_sandeen@bigfoot.com> |
12 | * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org> |
13 | * |
14 | * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu) |
15 | * Which was based on tda8425.c by Greg Alexander (c) 1998 |
16 | * |
17 | * OPTIONS: |
18 | * debug - set to 1 if you'd like to see debug messages |
19 | * set to 2 if you'd like to be inundated with debug messages |
20 | * |
21 | * loudness - set between 0 and 15 for varying degrees of loudness effect |
22 | * |
23 | * maxvol - set maximum volume to +20db (1), default is 0db(0) |
24 | */ |
25 | |
26 | #include <linux/module.h> |
27 | #include <linux/init.h> |
28 | #include <linux/kernel.h> |
29 | #include <linux/string.h> |
30 | #include <linux/timer.h> |
31 | #include <linux/delay.h> |
32 | #include <linux/errno.h> |
33 | #include <linux/slab.h> |
34 | #include <linux/videodev2.h> |
35 | #include <linux/i2c.h> |
36 | |
37 | #include <media/v4l2-device.h> |
38 | #include <media/v4l2-ioctl.h> |
39 | #include <media/v4l2-ctrls.h> |
40 | |
41 | #ifndef VIDEO_AUDIO_BALANCE |
42 | # define VIDEO_AUDIO_BALANCE 32 |
43 | #endif |
44 | |
45 | MODULE_AUTHOR("Eric Sandeen <eric_sandeen@bigfoot.com>" ); |
46 | MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip" ); |
47 | MODULE_LICENSE("GPL" ); |
48 | |
49 | static int maxvol; |
50 | static int loudness; /* disable loudness by default */ |
51 | static int debug; /* insmod parameter */ |
52 | module_param(debug, int, S_IRUGO | S_IWUSR); |
53 | MODULE_PARM_DESC(debug, "Set debugging level from 0 to 3. Default is off(0)." ); |
54 | module_param(loudness, int, S_IRUGO); |
55 | MODULE_PARM_DESC(loudness, "Turn loudness on(1) else off(0). Default is off(0)." ); |
56 | module_param(maxvol, int, S_IRUGO | S_IWUSR); |
57 | MODULE_PARM_DESC(maxvol, "Set maximum volume to +20dB(0) else +0dB(1). Default is +20dB(0)." ); |
58 | |
59 | |
60 | /* Structure of address and subaddresses for the tda7432 */ |
61 | |
62 | struct tda7432 { |
63 | struct v4l2_subdev sd; |
64 | struct v4l2_ctrl_handler hdl; |
65 | struct { |
66 | /* bass/treble cluster */ |
67 | struct v4l2_ctrl *bass; |
68 | struct v4l2_ctrl *treble; |
69 | }; |
70 | struct { |
71 | /* mute/balance cluster */ |
72 | struct v4l2_ctrl *mute; |
73 | struct v4l2_ctrl *balance; |
74 | }; |
75 | }; |
76 | |
77 | static inline struct tda7432 *to_state(struct v4l2_subdev *sd) |
78 | { |
79 | return container_of(sd, struct tda7432, sd); |
80 | } |
81 | |
82 | static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl) |
83 | { |
84 | return &container_of(ctrl->handler, struct tda7432, hdl)->sd; |
85 | } |
86 | |
87 | /* The TDA7432 is made by STS-Thompson |
88 | * http://www.st.com |
89 | * http://us.st.com/stonline/books/pdf/docs/4056.pdf |
90 | * |
91 | * TDA7432: I2C-bus controlled basic audio processor |
92 | * |
93 | * The TDA7432 controls basic audio functions like volume, balance, |
94 | * and tone control (including loudness). It also has four channel |
95 | * output (for front and rear). Since most vidcap cards probably |
96 | * don't have 4 channel output, this driver will set front & rear |
97 | * together (no independent control). |
98 | */ |
99 | |
100 | /* Subaddresses for TDA7432 */ |
101 | |
102 | #define TDA7432_IN 0x00 /* Input select */ |
103 | #define TDA7432_VL 0x01 /* Volume */ |
104 | #define TDA7432_TN 0x02 /* Bass, Treble (Tone) */ |
105 | #define TDA7432_LF 0x03 /* Attenuation LF (Left Front) */ |
106 | #define TDA7432_LR 0x04 /* Attenuation LR (Left Rear) */ |
107 | #define TDA7432_RF 0x05 /* Attenuation RF (Right Front) */ |
108 | #define TDA7432_RR 0x06 /* Attenuation RR (Right Rear) */ |
109 | #define TDA7432_LD 0x07 /* Loudness */ |
110 | |
111 | |
112 | /* Masks for bits in TDA7432 subaddresses */ |
113 | |
114 | /* Many of these not used - just for documentation */ |
115 | |
116 | /* Subaddress 0x00 - Input selection and bass control */ |
117 | |
118 | /* Bits 0,1,2 control input: |
119 | * 0x00 - Stereo input |
120 | * 0x02 - Mono input |
121 | * 0x03 - Mute (Using Attenuators Plays better with modules) |
122 | * Mono probably isn't used - I'm guessing only the stereo |
123 | * input is connected on most cards, so we'll set it to stereo. |
124 | * |
125 | * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut |
126 | * Bit 4 controls bass range: 0/1 is extended/standard bass range |
127 | * |
128 | * Highest 3 bits not used |
129 | */ |
130 | |
131 | #define TDA7432_STEREO_IN 0 |
132 | #define TDA7432_MONO_IN 2 /* Probably won't be used */ |
133 | #define TDA7432_BASS_SYM 1 << 3 |
134 | #define TDA7432_BASS_NORM 1 << 4 |
135 | |
136 | /* Subaddress 0x01 - Volume */ |
137 | |
138 | /* Lower 7 bits control volume from -79dB to +32dB in 1dB steps |
139 | * Recommended maximum is +20 dB |
140 | * |
141 | * +32dB: 0x00 |
142 | * +20dB: 0x0c |
143 | * 0dB: 0x20 |
144 | * -79dB: 0x6f |
145 | * |
146 | * MSB (bit 7) controls loudness: 1/0 is loudness on/off |
147 | */ |
148 | |
149 | #define TDA7432_VOL_0DB 0x20 |
150 | #define TDA7432_LD_ON 1 << 7 |
151 | |
152 | |
153 | /* Subaddress 0x02 - Tone control */ |
154 | |
155 | /* Bits 0,1,2 control absolute treble gain from 0dB to 14dB |
156 | * 0x0 is 14dB, 0x7 is 0dB |
157 | * |
158 | * Bit 3 controls treble attenuation/gain (sign) |
159 | * 1 = gain (+) |
160 | * 0 = attenuation (-) |
161 | * |
162 | * Bits 4,5,6 control absolute bass gain from 0dB to 14dB |
163 | * (This is only true for normal base range, set in 0x00) |
164 | * 0x0 << 4 is 14dB, 0x7 is 0dB |
165 | * |
166 | * Bit 7 controls bass attenuation/gain (sign) |
167 | * 1 << 7 = gain (+) |
168 | * 0 << 7 = attenuation (-) |
169 | * |
170 | * Example: |
171 | * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble |
172 | */ |
173 | |
174 | #define TDA7432_TREBLE_0DB 0xf |
175 | #define TDA7432_TREBLE 7 |
176 | #define TDA7432_TREBLE_GAIN 1 << 3 |
177 | #define TDA7432_BASS_0DB 0xf |
178 | #define TDA7432_BASS 7 << 4 |
179 | #define TDA7432_BASS_GAIN 1 << 7 |
180 | |
181 | |
182 | /* Subaddress 0x03 - Left Front attenuation */ |
183 | /* Subaddress 0x04 - Left Rear attenuation */ |
184 | /* Subaddress 0x05 - Right Front attenuation */ |
185 | /* Subaddress 0x06 - Right Rear attenuation */ |
186 | |
187 | /* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB |
188 | * in 1.5dB steps. |
189 | * |
190 | * 0x00 is 0dB |
191 | * 0x1f is -37.5dB |
192 | * |
193 | * Bit 5 mutes that channel when set (1 = mute, 0 = unmute) |
194 | * We'll use the mute on the input, though (above) |
195 | * Bits 6,7 unused |
196 | */ |
197 | |
198 | #define TDA7432_ATTEN_0DB 0x00 |
199 | #define TDA7432_MUTE 0x1 << 5 |
200 | |
201 | |
202 | /* Subaddress 0x07 - Loudness Control */ |
203 | |
204 | /* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps |
205 | * when bit 4 is NOT set |
206 | * |
207 | * 0x0 is 0dB |
208 | * 0xf is -15dB |
209 | * |
210 | * If bit 4 is set, then there is a flat attenuation according to |
211 | * the lower 4 bits, as above. |
212 | * |
213 | * Bits 5,6,7 unused |
214 | */ |
215 | |
216 | |
217 | |
218 | /* Begin code */ |
219 | |
220 | static int tda7432_write(struct v4l2_subdev *sd, int subaddr, int val) |
221 | { |
222 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
223 | unsigned char buffer[2]; |
224 | |
225 | v4l2_dbg(2, debug, sd, "In tda7432_write\n" ); |
226 | v4l2_dbg(1, debug, sd, "Writing %d 0x%x\n" , subaddr, val); |
227 | buffer[0] = subaddr; |
228 | buffer[1] = val; |
229 | if (2 != i2c_master_send(client, buf: buffer, count: 2)) { |
230 | v4l2_err(sd, "I/O error, trying (write %d 0x%x)\n" , |
231 | subaddr, val); |
232 | return -1; |
233 | } |
234 | return 0; |
235 | } |
236 | |
237 | static int tda7432_set(struct v4l2_subdev *sd) |
238 | { |
239 | struct i2c_client *client = v4l2_get_subdevdata(sd); |
240 | unsigned char buf[16]; |
241 | |
242 | buf[0] = TDA7432_IN; |
243 | buf[1] = TDA7432_STEREO_IN | /* Main (stereo) input */ |
244 | TDA7432_BASS_SYM | /* Symmetric bass cut */ |
245 | TDA7432_BASS_NORM; /* Normal bass range */ |
246 | buf[2] = 0x3b; |
247 | if (loudness) /* Turn loudness on? */ |
248 | buf[2] |= TDA7432_LD_ON; |
249 | buf[3] = TDA7432_TREBLE_0DB | (TDA7432_BASS_0DB << 4); |
250 | buf[4] = TDA7432_ATTEN_0DB; |
251 | buf[5] = TDA7432_ATTEN_0DB; |
252 | buf[6] = TDA7432_ATTEN_0DB; |
253 | buf[7] = TDA7432_ATTEN_0DB; |
254 | buf[8] = loudness; |
255 | if (9 != i2c_master_send(client, buf, count: 9)) { |
256 | v4l2_err(sd, "I/O error, trying tda7432_set\n" ); |
257 | return -1; |
258 | } |
259 | |
260 | return 0; |
261 | } |
262 | |
263 | static int tda7432_log_status(struct v4l2_subdev *sd) |
264 | { |
265 | struct tda7432 *state = to_state(sd); |
266 | |
267 | v4l2_ctrl_handler_log_status(hdl: &state->hdl, prefix: sd->name); |
268 | return 0; |
269 | } |
270 | |
271 | static int tda7432_s_ctrl(struct v4l2_ctrl *ctrl) |
272 | { |
273 | struct v4l2_subdev *sd = to_sd(ctrl); |
274 | struct tda7432 *t = to_state(sd); |
275 | u8 bass, treble, volume; |
276 | u8 lf, lr, rf, rr; |
277 | |
278 | switch (ctrl->id) { |
279 | case V4L2_CID_AUDIO_MUTE: |
280 | if (t->balance->val < 0) { |
281 | /* shifted to left, attenuate right */ |
282 | rr = rf = -t->balance->val; |
283 | lr = lf = TDA7432_ATTEN_0DB; |
284 | } else if (t->balance->val > 0) { |
285 | /* shifted to right, attenuate left */ |
286 | rr = rf = TDA7432_ATTEN_0DB; |
287 | lr = lf = t->balance->val; |
288 | } else { |
289 | /* centered */ |
290 | rr = rf = TDA7432_ATTEN_0DB; |
291 | lr = lf = TDA7432_ATTEN_0DB; |
292 | } |
293 | if (t->mute->val) { |
294 | lf |= TDA7432_MUTE; |
295 | lr |= TDA7432_MUTE; |
296 | rf |= TDA7432_MUTE; |
297 | rr |= TDA7432_MUTE; |
298 | } |
299 | /* Mute & update balance*/ |
300 | tda7432_write(sd, TDA7432_LF, val: lf); |
301 | tda7432_write(sd, TDA7432_LR, val: lr); |
302 | tda7432_write(sd, TDA7432_RF, val: rf); |
303 | tda7432_write(sd, TDA7432_RR, val: rr); |
304 | return 0; |
305 | case V4L2_CID_AUDIO_VOLUME: |
306 | volume = 0x6f - ctrl->val; |
307 | if (loudness) /* Turn on the loudness bit */ |
308 | volume |= TDA7432_LD_ON; |
309 | |
310 | tda7432_write(sd, TDA7432_VL, val: volume); |
311 | return 0; |
312 | case V4L2_CID_AUDIO_BASS: |
313 | bass = t->bass->val; |
314 | treble = t->treble->val; |
315 | if (bass >= 0x8) |
316 | bass = 14 - (bass - 8); |
317 | if (treble >= 0x8) |
318 | treble = 14 - (treble - 8); |
319 | |
320 | tda7432_write(sd, TDA7432_TN, val: 0x10 | (bass << 4) | treble); |
321 | return 0; |
322 | } |
323 | return -EINVAL; |
324 | } |
325 | |
326 | /* ----------------------------------------------------------------------- */ |
327 | |
328 | static const struct v4l2_ctrl_ops tda7432_ctrl_ops = { |
329 | .s_ctrl = tda7432_s_ctrl, |
330 | }; |
331 | |
332 | static const struct v4l2_subdev_core_ops tda7432_core_ops = { |
333 | .log_status = tda7432_log_status, |
334 | }; |
335 | |
336 | static const struct v4l2_subdev_ops tda7432_ops = { |
337 | .core = &tda7432_core_ops, |
338 | }; |
339 | |
340 | /* ----------------------------------------------------------------------- */ |
341 | |
342 | /* *********************** * |
343 | * i2c interface functions * |
344 | * *********************** */ |
345 | |
346 | static int tda7432_probe(struct i2c_client *client) |
347 | { |
348 | struct tda7432 *t; |
349 | struct v4l2_subdev *sd; |
350 | |
351 | v4l_info(client, "chip found @ 0x%02x (%s)\n" , |
352 | client->addr << 1, client->adapter->name); |
353 | |
354 | t = devm_kzalloc(dev: &client->dev, size: sizeof(*t), GFP_KERNEL); |
355 | if (!t) |
356 | return -ENOMEM; |
357 | sd = &t->sd; |
358 | v4l2_i2c_subdev_init(sd, client, ops: &tda7432_ops); |
359 | v4l2_ctrl_handler_init(&t->hdl, 5); |
360 | v4l2_ctrl_new_std(hdl: &t->hdl, ops: &tda7432_ctrl_ops, |
361 | V4L2_CID_AUDIO_VOLUME, min: 0, max: maxvol ? 0x68 : 0x4f, step: 1, def: maxvol ? 0x5d : 0x47); |
362 | t->mute = v4l2_ctrl_new_std(hdl: &t->hdl, ops: &tda7432_ctrl_ops, |
363 | V4L2_CID_AUDIO_MUTE, min: 0, max: 1, step: 1, def: 0); |
364 | t->balance = v4l2_ctrl_new_std(hdl: &t->hdl, ops: &tda7432_ctrl_ops, |
365 | V4L2_CID_AUDIO_BALANCE, min: -31, max: 31, step: 1, def: 0); |
366 | t->bass = v4l2_ctrl_new_std(hdl: &t->hdl, ops: &tda7432_ctrl_ops, |
367 | V4L2_CID_AUDIO_BASS, min: 0, max: 14, step: 1, def: 7); |
368 | t->treble = v4l2_ctrl_new_std(hdl: &t->hdl, ops: &tda7432_ctrl_ops, |
369 | V4L2_CID_AUDIO_TREBLE, min: 0, max: 14, step: 1, def: 7); |
370 | sd->ctrl_handler = &t->hdl; |
371 | if (t->hdl.error) { |
372 | int err = t->hdl.error; |
373 | |
374 | v4l2_ctrl_handler_free(hdl: &t->hdl); |
375 | return err; |
376 | } |
377 | v4l2_ctrl_cluster(ncontrols: 2, controls: &t->bass); |
378 | v4l2_ctrl_cluster(ncontrols: 2, controls: &t->mute); |
379 | v4l2_ctrl_handler_setup(hdl: &t->hdl); |
380 | if (loudness < 0 || loudness > 15) { |
381 | v4l2_warn(sd, "loudness parameter must be between 0 and 15\n" ); |
382 | if (loudness < 0) |
383 | loudness = 0; |
384 | if (loudness > 15) |
385 | loudness = 15; |
386 | } |
387 | |
388 | tda7432_set(sd); |
389 | return 0; |
390 | } |
391 | |
392 | static void tda7432_remove(struct i2c_client *client) |
393 | { |
394 | struct v4l2_subdev *sd = i2c_get_clientdata(client); |
395 | struct tda7432 *t = to_state(sd); |
396 | |
397 | tda7432_set(sd); |
398 | v4l2_device_unregister_subdev(sd); |
399 | v4l2_ctrl_handler_free(hdl: &t->hdl); |
400 | } |
401 | |
402 | static const struct i2c_device_id tda7432_id[] = { |
403 | { "tda7432" , 0 }, |
404 | { } |
405 | }; |
406 | MODULE_DEVICE_TABLE(i2c, tda7432_id); |
407 | |
408 | static struct i2c_driver tda7432_driver = { |
409 | .driver = { |
410 | .name = "tda7432" , |
411 | }, |
412 | .probe = tda7432_probe, |
413 | .remove = tda7432_remove, |
414 | .id_table = tda7432_id, |
415 | }; |
416 | |
417 | module_i2c_driver(tda7432_driver); |
418 | |