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 
winview_volume(struct bttv * btv,__u16 volume)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 
gvbctv3pci_audio(struct bttv * btv,struct v4l2_tuner * t,int set)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 
gvbctv5pci_audio(struct bttv * btv,struct v4l2_tuner * t,int set)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->rxsubchans = V4L2_TUNER_SUB_LANG1 |  V4L2_TUNER_SUB_LANG2;
105 			break;
106 		  case 0x30:
107 			t->rxsubchans = V4L2_TUNER_SUB_LANG2;
108 			break;
109 		  case 0x50:
110 			t->rxsubchans = V4L2_TUNER_SUB_LANG1;
111 			break;
112 		  case 0x60:
113 			t->rxsubchans = V4L2_TUNER_SUB_STEREO;
114 			break;
115 		  case 0x70:
116 			t->rxsubchans = V4L2_TUNER_SUB_MONO;
117 			break;
118 		  default:
119 			t->rxsubchans = V4L2_TUNER_SUB_MONO |
120 					 V4L2_TUNER_SUB_STEREO |
121 					 V4L2_TUNER_SUB_LANG1 |
122 					 V4L2_TUNER_SUB_LANG2;
123 		}
124 		t->audmode = V4L2_TUNER_MODE_STEREO |
125 			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
126 	}
127 }
128 
129 /*
130  * Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
131  *  I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
132  *  0xdde enables mono and 0xccd enables sap
133  *
134  * Petr Vandrovec <VANDROVE@vc.cvut.cz>
135  *  P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
136  *  input/output sound connection, so both must be set for output mode.
137  *
138  * Looks like it's needed only for the "tvphone", the "tvphone 98"
139  * handles this with a tda9840
140  *
141  */
142 
avermedia_tvphone_audio(struct bttv * btv,struct v4l2_tuner * t,int set)143 void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
144 {
145 	int val = 0;
146 
147 	if (set) {
148 		if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
149 			val = 0x02;
150 		if (t->audmode & V4L2_TUNER_MODE_STEREO)
151 			val = 0x01;
152 		if (val) {
153 			gpio_bits(0x03,val);
154 			if (bttv_gpio)
155 				bttv_gpio_tracking(btv,"avermedia");
156 		}
157 	} else {
158 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
159 			V4L2_TUNER_MODE_LANG1;
160 		return;
161 	}
162 }
163 
164 
avermedia_tv_stereo_audio(struct bttv * btv,struct v4l2_tuner * t,int set)165 void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
166 {
167 	int val = 0;
168 
169 	if (set) {
170 		if (t->audmode & V4L2_TUNER_MODE_LANG2)   /* SAP */
171 			val = 0x01;
172 		if (t->audmode & V4L2_TUNER_MODE_STEREO)  /* STEREO */
173 			val = 0x02;
174 		btaor(val, ~0x03, BT848_GPIO_DATA);
175 		if (bttv_gpio)
176 			bttv_gpio_tracking(btv,"avermedia");
177 	} else {
178 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
179 			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
180 		return;
181 	}
182 }
183 
184 /* Lifetec 9415 handling */
185 
lt9415_audio(struct bttv * btv,struct v4l2_tuner * t,int set)186 void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
187 {
188 	int val = 0;
189 
190 	if (gpio_read() & 0x4000) {
191 		t->audmode = V4L2_TUNER_MODE_MONO;
192 		return;
193 	}
194 
195 	if (set) {
196 		if (t->audmode & V4L2_TUNER_MODE_LANG2)  /* A2 SAP */
197 			val = 0x0080;
198 		if (t->audmode & V4L2_TUNER_MODE_STEREO) /* A2 stereo */
199 			val = 0x0880;
200 		if ((t->audmode & V4L2_TUNER_MODE_LANG1) ||
201 		    (t->audmode & V4L2_TUNER_MODE_MONO))
202 			val = 0;
203 		gpio_bits(0x0880, val);
204 		if (bttv_gpio)
205 			bttv_gpio_tracking(btv,"lt9415");
206 	} else {
207 		/* autodetect doesn't work with this card :-( */
208 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
209 			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
210 		return;
211 	}
212 }
213 
214 /* TDA9821 on TerraTV+ Bt848, Bt878 */
terratv_audio(struct bttv * btv,struct v4l2_tuner * t,int set)215 void terratv_audio(struct bttv *btv,  struct v4l2_tuner *t, int set)
216 {
217 	unsigned int con = 0;
218 
219 	if (set) {
220 		gpio_inout(0x180000,0x180000);
221 		if (t->audmode & V4L2_TUNER_MODE_LANG2)
222 			con = 0x080000;
223 		if (t->audmode & V4L2_TUNER_MODE_STEREO)
224 			con = 0x180000;
225 		gpio_bits(0x180000, con);
226 		if (bttv_gpio)
227 			bttv_gpio_tracking(btv,"terratv");
228 	} else {
229 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
230 			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
231 	}
232 }
233 
234 
winfast2000_audio(struct bttv * btv,struct v4l2_tuner * t,int set)235 void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
236 {
237 	unsigned long val = 0;
238 
239 	if (set) {
240 		/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
241 		if (t->audmode & V4L2_TUNER_MODE_MONO)		/* Mono */
242 			val = 0x420000;
243 		if (t->audmode & V4L2_TUNER_MODE_LANG1)	/* Mono */
244 			val = 0x420000;
245 		if (t->audmode & V4L2_TUNER_MODE_LANG2)	/* SAP */
246 			val = 0x410000;
247 		if (t->audmode & V4L2_TUNER_MODE_STEREO)	/* Stereo */
248 			val = 0x020000;
249 		if (val) {
250 			gpio_bits(0x430000, val);
251 			if (bttv_gpio)
252 				bttv_gpio_tracking(btv,"winfast2000");
253 		}
254 	} else {
255 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
256 			  V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
257 	}
258 }
259 
260 /*
261  * Dariusz Kowalewski <darekk@automex.pl>
262  * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
263  * revision 9B has on-board TDA9874A sound decoder).
264  *
265  * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
266  *       will mute this cards.
267  */
pvbt878p9b_audio(struct bttv * btv,struct v4l2_tuner * t,int set)268 void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
269 {
270 	unsigned int val = 0;
271 
272 	if (btv->radio_user)
273 		return;
274 
275 	if (set) {
276 		if (t->audmode & V4L2_TUNER_MODE_MONO)	{
277 			val = 0x01;
278 		}
279 		if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
280 		    || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
281 			val = 0x02;
282 		}
283 		if (val) {
284 			gpio_bits(0x03,val);
285 			if (bttv_gpio)
286 				bttv_gpio_tracking(btv,"pvbt878p9b");
287 		}
288 	} else {
289 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
290 			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
291 	}
292 }
293 
294 /*
295  * Dariusz Kowalewski <darekk@automex.pl>
296  * sound control for FlyVideo 2000S (with tda9874 decoder)
297  * based on pvbt878p9b_audio() - this is not tested, please fix!!!
298  */
fv2000s_audio(struct bttv * btv,struct v4l2_tuner * t,int set)299 void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
300 {
301 	unsigned int val = 0xffff;
302 
303 	if (btv->radio_user)
304 		return;
305 
306 	if (set) {
307 		if (t->audmode & V4L2_TUNER_MODE_MONO)	{
308 			val = 0x0000;
309 		}
310 		if ((t->audmode & (V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2))
311 		    || (t->audmode & V4L2_TUNER_MODE_STEREO)) {
312 			val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
313 		}
314 		if (val != 0xffff) {
315 			gpio_bits(0x1800, val);
316 			if (bttv_gpio)
317 				bttv_gpio_tracking(btv,"fv2000s");
318 		}
319 	} else {
320 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
321 			V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
322 	}
323 }
324 
325 /*
326  * sound control for Canopus WinDVR PCI
327  * Masaki Suzuki <masaki@btree.org>
328  */
windvr_audio(struct bttv * btv,struct v4l2_tuner * t,int set)329 void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
330 {
331 	unsigned long val = 0;
332 
333 	if (set) {
334 		if (t->audmode & V4L2_TUNER_MODE_MONO)
335 			val = 0x040000;
336 		if (t->audmode & V4L2_TUNER_MODE_LANG1)
337 			val = 0;
338 		if (t->audmode & V4L2_TUNER_MODE_LANG2)
339 			val = 0x100000;
340 		if (t->audmode & V4L2_TUNER_MODE_STEREO)
341 			val = 0;
342 		if (val) {
343 			gpio_bits(0x140000, val);
344 			if (bttv_gpio)
345 				bttv_gpio_tracking(btv,"windvr");
346 		}
347 	} else {
348 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
349 			  V4L2_TUNER_MODE_LANG1 | V4L2_TUNER_MODE_LANG2;
350 	}
351 }
352 
353 /*
354  * sound control for AD-TVK503
355  * Hiroshi Takekawa <sian@big.or.jp>
356  */
adtvk503_audio(struct bttv * btv,struct v4l2_tuner * t,int set)357 void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
358 {
359 	unsigned int con = 0xffffff;
360 
361 	/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
362 
363 	if (set) {
364 		/* btor(***, BT848_GPIO_OUT_EN); */
365 		if (t->audmode & V4L2_TUNER_MODE_LANG1)
366 			con = 0x00000000;
367 		if (t->audmode & V4L2_TUNER_MODE_LANG2)
368 			con = 0x00180000;
369 		if (t->audmode & V4L2_TUNER_MODE_STEREO)
370 			con = 0x00000000;
371 		if (t->audmode & V4L2_TUNER_MODE_MONO)
372 			con = 0x00060000;
373 		if (con != 0xffffff) {
374 			gpio_bits(0x1e0000,con);
375 			if (bttv_gpio)
376 				bttv_gpio_tracking(btv, "adtvk503");
377 		}
378 	} else {
379 		t->audmode = V4L2_TUNER_MODE_MONO | V4L2_TUNER_MODE_STEREO |
380 			  V4L2_TUNER_MODE_LANG1  | V4L2_TUNER_MODE_LANG2;
381 	}
382 }
383