V4L/DVB (6416): Split hooks on volume and audio mode and rework their handling
[pandora-kernel.git] / drivers / media / video / bt8xx / bttv-audio-hook.c
1 /*
2  * Handlers for board audio hooks, splitted from bttv-cards
3  *
4  * Copyright (c) 2006 Mauro Carvalho Chehab (mchehab@infradead.org)
5  * This code is placed under the terms of the GNU General Public License
6  */
7
8 #include "bttv-audio-hook.h"
9
10 #include <linux/delay.h>
11
12 /* ----------------------------------------------------------------------- */
13 /* winview                                                                 */
14
15 void winview_volume(struct bttv *btv, __u16 volume)
16 {
17         /* PT2254A programming Jon Tombs, jon@gte.esi.us.es */
18         int bits_out, loops, vol, data;
19
20         /* 32 levels logarithmic */
21         vol = 32 - ((volume>>11));
22         /* units */
23         bits_out = (PT2254_DBS_IN_2>>(vol%5));
24         /* tens */
25         bits_out |= (PT2254_DBS_IN_10>>(vol/5));
26         bits_out |= PT2254_L_CHANNEL | PT2254_R_CHANNEL;
27         data = gpio_read();
28         data &= ~(WINVIEW_PT2254_CLK| WINVIEW_PT2254_DATA|
29                   WINVIEW_PT2254_STROBE);
30         for (loops = 17; loops >= 0 ; loops--) {
31                 if (bits_out & (1<<loops))
32                         data |=  WINVIEW_PT2254_DATA;
33                 else
34                         data &= ~WINVIEW_PT2254_DATA;
35                 gpio_write(data);
36                 udelay(5);
37                 data |= WINVIEW_PT2254_CLK;
38                 gpio_write(data);
39                 udelay(5);
40                 data &= ~WINVIEW_PT2254_CLK;
41                 gpio_write(data);
42         }
43         data |=  WINVIEW_PT2254_STROBE;
44         data &= ~WINVIEW_PT2254_DATA;
45         gpio_write(data);
46         udelay(10);
47         data &= ~WINVIEW_PT2254_STROBE;
48         gpio_write(data);
49 }
50
51 /* ----------------------------------------------------------------------- */
52 /* mono/stereo control for various cards (which don't use i2c chips but    */
53 /* connect something to the GPIO pins                                      */
54
55 void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
56 {
57         unsigned int con = 0;
58
59         if (set) {
60                 gpio_inout(0x300, 0x300);
61                 if (t->audmode & V4L2_TUNER_MODE_LANG1)
62                         con = 0x000;
63                 if (t->audmode & V4L2_TUNER_MODE_LANG2)
64                         con = 0x300;
65                 if (t->audmode & V4L2_TUNER_MODE_STEREO)
66                         con = 0x200;
67 /*              if (t->audmode & V4L2_TUNER_MODE_MONO)
68  *                      con = 0x100; */
69                 gpio_bits(0x300, con);
70         } else {
71                 t->audmode = V4L2_TUNER_MODE_STEREO |
72                           V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
73         }
74 }
75
76 void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
77 {
78         unsigned int val, con;
79
80         if (btv->radio_user)
81                 return;
82
83         val = gpio_read();
84         if (set) {
85                 con = 0x000;
86                 if (t->audmode & V4L2_TUNER_MODE_LANG2) {
87                         if (t->audmode & V4L2_TUNER_MODE_LANG1) {
88                                 /* LANG1 + LANG2 */
89                                 con = 0x100;
90                         }
91                         else {
92                                 /* LANG2 */
93                                 con = 0x300;
94                         }
95                 }
96                 if (con != (val & 0x300)) {
97                         gpio_bits(0x300, con);
98                         if (bttv_gpio)
99                                 bttv_gpio_tracking(btv,"gvbctv5pci");
100                 }
101         } else {
102                 switch (val & 0x70) {
103                   case 0x10:
104                         t->audmode = V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
105                         break;
106                   case 0x30:
107                         t->audmode = V4L2_TUNER_MODE_LANG2;
108                         break;
109                   case 0x50:
110                         t->audmode = V4L2_TUNER_MODE_LANG1;
111                         break;
112                   case 0x60:
113                         t->audmode = V4L2_TUNER_MODE_STEREO;
114                         break;
115                   case 0x70:
116                         t->audmode = V4L2_TUNER_MODE_MONO;
117                         break;
118                   default:
119                         t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
120                                   V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
121                 }
122         }
123 }
124
125 /*
126  * Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
127  *  I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
128  *  0xdde enables mono and 0xccd enables sap
129  *
130  * Petr Vandrovec <VANDROVE@vc.cvut.cz>
131  *  P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
132  *  input/output sound connection, so both must be set for output mode.
133  *
134  * Looks like it's needed only for the "tvphone", the "tvphone 98"
135  * handles this with a tda9840
136  *
137  */
138
139 void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
140 {
141         int val = 0;
142
143         if (set) {
144                 if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
145                         val = 0x02;
146                 if (t->audmode & V4L2_TUNER_MODE_STEREO)
147                         val = 0x01;
148                 if (val) {
149                         gpio_bits(0x03,val);
150                         if (bttv_gpio)
151                                 bttv_gpio_tracking(btv,"avermedia");
152                 }
153         } else {
154                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
155                         V4L2_TUNER_MODE_LANG1;
156                 return;
157         }
158 }
159
160
161 void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
162 {
163         int val = 0;
164
165         if (set) {
166                 if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
167                         val = 0x01;
168                 if (t->audmode & V4L2_TUNER_MODE_STEREO)  /* STEREO */
169                         val = 0x02;
170                 btaor(val, ~0x03, BT848_GPIO_DATA);
171                 if (bttv_gpio)
172                         bttv_gpio_tracking(btv,"avermedia");
173         } else {
174                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
175                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
176                 return;
177         }
178 }
179
180 /* Lifetec 9415 handling */
181
182 void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
183 {
184         int val = 0;
185
186         if (gpio_read() & 0x4000) {
187                 t->audmode = V4L2_TUNER_MODE_MONO;
188                 return;
189         }
190
191         if (set) {
192                 if (t->audmode & V4L2_TUNER_MODE_LANG2)  /* A2 SAP */
193                         val = 0x0080;
194                 if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
195                         val = 0x0880;
196                 if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
197                     (t->audmode & V4L2_TUNER_MODE_MONO))
198                         val = 0;
199                 gpio_bits(0x0880, val);
200                 if (bttv_gpio)
201                         bttv_gpio_tracking(btv,"lt9415");
202         } else {
203                 /* autodetect doesn't work with this card :-( */
204                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
205                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
206                 return;
207         }
208 }
209
210 /* TDA9821 on TerraTV+ Bt848, Bt878 */
211 void terratv_audio(struct bttv *btv,  struct v4l2_tuner *t, int set)
212 {
213         unsigned int con = 0;
214
215         if (set) {
216                 gpio_inout(0x180000,0x180000);
217                 if (t->audmode & V4L2_TUNER_MODE_LANG2)
218                         con = 0x080000;
219                 if (t->audmode & V4L2_TUNER_MODE_STEREO)
220                         con = 0x180000;
221                 gpio_bits(0x180000, con);
222                 if (bttv_gpio)
223                         bttv_gpio_tracking(btv,"terratv");
224         } else {
225                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
226                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
227         }
228 }
229
230
231 void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
232 {
233         unsigned long val = 0;
234
235         if (set) {
236                 /*btor (0xc32000, BT848_GPIO_OUT_EN);*/
237                 if (t->audmode & V4L2_TUNER_MODE_MONO)          /* Mono */
238                         val = 0x420000;
239                 if (t->audmode & V4L2_TUNER_MODE_LANG1) /* Mono */
240                         val = 0x420000;
241                 if (t->audmode & V4L2_TUNER_MODE_LANG2) /* SAP */
242                         val = 0x410000;
243                 if (t->audmode & V4L2_TUNER_MODE_STEREO)        /* Stereo */
244                         val = 0x020000;
245                 if (val) {
246                         gpio_bits(0x430000, val);
247                         if (bttv_gpio)
248                                 bttv_gpio_tracking(btv,"winfast2000");
249                 }
250         } else {
251                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
252                           V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
253         }
254 }
255
256 /*
257  * Dariusz Kowalewski <darekk@automex.pl>
258  * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
259  * revision 9B has on-board TDA9874A sound decoder).
260  *
261  * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
262  *       will mute this cards.
263  */
264 void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
265 {
266         unsigned int val = 0;
267
268         if (btv->radio_user)
269                 return;
270
271         if (set) {
272                 if (t->audmode & V4L2_TUNER_MODE_MONO)  {
273                         val = 0x01;
274                 }
275                 if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
276                     || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
277                         val = 0x02;
278                 }
279                 if (val) {
280                         gpio_bits(0x03,val);
281                         if (bttv_gpio)
282                                 bttv_gpio_tracking(btv,"pvbt878p9b");
283                 }
284         } else {
285                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
286                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
287         }
288 }
289
290 /*
291  * Dariusz Kowalewski <darekk@automex.pl>
292  * sound control for FlyVideo 2000S (with tda9874 decoder)
293  * based on pvbt878p9b_audio() - this is not tested, please fix!!!
294  */
295 void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
296 {
297         unsigned int val = 0xffff;
298
299         if (btv->radio_user)
300                 return;
301
302         if (set) {
303                 if (t->audmode & V4L2_TUNER_MODE_MONO)  {
304                         val = 0x0000;
305                 }
306                 if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
307                     || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
308                         val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
309                 }
310                 if (val != 0xffff) {
311                         gpio_bits(0x1800, val);
312                         if (bttv_gpio)
313                                 bttv_gpio_tracking(btv,"fv2000s");
314                 }
315         } else {
316                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
317                         V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
318         }
319 }
320
321 /*
322  * sound control for Canopus WinDVR PCI
323  * Masaki Suzuki <masaki@btree.org>
324  */
325 void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
326 {
327         unsigned long val = 0;
328
329         if (set) {
330                 if (t->audmode & V4L2_TUNER_MODE_MONO)
331                         val = 0x040000;
332                 if (t->audmode & V4L2_TUNER_MODE_LANG1)
333                         val = 0;
334                 if (t->audmode & V4L2_TUNER_MODE_LANG2)
335                         val = 0x100000;
336                 if (t->audmode & V4L2_TUNER_MODE_STEREO)
337                         val = 0;
338                 if (val) {
339                         gpio_bits(0x140000, val);
340                         if (bttv_gpio)
341                                 bttv_gpio_tracking(btv,"windvr");
342                 }
343         } else {
344                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
345                           V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
346         }
347 }
348
349 /*
350  * sound control for AD-TVK503
351  * Hiroshi Takekawa <sian@big.or.jp>
352  */
353 void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
354 {
355         unsigned int con = 0xffffff;
356
357         /* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
358
359         if (set) {
360                 /* btor(***, BT848_GPIO_OUT_EN); */
361                 if (t->audmode & V4L2_TUNER_MODE_LANG1)
362                         con = 0x00000000;
363                 if (t->audmode & V4L2_TUNER_MODE_LANG2)
364                         con = 0x00180000;
365                 if (t->audmode & V4L2_TUNER_MODE_STEREO)
366                         con = 0x00000000;
367                 if (t->audmode & V4L2_TUNER_MODE_MONO)
368                         con = 0x00060000;
369                 if (con != 0xffffff) {
370                         gpio_bits(0x1e0000,con);
371                         if (bttv_gpio)
372                                 bttv_gpio_tracking(btv, "adtvk503");
373                 }
374         } else {
375                 t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
376                           V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
377         }
378 }