diff options
Diffstat (limited to 'drivers/media/video/saa7134/saa7134-tvaudio.c')
-rw-r--r-- | drivers/media/video/saa7134/saa7134-tvaudio.c | 1031 |
1 files changed, 1031 insertions, 0 deletions
diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c new file mode 100644 index 000000000000..ecac13c006d5 --- /dev/null +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c | |||
@@ -0,0 +1,1031 @@ | |||
1 | /* | ||
2 | * $Id: saa7134-tvaudio.c,v 1.22 2005/01/07 13:11:19 kraxel Exp $ | ||
3 | * | ||
4 | * device driver for philips saa7134 based TV cards | ||
5 | * tv audio decoder (fm stereo, nicam, ...) | ||
6 | * | ||
7 | * (c) 2001-03 Gerd Knorr <kraxel@bytesex.org> [SuSE Labs] | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License as published by | ||
11 | * the Free Software Foundation; either version 2 of the License, or | ||
12 | * (at your option) any later version. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, | ||
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | * GNU General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
22 | */ | ||
23 | |||
24 | #include <linux/init.h> | ||
25 | #include <linux/list.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/moduleparam.h> | ||
28 | #include <linux/kernel.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/smp_lock.h> | ||
32 | #include <asm/div64.h> | ||
33 | |||
34 | #include "saa7134-reg.h" | ||
35 | #include "saa7134.h" | ||
36 | |||
37 | /* ------------------------------------------------------------------ */ | ||
38 | |||
39 | static unsigned int audio_debug = 0; | ||
40 | module_param(audio_debug, int, 0644); | ||
41 | MODULE_PARM_DESC(audio_debug,"enable debug messages [tv audio]"); | ||
42 | |||
43 | static unsigned int audio_ddep = 0; | ||
44 | module_param(audio_ddep, int, 0644); | ||
45 | MODULE_PARM_DESC(audio_ddep,"audio ddep overwrite"); | ||
46 | |||
47 | static int audio_clock_override = UNSET; | ||
48 | module_param(audio_clock_override, int, 0644); | ||
49 | |||
50 | static int audio_clock_tweak = 0; | ||
51 | module_param(audio_clock_tweak, int, 0644); | ||
52 | MODULE_PARM_DESC(audio_clock_tweak, "Audio clock tick fine tuning for cards with audio crystal that's slightly off (range [-1024 .. 1024])"); | ||
53 | |||
54 | #define dprintk(fmt, arg...) if (audio_debug) \ | ||
55 | printk(KERN_DEBUG "%s/audio: " fmt, dev->name , ## arg) | ||
56 | #define d2printk(fmt, arg...) if (audio_debug > 1) \ | ||
57 | printk(KERN_DEBUG "%s/audio: " fmt, dev->name, ## arg) | ||
58 | |||
59 | #define print_regb(reg) printk("%s: reg 0x%03x [%-16s]: 0x%02x\n", \ | ||
60 | dev->name,(SAA7134_##reg),(#reg),saa_readb((SAA7134_##reg))) | ||
61 | |||
62 | /* msecs */ | ||
63 | #define SCAN_INITIAL_DELAY 1000 | ||
64 | #define SCAN_SAMPLE_DELAY 200 | ||
65 | #define SCAN_SUBCARRIER_DELAY 2000 | ||
66 | |||
67 | /* ------------------------------------------------------------------ */ | ||
68 | /* saa7134 code */ | ||
69 | |||
70 | static struct mainscan { | ||
71 | char *name; | ||
72 | v4l2_std_id std; | ||
73 | int carr; | ||
74 | } mainscan[] = { | ||
75 | { | ||
76 | .name = "M", | ||
77 | .std = V4L2_STD_NTSC | V4L2_STD_PAL_M, | ||
78 | .carr = 4500, | ||
79 | },{ | ||
80 | .name = "BG", | ||
81 | .std = V4L2_STD_PAL_BG, | ||
82 | .carr = 5500, | ||
83 | },{ | ||
84 | .name = "I", | ||
85 | .std = V4L2_STD_PAL_I, | ||
86 | .carr = 6000, | ||
87 | },{ | ||
88 | .name = "DKL", | ||
89 | .std = V4L2_STD_PAL_DK | V4L2_STD_SECAM, | ||
90 | .carr = 6500, | ||
91 | } | ||
92 | }; | ||
93 | |||
94 | static struct saa7134_tvaudio tvaudio[] = { | ||
95 | { | ||
96 | .name = "PAL-B/G FM-stereo", | ||
97 | .std = V4L2_STD_PAL, | ||
98 | .mode = TVAUDIO_FM_BG_STEREO, | ||
99 | .carr1 = 5500, | ||
100 | .carr2 = 5742, | ||
101 | },{ | ||
102 | .name = "PAL-D/K1 FM-stereo", | ||
103 | .std = V4L2_STD_PAL, | ||
104 | .carr1 = 6500, | ||
105 | .carr2 = 6258, | ||
106 | .mode = TVAUDIO_FM_BG_STEREO, | ||
107 | },{ | ||
108 | .name = "PAL-D/K2 FM-stereo", | ||
109 | .std = V4L2_STD_PAL, | ||
110 | .carr1 = 6500, | ||
111 | .carr2 = 6742, | ||
112 | .mode = TVAUDIO_FM_BG_STEREO, | ||
113 | },{ | ||
114 | .name = "PAL-D/K3 FM-stereo", | ||
115 | .std = V4L2_STD_PAL, | ||
116 | .carr1 = 6500, | ||
117 | .carr2 = 5742, | ||
118 | .mode = TVAUDIO_FM_BG_STEREO, | ||
119 | },{ | ||
120 | .name = "PAL-B/G NICAM", | ||
121 | .std = V4L2_STD_PAL, | ||
122 | .carr1 = 5500, | ||
123 | .carr2 = 5850, | ||
124 | .mode = TVAUDIO_NICAM_FM, | ||
125 | },{ | ||
126 | .name = "PAL-I NICAM", | ||
127 | .std = V4L2_STD_PAL, | ||
128 | .carr1 = 6000, | ||
129 | .carr2 = 6552, | ||
130 | .mode = TVAUDIO_NICAM_FM, | ||
131 | },{ | ||
132 | .name = "PAL-D/K NICAM", | ||
133 | .std = V4L2_STD_PAL, | ||
134 | .carr1 = 6500, | ||
135 | .carr2 = 5850, | ||
136 | .mode = TVAUDIO_NICAM_FM, | ||
137 | },{ | ||
138 | .name = "SECAM-L NICAM", | ||
139 | .std = V4L2_STD_SECAM, | ||
140 | .carr1 = 6500, | ||
141 | .carr2 = 5850, | ||
142 | .mode = TVAUDIO_NICAM_AM, | ||
143 | },{ | ||
144 | .name = "SECAM-D/K", | ||
145 | .std = V4L2_STD_SECAM, | ||
146 | .carr1 = 6500, | ||
147 | .carr2 = -1, | ||
148 | .mode = TVAUDIO_FM_MONO, | ||
149 | },{ | ||
150 | .name = "NTSC-M", | ||
151 | .std = V4L2_STD_NTSC, | ||
152 | .carr1 = 4500, | ||
153 | .carr2 = -1, | ||
154 | .mode = TVAUDIO_FM_MONO, | ||
155 | },{ | ||
156 | .name = "NTSC-A2 FM-stereo", | ||
157 | .std = V4L2_STD_NTSC, | ||
158 | .carr1 = 4500, | ||
159 | .carr2 = 4724, | ||
160 | .mode = TVAUDIO_FM_K_STEREO, | ||
161 | } | ||
162 | }; | ||
163 | #define TVAUDIO (sizeof(tvaudio)/sizeof(struct saa7134_tvaudio)) | ||
164 | |||
165 | /* ------------------------------------------------------------------ */ | ||
166 | |||
167 | static void tvaudio_init(struct saa7134_dev *dev) | ||
168 | { | ||
169 | int clock = saa7134_boards[dev->board].audio_clock; | ||
170 | |||
171 | if (UNSET != audio_clock_override) | ||
172 | clock = audio_clock_override; | ||
173 | |||
174 | /* init all audio registers */ | ||
175 | saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x00); | ||
176 | if (need_resched()) | ||
177 | schedule(); | ||
178 | else | ||
179 | udelay(10); | ||
180 | |||
181 | saa_writeb(SAA7134_AUDIO_CLOCK0, clock & 0xff); | ||
182 | saa_writeb(SAA7134_AUDIO_CLOCK1, (clock >> 8) & 0xff); | ||
183 | saa_writeb(SAA7134_AUDIO_CLOCK2, (clock >> 16) & 0xff); | ||
184 | saa_writeb(SAA7134_AUDIO_PLL_CTRL, 0x01); | ||
185 | |||
186 | saa_writeb(SAA7134_NICAM_ERROR_LOW, 0x14); | ||
187 | saa_writeb(SAA7134_NICAM_ERROR_HIGH, 0x50); | ||
188 | saa_writeb(SAA7134_MONITOR_SELECT, 0xa0); | ||
189 | saa_writeb(SAA7134_FM_DEMATRIX, 0x80); | ||
190 | } | ||
191 | |||
192 | static u32 tvaudio_carr2reg(u32 carrier) | ||
193 | { | ||
194 | u64 a = carrier; | ||
195 | |||
196 | a <<= 24; | ||
197 | do_div(a,12288); | ||
198 | return a; | ||
199 | } | ||
200 | |||
201 | static void tvaudio_setcarrier(struct saa7134_dev *dev, | ||
202 | int primary, int secondary) | ||
203 | { | ||
204 | if (-1 == secondary) | ||
205 | secondary = primary; | ||
206 | saa_writel(SAA7134_CARRIER1_FREQ0 >> 2, tvaudio_carr2reg(primary)); | ||
207 | saa_writel(SAA7134_CARRIER2_FREQ0 >> 2, tvaudio_carr2reg(secondary)); | ||
208 | } | ||
209 | |||
210 | static void mute_input_7134(struct saa7134_dev *dev) | ||
211 | { | ||
212 | unsigned int mute; | ||
213 | struct saa7134_input *in; | ||
214 | int ausel=0, ics=0, ocs=0; | ||
215 | int mask; | ||
216 | |||
217 | /* look what is to do ... */ | ||
218 | in = dev->input; | ||
219 | mute = (dev->ctl_mute || | ||
220 | (dev->automute && (&card(dev).radio) != in)); | ||
221 | if (PCI_DEVICE_ID_PHILIPS_SAA7130 == dev->pci->device && | ||
222 | card(dev).mute.name) { | ||
223 | /* 7130 - we'll mute using some unconnected audio input */ | ||
224 | if (mute) | ||
225 | in = &card(dev).mute; | ||
226 | } | ||
227 | if (dev->hw_mute == mute && | ||
228 | dev->hw_input == in) { | ||
229 | dprintk("mute/input: nothing to do [mute=%d,input=%s]\n", | ||
230 | mute,in->name); | ||
231 | return; | ||
232 | } | ||
233 | |||
234 | dprintk("ctl_mute=%d automute=%d input=%s => mute=%d input=%s\n", | ||
235 | dev->ctl_mute,dev->automute,dev->input->name,mute,in->name); | ||
236 | dev->hw_mute = mute; | ||
237 | dev->hw_input = in; | ||
238 | |||
239 | if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device) | ||
240 | /* 7134 mute */ | ||
241 | saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? 0xbf : 0xbb); | ||
242 | |||
243 | /* switch internal audio mux */ | ||
244 | switch (in->amux) { | ||
245 | case TV: ausel=0xc0; ics=0x00; ocs=0x02; break; | ||
246 | case LINE1: ausel=0x80; ics=0x00; ocs=0x00; break; | ||
247 | case LINE2: ausel=0x80; ics=0x08; ocs=0x01; break; | ||
248 | case LINE2_LEFT: ausel=0x80; ics=0x08; ocs=0x05; break; | ||
249 | } | ||
250 | saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, ausel); | ||
251 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, ics); | ||
252 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, ocs); | ||
253 | |||
254 | /* switch gpio-connected external audio mux */ | ||
255 | if (0 == card(dev).gpiomask) | ||
256 | return; | ||
257 | mask = card(dev).gpiomask; | ||
258 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); | ||
259 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); | ||
260 | saa7134_track_gpio(dev,in->name); | ||
261 | } | ||
262 | |||
263 | static void tvaudio_setmode(struct saa7134_dev *dev, | ||
264 | struct saa7134_tvaudio *audio, | ||
265 | char *note) | ||
266 | { | ||
267 | int acpf, tweak = 0; | ||
268 | |||
269 | if (dev->tvnorm->id == V4L2_STD_NTSC) { | ||
270 | acpf = 0x19066; | ||
271 | } else { | ||
272 | acpf = 0x1e000; | ||
273 | } | ||
274 | if (audio_clock_tweak > -1024 && audio_clock_tweak < 1024) | ||
275 | tweak = audio_clock_tweak; | ||
276 | |||
277 | if (note) | ||
278 | dprintk("tvaudio_setmode: %s %s [%d.%03d/%d.%03d MHz] acpf=%d%+d\n", | ||
279 | note,audio->name, | ||
280 | audio->carr1 / 1000, audio->carr1 % 1000, | ||
281 | audio->carr2 / 1000, audio->carr2 % 1000, | ||
282 | acpf, tweak); | ||
283 | |||
284 | acpf += tweak; | ||
285 | saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD0, (acpf & 0x0000ff) >> 0); | ||
286 | saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD1, (acpf & 0x00ff00) >> 8); | ||
287 | saa_writeb(SAA7134_AUDIO_CLOCKS_PER_FIELD2, (acpf & 0x030000) >> 16); | ||
288 | tvaudio_setcarrier(dev,audio->carr1,audio->carr2); | ||
289 | |||
290 | switch (audio->mode) { | ||
291 | case TVAUDIO_FM_MONO: | ||
292 | case TVAUDIO_FM_BG_STEREO: | ||
293 | saa_writeb(SAA7134_DEMODULATOR, 0x00); | ||
294 | saa_writeb(SAA7134_DCXO_IDENT_CTRL, 0x00); | ||
295 | saa_writeb(SAA7134_FM_DEEMPHASIS, 0x22); | ||
296 | saa_writeb(SAA7134_FM_DEMATRIX, 0x80); | ||
297 | saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0xa0); | ||
298 | break; | ||
299 | case TVAUDIO_FM_K_STEREO: | ||
300 | saa_writeb(SAA7134_DEMODULATOR, 0x00); | ||
301 | saa_writeb(SAA7134_DCXO_IDENT_CTRL, 0x01); | ||
302 | saa_writeb(SAA7134_FM_DEEMPHASIS, 0x22); | ||
303 | saa_writeb(SAA7134_FM_DEMATRIX, 0x80); | ||
304 | saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0xa0); | ||
305 | break; | ||
306 | case TVAUDIO_NICAM_FM: | ||
307 | saa_writeb(SAA7134_DEMODULATOR, 0x10); | ||
308 | saa_writeb(SAA7134_DCXO_IDENT_CTRL, 0x00); | ||
309 | saa_writeb(SAA7134_FM_DEEMPHASIS, 0x44); | ||
310 | saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0xa1); | ||
311 | saa_writeb(SAA7134_NICAM_CONFIG, 0x00); | ||
312 | break; | ||
313 | case TVAUDIO_NICAM_AM: | ||
314 | saa_writeb(SAA7134_DEMODULATOR, 0x12); | ||
315 | saa_writeb(SAA7134_DCXO_IDENT_CTRL, 0x00); | ||
316 | saa_writeb(SAA7134_FM_DEEMPHASIS, 0x44); | ||
317 | saa_writeb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0xa1); | ||
318 | saa_writeb(SAA7134_NICAM_CONFIG, 0x00); | ||
319 | break; | ||
320 | case TVAUDIO_FM_SAT_STEREO: | ||
321 | /* not implemented (yet) */ | ||
322 | break; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | static int tvaudio_sleep(struct saa7134_dev *dev, int timeout) | ||
327 | { | ||
328 | DECLARE_WAITQUEUE(wait, current); | ||
329 | |||
330 | add_wait_queue(&dev->thread.wq, &wait); | ||
331 | if (dev->thread.scan1 == dev->thread.scan2 && !dev->thread.shutdown) { | ||
332 | if (timeout < 0) { | ||
333 | set_current_state(TASK_INTERRUPTIBLE); | ||
334 | schedule(); | ||
335 | } else { | ||
336 | #if 0 | ||
337 | /* hmm, that one doesn't return on wakeup ... */ | ||
338 | msleep_interruptible(timeout); | ||
339 | #else | ||
340 | set_current_state(TASK_INTERRUPTIBLE); | ||
341 | schedule_timeout(msecs_to_jiffies(timeout)); | ||
342 | #endif | ||
343 | } | ||
344 | } | ||
345 | remove_wait_queue(&dev->thread.wq, &wait); | ||
346 | return dev->thread.scan1 != dev->thread.scan2; | ||
347 | } | ||
348 | |||
349 | static int tvaudio_checkcarrier(struct saa7134_dev *dev, struct mainscan *scan) | ||
350 | { | ||
351 | __s32 left,right,value; | ||
352 | |||
353 | if (audio_debug > 1) { | ||
354 | int i; | ||
355 | dprintk("debug %d:",scan->carr); | ||
356 | for (i = -150; i <= 150; i += 30) { | ||
357 | tvaudio_setcarrier(dev,scan->carr+i,scan->carr+i); | ||
358 | saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | ||
359 | if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) | ||
360 | return -1; | ||
361 | value = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | ||
362 | if (0 == i) | ||
363 | printk(" # %6d # ",value >> 16); | ||
364 | else | ||
365 | printk(" %6d",value >> 16); | ||
366 | } | ||
367 | printk("\n"); | ||
368 | } | ||
369 | |||
370 | if (dev->tvnorm->id & scan->std) { | ||
371 | tvaudio_setcarrier(dev,scan->carr-90,scan->carr-90); | ||
372 | saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | ||
373 | if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) | ||
374 | return -1; | ||
375 | left = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | ||
376 | |||
377 | tvaudio_setcarrier(dev,scan->carr+90,scan->carr+90); | ||
378 | saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | ||
379 | if (tvaudio_sleep(dev,SCAN_SAMPLE_DELAY)) | ||
380 | return -1; | ||
381 | right = saa_readl(SAA7134_LEVEL_READOUT1 >> 2); | ||
382 | |||
383 | left >>= 16; | ||
384 | right >>= 16; | ||
385 | value = left > right ? left - right : right - left; | ||
386 | dprintk("scanning %d.%03d MHz [%4s] => dc is %5d [%d/%d]\n", | ||
387 | scan->carr / 1000, scan->carr % 1000, | ||
388 | scan->name, value, left, right); | ||
389 | } else { | ||
390 | value = 0; | ||
391 | dprintk("skipping %d.%03d MHz [%4s]\n", | ||
392 | scan->carr / 1000, scan->carr % 1000, scan->name); | ||
393 | } | ||
394 | return value; | ||
395 | } | ||
396 | |||
397 | #if 0 | ||
398 | static void sifdebug_dump_regs(struct saa7134_dev *dev) | ||
399 | { | ||
400 | print_regb(AUDIO_STATUS); | ||
401 | print_regb(IDENT_SIF); | ||
402 | print_regb(LEVEL_READOUT1); | ||
403 | print_regb(LEVEL_READOUT2); | ||
404 | print_regb(DCXO_IDENT_CTRL); | ||
405 | print_regb(DEMODULATOR); | ||
406 | print_regb(AGC_GAIN_SELECT); | ||
407 | print_regb(MONITOR_SELECT); | ||
408 | print_regb(FM_DEEMPHASIS); | ||
409 | print_regb(FM_DEMATRIX); | ||
410 | print_regb(SIF_SAMPLE_FREQ); | ||
411 | print_regb(ANALOG_IO_SELECT); | ||
412 | } | ||
413 | #endif | ||
414 | |||
415 | static int tvaudio_getstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio) | ||
416 | { | ||
417 | __u32 idp,nicam; | ||
418 | int retval = -1; | ||
419 | |||
420 | switch (audio->mode) { | ||
421 | case TVAUDIO_FM_MONO: | ||
422 | return V4L2_TUNER_SUB_MONO; | ||
423 | case TVAUDIO_FM_K_STEREO: | ||
424 | case TVAUDIO_FM_BG_STEREO: | ||
425 | idp = (saa_readb(SAA7134_IDENT_SIF) & 0xe0) >> 5; | ||
426 | dprintk("getstereo: fm/stereo: idp=0x%x\n",idp); | ||
427 | if (0x03 == (idp & 0x03)) | ||
428 | retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
429 | else if (0x05 == (idp & 0x05)) | ||
430 | retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
431 | else if (0x01 == (idp & 0x01)) | ||
432 | retval = V4L2_TUNER_SUB_MONO; | ||
433 | break; | ||
434 | case TVAUDIO_FM_SAT_STEREO: | ||
435 | /* not implemented (yet) */ | ||
436 | break; | ||
437 | case TVAUDIO_NICAM_FM: | ||
438 | case TVAUDIO_NICAM_AM: | ||
439 | nicam = saa_readb(SAA7134_NICAM_STATUS); | ||
440 | dprintk("getstereo: nicam=0x%x\n",nicam); | ||
441 | switch (nicam & 0x0b) { | ||
442 | case 0x09: | ||
443 | retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
444 | break; | ||
445 | case 0x0a: | ||
446 | retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
447 | break; | ||
448 | case 0x08: | ||
449 | default: | ||
450 | retval = V4L2_TUNER_SUB_MONO; | ||
451 | break; | ||
452 | } | ||
453 | break; | ||
454 | } | ||
455 | if (retval != -1) | ||
456 | dprintk("found audio subchannels:%s%s%s%s\n", | ||
457 | (retval & V4L2_TUNER_SUB_MONO) ? " mono" : "", | ||
458 | (retval & V4L2_TUNER_SUB_STEREO) ? " stereo" : "", | ||
459 | (retval & V4L2_TUNER_SUB_LANG1) ? " lang1" : "", | ||
460 | (retval & V4L2_TUNER_SUB_LANG2) ? " lang2" : ""); | ||
461 | return retval; | ||
462 | } | ||
463 | |||
464 | static int tvaudio_setstereo(struct saa7134_dev *dev, struct saa7134_tvaudio *audio, | ||
465 | u32 mode) | ||
466 | { | ||
467 | static char *name[] = { | ||
468 | [ V4L2_TUNER_MODE_MONO ] = "mono", | ||
469 | [ V4L2_TUNER_MODE_STEREO ] = "stereo", | ||
470 | [ V4L2_TUNER_MODE_LANG1 ] = "lang1", | ||
471 | [ V4L2_TUNER_MODE_LANG2 ] = "lang2", | ||
472 | }; | ||
473 | static u32 fm[] = { | ||
474 | [ V4L2_TUNER_MODE_MONO ] = 0x00, /* ch1 */ | ||
475 | [ V4L2_TUNER_MODE_STEREO ] = 0x80, /* auto */ | ||
476 | [ V4L2_TUNER_MODE_LANG1 ] = 0x00, /* ch1 */ | ||
477 | [ V4L2_TUNER_MODE_LANG2 ] = 0x01, /* ch2 */ | ||
478 | }; | ||
479 | u32 reg; | ||
480 | |||
481 | switch (audio->mode) { | ||
482 | case TVAUDIO_FM_MONO: | ||
483 | /* nothing to do ... */ | ||
484 | break; | ||
485 | case TVAUDIO_FM_K_STEREO: | ||
486 | case TVAUDIO_FM_BG_STEREO: | ||
487 | dprintk("setstereo [fm] => %s\n", | ||
488 | name[ mode % ARRAY_SIZE(name) ]); | ||
489 | reg = fm[ mode % ARRAY_SIZE(fm) ]; | ||
490 | saa_writeb(SAA7134_FM_DEMATRIX, reg); | ||
491 | break; | ||
492 | case TVAUDIO_FM_SAT_STEREO: | ||
493 | case TVAUDIO_NICAM_AM: | ||
494 | case TVAUDIO_NICAM_FM: | ||
495 | /* FIXME */ | ||
496 | break; | ||
497 | } | ||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | static int tvaudio_thread(void *data) | ||
502 | { | ||
503 | struct saa7134_dev *dev = data; | ||
504 | int carr_vals[ARRAY_SIZE(mainscan)]; | ||
505 | unsigned int i, audio, nscan; | ||
506 | int max1,max2,carrier,rx,mode,lastmode,default_carrier; | ||
507 | |||
508 | daemonize("%s", dev->name); | ||
509 | allow_signal(SIGTERM); | ||
510 | for (;;) { | ||
511 | tvaudio_sleep(dev,-1); | ||
512 | if (dev->thread.shutdown || signal_pending(current)) | ||
513 | goto done; | ||
514 | |||
515 | restart: | ||
516 | dev->thread.scan1 = dev->thread.scan2; | ||
517 | dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1); | ||
518 | dev->tvaudio = NULL; | ||
519 | tvaudio_init(dev); | ||
520 | if (dev->ctl_automute) | ||
521 | dev->automute = 1; | ||
522 | mute_input_7134(dev); | ||
523 | |||
524 | /* give the tuner some time */ | ||
525 | if (tvaudio_sleep(dev,SCAN_INITIAL_DELAY)) | ||
526 | goto restart; | ||
527 | |||
528 | max1 = 0; | ||
529 | max2 = 0; | ||
530 | nscan = 0; | ||
531 | carrier = 0; | ||
532 | default_carrier = 0; | ||
533 | for (i = 0; i < ARRAY_SIZE(mainscan); i++) { | ||
534 | if (!(dev->tvnorm->id & mainscan[i].std)) | ||
535 | continue; | ||
536 | if (!default_carrier) | ||
537 | default_carrier = mainscan[i].carr; | ||
538 | nscan++; | ||
539 | } | ||
540 | |||
541 | if (1 == nscan) { | ||
542 | /* only one candidate -- skip scan ;) */ | ||
543 | max1 = 12345; | ||
544 | carrier = default_carrier; | ||
545 | } else { | ||
546 | /* scan for the main carrier */ | ||
547 | saa_writeb(SAA7134_MONITOR_SELECT,0x00); | ||
548 | tvaudio_setmode(dev,&tvaudio[0],NULL); | ||
549 | for (i = 0; i < ARRAY_SIZE(mainscan); i++) { | ||
550 | carr_vals[i] = tvaudio_checkcarrier(dev, mainscan+i); | ||
551 | if (dev->thread.scan1 != dev->thread.scan2) | ||
552 | goto restart; | ||
553 | } | ||
554 | for (max1 = 0, max2 = 0, i = 0; i < ARRAY_SIZE(mainscan); i++) { | ||
555 | if (max1 < carr_vals[i]) { | ||
556 | max2 = max1; | ||
557 | max1 = carr_vals[i]; | ||
558 | carrier = mainscan[i].carr; | ||
559 | } else if (max2 < carr_vals[i]) { | ||
560 | max2 = carr_vals[i]; | ||
561 | } | ||
562 | } | ||
563 | } | ||
564 | |||
565 | if (0 != carrier && max1 > 2000 && max1 > max2*3) { | ||
566 | /* found good carrier */ | ||
567 | dprintk("found %s main sound carrier @ %d.%03d MHz [%d/%d]\n", | ||
568 | dev->tvnorm->name, carrier/1000, carrier%1000, | ||
569 | max1, max2); | ||
570 | dev->last_carrier = carrier; | ||
571 | |||
572 | } else if (0 != dev->last_carrier) { | ||
573 | /* no carrier -- try last detected one as fallback */ | ||
574 | carrier = dev->last_carrier; | ||
575 | printk(KERN_WARNING "%s/audio: audio carrier scan failed, " | ||
576 | "using %d.%03d MHz [last detected]\n", | ||
577 | dev->name, carrier/1000, carrier%1000); | ||
578 | |||
579 | } else { | ||
580 | /* no carrier + no fallback -- use default */ | ||
581 | carrier = default_carrier; | ||
582 | printk(KERN_WARNING "%s/audio: audio carrier scan failed, " | ||
583 | "using %d.%03d MHz [default]\n", | ||
584 | dev->name, carrier/1000, carrier%1000); | ||
585 | } | ||
586 | tvaudio_setcarrier(dev,carrier,carrier); | ||
587 | dev->automute = 0; | ||
588 | saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x00); | ||
589 | saa7134_tvaudio_setmute(dev); | ||
590 | |||
591 | /* find the exact tv audio norm */ | ||
592 | for (audio = UNSET, i = 0; i < TVAUDIO; i++) { | ||
593 | if (dev->tvnorm->id != UNSET && | ||
594 | !(dev->tvnorm->id & tvaudio[i].std)) | ||
595 | continue; | ||
596 | if (tvaudio[i].carr1 != carrier) | ||
597 | continue; | ||
598 | |||
599 | if (UNSET == audio) | ||
600 | audio = i; | ||
601 | tvaudio_setmode(dev,&tvaudio[i],"trying"); | ||
602 | if (tvaudio_sleep(dev,SCAN_SUBCARRIER_DELAY)) | ||
603 | goto restart; | ||
604 | if (-1 != tvaudio_getstereo(dev,&tvaudio[i])) { | ||
605 | audio = i; | ||
606 | break; | ||
607 | } | ||
608 | } | ||
609 | saa_andorb(SAA7134_STEREO_DAC_OUTPUT_SELECT, 0x30, 0x30); | ||
610 | if (UNSET == audio) | ||
611 | continue; | ||
612 | tvaudio_setmode(dev,&tvaudio[audio],"using"); | ||
613 | tvaudio_setstereo(dev,&tvaudio[audio],V4L2_TUNER_MODE_MONO); | ||
614 | dev->tvaudio = &tvaudio[audio]; | ||
615 | |||
616 | lastmode = 42; | ||
617 | for (;;) { | ||
618 | if (tvaudio_sleep(dev,5000)) | ||
619 | goto restart; | ||
620 | if (dev->thread.shutdown || signal_pending(current)) | ||
621 | break; | ||
622 | if (UNSET == dev->thread.mode) { | ||
623 | rx = tvaudio_getstereo(dev,&tvaudio[i]); | ||
624 | mode = saa7134_tvaudio_rx2mode(rx); | ||
625 | } else { | ||
626 | mode = dev->thread.mode; | ||
627 | } | ||
628 | if (lastmode != mode) { | ||
629 | tvaudio_setstereo(dev,&tvaudio[audio],mode); | ||
630 | lastmode = mode; | ||
631 | } | ||
632 | } | ||
633 | } | ||
634 | |||
635 | done: | ||
636 | complete_and_exit(&dev->thread.exit, 0); | ||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | /* ------------------------------------------------------------------ */ | ||
641 | /* saa7133 / saa7135 code */ | ||
642 | |||
643 | static char *stdres[0x20] = { | ||
644 | [0x00] = "no standard detected", | ||
645 | [0x01] = "B/G (in progress)", | ||
646 | [0x02] = "D/K (in progress)", | ||
647 | [0x03] = "M (in progress)", | ||
648 | |||
649 | [0x04] = "B/G A2", | ||
650 | [0x05] = "B/G NICAM", | ||
651 | [0x06] = "D/K A2 (1)", | ||
652 | [0x07] = "D/K A2 (2)", | ||
653 | [0x08] = "D/K A2 (3)", | ||
654 | [0x09] = "D/K NICAM", | ||
655 | [0x0a] = "L NICAM", | ||
656 | [0x0b] = "I NICAM", | ||
657 | |||
658 | [0x0c] = "M Korea", | ||
659 | [0x0d] = "M BTSC ", | ||
660 | [0x0e] = "M EIAJ", | ||
661 | |||
662 | [0x0f] = "FM radio / IF 10.7 / 50 deemp", | ||
663 | [0x10] = "FM radio / IF 10.7 / 75 deemp", | ||
664 | [0x11] = "FM radio / IF sel / 50 deemp", | ||
665 | [0x12] = "FM radio / IF sel / 75 deemp", | ||
666 | |||
667 | [0x13 ... 0x1e ] = "unknown", | ||
668 | [0x1f] = "??? [in progress]", | ||
669 | }; | ||
670 | |||
671 | #define DSP_RETRY 32 | ||
672 | #define DSP_DELAY 16 | ||
673 | |||
674 | static inline int saa_dsp_wait_bit(struct saa7134_dev *dev, int bit) | ||
675 | { | ||
676 | int state, count = DSP_RETRY; | ||
677 | |||
678 | state = saa_readb(SAA7135_DSP_RWSTATE); | ||
679 | if (unlikely(state & SAA7135_DSP_RWSTATE_ERR)) { | ||
680 | printk("%s: dsp access error\n",dev->name); | ||
681 | /* FIXME: send ack ... */ | ||
682 | return -EIO; | ||
683 | } | ||
684 | while (0 == (state & bit)) { | ||
685 | if (unlikely(0 == count)) { | ||
686 | printk("%s: dsp access wait timeout [bit=%s]\n", | ||
687 | dev->name, | ||
688 | (bit & SAA7135_DSP_RWSTATE_WRR) ? "WRR" : | ||
689 | (bit & SAA7135_DSP_RWSTATE_RDB) ? "RDB" : | ||
690 | (bit & SAA7135_DSP_RWSTATE_IDA) ? "IDA" : | ||
691 | "???"); | ||
692 | return -EIO; | ||
693 | } | ||
694 | saa_wait(DSP_DELAY); | ||
695 | state = saa_readb(SAA7135_DSP_RWSTATE); | ||
696 | count--; | ||
697 | } | ||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | #if 0 | ||
702 | static int saa_dsp_readl(struct saa7134_dev *dev, int reg, u32 *value) | ||
703 | { | ||
704 | int err; | ||
705 | |||
706 | d2printk("dsp read reg 0x%x\n", reg<<2); | ||
707 | saa_readl(reg); | ||
708 | err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_RDB); | ||
709 | if (err < 0) | ||
710 | return err; | ||
711 | *value = saa_readl(reg); | ||
712 | d2printk("dsp read => 0x%06x\n", *value & 0xffffff); | ||
713 | err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_IDA); | ||
714 | if (err < 0) | ||
715 | return err; | ||
716 | return 0; | ||
717 | } | ||
718 | #endif | ||
719 | |||
720 | int saa_dsp_writel(struct saa7134_dev *dev, int reg, u32 value) | ||
721 | { | ||
722 | int err; | ||
723 | |||
724 | d2printk("dsp write reg 0x%x = 0x%06x\n",reg<<2,value); | ||
725 | err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR); | ||
726 | if (err < 0) | ||
727 | return err; | ||
728 | saa_writel(reg,value); | ||
729 | err = saa_dsp_wait_bit(dev,SAA7135_DSP_RWSTATE_WRR); | ||
730 | if (err < 0) | ||
731 | return err; | ||
732 | return 0; | ||
733 | } | ||
734 | |||
735 | static int getstereo_7133(struct saa7134_dev *dev) | ||
736 | { | ||
737 | int retval = V4L2_TUNER_SUB_MONO; | ||
738 | u32 value; | ||
739 | |||
740 | value = saa_readl(0x528 >> 2); | ||
741 | if (value & 0x20) | ||
742 | retval = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO; | ||
743 | if (value & 0x40) | ||
744 | retval = V4L2_TUNER_SUB_LANG1 | V4L2_TUNER_SUB_LANG2; | ||
745 | return retval; | ||
746 | } | ||
747 | |||
748 | static int mute_input_7133(struct saa7134_dev *dev) | ||
749 | { | ||
750 | u32 reg = 0; | ||
751 | int mask; | ||
752 | |||
753 | switch (dev->input->amux) { | ||
754 | case TV: | ||
755 | reg = 0x02; | ||
756 | break; | ||
757 | case LINE1: | ||
758 | reg = 0x00; | ||
759 | break; | ||
760 | case LINE2: | ||
761 | case LINE2_LEFT: | ||
762 | reg = 0x01; | ||
763 | break; | ||
764 | } | ||
765 | if (dev->ctl_mute) | ||
766 | reg = 0x07; | ||
767 | saa_writel(0x594 >> 2, reg); | ||
768 | |||
769 | /* switch gpio-connected external audio mux */ | ||
770 | if (0 != card(dev).gpiomask) { | ||
771 | mask = card(dev).gpiomask; | ||
772 | saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); | ||
773 | saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, dev->input->gpio); | ||
774 | saa7134_track_gpio(dev,dev->input->name); | ||
775 | } | ||
776 | return 0; | ||
777 | } | ||
778 | |||
779 | static int tvaudio_thread_ddep(void *data) | ||
780 | { | ||
781 | struct saa7134_dev *dev = data; | ||
782 | u32 value, norms, clock; | ||
783 | |||
784 | daemonize("%s", dev->name); | ||
785 | allow_signal(SIGTERM); | ||
786 | |||
787 | clock = saa7134_boards[dev->board].audio_clock; | ||
788 | if (UNSET != audio_clock_override) | ||
789 | clock = audio_clock_override; | ||
790 | saa_writel(0x598 >> 2, clock); | ||
791 | |||
792 | /* unmute */ | ||
793 | saa_dsp_writel(dev, 0x474 >> 2, 0x00); | ||
794 | saa_dsp_writel(dev, 0x450 >> 2, 0x00); | ||
795 | |||
796 | for (;;) { | ||
797 | tvaudio_sleep(dev,-1); | ||
798 | if (dev->thread.shutdown || signal_pending(current)) | ||
799 | goto done; | ||
800 | |||
801 | restart: | ||
802 | dev->thread.scan1 = dev->thread.scan2; | ||
803 | dprintk("tvaudio thread scan start [%d]\n",dev->thread.scan1); | ||
804 | |||
805 | if (audio_ddep >= 0x04 && audio_ddep <= 0x0e) { | ||
806 | /* insmod option override */ | ||
807 | norms = (audio_ddep << 2) | 0x01; | ||
808 | dprintk("ddep override: %s\n",stdres[audio_ddep]); | ||
809 | } else if (&card(dev).radio == dev->input) { | ||
810 | dprintk("FM Radio\n"); | ||
811 | norms = (0x0f << 2) | 0x01; | ||
812 | } else { | ||
813 | /* (let chip) scan for sound carrier */ | ||
814 | norms = 0; | ||
815 | if (dev->tvnorm->id & V4L2_STD_PAL) { | ||
816 | dprintk("PAL scan\n"); | ||
817 | norms |= 0x2c; /* B/G + D/K + I */ | ||
818 | } | ||
819 | if (dev->tvnorm->id & V4L2_STD_NTSC) { | ||
820 | dprintk("NTSC scan\n"); | ||
821 | norms |= 0x40; /* M */ | ||
822 | } | ||
823 | if (dev->tvnorm->id & V4L2_STD_SECAM) { | ||
824 | dprintk("SECAM scan\n"); | ||
825 | norms |= 0x18; /* L + D/K */ | ||
826 | } | ||
827 | if (0 == norms) | ||
828 | norms = 0x7c; /* all */ | ||
829 | dprintk("scanning:%s%s%s%s%s\n", | ||
830 | (norms & 0x04) ? " B/G" : "", | ||
831 | (norms & 0x08) ? " D/K" : "", | ||
832 | (norms & 0x10) ? " L/L'" : "", | ||
833 | (norms & 0x20) ? " I" : "", | ||
834 | (norms & 0x40) ? " M" : ""); | ||
835 | } | ||
836 | |||
837 | /* kick automatic standard detection */ | ||
838 | saa_dsp_writel(dev, 0x454 >> 2, 0); | ||
839 | saa_dsp_writel(dev, 0x454 >> 2, norms | 0x80); | ||
840 | |||
841 | /* setup crossbars */ | ||
842 | saa_dsp_writel(dev, 0x464 >> 2, 0x000000); | ||
843 | saa_dsp_writel(dev, 0x470 >> 2, 0x101010); | ||
844 | |||
845 | if (tvaudio_sleep(dev,3000)) | ||
846 | goto restart; | ||
847 | value = saa_readl(0x528 >> 2) & 0xffffff; | ||
848 | |||
849 | dprintk("tvaudio thread status: 0x%x [%s%s%s]\n", | ||
850 | value, stdres[value & 0x1f], | ||
851 | (value & 0x000020) ? ",stereo" : "", | ||
852 | (value & 0x000040) ? ",dual" : ""); | ||
853 | dprintk("detailed status: " | ||
854 | "%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s#%s\n", | ||
855 | (value & 0x000080) ? " A2/EIAJ pilot tone " : "", | ||
856 | (value & 0x000100) ? " A2/EIAJ dual " : "", | ||
857 | (value & 0x000200) ? " A2/EIAJ stereo " : "", | ||
858 | (value & 0x000400) ? " A2/EIAJ noise mute " : "", | ||
859 | |||
860 | (value & 0x000800) ? " BTSC/FM radio pilot " : "", | ||
861 | (value & 0x001000) ? " SAP carrier " : "", | ||
862 | (value & 0x002000) ? " BTSC stereo noise mute " : "", | ||
863 | (value & 0x004000) ? " SAP noise mute " : "", | ||
864 | (value & 0x008000) ? " VDSP " : "", | ||
865 | |||
866 | (value & 0x010000) ? " NICST " : "", | ||
867 | (value & 0x020000) ? " NICDU " : "", | ||
868 | (value & 0x040000) ? " NICAM muted " : "", | ||
869 | (value & 0x080000) ? " NICAM reserve sound " : "", | ||
870 | |||
871 | (value & 0x100000) ? " init done " : ""); | ||
872 | } | ||
873 | |||
874 | done: | ||
875 | complete_and_exit(&dev->thread.exit, 0); | ||
876 | return 0; | ||
877 | } | ||
878 | |||
879 | /* ------------------------------------------------------------------ */ | ||
880 | /* common stuff + external entry points */ | ||
881 | |||
882 | static void saa7134_enable_i2s(struct saa7134_dev *dev) | ||
883 | { | ||
884 | int i2s_format; | ||
885 | |||
886 | if (!card_is_empress(dev)) | ||
887 | return; | ||
888 | i2s_format = (dev->input->amux == TV) ? 0x00 : 0x01; | ||
889 | |||
890 | /* enable I2S audio output for the mpeg encoder */ | ||
891 | saa_writeb(SAA7134_I2S_OUTPUT_SELECT, 0x80); | ||
892 | saa_writeb(SAA7134_I2S_OUTPUT_FORMAT, i2s_format); | ||
893 | saa_writeb(SAA7134_I2S_OUTPUT_LEVEL, 0x0F); | ||
894 | saa_writeb(SAA7134_I2S_AUDIO_OUTPUT, 0x01); | ||
895 | } | ||
896 | |||
897 | int saa7134_tvaudio_rx2mode(u32 rx) | ||
898 | { | ||
899 | u32 mode; | ||
900 | |||
901 | mode = V4L2_TUNER_MODE_MONO; | ||
902 | if (rx & V4L2_TUNER_SUB_STEREO) | ||
903 | mode = V4L2_TUNER_MODE_STEREO; | ||
904 | else if (rx & V4L2_TUNER_SUB_LANG1) | ||
905 | mode = V4L2_TUNER_MODE_LANG1; | ||
906 | else if (rx & V4L2_TUNER_SUB_LANG2) | ||
907 | mode = V4L2_TUNER_MODE_LANG2; | ||
908 | return mode; | ||
909 | } | ||
910 | |||
911 | void saa7134_tvaudio_setmute(struct saa7134_dev *dev) | ||
912 | { | ||
913 | switch (dev->pci->device) { | ||
914 | case PCI_DEVICE_ID_PHILIPS_SAA7130: | ||
915 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
916 | mute_input_7134(dev); | ||
917 | break; | ||
918 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
919 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
920 | mute_input_7133(dev); | ||
921 | break; | ||
922 | } | ||
923 | } | ||
924 | |||
925 | void saa7134_tvaudio_setinput(struct saa7134_dev *dev, | ||
926 | struct saa7134_input *in) | ||
927 | { | ||
928 | dev->input = in; | ||
929 | switch (dev->pci->device) { | ||
930 | case PCI_DEVICE_ID_PHILIPS_SAA7130: | ||
931 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
932 | mute_input_7134(dev); | ||
933 | break; | ||
934 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
935 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
936 | mute_input_7133(dev); | ||
937 | break; | ||
938 | } | ||
939 | saa7134_enable_i2s(dev); | ||
940 | } | ||
941 | |||
942 | void saa7134_tvaudio_setvolume(struct saa7134_dev *dev, int level) | ||
943 | { | ||
944 | switch (dev->pci->device) { | ||
945 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
946 | saa_writeb(SAA7134_CHANNEL1_LEVEL, level & 0x1f); | ||
947 | saa_writeb(SAA7134_CHANNEL2_LEVEL, level & 0x1f); | ||
948 | saa_writeb(SAA7134_NICAM_LEVEL_ADJUST, level & 0x1f); | ||
949 | break; | ||
950 | } | ||
951 | } | ||
952 | |||
953 | int saa7134_tvaudio_getstereo(struct saa7134_dev *dev) | ||
954 | { | ||
955 | int retval = V4L2_TUNER_SUB_MONO; | ||
956 | |||
957 | switch (dev->pci->device) { | ||
958 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
959 | if (dev->tvaudio) | ||
960 | retval = tvaudio_getstereo(dev,dev->tvaudio); | ||
961 | break; | ||
962 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
963 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
964 | retval = getstereo_7133(dev); | ||
965 | break; | ||
966 | } | ||
967 | return retval; | ||
968 | } | ||
969 | |||
970 | int saa7134_tvaudio_init2(struct saa7134_dev *dev) | ||
971 | { | ||
972 | DECLARE_MUTEX_LOCKED(sem); | ||
973 | int (*my_thread)(void *data) = NULL; | ||
974 | |||
975 | switch (dev->pci->device) { | ||
976 | case PCI_DEVICE_ID_PHILIPS_SAA7134: | ||
977 | my_thread = tvaudio_thread; | ||
978 | break; | ||
979 | case PCI_DEVICE_ID_PHILIPS_SAA7133: | ||
980 | case PCI_DEVICE_ID_PHILIPS_SAA7135: | ||
981 | my_thread = tvaudio_thread_ddep; | ||
982 | break; | ||
983 | } | ||
984 | |||
985 | dev->thread.pid = -1; | ||
986 | if (my_thread) { | ||
987 | /* start tvaudio thread */ | ||
988 | init_waitqueue_head(&dev->thread.wq); | ||
989 | init_completion(&dev->thread.exit); | ||
990 | dev->thread.pid = kernel_thread(my_thread,dev,0); | ||
991 | if (dev->thread.pid < 0) | ||
992 | printk(KERN_WARNING "%s: kernel_thread() failed\n", | ||
993 | dev->name); | ||
994 | saa7134_tvaudio_do_scan(dev); | ||
995 | } | ||
996 | |||
997 | saa7134_enable_i2s(dev); | ||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | int saa7134_tvaudio_fini(struct saa7134_dev *dev) | ||
1002 | { | ||
1003 | /* shutdown tvaudio thread */ | ||
1004 | if (dev->thread.pid >= 0) { | ||
1005 | dev->thread.shutdown = 1; | ||
1006 | wake_up_interruptible(&dev->thread.wq); | ||
1007 | wait_for_completion(&dev->thread.exit); | ||
1008 | } | ||
1009 | saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x07, 0x00); /* LINE1 */ | ||
1010 | return 0; | ||
1011 | } | ||
1012 | |||
1013 | int saa7134_tvaudio_do_scan(struct saa7134_dev *dev) | ||
1014 | { | ||
1015 | if (dev->thread.pid >= 0) { | ||
1016 | dev->thread.mode = UNSET; | ||
1017 | dev->thread.scan2++; | ||
1018 | wake_up_interruptible(&dev->thread.wq); | ||
1019 | } else { | ||
1020 | dev->automute = 0; | ||
1021 | saa7134_tvaudio_setmute(dev); | ||
1022 | } | ||
1023 | return 0; | ||
1024 | } | ||
1025 | |||
1026 | /* ----------------------------------------------------------- */ | ||
1027 | /* | ||
1028 | * Local variables: | ||
1029 | * c-basic-offset: 8 | ||
1030 | * End: | ||
1031 | */ | ||