1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Handlers for board audio hooks, split from bttv-cards
4 *
5 * Copyright (c) 2006 Mauro Carvalho Chehab <mchehab@kernel.org>
6 */
7
8#include "bttv-audio-hook.h"
9
10#include <linux/delay.h>
11
12/* ----------------------------------------------------------------------- */
13/* winview                                                                 */
14
15void 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
55void gvbctv3pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
56{
57	unsigned int con;
58
59	if (!set) {
60		/* Not much to do here */
61		t->audmode = V4L2_TUNER_MODE_LANG1;
62		t->rxsubchans = V4L2_TUNER_SUB_MONO |
63				V4L2_TUNER_SUB_STEREO |
64				V4L2_TUNER_SUB_LANG1 |
65				V4L2_TUNER_SUB_LANG2;
66
67		return;
68	}
69
70	gpio_inout(0x300, 0x300);
71	switch (t->audmode) {
72	case V4L2_TUNER_MODE_LANG1:
73	default:
74		con = 0x000;
75		break;
76	case V4L2_TUNER_MODE_LANG2:
77		con = 0x300;
78		break;
79	case V4L2_TUNER_MODE_STEREO:
80		con = 0x200;
81		break;
82	}
83	gpio_bits(0x300, con);
84}
85
86void gvbctv5pci_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
87{
88	unsigned int val, con;
89
90	if (btv->radio_user)
91		return;
92
93	val = gpio_read();
94	if (set) {
95		switch (t->audmode) {
96		case V4L2_TUNER_MODE_LANG2:
97			con = 0x300;
98			break;
99		case V4L2_TUNER_MODE_LANG1_LANG2:
100			con = 0x100;
101			break;
102		default:
103			con = 0x000;
104			break;
105		}
106		if (con != (val & 0x300)) {
107			gpio_bits(0x300, con);
108			if (bttv_gpio)
109				bttv_gpio_tracking(btv, "gvbctv5pci");
110		}
111	} else {
112		switch (val & 0x70) {
113		  case 0x10:
114			t->rxsubchans = V4L2_TUNER_SUB_LANG1 |  V4L2_TUNER_SUB_LANG2;
115			t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
116			break;
117		  case 0x30:
118			t->rxsubchans = V4L2_TUNER_SUB_LANG2;
119			t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
120			break;
121		  case 0x50:
122			t->rxsubchans = V4L2_TUNER_SUB_LANG1;
123			t->audmode = V4L2_TUNER_MODE_LANG1_LANG2;
124			break;
125		  case 0x60:
126			t->rxsubchans = V4L2_TUNER_SUB_STEREO;
127			t->audmode = V4L2_TUNER_MODE_STEREO;
128			break;
129		  case 0x70:
130			t->rxsubchans = V4L2_TUNER_SUB_MONO;
131			t->audmode = V4L2_TUNER_MODE_MONO;
132			break;
133		  default:
134			t->rxsubchans = V4L2_TUNER_SUB_MONO |
135					 V4L2_TUNER_SUB_STEREO |
136					 V4L2_TUNER_SUB_LANG1 |
137					 V4L2_TUNER_SUB_LANG2;
138			t->audmode = V4L2_TUNER_MODE_LANG1;
139		}
140	}
141}
142
143/*
144 * Mario Medina Nussbaum <medisoft@alohabbs.org.mx>
145 *  I discover that on BT848_GPIO_DATA address a byte 0xcce enable stereo,
146 *  0xdde enables mono and 0xccd enables sap
147 *
148 * Petr Vandrovec <VANDROVE@vc.cvut.cz>
149 *  P.S.: At least mask in line above is wrong - GPIO pins 3,2 select
150 *  input/output sound connection, so both must be set for output mode.
151 *
152 * Looks like it's needed only for the "tvphone", the "tvphone 98"
153 * handles this with a tda9840
154 *
155 */
156
157void avermedia_tvphone_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
158{
159	int val;
160
161	if (!set) {
162		/* Not much to do here */
163		t->audmode = V4L2_TUNER_MODE_LANG1;
164		t->rxsubchans = V4L2_TUNER_SUB_MONO |
165				V4L2_TUNER_SUB_STEREO |
166				V4L2_TUNER_SUB_LANG1 |
167				V4L2_TUNER_SUB_LANG2;
168
169		return;
170	}
171
172	switch (t->audmode) {
173	case V4L2_TUNER_MODE_LANG2:   /* SAP */
174		val = 0x02;
175		break;
176	case V4L2_TUNER_MODE_STEREO:
177		val = 0x01;
178		break;
179	default:
180		return;
181	}
182	gpio_bits(0x03, val);
183	if (bttv_gpio)
184		bttv_gpio_tracking(btv, "avermedia");
185}
186
187
188void avermedia_tv_stereo_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
189{
190	int val = 0;
191
192	if (!set) {
193		/* Not much to do here */
194		t->audmode = V4L2_TUNER_MODE_LANG1;
195		t->rxsubchans = V4L2_TUNER_SUB_MONO |
196				V4L2_TUNER_SUB_STEREO |
197				V4L2_TUNER_SUB_LANG1 |
198				V4L2_TUNER_SUB_LANG2;
199
200		return;
201	}
202
203	switch (t->audmode) {
204	case V4L2_TUNER_MODE_LANG2:   /* SAP */
205		val = 0x01;
206		break;
207	case V4L2_TUNER_MODE_STEREO:
208		val = 0x02;
209		break;
210	default:
211		val = 0;
212		break;
213	}
214	btaor(val, ~0x03, BT848_GPIO_DATA);
215	if (bttv_gpio)
216		bttv_gpio_tracking(btv, "avermedia");
217}
218
219/* Lifetec 9415 handling */
220
221void lt9415_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
222{
223	int val = 0;
224
225	if (gpio_read() & 0x4000) {
226		t->audmode = V4L2_TUNER_MODE_MONO;
227		return;
228	}
229
230	if (!set) {
231		/* Not much to do here */
232		t->audmode = V4L2_TUNER_MODE_LANG1;
233		t->rxsubchans = V4L2_TUNER_SUB_MONO |
234				V4L2_TUNER_SUB_STEREO |
235				V4L2_TUNER_SUB_LANG1 |
236				V4L2_TUNER_SUB_LANG2;
237
238		return;
239	}
240
241	switch (t->audmode) {
242	case V4L2_TUNER_MODE_LANG2:	/* A2 SAP */
243		val = 0x0080;
244		break;
245	case V4L2_TUNER_MODE_STEREO:	/* A2 stereo */
246		val = 0x0880;
247		break;
248	default:
249		val = 0;
250		break;
251	}
252
253	gpio_bits(0x0880, val);
254	if (bttv_gpio)
255		bttv_gpio_tracking(btv, "lt9415");
256}
257
258/* TDA9821 on TerraTV+ Bt848, Bt878 */
259void terratv_audio(struct bttv *btv,  struct v4l2_tuner *t, int set)
260{
261	unsigned int con = 0;
262
263	if (!set) {
264		/* Not much to do here */
265		t->audmode = V4L2_TUNER_MODE_LANG1;
266		t->rxsubchans = V4L2_TUNER_SUB_MONO |
267				V4L2_TUNER_SUB_STEREO |
268				V4L2_TUNER_SUB_LANG1 |
269				V4L2_TUNER_SUB_LANG2;
270
271		return;
272	}
273
274	gpio_inout(0x180000, 0x180000);
275	switch (t->audmode) {
276	case V4L2_TUNER_MODE_LANG2:
277		con = 0x080000;
278		break;
279	case V4L2_TUNER_MODE_STEREO:
280		con = 0x180000;
281		break;
282	default:
283		con = 0;
284		break;
285	}
286	gpio_bits(0x180000, con);
287	if (bttv_gpio)
288		bttv_gpio_tracking(btv, "terratv");
289}
290
291
292void winfast2000_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
293{
294	unsigned long val;
295
296	if (!set) {
297		/* Not much to do here */
298		t->audmode = V4L2_TUNER_MODE_LANG1;
299		t->rxsubchans = V4L2_TUNER_SUB_MONO |
300				V4L2_TUNER_SUB_STEREO |
301				V4L2_TUNER_SUB_LANG1 |
302				V4L2_TUNER_SUB_LANG2;
303
304		return;
305	}
306
307	/*btor (0xc32000, BT848_GPIO_OUT_EN);*/
308	switch (t->audmode) {
309	case V4L2_TUNER_MODE_MONO:
310	case V4L2_TUNER_MODE_LANG1:
311		val = 0x420000;
312		break;
313	case V4L2_TUNER_MODE_LANG2: /* SAP */
314		val = 0x410000;
315		break;
316	case V4L2_TUNER_MODE_STEREO:
317		val = 0x020000;
318		break;
319	default:
320		return;
321	}
322
323	gpio_bits(0x430000, val);
324	if (bttv_gpio)
325		bttv_gpio_tracking(btv, "winfast2000");
326}
327
328/*
329 * Dariusz Kowalewski <darekk@automex.pl>
330 * sound control for Prolink PV-BT878P+9B (PixelView PlayTV Pro FM+NICAM
331 * revision 9B has on-board TDA9874A sound decoder).
332 *
333 * Note: There are card variants without tda9874a. Forcing the "stereo sound route"
334 *       will mute this cards.
335 */
336void pvbt878p9b_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
337{
338	unsigned int val = 0;
339
340	if (btv->radio_user)
341		return;
342
343	if (!set) {
344		/* Not much to do here */
345		t->audmode = V4L2_TUNER_MODE_LANG1;
346		t->rxsubchans = V4L2_TUNER_SUB_MONO |
347				V4L2_TUNER_SUB_STEREO |
348				V4L2_TUNER_SUB_LANG1 |
349				V4L2_TUNER_SUB_LANG2;
350
351		return;
352	}
353
354	switch (t->audmode) {
355	case V4L2_TUNER_MODE_MONO:
356		val = 0x01;
357		break;
358	case V4L2_TUNER_MODE_LANG1:
359	case V4L2_TUNER_MODE_LANG2:
360	case V4L2_TUNER_MODE_STEREO:
361		val = 0x02;
362		break;
363	default:
364		return;
365	}
366
367	gpio_bits(0x03, val);
368	if (bttv_gpio)
369		bttv_gpio_tracking(btv, "pvbt878p9b");
370}
371
372/*
373 * Dariusz Kowalewski <darekk@automex.pl>
374 * sound control for FlyVideo 2000S (with tda9874 decoder)
375 * based on pvbt878p9b_audio() - this is not tested, please fix!!!
376 */
377void fv2000s_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
378{
379	unsigned int val;
380
381	if (btv->radio_user)
382		return;
383
384	if (!set) {
385		/* Not much to do here */
386		t->audmode = V4L2_TUNER_MODE_LANG1;
387		t->rxsubchans = V4L2_TUNER_SUB_MONO |
388				V4L2_TUNER_SUB_STEREO |
389				V4L2_TUNER_SUB_LANG1 |
390				V4L2_TUNER_SUB_LANG2;
391
392		return;
393	}
394
395	switch (t->audmode) {
396	case V4L2_TUNER_MODE_MONO:
397		val = 0x0000;
398		break;
399	case V4L2_TUNER_MODE_LANG1:
400	case V4L2_TUNER_MODE_LANG2:
401	case V4L2_TUNER_MODE_STEREO:
402		val = 0x1080; /*-dk-???: 0x0880, 0x0080, 0x1800 ... */
403		break;
404	default:
405		return;
406	}
407	gpio_bits(0x1800, val);
408	if (bttv_gpio)
409		bttv_gpio_tracking(btv, "fv2000s");
410}
411
412/*
413 * sound control for Canopus WinDVR PCI
414 * Masaki Suzuki <masaki@btree.org>
415 */
416void windvr_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
417{
418	unsigned long val;
419
420	if (!set) {
421		/* Not much to do here */
422		t->audmode = V4L2_TUNER_MODE_LANG1;
423		t->rxsubchans = V4L2_TUNER_SUB_MONO |
424				V4L2_TUNER_SUB_STEREO |
425				V4L2_TUNER_SUB_LANG1 |
426				V4L2_TUNER_SUB_LANG2;
427
428		return;
429	}
430
431	switch (t->audmode) {
432	case V4L2_TUNER_MODE_MONO:
433		val = 0x040000;
434		break;
435	case V4L2_TUNER_MODE_LANG2:
436		val = 0x100000;
437		break;
438	default:
439		return;
440	}
441
442	gpio_bits(0x140000, val);
443	if (bttv_gpio)
444		bttv_gpio_tracking(btv, "windvr");
445}
446
447/*
448 * sound control for AD-TVK503
449 * Hiroshi Takekawa <sian@big.or.jp>
450 */
451void adtvk503_audio(struct bttv *btv, struct v4l2_tuner *t, int set)
452{
453	unsigned int con = 0xffffff;
454
455	/* btaor(0x1e0000, ~0x1e0000, BT848_GPIO_OUT_EN); */
456
457	if (!set) {
458		/* Not much to do here */
459		t->audmode = V4L2_TUNER_MODE_LANG1;
460		t->rxsubchans = V4L2_TUNER_SUB_MONO |
461				V4L2_TUNER_SUB_STEREO |
462				V4L2_TUNER_SUB_LANG1 |
463				V4L2_TUNER_SUB_LANG2;
464
465		return;
466	}
467
468	/* btor(***, BT848_GPIO_OUT_EN); */
469	switch (t->audmode) {
470	case V4L2_TUNER_MODE_LANG1:
471		con = 0x00000000;
472		break;
473	case V4L2_TUNER_MODE_LANG2:
474		con = 0x00180000;
475		break;
476	case V4L2_TUNER_MODE_STEREO:
477		con = 0x00000000;
478		break;
479	case V4L2_TUNER_MODE_MONO:
480		con = 0x00060000;
481		break;
482	default:
483		return;
484	}
485
486	gpio_bits(0x1e0000, con);
487	if (bttv_gpio)
488		bttv_gpio_tracking(btv, "adtvk503");
489}
490