OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [media/] [video/] [tda7432.c] - Blame information for rev 78

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * For the STS-Thompson TDA7432 audio processor chip
3
 *
4
 * Handles audio functions: volume, balance, tone, loudness
5
 * This driver will not complain if used with any
6
 * other i2c device with the same address.
7
 *
8
 * Muting and tone control by Jonathan Isom <jisom@ematic.com>
9
 *
10
 * Copyright (c) 2000 Eric Sandeen <eric_sandeen@bigfoot.com>
11
 * This code is placed under the terms of the GNU General Public License
12
 * Based on tda9855.c by Steve VanDeBogart (vandebo@uclink.berkeley.edu)
13
 * Which was based on tda8425.c by Greg Alexander (c) 1998
14
 *
15
 * OPTIONS:
16
 * debug    - set to 1 if you'd like to see debug messages
17
 *            set to 2 if you'd like to be inundated with debug messages
18
 *
19
 * loudness - set between 0 and 15 for varying degrees of loudness effect
20
 *
21
 * maxvol   - set maximium volume to +20db (1), default is 0db(0)
22
 *
23
 *
24
 *  Revision: 0.7 - maxvol module parm to set maximium volume 0db or +20db
25
 *                              store if muted so we can return it
26
 *                              change balance only if flaged to
27
 *  Revision: 0.6 - added tone controls
28
 *  Revision: 0.5 - Fixed odd balance problem
29
 *  Revision: 0.4 - added muting
30
 *  Revision: 0.3 - Fixed silly reversed volume controls.  :)
31
 *  Revision: 0.2 - Cleaned up #defines
32
 *                      fixed volume control
33
 *          Added I2C_DRIVERID_TDA7432
34
 *                      added loudness insmod control
35
 *  Revision: 0.1 - initial version
36
 */
37
 
38
#include <linux/module.h>
39
#include <linux/init.h>
40
#include <linux/kernel.h>
41
#include <linux/string.h>
42
#include <linux/timer.h>
43
#include <linux/delay.h>
44
#include <linux/errno.h>
45
#include <linux/slab.h>
46
#include <linux/videodev.h>
47
#include <linux/i2c.h>
48
 
49
#include <media/v4l2-common.h>
50
#include <media/i2c-addr.h>
51
 
52
#ifndef VIDEO_AUDIO_BALANCE
53
# define VIDEO_AUDIO_BALANCE 32
54
#endif
55
 
56
MODULE_AUTHOR("Eric Sandeen <eric_sandeen@bigfoot.com>");
57
MODULE_DESCRIPTION("bttv driver for the tda7432 audio processor chip");
58
MODULE_LICENSE("GPL");
59
 
60
static int maxvol;
61
static int loudness; /* disable loudness by default */
62
static int debug;        /* insmod parameter */
63
module_param(debug, int, S_IRUGO | S_IWUSR);
64
module_param(loudness, int, S_IRUGO);
65
MODULE_PARM_DESC(maxvol,"Set maximium volume to +20db (0), default is 0db(1)");
66
module_param(maxvol, int, S_IRUGO | S_IWUSR);
67
 
68
 
69
/* Address to scan (I2C address of this chip) */
70
static unsigned short normal_i2c[] = {
71
        I2C_ADDR_TDA7432 >> 1,
72
        I2C_CLIENT_END,
73
};
74
I2C_CLIENT_INSMOD;
75
 
76
/* Structure of address and subaddresses for the tda7432 */
77
 
78
struct tda7432 {
79
        int addr;
80
        int input;
81
        int volume;
82
        int muted;
83
        int bass, treble;
84
        int lf, lr, rf, rr;
85
        int loud;
86
        struct i2c_client c;
87
};
88
static struct i2c_driver driver;
89
static struct i2c_client client_template;
90
 
91
/* The TDA7432 is made by STS-Thompson
92
 * http://www.st.com
93
 * http://us.st.com/stonline/books/pdf/docs/4056.pdf
94
 *
95
 * TDA7432: I2C-bus controlled basic audio processor
96
 *
97
 * The TDA7432 controls basic audio functions like volume, balance,
98
 * and tone control (including loudness).  It also has four channel
99
 * output (for front and rear).  Since most vidcap cards probably
100
 * don't have 4 channel output, this driver will set front & rear
101
 * together (no independent control).
102
 */
103
 
104
                /* Subaddresses for TDA7432 */
105
 
106
#define TDA7432_IN      0x00 /* Input select                 */
107
#define TDA7432_VL      0x01 /* Volume                       */
108
#define TDA7432_TN      0x02 /* Bass, Treble (Tone)          */
109
#define TDA7432_LF      0x03 /* Attenuation LF (Left Front)  */
110
#define TDA7432_LR      0x04 /* Attenuation LR (Left Rear)   */
111
#define TDA7432_RF      0x05 /* Attenuation RF (Right Front) */
112
#define TDA7432_RR      0x06 /* Attenuation RR (Right Rear)  */
113
#define TDA7432_LD      0x07 /* Loudness                     */
114
 
115
 
116
                /* Masks for bits in TDA7432 subaddresses */
117
 
118
/* Many of these not used - just for documentation */
119
 
120
/* Subaddress 0x00 - Input selection and bass control */
121
 
122
/* Bits 0,1,2 control input:
123
 * 0x00 - Stereo input
124
 * 0x02 - Mono input
125
 * 0x03 - Mute  (Using Attenuators Plays better with modules)
126
 * Mono probably isn't used - I'm guessing only the stereo
127
 * input is connected on most cards, so we'll set it to stereo.
128
 *
129
 * Bit 3 controls bass cut: 0/1 is non-symmetric/symmetric bass cut
130
 * Bit 4 controls bass range: 0/1 is extended/standard bass range
131
 *
132
 * Highest 3 bits not used
133
 */
134
 
135
#define TDA7432_STEREO_IN       0
136
#define TDA7432_MONO_IN         2       /* Probably won't be used */
137
#define TDA7432_BASS_SYM        1 << 3
138
#define TDA7432_BASS_NORM       1 << 4
139
 
140
/* Subaddress 0x01 - Volume */
141
 
142
/* Lower 7 bits control volume from -79dB to +32dB in 1dB steps
143
 * Recommended maximum is +20 dB
144
 *
145
 * +32dB: 0x00
146
 * +20dB: 0x0c
147
 *   0dB: 0x20
148
 * -79dB: 0x6f
149
 *
150
 * MSB (bit 7) controls loudness: 1/0 is loudness on/off
151
 */
152
 
153
#define TDA7432_VOL_0DB         0x20
154
#define TDA7432_LD_ON           1 << 7
155
 
156
 
157
/* Subaddress 0x02 - Tone control */
158
 
159
/* Bits 0,1,2 control absolute treble gain from 0dB to 14dB
160
 * 0x0 is 14dB, 0x7 is 0dB
161
 *
162
 * Bit 3 controls treble attenuation/gain (sign)
163
 * 1 = gain (+)
164
 * 0 = attenuation (-)
165
 *
166
 * Bits 4,5,6 control absolute bass gain from 0dB to 14dB
167
 * (This is only true for normal base range, set in 0x00)
168
 * 0x0 << 4 is 14dB, 0x7 is 0dB
169
 *
170
 * Bit 7 controls bass attenuation/gain (sign)
171
 * 1 << 7 = gain (+)
172
 * 0 << 7 = attenuation (-)
173
 *
174
 * Example:
175
 * 1 1 0 1 0 1 0 1 is +4dB bass, -4dB treble
176
 */
177
 
178
#define TDA7432_TREBLE_0DB              0xf
179
#define TDA7432_TREBLE                  7
180
#define TDA7432_TREBLE_GAIN             1 << 3
181
#define TDA7432_BASS_0DB                0xf
182
#define TDA7432_BASS                    7 << 4
183
#define TDA7432_BASS_GAIN               1 << 7
184
 
185
 
186
/* Subaddress 0x03 - Left  Front attenuation */
187
/* Subaddress 0x04 - Left  Rear  attenuation */
188
/* Subaddress 0x05 - Right Front attenuation */
189
/* Subaddress 0x06 - Right Rear  attenuation */
190
 
191
/* Bits 0,1,2,3,4 control attenuation from 0dB to -37.5dB
192
 * in 1.5dB steps.
193
 *
194
 * 0x00 is     0dB
195
 * 0x1f is -37.5dB
196
 *
197
 * Bit 5 mutes that channel when set (1 = mute, 0 = unmute)
198
 * We'll use the mute on the input, though (above)
199
 * Bits 6,7 unused
200
 */
201
 
202
#define TDA7432_ATTEN_0DB       0x00
203
#define TDA7432_MUTE        0x1 << 5
204
 
205
 
206
/* Subaddress 0x07 - Loudness Control */
207
 
208
/* Bits 0,1,2,3 control loudness from 0dB to -15dB in 1dB steps
209
 * when bit 4 is NOT set
210
 *
211
 * 0x0 is   0dB
212
 * 0xf is -15dB
213
 *
214
 * If bit 4 is set, then there is a flat attenuation according to
215
 * the lower 4 bits, as above.
216
 *
217
 * Bits 5,6,7 unused
218
 */
219
 
220
 
221
 
222
/* Begin code */
223
 
224
static int tda7432_write(struct i2c_client *client, int subaddr, int val)
225
{
226
        unsigned char buffer[2];
227
        v4l_dbg(2, debug,client,"In tda7432_write\n");
228
        v4l_dbg(1, debug,client,"Writing %d 0x%x\n", subaddr, val);
229
        buffer[0] = subaddr;
230
        buffer[1] = val;
231
        if (2 != i2c_master_send(client,buffer,2)) {
232
                v4l_err(client,"I/O error, trying (write %d 0x%x)\n",
233
                       subaddr, val);
234
                return -1;
235
        }
236
        return 0;
237
}
238
 
239
/* I don't think we ever actually _read_ the chip... */
240
 
241
static int tda7432_set(struct i2c_client *client)
242
{
243
        struct tda7432 *t = i2c_get_clientdata(client);
244
        unsigned char buf[16];
245
        v4l_dbg(2, debug,client,"In tda7432_set\n");
246
 
247
        v4l_dbg(1, debug,client,
248
                "tda7432: 7432_set(0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x)\n",
249
                t->input,t->volume,t->bass,t->treble,t->lf,t->lr,t->rf,t->rr,t->loud);
250
        buf[0]  = TDA7432_IN;
251
        buf[1]  = t->input;
252
        buf[2]  = t->volume;
253
        buf[3]  = t->bass;
254
        buf[4]  = t->treble;
255
        buf[5]  = t->lf;
256
        buf[6]  = t->lr;
257
        buf[7]  = t->rf;
258
        buf[8]  = t->rr;
259
        buf[9]  = t->loud;
260
        if (10 != i2c_master_send(client,buf,10)) {
261
                v4l_err(client,"I/O error, trying tda7432_set\n");
262
                return -1;
263
        }
264
 
265
        return 0;
266
}
267
 
268
static void do_tda7432_init(struct i2c_client *client)
269
{
270
        struct tda7432 *t = i2c_get_clientdata(client);
271
        v4l_dbg(2, debug,client,"In tda7432_init\n");
272
 
273
        t->input  = TDA7432_STEREO_IN |  /* Main (stereo) input   */
274
                    TDA7432_BASS_SYM  |  /* Symmetric bass cut    */
275
                    TDA7432_BASS_NORM;   /* Normal bass range     */
276
        t->volume =  0x3b ;                              /* -27dB Volume            */
277
        if (loudness)                    /* Turn loudness on?     */
278
                t->volume |= TDA7432_LD_ON;
279
        t->muted    = VIDEO_AUDIO_MUTE;
280
        t->treble   = TDA7432_TREBLE_0DB; /* 0dB Treble            */
281
        t->bass         = TDA7432_BASS_0DB;      /* 0dB Bass              */
282
        t->lf     = TDA7432_ATTEN_0DB;   /* 0dB attenuation       */
283
        t->lr     = TDA7432_ATTEN_0DB;   /* 0dB attenuation       */
284
        t->rf     = TDA7432_ATTEN_0DB;   /* 0dB attenuation       */
285
        t->rr     = TDA7432_ATTEN_0DB;   /* 0dB attenuation       */
286
        t->loud   = loudness;            /* insmod parameter      */
287
 
288
        tda7432_set(client);
289
}
290
 
291
/* *********************** *
292
 * i2c interface functions *
293
 * *********************** */
294
 
295
static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind)
296
{
297
        struct tda7432 *t;
298
        struct i2c_client *client;
299
 
300
        t = kzalloc(sizeof *t,GFP_KERNEL);
301
        if (!t)
302
                return -ENOMEM;
303
 
304
        client = &t->c;
305
        memcpy(client,&client_template,sizeof(struct i2c_client));
306
        client->adapter = adap;
307
        client->addr = addr;
308
        i2c_set_clientdata(client, t);
309
 
310
        do_tda7432_init(client);
311
        i2c_attach_client(client);
312
 
313
        v4l_info(client, "chip found @ 0x%x (%s)\n", addr << 1, adap->name);
314
        return 0;
315
}
316
 
317
static int tda7432_probe(struct i2c_adapter *adap)
318
{
319
        if (adap->class & I2C_CLASS_TV_ANALOG)
320
                return i2c_probe(adap, &addr_data, tda7432_attach);
321
        return 0;
322
}
323
 
324
static int tda7432_detach(struct i2c_client *client)
325
{
326
        struct tda7432 *t  = i2c_get_clientdata(client);
327
 
328
        do_tda7432_init(client);
329
        i2c_detach_client(client);
330
 
331
        kfree(t);
332
        return 0;
333
}
334
 
335
static int tda7432_command(struct i2c_client *client,
336
                           unsigned int cmd, void *arg)
337
{
338
        struct tda7432 *t = i2c_get_clientdata(client);
339
        v4l_dbg(2, debug,client,"In tda7432_command\n");
340
        if (debug>1)
341
                v4l_i2c_print_ioctl(client,cmd);
342
 
343
        switch (cmd) {
344
        /* --- v4l ioctls --- */
345
        /* take care: bttv does userspace copying, we'll get a
346
           kernel pointer here... */
347
 
348
        /* Query card - scale from TDA7432 settings to V4L settings */
349
        case VIDIOCGAUDIO:
350
        {
351
                struct video_audio *va = arg;
352
 
353
                va->flags |= VIDEO_AUDIO_VOLUME |
354
                        VIDEO_AUDIO_BASS |
355
                        VIDEO_AUDIO_TREBLE |
356
                        VIDEO_AUDIO_MUTABLE;
357
                if (t->muted)
358
                        va->flags |= VIDEO_AUDIO_MUTE;
359
                va->mode |= VIDEO_SOUND_STEREO;
360
                /* Master volume control
361
                 * V4L volume is min 0, max 65535
362
                 * TDA7432 Volume:
363
                 * Min (-79dB) is 0x6f
364
                 * Max (+20dB) is 0x07 (630)
365
                 * Max (0dB) is 0x20 (829)
366
                 * (Mask out bit 7 of vol - it's for the loudness setting)
367
                 */
368
                if (!maxvol){  /* max +20db */
369
                        va->volume = ( 0x6f - (t->volume & 0x7F) ) * 630;
370
                } else {       /* max 0db   */
371
                        va->volume = ( 0x6f - (t->volume & 0x7F) ) * 829;
372
                }
373
 
374
                /* Balance depends on L,R attenuation
375
                 * V4L balance is 0 to 65535, middle is 32768
376
                 * TDA7432 attenuation: min (0dB) is 0, max (-37.5dB) is 0x1f
377
                 * to scale up to V4L numbers, mult by 1057
378
                 * attenuation exists for lf, lr, rf, rr
379
                 * we use only lf and rf (front channels)
380
                 */
381
 
382
                if ( (t->lf) < (t->rf) )
383
                        /* right is attenuated, balance shifted left */
384
                        va->balance = (32768 - 1057*(t->rf));
385
                else
386
                        /* left is attenuated, balance shifted right */
387
                        va->balance = (32768 + 1057*(t->lf));
388
 
389
                /* Bass/treble 4 bits each */
390
                va->bass=t->bass;
391
                if(va->bass >= 0x8)
392
                        va->bass = ~(va->bass - 0x8) & 0xf;
393
                va->bass = (va->bass << 12)+(va->bass << 8)+(va->bass << 4)+(va->bass);
394
                va->treble=t->treble;
395
                if(va->treble >= 0x8)
396
                        va->treble = ~(va->treble - 0x8) & 0xf;
397
                va->treble = (va->treble << 12)+(va->treble << 8)+(va->treble << 4)+(va->treble);
398
 
399
                break; /* VIDIOCGAUDIO case */
400
        }
401
 
402
        /* Set card - scale from V4L settings to TDA7432 settings */
403
        case VIDIOCSAUDIO:
404
        {
405
                struct video_audio *va = arg;
406
 
407
                if(va->flags & VIDEO_AUDIO_VOLUME){
408
                        if(!maxvol){ /* max +20db */
409
                                t->volume = 0x6f - ((va->volume)/630);
410
                        } else {    /* max 0db   */
411
                                t->volume = 0x6f - ((va->volume)/829);
412
                        }
413
 
414
                if (loudness)           /* Turn on the loudness bit */
415
                        t->volume |= TDA7432_LD_ON;
416
 
417
                        tda7432_write(client,TDA7432_VL, t->volume);
418
                }
419
 
420
                if(va->flags & VIDEO_AUDIO_BASS)
421
                {
422
                        t->bass = va->bass >> 12;
423
                        if(t->bass>= 0x8)
424
                                        t->bass = (~t->bass & 0xf) + 0x8 ;
425
                }
426
                if(va->flags & VIDEO_AUDIO_TREBLE)
427
                {
428
                        t->treble= va->treble >> 12;
429
                        if(t->treble>= 0x8)
430
                                        t->treble = (~t->treble & 0xf) + 0x8 ;
431
                }
432
                if(va->flags & (VIDEO_AUDIO_TREBLE| VIDEO_AUDIO_BASS))
433
                        tda7432_write(client,TDA7432_TN, 0x10 | (t->bass << 4) | t->treble );
434
 
435
                if(va->flags & VIDEO_AUDIO_BALANCE)     {
436
                if (va->balance < 32768)
437
                {
438
                        /* shifted to left, attenuate right */
439
                        t->rr = (32768 - va->balance)/1057;
440
                        t->rf = t->rr;
441
                        t->lr = TDA7432_ATTEN_0DB;
442
                        t->lf = TDA7432_ATTEN_0DB;
443
                }
444
                else if(va->balance > 32769)
445
                {
446
                        /* shifted to right, attenuate left */
447
                        t->lf = (va->balance - 32768)/1057;
448
                        t->lr = t->lf;
449
                        t->rr = TDA7432_ATTEN_0DB;
450
                        t->rf = TDA7432_ATTEN_0DB;
451
                }
452
                else
453
                {
454
                        /* centered */
455
                        t->rr = TDA7432_ATTEN_0DB;
456
                        t->rf = TDA7432_ATTEN_0DB;
457
                        t->lf = TDA7432_ATTEN_0DB;
458
                        t->lr = TDA7432_ATTEN_0DB;
459
                }
460
                }
461
 
462
                t->muted=(va->flags & VIDEO_AUDIO_MUTE);
463
                if (t->muted)
464
                {
465
                        /* Mute & update balance*/
466
                        tda7432_write(client,TDA7432_LF, t->lf | TDA7432_MUTE);
467
                        tda7432_write(client,TDA7432_LR, t->lr | TDA7432_MUTE);
468
                        tda7432_write(client,TDA7432_RF, t->rf | TDA7432_MUTE);
469
                        tda7432_write(client,TDA7432_RR, t->rr | TDA7432_MUTE);
470
                } else {
471
                        tda7432_write(client,TDA7432_LF, t->lf);
472
                        tda7432_write(client,TDA7432_LR, t->lr);
473
                        tda7432_write(client,TDA7432_RF, t->rf);
474
                        tda7432_write(client,TDA7432_RR, t->rr);
475
                }
476
 
477
                break;
478
 
479
        } /* end of VIDEOCSAUDIO case */
480
 
481
        } /* end of (cmd) switch */
482
 
483
        return 0;
484
}
485
 
486
static struct i2c_driver driver = {
487
        .driver = {
488
                .name    = "tda7432",
489
        },
490
        .id              = I2C_DRIVERID_TDA7432,
491
        .attach_adapter  = tda7432_probe,
492
        .detach_client   = tda7432_detach,
493
        .command         = tda7432_command,
494
};
495
 
496
static struct i2c_client client_template =
497
{
498
        .name       = "tda7432",
499
        .driver     = &driver,
500
};
501
 
502
static int __init tda7432_init(void)
503
{
504
        if ( (loudness < 0) || (loudness > 15) ) {
505
                printk(KERN_ERR "loudness parameter must be between 0 and 15\n");
506
                return -EINVAL;
507
        }
508
 
509
        return i2c_add_driver(&driver);
510
}
511
 
512
static void __exit tda7432_fini(void)
513
{
514
        i2c_del_driver(&driver);
515
}
516
 
517
module_init(tda7432_init);
518
module_exit(tda7432_fini);
519
 
520
/*
521
 * Local variables:
522
 * c-basic-offset: 8
523
 * End:
524
 */

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.