1 /* 2 * cx88x-audio.c - Conexant CX23880/23881 audio downstream driver driver 3 * 4 * (c) 2001 Michael Eskin, Tom Zakrajsek [Windows version] 5 * (c) 2002 Yurij Sysoev <yurij@naturesoft.net> 6 * (c) 2003 Gerd Knorr <kraxel@bytesex.org> 7 * 8 * ----------------------------------------------------------------------- 9 * 10 * Lot of voodoo here. Even the data sheet doesn't help to 11 * understand what is going on here, the documentation for the audio 12 * part of the cx2388x chip is *very* bad. 13 * 14 * Some of this comes from party done linux driver sources I got from 15 * [undocumented]. 16 * 17 * Some comes from the dscaler sources, one of the dscaler driver guy works 18 * for Conexant ... 19 * 20 * ----------------------------------------------------------------------- 21 * 22 * This program is free software; you can redistribute it and/or modify 23 * it under the terms of the GNU General Public License as published by 24 * the Free Software Foundation; either version 2 of the License, or 25 * (at your option) any later version. 26 * 27 * This program is distributed in the hope that it will be useful, 28 * but WITHOUT ANY WARRANTY; without even the implied warranty of 29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 * GNU General Public License for more details. 31 */ 32 33 #include "cx88.h" 34 35 #include <linux/module.h> 36 #include <linux/errno.h> 37 #include <linux/freezer.h> 38 #include <linux/kernel.h> 39 #include <linux/mm.h> 40 #include <linux/poll.h> 41 #include <linux/signal.h> 42 #include <linux/ioport.h> 43 #include <linux/types.h> 44 #include <linux/interrupt.h> 45 #include <linux/vmalloc.h> 46 #include <linux/init.h> 47 #include <linux/delay.h> 48 #include <linux/kthread.h> 49 50 static unsigned int audio_debug; 51 module_param(audio_debug, int, 0644); 52 MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]"); 53 54 static unsigned int always_analog; 55 module_param(always_analog, int, 0644); 56 MODULE_PARM_DESC(always_analog, "force analog audio out"); 57 58 static unsigned int radio_deemphasis; 59 module_param(radio_deemphasis, int, 0644); 60 MODULE_PARM_DESC(radio_deemphasis, 61 "Radio deemphasis time constant, 0=None, 1=50us (elsewhere), 2=75us (USA)"); 62 63 #define dprintk(fmt, arg...) do { \ 64 if (audio_debug) \ 65 printk(KERN_DEBUG pr_fmt("%s: tvaudio:" fmt), \ 66 __func__, ##arg); \ 67 } while (0) 68 /* ----------------------------------------------------------- */ 69 70 static const char * const aud_ctl_names[64] = { 71 [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO", 72 [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO", 73 [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP", 74 [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO", 75 [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP", 76 [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1", 77 [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2", 78 [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO", 79 [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2", 80 [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO", 81 [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1", 82 [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2", 83 [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO", 84 [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2", 85 [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO", 86 [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1", 87 [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2", 88 [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO", 89 [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2", 90 [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO", 91 [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO", 92 [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO", 93 [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO", 94 }; 95 96 struct rlist { 97 u32 reg; 98 u32 val; 99 }; 100 101 static void set_audio_registers(struct cx88_core *core, const struct rlist *l) 102 { 103 int i; 104 105 for (i = 0; l[i].reg; i++) { 106 switch (l[i].reg) { 107 case AUD_PDF_DDS_CNST_BYTE2: 108 case AUD_PDF_DDS_CNST_BYTE1: 109 case AUD_PDF_DDS_CNST_BYTE0: 110 case AUD_QAM_MODE: 111 case AUD_PHACC_FREQ_8MSB: 112 case AUD_PHACC_FREQ_8LSB: 113 cx_writeb(l[i].reg, l[i].val); 114 break; 115 default: 116 cx_write(l[i].reg, l[i].val); 117 break; 118 } 119 } 120 } 121 122 static void set_audio_start(struct cx88_core *core, u32 mode) 123 { 124 /* mute */ 125 cx_write(AUD_VOL_CTL, (1 << 6)); 126 127 /* start programming */ 128 cx_write(AUD_INIT, mode); 129 cx_write(AUD_INIT_LD, 0x0001); 130 cx_write(AUD_SOFT_RESET, 0x0001); 131 } 132 133 static void set_audio_finish(struct cx88_core *core, u32 ctl) 134 { 135 u32 volume; 136 137 /* restart dma; This avoids buzz in NICAM and is good in others */ 138 cx88_stop_audio_dma(core); 139 cx_write(AUD_RATE_THRES_DMD, 0x000000C0); 140 cx88_start_audio_dma(core); 141 142 if (core->board.mpeg & CX88_MPEG_BLACKBIRD) { 143 cx_write(AUD_I2SINPUTCNTL, 4); 144 cx_write(AUD_BAUDRATE, 1); 145 /* 146 * 'pass-thru mode': this enables the i2s 147 * output to the mpeg encoder 148 */ 149 cx_set(AUD_CTL, EN_I2SOUT_ENABLE); 150 cx_write(AUD_I2SOUTPUTCNTL, 1); 151 cx_write(AUD_I2SCNTL, 0); 152 /* cx_write(AUD_APB_IN_RATE_ADJ, 0); */ 153 } 154 if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) { 155 ctl |= EN_DAC_ENABLE; 156 cx_write(AUD_CTL, ctl); 157 } 158 159 /* finish programming */ 160 cx_write(AUD_SOFT_RESET, 0x0000); 161 162 /* unmute */ 163 volume = cx_sread(SHADOW_AUD_VOL_CTL); 164 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume); 165 166 core->last_change = jiffies; 167 } 168 169 /* ----------------------------------------------------------- */ 170 171 static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap, 172 u32 mode) 173 { 174 static const struct rlist btsc[] = { 175 {AUD_AFE_12DB_EN, 0x00000001}, 176 {AUD_OUT1_SEL, 0x00000013}, 177 {AUD_OUT1_SHIFT, 0x00000000}, 178 {AUD_POLY0_DDS_CONSTANT, 0x0012010c}, 179 {AUD_DMD_RA_DDS, 0x00c3e7aa}, 180 {AUD_DBX_IN_GAIN, 0x00004734}, 181 {AUD_DBX_WBE_GAIN, 0x00004640}, 182 {AUD_DBX_SE_GAIN, 0x00008d31}, 183 {AUD_DCOC_0_SRC, 0x0000001a}, 184 {AUD_IIR1_4_SEL, 0x00000021}, 185 {AUD_DCOC_PASS_IN, 0x00000003}, 186 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 187 {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 188 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 189 {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 190 {AUD_DN0_FREQ, 0x0000283b}, 191 {AUD_DN2_SRC_SEL, 0x00000008}, 192 {AUD_DN2_FREQ, 0x00003000}, 193 {AUD_DN2_AFC, 0x00000002}, 194 {AUD_DN2_SHFT, 0x00000000}, 195 {AUD_IIR2_2_SEL, 0x00000020}, 196 {AUD_IIR2_2_SHIFT, 0x00000000}, 197 {AUD_IIR2_3_SEL, 0x0000001f}, 198 {AUD_IIR2_3_SHIFT, 0x00000000}, 199 {AUD_CRDC1_SRC_SEL, 0x000003ce}, 200 {AUD_CRDC1_SHIFT, 0x00000000}, 201 {AUD_CORDIC_SHIFT_1, 0x00000007}, 202 {AUD_DCOC_1_SRC, 0x0000001b}, 203 {AUD_DCOC1_SHIFT, 0x00000000}, 204 {AUD_RDSI_SEL, 0x00000008}, 205 {AUD_RDSQ_SEL, 0x00000008}, 206 {AUD_RDSI_SHIFT, 0x00000000}, 207 {AUD_RDSQ_SHIFT, 0x00000000}, 208 {AUD_POLYPH80SCALEFAC, 0x00000003}, 209 { /* end of list */ }, 210 }; 211 static const struct rlist btsc_sap[] = { 212 {AUD_AFE_12DB_EN, 0x00000001}, 213 {AUD_DBX_IN_GAIN, 0x00007200}, 214 {AUD_DBX_WBE_GAIN, 0x00006200}, 215 {AUD_DBX_SE_GAIN, 0x00006200}, 216 {AUD_IIR1_1_SEL, 0x00000000}, 217 {AUD_IIR1_3_SEL, 0x00000001}, 218 {AUD_DN1_SRC_SEL, 0x00000007}, 219 {AUD_IIR1_4_SHIFT, 0x00000006}, 220 {AUD_IIR2_1_SHIFT, 0x00000000}, 221 {AUD_IIR2_2_SHIFT, 0x00000000}, 222 {AUD_IIR3_0_SHIFT, 0x00000000}, 223 {AUD_IIR3_1_SHIFT, 0x00000000}, 224 {AUD_IIR3_0_SEL, 0x0000000d}, 225 {AUD_IIR3_1_SEL, 0x0000000e}, 226 {AUD_DEEMPH1_SRC_SEL, 0x00000014}, 227 {AUD_DEEMPH1_SHIFT, 0x00000000}, 228 {AUD_DEEMPH1_G0, 0x00004000}, 229 {AUD_DEEMPH1_A0, 0x00000000}, 230 {AUD_DEEMPH1_B0, 0x00000000}, 231 {AUD_DEEMPH1_A1, 0x00000000}, 232 {AUD_DEEMPH1_B1, 0x00000000}, 233 {AUD_OUT0_SEL, 0x0000003f}, 234 {AUD_OUT1_SEL, 0x0000003f}, 235 {AUD_DN1_AFC, 0x00000002}, 236 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 237 {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 238 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 239 {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 240 {AUD_IIR1_0_SEL, 0x0000001d}, 241 {AUD_IIR1_2_SEL, 0x0000001e}, 242 {AUD_IIR2_1_SEL, 0x00000002}, 243 {AUD_IIR2_2_SEL, 0x00000004}, 244 {AUD_IIR3_2_SEL, 0x0000000f}, 245 {AUD_DCOC2_SHIFT, 0x00000001}, 246 {AUD_IIR3_2_SHIFT, 0x00000001}, 247 {AUD_DEEMPH0_SRC_SEL, 0x00000014}, 248 {AUD_CORDIC_SHIFT_1, 0x00000006}, 249 {AUD_POLY0_DDS_CONSTANT, 0x000e4db2}, 250 {AUD_DMD_RA_DDS, 0x00f696e6}, 251 {AUD_IIR2_3_SEL, 0x00000025}, 252 {AUD_IIR1_4_SEL, 0x00000021}, 253 {AUD_DN1_FREQ, 0x0000c965}, 254 {AUD_DCOC_PASS_IN, 0x00000003}, 255 {AUD_DCOC_0_SRC, 0x0000001a}, 256 {AUD_DCOC_1_SRC, 0x0000001b}, 257 {AUD_DCOC1_SHIFT, 0x00000000}, 258 {AUD_RDSI_SEL, 0x00000009}, 259 {AUD_RDSQ_SEL, 0x00000009}, 260 {AUD_RDSI_SHIFT, 0x00000000}, 261 {AUD_RDSQ_SHIFT, 0x00000000}, 262 {AUD_POLYPH80SCALEFAC, 0x00000003}, 263 { /* end of list */ }, 264 }; 265 266 mode |= EN_FMRADIO_EN_RDS; 267 268 if (sap) { 269 dprintk("%s SAP (status: unknown)\n", __func__); 270 set_audio_start(core, SEL_SAP); 271 set_audio_registers(core, btsc_sap); 272 set_audio_finish(core, mode); 273 } else { 274 dprintk("%s (status: known-good)\n", __func__); 275 set_audio_start(core, SEL_BTSC); 276 set_audio_registers(core, btsc); 277 set_audio_finish(core, mode); 278 } 279 } 280 281 static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode) 282 { 283 static const struct rlist nicam_l[] = { 284 {AUD_AFE_12DB_EN, 0x00000001}, 285 {AUD_RATE_ADJ1, 0x00000060}, 286 {AUD_RATE_ADJ2, 0x000000F9}, 287 {AUD_RATE_ADJ3, 0x000001CC}, 288 {AUD_RATE_ADJ4, 0x000002B3}, 289 {AUD_RATE_ADJ5, 0x00000726}, 290 {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, 291 {AUD_DEEMPHDENOM2_R, 0x00000000}, 292 {AUD_ERRLOGPERIOD_R, 0x00000064}, 293 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, 294 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, 295 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, 296 {AUD_POLYPH80SCALEFAC, 0x00000003}, 297 {AUD_DMD_RA_DDS, 0x00C00000}, 298 {AUD_PLL_INT, 0x0000001E}, 299 {AUD_PLL_DDS, 0x00000000}, 300 {AUD_PLL_FRAC, 0x0000E542}, 301 {AUD_START_TIMER, 0x00000000}, 302 {AUD_DEEMPHNUMER1_R, 0x000353DE}, 303 {AUD_DEEMPHNUMER2_R, 0x000001B1}, 304 {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 305 {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 306 {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 307 {AUD_QAM_MODE, 0x05}, 308 {AUD_PHACC_FREQ_8MSB, 0x34}, 309 {AUD_PHACC_FREQ_8LSB, 0x4C}, 310 {AUD_DEEMPHGAIN_R, 0x00006680}, 311 {AUD_RATE_THRES_DMD, 0x000000C0}, 312 { /* end of list */ }, 313 }; 314 315 static const struct rlist nicam_bgdki_common[] = { 316 {AUD_AFE_12DB_EN, 0x00000001}, 317 {AUD_RATE_ADJ1, 0x00000010}, 318 {AUD_RATE_ADJ2, 0x00000040}, 319 {AUD_RATE_ADJ3, 0x00000100}, 320 {AUD_RATE_ADJ4, 0x00000400}, 321 {AUD_RATE_ADJ5, 0x00001000}, 322 {AUD_ERRLOGPERIOD_R, 0x00000fff}, 323 {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff}, 324 {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff}, 325 {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f}, 326 {AUD_POLYPH80SCALEFAC, 0x00000003}, 327 {AUD_DEEMPHGAIN_R, 0x000023c2}, 328 {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, 329 {AUD_DEEMPHNUMER2_R, 0x0003023e}, 330 {AUD_DEEMPHDENOM1_R, 0x0000f3d0}, 331 {AUD_DEEMPHDENOM2_R, 0x00000000}, 332 {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 333 {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 334 {AUD_QAM_MODE, 0x05}, 335 { /* end of list */ }, 336 }; 337 338 static const struct rlist nicam_i[] = { 339 {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 340 {AUD_PHACC_FREQ_8MSB, 0x3a}, 341 {AUD_PHACC_FREQ_8LSB, 0x93}, 342 { /* end of list */ }, 343 }; 344 345 static const struct rlist nicam_default[] = { 346 {AUD_PDF_DDS_CNST_BYTE0, 0x16}, 347 {AUD_PHACC_FREQ_8MSB, 0x34}, 348 {AUD_PHACC_FREQ_8LSB, 0x4c}, 349 { /* end of list */ }, 350 }; 351 352 set_audio_start(core, SEL_NICAM); 353 switch (core->tvaudio) { 354 case WW_L: 355 dprintk("%s SECAM-L NICAM (status: devel)\n", __func__); 356 set_audio_registers(core, nicam_l); 357 break; 358 case WW_I: 359 dprintk("%s PAL-I NICAM (status: known-good)\n", __func__); 360 set_audio_registers(core, nicam_bgdki_common); 361 set_audio_registers(core, nicam_i); 362 break; 363 case WW_NONE: 364 case WW_BTSC: 365 case WW_BG: 366 case WW_DK: 367 case WW_EIAJ: 368 case WW_I2SPT: 369 case WW_FM: 370 case WW_I2SADC: 371 case WW_M: 372 dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__); 373 set_audio_registers(core, nicam_bgdki_common); 374 set_audio_registers(core, nicam_default); 375 break; 376 } 377 378 mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS; 379 set_audio_finish(core, mode); 380 } 381 382 static void set_audio_standard_A2(struct cx88_core *core, u32 mode) 383 { 384 static const struct rlist a2_bgdk_common[] = { 385 {AUD_ERRLOGPERIOD_R, 0x00000064}, 386 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, 387 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, 388 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, 389 {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 390 {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 391 {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 392 {AUD_QAM_MODE, 0x05}, 393 {AUD_PHACC_FREQ_8MSB, 0x34}, 394 {AUD_PHACC_FREQ_8LSB, 0x4c}, 395 {AUD_RATE_ADJ1, 0x00000100}, 396 {AUD_RATE_ADJ2, 0x00000200}, 397 {AUD_RATE_ADJ3, 0x00000300}, 398 {AUD_RATE_ADJ4, 0x00000400}, 399 {AUD_RATE_ADJ5, 0x00000500}, 400 {AUD_THR_FR, 0x00000000}, 401 {AAGC_HYST, 0x0000001a}, 402 {AUD_PILOT_BQD_1_K0, 0x0000755b}, 403 {AUD_PILOT_BQD_1_K1, 0x00551340}, 404 {AUD_PILOT_BQD_1_K2, 0x006d30be}, 405 {AUD_PILOT_BQD_1_K3, 0xffd394af}, 406 {AUD_PILOT_BQD_1_K4, 0x00400000}, 407 {AUD_PILOT_BQD_2_K0, 0x00040000}, 408 {AUD_PILOT_BQD_2_K1, 0x002a4841}, 409 {AUD_PILOT_BQD_2_K2, 0x00400000}, 410 {AUD_PILOT_BQD_2_K3, 0x00000000}, 411 {AUD_PILOT_BQD_2_K4, 0x00000000}, 412 {AUD_MODE_CHG_TIMER, 0x00000040}, 413 {AUD_AFE_12DB_EN, 0x00000001}, 414 {AUD_CORDIC_SHIFT_0, 0x00000007}, 415 {AUD_CORDIC_SHIFT_1, 0x00000007}, 416 {AUD_DEEMPH0_G0, 0x00000380}, 417 {AUD_DEEMPH1_G0, 0x00000380}, 418 {AUD_DCOC_0_SRC, 0x0000001a}, 419 {AUD_DCOC0_SHIFT, 0x00000000}, 420 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 421 {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 422 {AUD_DCOC_PASS_IN, 0x00000003}, 423 {AUD_IIR3_0_SEL, 0x00000021}, 424 {AUD_DN2_AFC, 0x00000002}, 425 {AUD_DCOC_1_SRC, 0x0000001b}, 426 {AUD_DCOC1_SHIFT, 0x00000000}, 427 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 428 {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 429 {AUD_IIR3_1_SEL, 0x00000023}, 430 {AUD_RDSI_SEL, 0x00000017}, 431 {AUD_RDSI_SHIFT, 0x00000000}, 432 {AUD_RDSQ_SEL, 0x00000017}, 433 {AUD_RDSQ_SHIFT, 0x00000000}, 434 {AUD_PLL_INT, 0x0000001e}, 435 {AUD_PLL_DDS, 0x00000000}, 436 {AUD_PLL_FRAC, 0x0000e542}, 437 {AUD_POLYPH80SCALEFAC, 0x00000001}, 438 {AUD_START_TIMER, 0x00000000}, 439 { /* end of list */ }, 440 }; 441 442 static const struct rlist a2_bg[] = { 443 {AUD_DMD_RA_DDS, 0x002a4f2f}, 444 {AUD_C1_UP_THR, 0x00007000}, 445 {AUD_C1_LO_THR, 0x00005400}, 446 {AUD_C2_UP_THR, 0x00005400}, 447 {AUD_C2_LO_THR, 0x00003000}, 448 { /* end of list */ }, 449 }; 450 451 static const struct rlist a2_dk[] = { 452 {AUD_DMD_RA_DDS, 0x002a4f2f}, 453 {AUD_C1_UP_THR, 0x00007000}, 454 {AUD_C1_LO_THR, 0x00005400}, 455 {AUD_C2_UP_THR, 0x00005400}, 456 {AUD_C2_LO_THR, 0x00003000}, 457 {AUD_DN0_FREQ, 0x00003a1c}, 458 {AUD_DN2_FREQ, 0x0000d2e0}, 459 { /* end of list */ }, 460 }; 461 462 static const struct rlist a1_i[] = { 463 {AUD_ERRLOGPERIOD_R, 0x00000064}, 464 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff}, 465 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f}, 466 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f}, 467 {AUD_PDF_DDS_CNST_BYTE2, 0x06}, 468 {AUD_PDF_DDS_CNST_BYTE1, 0x82}, 469 {AUD_PDF_DDS_CNST_BYTE0, 0x12}, 470 {AUD_QAM_MODE, 0x05}, 471 {AUD_PHACC_FREQ_8MSB, 0x3a}, 472 {AUD_PHACC_FREQ_8LSB, 0x93}, 473 {AUD_DMD_RA_DDS, 0x002a4f2f}, 474 {AUD_PLL_INT, 0x0000001e}, 475 {AUD_PLL_DDS, 0x00000004}, 476 {AUD_PLL_FRAC, 0x0000e542}, 477 {AUD_RATE_ADJ1, 0x00000100}, 478 {AUD_RATE_ADJ2, 0x00000200}, 479 {AUD_RATE_ADJ3, 0x00000300}, 480 {AUD_RATE_ADJ4, 0x00000400}, 481 {AUD_RATE_ADJ5, 0x00000500}, 482 {AUD_THR_FR, 0x00000000}, 483 {AUD_PILOT_BQD_1_K0, 0x0000755b}, 484 {AUD_PILOT_BQD_1_K1, 0x00551340}, 485 {AUD_PILOT_BQD_1_K2, 0x006d30be}, 486 {AUD_PILOT_BQD_1_K3, 0xffd394af}, 487 {AUD_PILOT_BQD_1_K4, 0x00400000}, 488 {AUD_PILOT_BQD_2_K0, 0x00040000}, 489 {AUD_PILOT_BQD_2_K1, 0x002a4841}, 490 {AUD_PILOT_BQD_2_K2, 0x00400000}, 491 {AUD_PILOT_BQD_2_K3, 0x00000000}, 492 {AUD_PILOT_BQD_2_K4, 0x00000000}, 493 {AUD_MODE_CHG_TIMER, 0x00000060}, 494 {AUD_AFE_12DB_EN, 0x00000001}, 495 {AAGC_HYST, 0x0000000a}, 496 {AUD_CORDIC_SHIFT_0, 0x00000007}, 497 {AUD_CORDIC_SHIFT_1, 0x00000007}, 498 {AUD_C1_UP_THR, 0x00007000}, 499 {AUD_C1_LO_THR, 0x00005400}, 500 {AUD_C2_UP_THR, 0x00005400}, 501 {AUD_C2_LO_THR, 0x00003000}, 502 {AUD_DCOC_0_SRC, 0x0000001a}, 503 {AUD_DCOC0_SHIFT, 0x00000000}, 504 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a}, 505 {AUD_DCOC_0_SHIFT_IN1, 0x00000008}, 506 {AUD_DCOC_PASS_IN, 0x00000003}, 507 {AUD_IIR3_0_SEL, 0x00000021}, 508 {AUD_DN2_AFC, 0x00000002}, 509 {AUD_DCOC_1_SRC, 0x0000001b}, 510 {AUD_DCOC1_SHIFT, 0x00000000}, 511 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a}, 512 {AUD_DCOC_1_SHIFT_IN1, 0x00000008}, 513 {AUD_IIR3_1_SEL, 0x00000023}, 514 {AUD_DN0_FREQ, 0x000035a3}, 515 {AUD_DN2_FREQ, 0x000029c7}, 516 {AUD_CRDC0_SRC_SEL, 0x00000511}, 517 {AUD_IIR1_0_SEL, 0x00000001}, 518 {AUD_IIR1_1_SEL, 0x00000000}, 519 {AUD_IIR3_2_SEL, 0x00000003}, 520 {AUD_IIR3_2_SHIFT, 0x00000000}, 521 {AUD_IIR3_0_SEL, 0x00000002}, 522 {AUD_IIR2_0_SEL, 0x00000021}, 523 {AUD_IIR2_0_SHIFT, 0x00000002}, 524 {AUD_DEEMPH0_SRC_SEL, 0x0000000b}, 525 {AUD_DEEMPH1_SRC_SEL, 0x0000000b}, 526 {AUD_POLYPH80SCALEFAC, 0x00000001}, 527 {AUD_START_TIMER, 0x00000000}, 528 { /* end of list */ }, 529 }; 530 531 static const struct rlist am_l[] = { 532 {AUD_ERRLOGPERIOD_R, 0x00000064}, 533 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF}, 534 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F}, 535 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F}, 536 {AUD_PDF_DDS_CNST_BYTE2, 0x48}, 537 {AUD_PDF_DDS_CNST_BYTE1, 0x3D}, 538 {AUD_QAM_MODE, 0x00}, 539 {AUD_PDF_DDS_CNST_BYTE0, 0xf5}, 540 {AUD_PHACC_FREQ_8MSB, 0x3a}, 541 {AUD_PHACC_FREQ_8LSB, 0x4a}, 542 {AUD_DEEMPHGAIN_R, 0x00006680}, 543 {AUD_DEEMPHNUMER1_R, 0x000353DE}, 544 {AUD_DEEMPHNUMER2_R, 0x000001B1}, 545 {AUD_DEEMPHDENOM1_R, 0x0000F3D0}, 546 {AUD_DEEMPHDENOM2_R, 0x00000000}, 547 {AUD_FM_MODE_ENABLE, 0x00000007}, 548 {AUD_POLYPH80SCALEFAC, 0x00000003}, 549 {AUD_AFE_12DB_EN, 0x00000001}, 550 {AAGC_GAIN, 0x00000000}, 551 {AAGC_HYST, 0x00000018}, 552 {AAGC_DEF, 0x00000020}, 553 {AUD_DN0_FREQ, 0x00000000}, 554 {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2}, 555 {AUD_DCOC_0_SRC, 0x00000021}, 556 {AUD_IIR1_0_SEL, 0x00000000}, 557 {AUD_IIR1_0_SHIFT, 0x00000007}, 558 {AUD_IIR1_1_SEL, 0x00000002}, 559 {AUD_IIR1_1_SHIFT, 0x00000000}, 560 {AUD_DCOC_1_SRC, 0x00000003}, 561 {AUD_DCOC1_SHIFT, 0x00000000}, 562 {AUD_DCOC_PASS_IN, 0x00000000}, 563 {AUD_IIR1_2_SEL, 0x00000023}, 564 {AUD_IIR1_2_SHIFT, 0x00000000}, 565 {AUD_IIR1_3_SEL, 0x00000004}, 566 {AUD_IIR1_3_SHIFT, 0x00000007}, 567 {AUD_IIR1_4_SEL, 0x00000005}, 568 {AUD_IIR1_4_SHIFT, 0x00000007}, 569 {AUD_IIR3_0_SEL, 0x00000007}, 570 {AUD_IIR3_0_SHIFT, 0x00000000}, 571 {AUD_DEEMPH0_SRC_SEL, 0x00000011}, 572 {AUD_DEEMPH0_SHIFT, 0x00000000}, 573 {AUD_DEEMPH0_G0, 0x00007000}, 574 {AUD_DEEMPH0_A0, 0x00000000}, 575 {AUD_DEEMPH0_B0, 0x00000000}, 576 {AUD_DEEMPH0_A1, 0x00000000}, 577 {AUD_DEEMPH0_B1, 0x00000000}, 578 {AUD_DEEMPH1_SRC_SEL, 0x00000011}, 579 {AUD_DEEMPH1_SHIFT, 0x00000000}, 580 {AUD_DEEMPH1_G0, 0x00007000}, 581 {AUD_DEEMPH1_A0, 0x00000000}, 582 {AUD_DEEMPH1_B0, 0x00000000}, 583 {AUD_DEEMPH1_A1, 0x00000000}, 584 {AUD_DEEMPH1_B1, 0x00000000}, 585 {AUD_OUT0_SEL, 0x0000003F}, 586 {AUD_OUT1_SEL, 0x0000003F}, 587 {AUD_DMD_RA_DDS, 0x00F5C285}, 588 {AUD_PLL_INT, 0x0000001E}, 589 {AUD_PLL_DDS, 0x00000000}, 590 {AUD_PLL_FRAC, 0x0000E542}, 591 {AUD_RATE_ADJ1, 0x00000100}, 592 {AUD_RATE_ADJ2, 0x00000200}, 593 {AUD_RATE_ADJ3, 0x00000300}, 594 {AUD_RATE_ADJ4, 0x00000400}, 595 {AUD_RATE_ADJ5, 0x00000500}, 596 {AUD_RATE_THRES_DMD, 0x000000C0}, 597 { /* end of list */ }, 598 }; 599 600 static const struct rlist a2_deemph50[] = { 601 {AUD_DEEMPH0_G0, 0x00000380}, 602 {AUD_DEEMPH1_G0, 0x00000380}, 603 {AUD_DEEMPHGAIN_R, 0x000011e1}, 604 {AUD_DEEMPHNUMER1_R, 0x0002a7bc}, 605 {AUD_DEEMPHNUMER2_R, 0x0003023c}, 606 { /* end of list */ }, 607 }; 608 609 set_audio_start(core, SEL_A2); 610 switch (core->tvaudio) { 611 case WW_BG: 612 dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__); 613 set_audio_registers(core, a2_bgdk_common); 614 set_audio_registers(core, a2_bg); 615 set_audio_registers(core, a2_deemph50); 616 break; 617 case WW_DK: 618 dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__); 619 set_audio_registers(core, a2_bgdk_common); 620 set_audio_registers(core, a2_dk); 621 set_audio_registers(core, a2_deemph50); 622 break; 623 case WW_I: 624 dprintk("%s PAL-I A1 (status: known-good)\n", __func__); 625 set_audio_registers(core, a1_i); 626 set_audio_registers(core, a2_deemph50); 627 break; 628 case WW_L: 629 dprintk("%s AM-L (status: devel)\n", __func__); 630 set_audio_registers(core, am_l); 631 break; 632 case WW_NONE: 633 case WW_BTSC: 634 case WW_EIAJ: 635 case WW_I2SPT: 636 case WW_FM: 637 case WW_I2SADC: 638 case WW_M: 639 dprintk("%s Warning: wrong value\n", __func__); 640 return; 641 } 642 643 mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF; 644 set_audio_finish(core, mode); 645 } 646 647 static void set_audio_standard_EIAJ(struct cx88_core *core) 648 { 649 static const struct rlist eiaj[] = { 650 /* TODO: eiaj register settings are not there yet ... */ 651 652 { /* end of list */ }, 653 }; 654 dprintk("%s (status: unknown)\n", __func__); 655 656 set_audio_start(core, SEL_EIAJ); 657 set_audio_registers(core, eiaj); 658 set_audio_finish(core, EN_EIAJ_AUTO_STEREO); 659 } 660 661 static void set_audio_standard_FM(struct cx88_core *core, 662 enum cx88_deemph_type deemph) 663 { 664 static const struct rlist fm_deemph_50[] = { 665 {AUD_DEEMPH0_G0, 0x0C45}, 666 {AUD_DEEMPH0_A0, 0x6262}, 667 {AUD_DEEMPH0_B0, 0x1C29}, 668 {AUD_DEEMPH0_A1, 0x3FC66}, 669 {AUD_DEEMPH0_B1, 0x399A}, 670 671 {AUD_DEEMPH1_G0, 0x0D80}, 672 {AUD_DEEMPH1_A0, 0x6262}, 673 {AUD_DEEMPH1_B0, 0x1C29}, 674 {AUD_DEEMPH1_A1, 0x3FC66}, 675 {AUD_DEEMPH1_B1, 0x399A}, 676 677 {AUD_POLYPH80SCALEFAC, 0x0003}, 678 { /* end of list */ }, 679 }; 680 static const struct rlist fm_deemph_75[] = { 681 {AUD_DEEMPH0_G0, 0x091B}, 682 {AUD_DEEMPH0_A0, 0x6B68}, 683 {AUD_DEEMPH0_B0, 0x11EC}, 684 {AUD_DEEMPH0_A1, 0x3FC66}, 685 {AUD_DEEMPH0_B1, 0x399A}, 686 687 {AUD_DEEMPH1_G0, 0x0AA0}, 688 {AUD_DEEMPH1_A0, 0x6B68}, 689 {AUD_DEEMPH1_B0, 0x11EC}, 690 {AUD_DEEMPH1_A1, 0x3FC66}, 691 {AUD_DEEMPH1_B1, 0x399A}, 692 693 {AUD_POLYPH80SCALEFAC, 0x0003}, 694 { /* end of list */ }, 695 }; 696 697 /* 698 * It is enough to leave default values? 699 * 700 * No, it's not! The deemphasis registers are reset to the 75us 701 * values by default. Analyzing the spectrum of the decoded audio 702 * reveals that "no deemphasis" is the same as 75 us, while the 50 us 703 * setting results in less deemphasis. 704 */ 705 static const struct rlist fm_no_deemph[] = { 706 {AUD_POLYPH80SCALEFAC, 0x0003}, 707 { /* end of list */ }, 708 }; 709 710 dprintk("%s (status: unknown)\n", __func__); 711 set_audio_start(core, SEL_FMRADIO); 712 713 switch (deemph) { 714 default: 715 case FM_NO_DEEMPH: 716 set_audio_registers(core, fm_no_deemph); 717 break; 718 719 case FM_DEEMPH_50: 720 set_audio_registers(core, fm_deemph_50); 721 break; 722 723 case FM_DEEMPH_75: 724 set_audio_registers(core, fm_deemph_75); 725 break; 726 } 727 728 set_audio_finish(core, EN_FMRADIO_AUTO_STEREO); 729 } 730 731 /* ----------------------------------------------------------- */ 732 733 static int cx88_detect_nicam(struct cx88_core *core) 734 { 735 int i, j = 0; 736 737 dprintk("start nicam autodetect.\n"); 738 739 for (i = 0; i < 6; i++) { 740 /* if bit1=1 then nicam is detected */ 741 j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1); 742 743 if (j == 1) { 744 dprintk("nicam is detected.\n"); 745 return 1; 746 } 747 748 /* wait a little bit for next reading status */ 749 usleep_range(10000, 20000); 750 } 751 752 dprintk("nicam is not detected.\n"); 753 return 0; 754 } 755 756 void cx88_set_tvaudio(struct cx88_core *core) 757 { 758 switch (core->tvaudio) { 759 case WW_BTSC: 760 set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO); 761 break; 762 case WW_BG: 763 case WW_DK: 764 case WW_M: 765 case WW_I: 766 case WW_L: 767 /* prepare all dsp registers */ 768 set_audio_standard_A2(core, EN_A2_FORCE_MONO1); 769 770 /* 771 * set nicam mode - otherwise 772 * AUD_NICAM_STATUS2 contains wrong values 773 */ 774 set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO); 775 if (cx88_detect_nicam(core) == 0) { 776 /* fall back to fm / am mono */ 777 set_audio_standard_A2(core, EN_A2_FORCE_MONO1); 778 core->audiomode_current = V4L2_TUNER_MODE_MONO; 779 core->use_nicam = 0; 780 } else { 781 core->use_nicam = 1; 782 } 783 break; 784 case WW_EIAJ: 785 set_audio_standard_EIAJ(core); 786 break; 787 case WW_FM: 788 set_audio_standard_FM(core, radio_deemphasis); 789 break; 790 case WW_I2SADC: 791 set_audio_start(core, 0x01); 792 /* 793 * Slave/Philips/Autobaud 794 * NB on Nova-S bit1 NPhilipsSony appears to be inverted: 795 * 0= Sony, 1=Philips 796 */ 797 cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl); 798 /* Switch to "I2S ADC mode" */ 799 cx_write(AUD_I2SCNTL, 0x1); 800 set_audio_finish(core, EN_I2SIN_ENABLE); 801 break; 802 case WW_NONE: 803 case WW_I2SPT: 804 pr_info("unknown tv audio mode [%d]\n", core->tvaudio); 805 break; 806 } 807 } 808 EXPORT_SYMBOL(cx88_set_tvaudio); 809 810 void cx88_newstation(struct cx88_core *core) 811 { 812 core->audiomode_manual = UNSET; 813 core->last_change = jiffies; 814 } 815 EXPORT_SYMBOL(cx88_newstation); 816 817 void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t) 818 { 819 static const char * const m[] = { "stereo", "dual mono", 820 "mono", "sap" }; 821 static const char * const p[] = { "no pilot", "pilot c1", 822 "pilot c2", "?" }; 823 u32 reg, mode, pilot; 824 825 reg = cx_read(AUD_STATUS); 826 mode = reg & 0x03; 827 pilot = (reg >> 2) & 0x03; 828 829 if (core->astat != reg) 830 dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n", 831 reg, m[mode], p[pilot], 832 aud_ctl_names[cx_read(AUD_CTL) & 63]); 833 core->astat = reg; 834 835 t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP | 836 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2; 837 t->rxsubchans = UNSET; 838 t->audmode = V4L2_TUNER_MODE_MONO; 839 840 switch (mode) { 841 case 0: 842 t->audmode = V4L2_TUNER_MODE_STEREO; 843 break; 844 case 1: 845 t->audmode = V4L2_TUNER_MODE_LANG2; 846 break; 847 case 2: 848 t->audmode = V4L2_TUNER_MODE_MONO; 849 break; 850 case 3: 851 t->audmode = V4L2_TUNER_MODE_SAP; 852 break; 853 } 854 855 switch (core->tvaudio) { 856 case WW_BTSC: 857 case WW_BG: 858 case WW_DK: 859 case WW_M: 860 case WW_EIAJ: 861 if (!core->use_nicam) { 862 t->rxsubchans = cx88_dsp_detect_stereo_sap(core); 863 break; 864 } 865 break; 866 case WW_NONE: 867 case WW_I: 868 case WW_L: 869 case WW_I2SPT: 870 case WW_FM: 871 case WW_I2SADC: 872 /* nothing */ 873 break; 874 } 875 876 /* If software stereo detection is not supported... */ 877 if (t->rxsubchans == UNSET) { 878 t->rxsubchans = V4L2_TUNER_SUB_MONO; 879 /* 880 * If the hardware itself detected stereo, also return 881 * stereo as an available subchannel 882 */ 883 if (t->audmode == V4L2_TUNER_MODE_STEREO) 884 t->rxsubchans |= V4L2_TUNER_SUB_STEREO; 885 } 886 } 887 EXPORT_SYMBOL(cx88_get_stereo); 888 889 890 void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual) 891 { 892 u32 ctl = UNSET; 893 u32 mask = UNSET; 894 895 if (manual) { 896 core->audiomode_manual = mode; 897 } else { 898 if (core->audiomode_manual != UNSET) 899 return; 900 } 901 core->audiomode_current = mode; 902 903 switch (core->tvaudio) { 904 case WW_BTSC: 905 switch (mode) { 906 case V4L2_TUNER_MODE_MONO: 907 set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO); 908 break; 909 case V4L2_TUNER_MODE_LANG1: 910 set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO); 911 break; 912 case V4L2_TUNER_MODE_LANG2: 913 set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP); 914 break; 915 case V4L2_TUNER_MODE_STEREO: 916 case V4L2_TUNER_MODE_LANG1_LANG2: 917 set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO); 918 break; 919 } 920 break; 921 case WW_BG: 922 case WW_DK: 923 case WW_M: 924 case WW_I: 925 case WW_L: 926 if (core->use_nicam == 1) { 927 switch (mode) { 928 case V4L2_TUNER_MODE_MONO: 929 case V4L2_TUNER_MODE_LANG1: 930 set_audio_standard_NICAM(core, 931 EN_NICAM_FORCE_MONO1); 932 break; 933 case V4L2_TUNER_MODE_LANG2: 934 set_audio_standard_NICAM(core, 935 EN_NICAM_FORCE_MONO2); 936 break; 937 case V4L2_TUNER_MODE_STEREO: 938 case V4L2_TUNER_MODE_LANG1_LANG2: 939 set_audio_standard_NICAM(core, 940 EN_NICAM_FORCE_STEREO); 941 break; 942 } 943 } else { 944 if ((core->tvaudio == WW_I) || 945 (core->tvaudio == WW_L)) { 946 /* fall back to fm / am mono */ 947 set_audio_standard_A2(core, EN_A2_FORCE_MONO1); 948 } else { 949 /* TODO: Add A2 autodection */ 950 mask = 0x3f; 951 switch (mode) { 952 case V4L2_TUNER_MODE_MONO: 953 case V4L2_TUNER_MODE_LANG1: 954 ctl = EN_A2_FORCE_MONO1; 955 break; 956 case V4L2_TUNER_MODE_LANG2: 957 ctl = EN_A2_FORCE_MONO2; 958 break; 959 case V4L2_TUNER_MODE_STEREO: 960 case V4L2_TUNER_MODE_LANG1_LANG2: 961 ctl = EN_A2_FORCE_STEREO; 962 break; 963 } 964 } 965 } 966 break; 967 case WW_FM: 968 switch (mode) { 969 case V4L2_TUNER_MODE_MONO: 970 ctl = EN_FMRADIO_FORCE_MONO; 971 mask = 0x3f; 972 break; 973 case V4L2_TUNER_MODE_STEREO: 974 ctl = EN_FMRADIO_AUTO_STEREO; 975 mask = 0x3f; 976 break; 977 } 978 break; 979 case WW_I2SADC: 980 case WW_NONE: 981 case WW_EIAJ: 982 case WW_I2SPT: 983 /* DO NOTHING */ 984 break; 985 } 986 987 if (ctl != UNSET) { 988 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x [status=0x%x,ctl=0x%x,vol=0x%x]\n", 989 mask, ctl, cx_read(AUD_STATUS), 990 cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL)); 991 cx_andor(AUD_CTL, mask, ctl); 992 } 993 } 994 EXPORT_SYMBOL(cx88_set_stereo); 995 996 int cx88_audio_thread(void *data) 997 { 998 struct cx88_core *core = data; 999 struct v4l2_tuner t; 1000 u32 mode = 0; 1001 1002 dprintk("cx88: tvaudio thread started\n"); 1003 set_freezable(); 1004 for (;;) { 1005 msleep_interruptible(1000); 1006 if (kthread_should_stop()) 1007 break; 1008 try_to_freeze(); 1009 1010 switch (core->tvaudio) { 1011 case WW_BG: 1012 case WW_DK: 1013 case WW_M: 1014 case WW_I: 1015 case WW_L: 1016 if (core->use_nicam) 1017 goto hw_autodetect; 1018 1019 /* just monitor the audio status for now ... */ 1020 memset(&t, 0, sizeof(t)); 1021 cx88_get_stereo(core, &t); 1022 1023 if (core->audiomode_manual != UNSET) 1024 /* manually set, don't do anything. */ 1025 continue; 1026 1027 /* monitor signal and set stereo if available */ 1028 if (t.rxsubchans & V4L2_TUNER_SUB_STEREO) 1029 mode = V4L2_TUNER_MODE_STEREO; 1030 else 1031 mode = V4L2_TUNER_MODE_MONO; 1032 if (mode == core->audiomode_current) 1033 continue; 1034 /* automatically switch to best available mode */ 1035 cx88_set_stereo(core, mode, 0); 1036 break; 1037 case WW_NONE: 1038 case WW_BTSC: 1039 case WW_EIAJ: 1040 case WW_I2SPT: 1041 case WW_FM: 1042 case WW_I2SADC: 1043 hw_autodetect: 1044 /* 1045 * stereo autodetection is supported by hardware so 1046 * we don't need to do it manually. Do nothing. 1047 */ 1048 break; 1049 } 1050 } 1051 1052 dprintk("cx88: tvaudio thread exiting\n"); 1053 return 0; 1054 } 1055 EXPORT_SYMBOL(cx88_audio_thread); 1056