0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "cx88.h"
0025
0026 #include <linux/module.h>
0027 #include <linux/errno.h>
0028 #include <linux/freezer.h>
0029 #include <linux/kernel.h>
0030 #include <linux/mm.h>
0031 #include <linux/poll.h>
0032 #include <linux/signal.h>
0033 #include <linux/ioport.h>
0034 #include <linux/types.h>
0035 #include <linux/interrupt.h>
0036 #include <linux/vmalloc.h>
0037 #include <linux/init.h>
0038 #include <linux/delay.h>
0039 #include <linux/kthread.h>
0040
0041 static unsigned int audio_debug;
0042 module_param(audio_debug, int, 0644);
0043 MODULE_PARM_DESC(audio_debug, "enable debug messages [audio]");
0044
0045 static unsigned int always_analog;
0046 module_param(always_analog, int, 0644);
0047 MODULE_PARM_DESC(always_analog, "force analog audio out");
0048
0049 static unsigned int radio_deemphasis;
0050 module_param(radio_deemphasis, int, 0644);
0051 MODULE_PARM_DESC(radio_deemphasis,
0052 "Radio deemphasis time constant, 0=None, 1=50us (elsewhere), 2=75us (USA)");
0053
0054 #define dprintk(fmt, arg...) do { \
0055 if (audio_debug) \
0056 printk(KERN_DEBUG pr_fmt("%s: tvaudio:" fmt), \
0057 __func__, ##arg); \
0058 } while (0)
0059
0060
0061 static const char * const aud_ctl_names[64] = {
0062 [EN_BTSC_FORCE_MONO] = "BTSC_FORCE_MONO",
0063 [EN_BTSC_FORCE_STEREO] = "BTSC_FORCE_STEREO",
0064 [EN_BTSC_FORCE_SAP] = "BTSC_FORCE_SAP",
0065 [EN_BTSC_AUTO_STEREO] = "BTSC_AUTO_STEREO",
0066 [EN_BTSC_AUTO_SAP] = "BTSC_AUTO_SAP",
0067 [EN_A2_FORCE_MONO1] = "A2_FORCE_MONO1",
0068 [EN_A2_FORCE_MONO2] = "A2_FORCE_MONO2",
0069 [EN_A2_FORCE_STEREO] = "A2_FORCE_STEREO",
0070 [EN_A2_AUTO_MONO2] = "A2_AUTO_MONO2",
0071 [EN_A2_AUTO_STEREO] = "A2_AUTO_STEREO",
0072 [EN_EIAJ_FORCE_MONO1] = "EIAJ_FORCE_MONO1",
0073 [EN_EIAJ_FORCE_MONO2] = "EIAJ_FORCE_MONO2",
0074 [EN_EIAJ_FORCE_STEREO] = "EIAJ_FORCE_STEREO",
0075 [EN_EIAJ_AUTO_MONO2] = "EIAJ_AUTO_MONO2",
0076 [EN_EIAJ_AUTO_STEREO] = "EIAJ_AUTO_STEREO",
0077 [EN_NICAM_FORCE_MONO1] = "NICAM_FORCE_MONO1",
0078 [EN_NICAM_FORCE_MONO2] = "NICAM_FORCE_MONO2",
0079 [EN_NICAM_FORCE_STEREO] = "NICAM_FORCE_STEREO",
0080 [EN_NICAM_AUTO_MONO2] = "NICAM_AUTO_MONO2",
0081 [EN_NICAM_AUTO_STEREO] = "NICAM_AUTO_STEREO",
0082 [EN_FMRADIO_FORCE_MONO] = "FMRADIO_FORCE_MONO",
0083 [EN_FMRADIO_FORCE_STEREO] = "FMRADIO_FORCE_STEREO",
0084 [EN_FMRADIO_AUTO_STEREO] = "FMRADIO_AUTO_STEREO",
0085 };
0086
0087 struct rlist {
0088 u32 reg;
0089 u32 val;
0090 };
0091
0092 static void set_audio_registers(struct cx88_core *core, const struct rlist *l)
0093 {
0094 int i;
0095
0096 for (i = 0; l[i].reg; i++) {
0097 switch (l[i].reg) {
0098 case AUD_PDF_DDS_CNST_BYTE2:
0099 case AUD_PDF_DDS_CNST_BYTE1:
0100 case AUD_PDF_DDS_CNST_BYTE0:
0101 case AUD_QAM_MODE:
0102 case AUD_PHACC_FREQ_8MSB:
0103 case AUD_PHACC_FREQ_8LSB:
0104 cx_writeb(l[i].reg, l[i].val);
0105 break;
0106 default:
0107 cx_write(l[i].reg, l[i].val);
0108 break;
0109 }
0110 }
0111 }
0112
0113 static void set_audio_start(struct cx88_core *core, u32 mode)
0114 {
0115
0116 cx_write(AUD_VOL_CTL, (1 << 6));
0117
0118
0119 cx_write(AUD_INIT, mode);
0120 cx_write(AUD_INIT_LD, 0x0001);
0121 cx_write(AUD_SOFT_RESET, 0x0001);
0122 }
0123
0124 static void set_audio_finish(struct cx88_core *core, u32 ctl)
0125 {
0126 u32 volume;
0127
0128
0129 cx88_stop_audio_dma(core);
0130 cx_write(AUD_RATE_THRES_DMD, 0x000000C0);
0131 cx88_start_audio_dma(core);
0132
0133 if (core->board.mpeg & CX88_MPEG_BLACKBIRD) {
0134 cx_write(AUD_I2SINPUTCNTL, 4);
0135 cx_write(AUD_BAUDRATE, 1);
0136
0137
0138
0139
0140 cx_set(AUD_CTL, EN_I2SOUT_ENABLE);
0141 cx_write(AUD_I2SOUTPUTCNTL, 1);
0142 cx_write(AUD_I2SCNTL, 0);
0143
0144 }
0145 if ((always_analog) || (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))) {
0146 ctl |= EN_DAC_ENABLE;
0147 cx_write(AUD_CTL, ctl);
0148 }
0149
0150
0151 cx_write(AUD_SOFT_RESET, 0x0000);
0152
0153
0154 volume = cx_sread(SHADOW_AUD_VOL_CTL);
0155 cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, volume);
0156
0157 core->last_change = jiffies;
0158 }
0159
0160
0161
0162 static void set_audio_standard_BTSC(struct cx88_core *core, unsigned int sap,
0163 u32 mode)
0164 {
0165 static const struct rlist btsc[] = {
0166 {AUD_AFE_12DB_EN, 0x00000001},
0167 {AUD_OUT1_SEL, 0x00000013},
0168 {AUD_OUT1_SHIFT, 0x00000000},
0169 {AUD_POLY0_DDS_CONSTANT, 0x0012010c},
0170 {AUD_DMD_RA_DDS, 0x00c3e7aa},
0171 {AUD_DBX_IN_GAIN, 0x00004734},
0172 {AUD_DBX_WBE_GAIN, 0x00004640},
0173 {AUD_DBX_SE_GAIN, 0x00008d31},
0174 {AUD_DCOC_0_SRC, 0x0000001a},
0175 {AUD_IIR1_4_SEL, 0x00000021},
0176 {AUD_DCOC_PASS_IN, 0x00000003},
0177 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
0178 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
0179 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
0180 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
0181 {AUD_DN0_FREQ, 0x0000283b},
0182 {AUD_DN2_SRC_SEL, 0x00000008},
0183 {AUD_DN2_FREQ, 0x00003000},
0184 {AUD_DN2_AFC, 0x00000002},
0185 {AUD_DN2_SHFT, 0x00000000},
0186 {AUD_IIR2_2_SEL, 0x00000020},
0187 {AUD_IIR2_2_SHIFT, 0x00000000},
0188 {AUD_IIR2_3_SEL, 0x0000001f},
0189 {AUD_IIR2_3_SHIFT, 0x00000000},
0190 {AUD_CRDC1_SRC_SEL, 0x000003ce},
0191 {AUD_CRDC1_SHIFT, 0x00000000},
0192 {AUD_CORDIC_SHIFT_1, 0x00000007},
0193 {AUD_DCOC_1_SRC, 0x0000001b},
0194 {AUD_DCOC1_SHIFT, 0x00000000},
0195 {AUD_RDSI_SEL, 0x00000008},
0196 {AUD_RDSQ_SEL, 0x00000008},
0197 {AUD_RDSI_SHIFT, 0x00000000},
0198 {AUD_RDSQ_SHIFT, 0x00000000},
0199 {AUD_POLYPH80SCALEFAC, 0x00000003},
0200 { },
0201 };
0202 static const struct rlist btsc_sap[] = {
0203 {AUD_AFE_12DB_EN, 0x00000001},
0204 {AUD_DBX_IN_GAIN, 0x00007200},
0205 {AUD_DBX_WBE_GAIN, 0x00006200},
0206 {AUD_DBX_SE_GAIN, 0x00006200},
0207 {AUD_IIR1_1_SEL, 0x00000000},
0208 {AUD_IIR1_3_SEL, 0x00000001},
0209 {AUD_DN1_SRC_SEL, 0x00000007},
0210 {AUD_IIR1_4_SHIFT, 0x00000006},
0211 {AUD_IIR2_1_SHIFT, 0x00000000},
0212 {AUD_IIR2_2_SHIFT, 0x00000000},
0213 {AUD_IIR3_0_SHIFT, 0x00000000},
0214 {AUD_IIR3_1_SHIFT, 0x00000000},
0215 {AUD_IIR3_0_SEL, 0x0000000d},
0216 {AUD_IIR3_1_SEL, 0x0000000e},
0217 {AUD_DEEMPH1_SRC_SEL, 0x00000014},
0218 {AUD_DEEMPH1_SHIFT, 0x00000000},
0219 {AUD_DEEMPH1_G0, 0x00004000},
0220 {AUD_DEEMPH1_A0, 0x00000000},
0221 {AUD_DEEMPH1_B0, 0x00000000},
0222 {AUD_DEEMPH1_A1, 0x00000000},
0223 {AUD_DEEMPH1_B1, 0x00000000},
0224 {AUD_OUT0_SEL, 0x0000003f},
0225 {AUD_OUT1_SEL, 0x0000003f},
0226 {AUD_DN1_AFC, 0x00000002},
0227 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
0228 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
0229 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
0230 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
0231 {AUD_IIR1_0_SEL, 0x0000001d},
0232 {AUD_IIR1_2_SEL, 0x0000001e},
0233 {AUD_IIR2_1_SEL, 0x00000002},
0234 {AUD_IIR2_2_SEL, 0x00000004},
0235 {AUD_IIR3_2_SEL, 0x0000000f},
0236 {AUD_DCOC2_SHIFT, 0x00000001},
0237 {AUD_IIR3_2_SHIFT, 0x00000001},
0238 {AUD_DEEMPH0_SRC_SEL, 0x00000014},
0239 {AUD_CORDIC_SHIFT_1, 0x00000006},
0240 {AUD_POLY0_DDS_CONSTANT, 0x000e4db2},
0241 {AUD_DMD_RA_DDS, 0x00f696e6},
0242 {AUD_IIR2_3_SEL, 0x00000025},
0243 {AUD_IIR1_4_SEL, 0x00000021},
0244 {AUD_DN1_FREQ, 0x0000c965},
0245 {AUD_DCOC_PASS_IN, 0x00000003},
0246 {AUD_DCOC_0_SRC, 0x0000001a},
0247 {AUD_DCOC_1_SRC, 0x0000001b},
0248 {AUD_DCOC1_SHIFT, 0x00000000},
0249 {AUD_RDSI_SEL, 0x00000009},
0250 {AUD_RDSQ_SEL, 0x00000009},
0251 {AUD_RDSI_SHIFT, 0x00000000},
0252 {AUD_RDSQ_SHIFT, 0x00000000},
0253 {AUD_POLYPH80SCALEFAC, 0x00000003},
0254 { },
0255 };
0256
0257 mode |= EN_FMRADIO_EN_RDS;
0258
0259 if (sap) {
0260 dprintk("%s SAP (status: unknown)\n", __func__);
0261 set_audio_start(core, SEL_SAP);
0262 set_audio_registers(core, btsc_sap);
0263 set_audio_finish(core, mode);
0264 } else {
0265 dprintk("%s (status: known-good)\n", __func__);
0266 set_audio_start(core, SEL_BTSC);
0267 set_audio_registers(core, btsc);
0268 set_audio_finish(core, mode);
0269 }
0270 }
0271
0272 static void set_audio_standard_NICAM(struct cx88_core *core, u32 mode)
0273 {
0274 static const struct rlist nicam_l[] = {
0275 {AUD_AFE_12DB_EN, 0x00000001},
0276 {AUD_RATE_ADJ1, 0x00000060},
0277 {AUD_RATE_ADJ2, 0x000000F9},
0278 {AUD_RATE_ADJ3, 0x000001CC},
0279 {AUD_RATE_ADJ4, 0x000002B3},
0280 {AUD_RATE_ADJ5, 0x00000726},
0281 {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
0282 {AUD_DEEMPHDENOM2_R, 0x00000000},
0283 {AUD_ERRLOGPERIOD_R, 0x00000064},
0284 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
0285 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
0286 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
0287 {AUD_POLYPH80SCALEFAC, 0x00000003},
0288 {AUD_DMD_RA_DDS, 0x00C00000},
0289 {AUD_PLL_INT, 0x0000001E},
0290 {AUD_PLL_DDS, 0x00000000},
0291 {AUD_PLL_FRAC, 0x0000E542},
0292 {AUD_START_TIMER, 0x00000000},
0293 {AUD_DEEMPHNUMER1_R, 0x000353DE},
0294 {AUD_DEEMPHNUMER2_R, 0x000001B1},
0295 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
0296 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
0297 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
0298 {AUD_QAM_MODE, 0x05},
0299 {AUD_PHACC_FREQ_8MSB, 0x34},
0300 {AUD_PHACC_FREQ_8LSB, 0x4C},
0301 {AUD_DEEMPHGAIN_R, 0x00006680},
0302 {AUD_RATE_THRES_DMD, 0x000000C0},
0303 { },
0304 };
0305
0306 static const struct rlist nicam_bgdki_common[] = {
0307 {AUD_AFE_12DB_EN, 0x00000001},
0308 {AUD_RATE_ADJ1, 0x00000010},
0309 {AUD_RATE_ADJ2, 0x00000040},
0310 {AUD_RATE_ADJ3, 0x00000100},
0311 {AUD_RATE_ADJ4, 0x00000400},
0312 {AUD_RATE_ADJ5, 0x00001000},
0313 {AUD_ERRLOGPERIOD_R, 0x00000fff},
0314 {AUD_ERRINTRPTTHSHLD1_R, 0x000003ff},
0315 {AUD_ERRINTRPTTHSHLD2_R, 0x000000ff},
0316 {AUD_ERRINTRPTTHSHLD3_R, 0x0000003f},
0317 {AUD_POLYPH80SCALEFAC, 0x00000003},
0318 {AUD_DEEMPHGAIN_R, 0x000023c2},
0319 {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
0320 {AUD_DEEMPHNUMER2_R, 0x0003023e},
0321 {AUD_DEEMPHDENOM1_R, 0x0000f3d0},
0322 {AUD_DEEMPHDENOM2_R, 0x00000000},
0323 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
0324 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
0325 {AUD_QAM_MODE, 0x05},
0326 { },
0327 };
0328
0329 static const struct rlist nicam_i[] = {
0330 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
0331 {AUD_PHACC_FREQ_8MSB, 0x3a},
0332 {AUD_PHACC_FREQ_8LSB, 0x93},
0333 { },
0334 };
0335
0336 static const struct rlist nicam_default[] = {
0337 {AUD_PDF_DDS_CNST_BYTE0, 0x16},
0338 {AUD_PHACC_FREQ_8MSB, 0x34},
0339 {AUD_PHACC_FREQ_8LSB, 0x4c},
0340 { },
0341 };
0342
0343 set_audio_start(core, SEL_NICAM);
0344 switch (core->tvaudio) {
0345 case WW_L:
0346 dprintk("%s SECAM-L NICAM (status: devel)\n", __func__);
0347 set_audio_registers(core, nicam_l);
0348 break;
0349 case WW_I:
0350 dprintk("%s PAL-I NICAM (status: known-good)\n", __func__);
0351 set_audio_registers(core, nicam_bgdki_common);
0352 set_audio_registers(core, nicam_i);
0353 break;
0354 case WW_NONE:
0355 case WW_BTSC:
0356 case WW_BG:
0357 case WW_DK:
0358 case WW_EIAJ:
0359 case WW_I2SPT:
0360 case WW_FM:
0361 case WW_I2SADC:
0362 case WW_M:
0363 dprintk("%s PAL-BGDK NICAM (status: known-good)\n", __func__);
0364 set_audio_registers(core, nicam_bgdki_common);
0365 set_audio_registers(core, nicam_default);
0366 break;
0367 }
0368
0369 mode |= EN_DMTRX_LR | EN_DMTRX_BYPASS;
0370 set_audio_finish(core, mode);
0371 }
0372
0373 static void set_audio_standard_A2(struct cx88_core *core, u32 mode)
0374 {
0375 static const struct rlist a2_bgdk_common[] = {
0376 {AUD_ERRLOGPERIOD_R, 0x00000064},
0377 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
0378 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
0379 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
0380 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
0381 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
0382 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
0383 {AUD_QAM_MODE, 0x05},
0384 {AUD_PHACC_FREQ_8MSB, 0x34},
0385 {AUD_PHACC_FREQ_8LSB, 0x4c},
0386 {AUD_RATE_ADJ1, 0x00000100},
0387 {AUD_RATE_ADJ2, 0x00000200},
0388 {AUD_RATE_ADJ3, 0x00000300},
0389 {AUD_RATE_ADJ4, 0x00000400},
0390 {AUD_RATE_ADJ5, 0x00000500},
0391 {AUD_THR_FR, 0x00000000},
0392 {AAGC_HYST, 0x0000001a},
0393 {AUD_PILOT_BQD_1_K0, 0x0000755b},
0394 {AUD_PILOT_BQD_1_K1, 0x00551340},
0395 {AUD_PILOT_BQD_1_K2, 0x006d30be},
0396 {AUD_PILOT_BQD_1_K3, 0xffd394af},
0397 {AUD_PILOT_BQD_1_K4, 0x00400000},
0398 {AUD_PILOT_BQD_2_K0, 0x00040000},
0399 {AUD_PILOT_BQD_2_K1, 0x002a4841},
0400 {AUD_PILOT_BQD_2_K2, 0x00400000},
0401 {AUD_PILOT_BQD_2_K3, 0x00000000},
0402 {AUD_PILOT_BQD_2_K4, 0x00000000},
0403 {AUD_MODE_CHG_TIMER, 0x00000040},
0404 {AUD_AFE_12DB_EN, 0x00000001},
0405 {AUD_CORDIC_SHIFT_0, 0x00000007},
0406 {AUD_CORDIC_SHIFT_1, 0x00000007},
0407 {AUD_DEEMPH0_G0, 0x00000380},
0408 {AUD_DEEMPH1_G0, 0x00000380},
0409 {AUD_DCOC_0_SRC, 0x0000001a},
0410 {AUD_DCOC0_SHIFT, 0x00000000},
0411 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
0412 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
0413 {AUD_DCOC_PASS_IN, 0x00000003},
0414 {AUD_IIR3_0_SEL, 0x00000021},
0415 {AUD_DN2_AFC, 0x00000002},
0416 {AUD_DCOC_1_SRC, 0x0000001b},
0417 {AUD_DCOC1_SHIFT, 0x00000000},
0418 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
0419 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
0420 {AUD_IIR3_1_SEL, 0x00000023},
0421 {AUD_RDSI_SEL, 0x00000017},
0422 {AUD_RDSI_SHIFT, 0x00000000},
0423 {AUD_RDSQ_SEL, 0x00000017},
0424 {AUD_RDSQ_SHIFT, 0x00000000},
0425 {AUD_PLL_INT, 0x0000001e},
0426 {AUD_PLL_DDS, 0x00000000},
0427 {AUD_PLL_FRAC, 0x0000e542},
0428 {AUD_POLYPH80SCALEFAC, 0x00000001},
0429 {AUD_START_TIMER, 0x00000000},
0430 { },
0431 };
0432
0433 static const struct rlist a2_bg[] = {
0434 {AUD_DMD_RA_DDS, 0x002a4f2f},
0435 {AUD_C1_UP_THR, 0x00007000},
0436 {AUD_C1_LO_THR, 0x00005400},
0437 {AUD_C2_UP_THR, 0x00005400},
0438 {AUD_C2_LO_THR, 0x00003000},
0439 { },
0440 };
0441
0442 static const struct rlist a2_dk[] = {
0443 {AUD_DMD_RA_DDS, 0x002a4f2f},
0444 {AUD_C1_UP_THR, 0x00007000},
0445 {AUD_C1_LO_THR, 0x00005400},
0446 {AUD_C2_UP_THR, 0x00005400},
0447 {AUD_C2_LO_THR, 0x00003000},
0448 {AUD_DN0_FREQ, 0x00003a1c},
0449 {AUD_DN2_FREQ, 0x0000d2e0},
0450 { },
0451 };
0452
0453 static const struct rlist a1_i[] = {
0454 {AUD_ERRLOGPERIOD_R, 0x00000064},
0455 {AUD_ERRINTRPTTHSHLD1_R, 0x00000fff},
0456 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001f},
0457 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000f},
0458 {AUD_PDF_DDS_CNST_BYTE2, 0x06},
0459 {AUD_PDF_DDS_CNST_BYTE1, 0x82},
0460 {AUD_PDF_DDS_CNST_BYTE0, 0x12},
0461 {AUD_QAM_MODE, 0x05},
0462 {AUD_PHACC_FREQ_8MSB, 0x3a},
0463 {AUD_PHACC_FREQ_8LSB, 0x93},
0464 {AUD_DMD_RA_DDS, 0x002a4f2f},
0465 {AUD_PLL_INT, 0x0000001e},
0466 {AUD_PLL_DDS, 0x00000004},
0467 {AUD_PLL_FRAC, 0x0000e542},
0468 {AUD_RATE_ADJ1, 0x00000100},
0469 {AUD_RATE_ADJ2, 0x00000200},
0470 {AUD_RATE_ADJ3, 0x00000300},
0471 {AUD_RATE_ADJ4, 0x00000400},
0472 {AUD_RATE_ADJ5, 0x00000500},
0473 {AUD_THR_FR, 0x00000000},
0474 {AUD_PILOT_BQD_1_K0, 0x0000755b},
0475 {AUD_PILOT_BQD_1_K1, 0x00551340},
0476 {AUD_PILOT_BQD_1_K2, 0x006d30be},
0477 {AUD_PILOT_BQD_1_K3, 0xffd394af},
0478 {AUD_PILOT_BQD_1_K4, 0x00400000},
0479 {AUD_PILOT_BQD_2_K0, 0x00040000},
0480 {AUD_PILOT_BQD_2_K1, 0x002a4841},
0481 {AUD_PILOT_BQD_2_K2, 0x00400000},
0482 {AUD_PILOT_BQD_2_K3, 0x00000000},
0483 {AUD_PILOT_BQD_2_K4, 0x00000000},
0484 {AUD_MODE_CHG_TIMER, 0x00000060},
0485 {AUD_AFE_12DB_EN, 0x00000001},
0486 {AAGC_HYST, 0x0000000a},
0487 {AUD_CORDIC_SHIFT_0, 0x00000007},
0488 {AUD_CORDIC_SHIFT_1, 0x00000007},
0489 {AUD_C1_UP_THR, 0x00007000},
0490 {AUD_C1_LO_THR, 0x00005400},
0491 {AUD_C2_UP_THR, 0x00005400},
0492 {AUD_C2_LO_THR, 0x00003000},
0493 {AUD_DCOC_0_SRC, 0x0000001a},
0494 {AUD_DCOC0_SHIFT, 0x00000000},
0495 {AUD_DCOC_0_SHIFT_IN0, 0x0000000a},
0496 {AUD_DCOC_0_SHIFT_IN1, 0x00000008},
0497 {AUD_DCOC_PASS_IN, 0x00000003},
0498 {AUD_IIR3_0_SEL, 0x00000021},
0499 {AUD_DN2_AFC, 0x00000002},
0500 {AUD_DCOC_1_SRC, 0x0000001b},
0501 {AUD_DCOC1_SHIFT, 0x00000000},
0502 {AUD_DCOC_1_SHIFT_IN0, 0x0000000a},
0503 {AUD_DCOC_1_SHIFT_IN1, 0x00000008},
0504 {AUD_IIR3_1_SEL, 0x00000023},
0505 {AUD_DN0_FREQ, 0x000035a3},
0506 {AUD_DN2_FREQ, 0x000029c7},
0507 {AUD_CRDC0_SRC_SEL, 0x00000511},
0508 {AUD_IIR1_0_SEL, 0x00000001},
0509 {AUD_IIR1_1_SEL, 0x00000000},
0510 {AUD_IIR3_2_SEL, 0x00000003},
0511 {AUD_IIR3_2_SHIFT, 0x00000000},
0512 {AUD_IIR3_0_SEL, 0x00000002},
0513 {AUD_IIR2_0_SEL, 0x00000021},
0514 {AUD_IIR2_0_SHIFT, 0x00000002},
0515 {AUD_DEEMPH0_SRC_SEL, 0x0000000b},
0516 {AUD_DEEMPH1_SRC_SEL, 0x0000000b},
0517 {AUD_POLYPH80SCALEFAC, 0x00000001},
0518 {AUD_START_TIMER, 0x00000000},
0519 { },
0520 };
0521
0522 static const struct rlist am_l[] = {
0523 {AUD_ERRLOGPERIOD_R, 0x00000064},
0524 {AUD_ERRINTRPTTHSHLD1_R, 0x00000FFF},
0525 {AUD_ERRINTRPTTHSHLD2_R, 0x0000001F},
0526 {AUD_ERRINTRPTTHSHLD3_R, 0x0000000F},
0527 {AUD_PDF_DDS_CNST_BYTE2, 0x48},
0528 {AUD_PDF_DDS_CNST_BYTE1, 0x3D},
0529 {AUD_QAM_MODE, 0x00},
0530 {AUD_PDF_DDS_CNST_BYTE0, 0xf5},
0531 {AUD_PHACC_FREQ_8MSB, 0x3a},
0532 {AUD_PHACC_FREQ_8LSB, 0x4a},
0533 {AUD_DEEMPHGAIN_R, 0x00006680},
0534 {AUD_DEEMPHNUMER1_R, 0x000353DE},
0535 {AUD_DEEMPHNUMER2_R, 0x000001B1},
0536 {AUD_DEEMPHDENOM1_R, 0x0000F3D0},
0537 {AUD_DEEMPHDENOM2_R, 0x00000000},
0538 {AUD_FM_MODE_ENABLE, 0x00000007},
0539 {AUD_POLYPH80SCALEFAC, 0x00000003},
0540 {AUD_AFE_12DB_EN, 0x00000001},
0541 {AAGC_GAIN, 0x00000000},
0542 {AAGC_HYST, 0x00000018},
0543 {AAGC_DEF, 0x00000020},
0544 {AUD_DN0_FREQ, 0x00000000},
0545 {AUD_POLY0_DDS_CONSTANT, 0x000E4DB2},
0546 {AUD_DCOC_0_SRC, 0x00000021},
0547 {AUD_IIR1_0_SEL, 0x00000000},
0548 {AUD_IIR1_0_SHIFT, 0x00000007},
0549 {AUD_IIR1_1_SEL, 0x00000002},
0550 {AUD_IIR1_1_SHIFT, 0x00000000},
0551 {AUD_DCOC_1_SRC, 0x00000003},
0552 {AUD_DCOC1_SHIFT, 0x00000000},
0553 {AUD_DCOC_PASS_IN, 0x00000000},
0554 {AUD_IIR1_2_SEL, 0x00000023},
0555 {AUD_IIR1_2_SHIFT, 0x00000000},
0556 {AUD_IIR1_3_SEL, 0x00000004},
0557 {AUD_IIR1_3_SHIFT, 0x00000007},
0558 {AUD_IIR1_4_SEL, 0x00000005},
0559 {AUD_IIR1_4_SHIFT, 0x00000007},
0560 {AUD_IIR3_0_SEL, 0x00000007},
0561 {AUD_IIR3_0_SHIFT, 0x00000000},
0562 {AUD_DEEMPH0_SRC_SEL, 0x00000011},
0563 {AUD_DEEMPH0_SHIFT, 0x00000000},
0564 {AUD_DEEMPH0_G0, 0x00007000},
0565 {AUD_DEEMPH0_A0, 0x00000000},
0566 {AUD_DEEMPH0_B0, 0x00000000},
0567 {AUD_DEEMPH0_A1, 0x00000000},
0568 {AUD_DEEMPH0_B1, 0x00000000},
0569 {AUD_DEEMPH1_SRC_SEL, 0x00000011},
0570 {AUD_DEEMPH1_SHIFT, 0x00000000},
0571 {AUD_DEEMPH1_G0, 0x00007000},
0572 {AUD_DEEMPH1_A0, 0x00000000},
0573 {AUD_DEEMPH1_B0, 0x00000000},
0574 {AUD_DEEMPH1_A1, 0x00000000},
0575 {AUD_DEEMPH1_B1, 0x00000000},
0576 {AUD_OUT0_SEL, 0x0000003F},
0577 {AUD_OUT1_SEL, 0x0000003F},
0578 {AUD_DMD_RA_DDS, 0x00F5C285},
0579 {AUD_PLL_INT, 0x0000001E},
0580 {AUD_PLL_DDS, 0x00000000},
0581 {AUD_PLL_FRAC, 0x0000E542},
0582 {AUD_RATE_ADJ1, 0x00000100},
0583 {AUD_RATE_ADJ2, 0x00000200},
0584 {AUD_RATE_ADJ3, 0x00000300},
0585 {AUD_RATE_ADJ4, 0x00000400},
0586 {AUD_RATE_ADJ5, 0x00000500},
0587 {AUD_RATE_THRES_DMD, 0x000000C0},
0588 { },
0589 };
0590
0591 static const struct rlist a2_deemph50[] = {
0592 {AUD_DEEMPH0_G0, 0x00000380},
0593 {AUD_DEEMPH1_G0, 0x00000380},
0594 {AUD_DEEMPHGAIN_R, 0x000011e1},
0595 {AUD_DEEMPHNUMER1_R, 0x0002a7bc},
0596 {AUD_DEEMPHNUMER2_R, 0x0003023c},
0597 { },
0598 };
0599
0600 set_audio_start(core, SEL_A2);
0601 switch (core->tvaudio) {
0602 case WW_BG:
0603 dprintk("%s PAL-BG A1/2 (status: known-good)\n", __func__);
0604 set_audio_registers(core, a2_bgdk_common);
0605 set_audio_registers(core, a2_bg);
0606 set_audio_registers(core, a2_deemph50);
0607 break;
0608 case WW_DK:
0609 dprintk("%s PAL-DK A1/2 (status: known-good)\n", __func__);
0610 set_audio_registers(core, a2_bgdk_common);
0611 set_audio_registers(core, a2_dk);
0612 set_audio_registers(core, a2_deemph50);
0613 break;
0614 case WW_I:
0615 dprintk("%s PAL-I A1 (status: known-good)\n", __func__);
0616 set_audio_registers(core, a1_i);
0617 set_audio_registers(core, a2_deemph50);
0618 break;
0619 case WW_L:
0620 dprintk("%s AM-L (status: devel)\n", __func__);
0621 set_audio_registers(core, am_l);
0622 break;
0623 case WW_NONE:
0624 case WW_BTSC:
0625 case WW_EIAJ:
0626 case WW_I2SPT:
0627 case WW_FM:
0628 case WW_I2SADC:
0629 case WW_M:
0630 dprintk("%s Warning: wrong value\n", __func__);
0631 return;
0632 }
0633
0634 mode |= EN_FMRADIO_EN_RDS | EN_DMTRX_SUMDIFF;
0635 set_audio_finish(core, mode);
0636 }
0637
0638 static void set_audio_standard_EIAJ(struct cx88_core *core)
0639 {
0640 static const struct rlist eiaj[] = {
0641
0642
0643 { },
0644 };
0645 dprintk("%s (status: unknown)\n", __func__);
0646
0647 set_audio_start(core, SEL_EIAJ);
0648 set_audio_registers(core, eiaj);
0649 set_audio_finish(core, EN_EIAJ_AUTO_STEREO);
0650 }
0651
0652 static void set_audio_standard_FM(struct cx88_core *core,
0653 enum cx88_deemph_type deemph)
0654 {
0655 static const struct rlist fm_deemph_50[] = {
0656 {AUD_DEEMPH0_G0, 0x0C45},
0657 {AUD_DEEMPH0_A0, 0x6262},
0658 {AUD_DEEMPH0_B0, 0x1C29},
0659 {AUD_DEEMPH0_A1, 0x3FC66},
0660 {AUD_DEEMPH0_B1, 0x399A},
0661
0662 {AUD_DEEMPH1_G0, 0x0D80},
0663 {AUD_DEEMPH1_A0, 0x6262},
0664 {AUD_DEEMPH1_B0, 0x1C29},
0665 {AUD_DEEMPH1_A1, 0x3FC66},
0666 {AUD_DEEMPH1_B1, 0x399A},
0667
0668 {AUD_POLYPH80SCALEFAC, 0x0003},
0669 { },
0670 };
0671 static const struct rlist fm_deemph_75[] = {
0672 {AUD_DEEMPH0_G0, 0x091B},
0673 {AUD_DEEMPH0_A0, 0x6B68},
0674 {AUD_DEEMPH0_B0, 0x11EC},
0675 {AUD_DEEMPH0_A1, 0x3FC66},
0676 {AUD_DEEMPH0_B1, 0x399A},
0677
0678 {AUD_DEEMPH1_G0, 0x0AA0},
0679 {AUD_DEEMPH1_A0, 0x6B68},
0680 {AUD_DEEMPH1_B0, 0x11EC},
0681 {AUD_DEEMPH1_A1, 0x3FC66},
0682 {AUD_DEEMPH1_B1, 0x399A},
0683
0684 {AUD_POLYPH80SCALEFAC, 0x0003},
0685 { },
0686 };
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696 static const struct rlist fm_no_deemph[] = {
0697 {AUD_POLYPH80SCALEFAC, 0x0003},
0698 { },
0699 };
0700
0701 dprintk("%s (status: unknown)\n", __func__);
0702 set_audio_start(core, SEL_FMRADIO);
0703
0704 switch (deemph) {
0705 default:
0706 case FM_NO_DEEMPH:
0707 set_audio_registers(core, fm_no_deemph);
0708 break;
0709
0710 case FM_DEEMPH_50:
0711 set_audio_registers(core, fm_deemph_50);
0712 break;
0713
0714 case FM_DEEMPH_75:
0715 set_audio_registers(core, fm_deemph_75);
0716 break;
0717 }
0718
0719 set_audio_finish(core, EN_FMRADIO_AUTO_STEREO);
0720 }
0721
0722
0723
0724 static int cx88_detect_nicam(struct cx88_core *core)
0725 {
0726 int i, j = 0;
0727
0728 dprintk("start nicam autodetect.\n");
0729
0730 for (i = 0; i < 6; i++) {
0731
0732 j += ((cx_read(AUD_NICAM_STATUS2) & 0x02) >> 1);
0733
0734 if (j == 1) {
0735 dprintk("nicam is detected.\n");
0736 return 1;
0737 }
0738
0739
0740 usleep_range(10000, 20000);
0741 }
0742
0743 dprintk("nicam is not detected.\n");
0744 return 0;
0745 }
0746
0747 void cx88_set_tvaudio(struct cx88_core *core)
0748 {
0749 switch (core->tvaudio) {
0750 case WW_BTSC:
0751 set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
0752 break;
0753 case WW_BG:
0754 case WW_DK:
0755 case WW_M:
0756 case WW_I:
0757 case WW_L:
0758
0759 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
0760
0761
0762
0763
0764
0765 set_audio_standard_NICAM(core, EN_NICAM_AUTO_STEREO);
0766 if (cx88_detect_nicam(core) == 0) {
0767
0768 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
0769 core->audiomode_current = V4L2_TUNER_MODE_MONO;
0770 core->use_nicam = 0;
0771 } else {
0772 core->use_nicam = 1;
0773 }
0774 break;
0775 case WW_EIAJ:
0776 set_audio_standard_EIAJ(core);
0777 break;
0778 case WW_FM:
0779 set_audio_standard_FM(core, radio_deemphasis);
0780 break;
0781 case WW_I2SADC:
0782 set_audio_start(core, 0x01);
0783
0784
0785
0786
0787
0788 cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
0789
0790 cx_write(AUD_I2SCNTL, 0x1);
0791 set_audio_finish(core, EN_I2SIN_ENABLE);
0792 break;
0793 case WW_NONE:
0794 case WW_I2SPT:
0795 pr_info("unknown tv audio mode [%d]\n", core->tvaudio);
0796 break;
0797 }
0798 }
0799 EXPORT_SYMBOL(cx88_set_tvaudio);
0800
0801 void cx88_newstation(struct cx88_core *core)
0802 {
0803 core->audiomode_manual = UNSET;
0804 core->last_change = jiffies;
0805 }
0806 EXPORT_SYMBOL(cx88_newstation);
0807
0808 void cx88_get_stereo(struct cx88_core *core, struct v4l2_tuner *t)
0809 {
0810 static const char * const m[] = { "stereo", "dual mono",
0811 "mono", "sap" };
0812 static const char * const p[] = { "no pilot", "pilot c1",
0813 "pilot c2", "?" };
0814 u32 reg, mode, pilot;
0815
0816 reg = cx_read(AUD_STATUS);
0817 mode = reg & 0x03;
0818 pilot = (reg >> 2) & 0x03;
0819
0820 if (core->astat != reg)
0821 dprintk("AUD_STATUS: 0x%x [%s/%s] ctl=%s\n",
0822 reg, m[mode], p[pilot],
0823 aud_ctl_names[cx_read(AUD_CTL) & 63]);
0824 core->astat = reg;
0825
0826 t->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_SAP |
0827 V4L2_TUNER_CAP_LANG1 | V4L2_TUNER_CAP_LANG2;
0828 t->rxsubchans = UNSET;
0829 t->audmode = V4L2_TUNER_MODE_MONO;
0830
0831 switch (mode) {
0832 case 0:
0833 t->audmode = V4L2_TUNER_MODE_STEREO;
0834 break;
0835 case 1:
0836 t->audmode = V4L2_TUNER_MODE_LANG2;
0837 break;
0838 case 2:
0839 t->audmode = V4L2_TUNER_MODE_MONO;
0840 break;
0841 case 3:
0842 t->audmode = V4L2_TUNER_MODE_SAP;
0843 break;
0844 }
0845
0846 switch (core->tvaudio) {
0847 case WW_BTSC:
0848 case WW_BG:
0849 case WW_DK:
0850 case WW_M:
0851 case WW_EIAJ:
0852 if (!core->use_nicam) {
0853 t->rxsubchans = cx88_dsp_detect_stereo_sap(core);
0854 break;
0855 }
0856 break;
0857 case WW_NONE:
0858 case WW_I:
0859 case WW_L:
0860 case WW_I2SPT:
0861 case WW_FM:
0862 case WW_I2SADC:
0863
0864 break;
0865 }
0866
0867
0868 if (t->rxsubchans == UNSET) {
0869 t->rxsubchans = V4L2_TUNER_SUB_MONO;
0870
0871
0872
0873
0874 if (t->audmode == V4L2_TUNER_MODE_STEREO)
0875 t->rxsubchans |= V4L2_TUNER_SUB_STEREO;
0876 }
0877 }
0878 EXPORT_SYMBOL(cx88_get_stereo);
0879
0880
0881 void cx88_set_stereo(struct cx88_core *core, u32 mode, int manual)
0882 {
0883 u32 ctl = UNSET;
0884 u32 mask = UNSET;
0885
0886 if (manual) {
0887 core->audiomode_manual = mode;
0888 } else {
0889 if (core->audiomode_manual != UNSET)
0890 return;
0891 }
0892 core->audiomode_current = mode;
0893
0894 switch (core->tvaudio) {
0895 case WW_BTSC:
0896 switch (mode) {
0897 case V4L2_TUNER_MODE_MONO:
0898 set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_MONO);
0899 break;
0900 case V4L2_TUNER_MODE_LANG1:
0901 set_audio_standard_BTSC(core, 0, EN_BTSC_AUTO_STEREO);
0902 break;
0903 case V4L2_TUNER_MODE_LANG2:
0904 set_audio_standard_BTSC(core, 1, EN_BTSC_FORCE_SAP);
0905 break;
0906 case V4L2_TUNER_MODE_STEREO:
0907 case V4L2_TUNER_MODE_LANG1_LANG2:
0908 set_audio_standard_BTSC(core, 0, EN_BTSC_FORCE_STEREO);
0909 break;
0910 }
0911 break;
0912 case WW_BG:
0913 case WW_DK:
0914 case WW_M:
0915 case WW_I:
0916 case WW_L:
0917 if (core->use_nicam == 1) {
0918 switch (mode) {
0919 case V4L2_TUNER_MODE_MONO:
0920 case V4L2_TUNER_MODE_LANG1:
0921 set_audio_standard_NICAM(core,
0922 EN_NICAM_FORCE_MONO1);
0923 break;
0924 case V4L2_TUNER_MODE_LANG2:
0925 set_audio_standard_NICAM(core,
0926 EN_NICAM_FORCE_MONO2);
0927 break;
0928 case V4L2_TUNER_MODE_STEREO:
0929 case V4L2_TUNER_MODE_LANG1_LANG2:
0930 set_audio_standard_NICAM(core,
0931 EN_NICAM_FORCE_STEREO);
0932 break;
0933 }
0934 } else {
0935 if ((core->tvaudio == WW_I) ||
0936 (core->tvaudio == WW_L)) {
0937
0938 set_audio_standard_A2(core, EN_A2_FORCE_MONO1);
0939 } else {
0940
0941 mask = 0x3f;
0942 switch (mode) {
0943 case V4L2_TUNER_MODE_MONO:
0944 case V4L2_TUNER_MODE_LANG1:
0945 ctl = EN_A2_FORCE_MONO1;
0946 break;
0947 case V4L2_TUNER_MODE_LANG2:
0948 ctl = EN_A2_FORCE_MONO2;
0949 break;
0950 case V4L2_TUNER_MODE_STEREO:
0951 case V4L2_TUNER_MODE_LANG1_LANG2:
0952 ctl = EN_A2_FORCE_STEREO;
0953 break;
0954 }
0955 }
0956 }
0957 break;
0958 case WW_FM:
0959 switch (mode) {
0960 case V4L2_TUNER_MODE_MONO:
0961 ctl = EN_FMRADIO_FORCE_MONO;
0962 mask = 0x3f;
0963 break;
0964 case V4L2_TUNER_MODE_STEREO:
0965 ctl = EN_FMRADIO_AUTO_STEREO;
0966 mask = 0x3f;
0967 break;
0968 }
0969 break;
0970 case WW_I2SADC:
0971 case WW_NONE:
0972 case WW_EIAJ:
0973 case WW_I2SPT:
0974
0975 break;
0976 }
0977
0978 if (ctl != UNSET) {
0979 dprintk("cx88_set_stereo: mask 0x%x, ctl 0x%x [status=0x%x,ctl=0x%x,vol=0x%x]\n",
0980 mask, ctl, cx_read(AUD_STATUS),
0981 cx_read(AUD_CTL), cx_sread(SHADOW_AUD_VOL_CTL));
0982 cx_andor(AUD_CTL, mask, ctl);
0983 }
0984 }
0985 EXPORT_SYMBOL(cx88_set_stereo);
0986
0987 int cx88_audio_thread(void *data)
0988 {
0989 struct cx88_core *core = data;
0990 struct v4l2_tuner t;
0991 u32 mode = 0;
0992
0993 dprintk("cx88: tvaudio thread started\n");
0994 set_freezable();
0995 for (;;) {
0996 msleep_interruptible(1000);
0997 if (kthread_should_stop())
0998 break;
0999 try_to_freeze();
1000
1001 switch (core->tvaudio) {
1002 case WW_BG:
1003 case WW_DK:
1004 case WW_M:
1005 case WW_I:
1006 case WW_L:
1007 if (core->use_nicam)
1008 goto hw_autodetect;
1009
1010
1011 memset(&t, 0, sizeof(t));
1012 cx88_get_stereo(core, &t);
1013
1014 if (core->audiomode_manual != UNSET)
1015
1016 continue;
1017
1018
1019 if (t.rxsubchans & V4L2_TUNER_SUB_STEREO)
1020 mode = V4L2_TUNER_MODE_STEREO;
1021 else
1022 mode = V4L2_TUNER_MODE_MONO;
1023 if (mode == core->audiomode_current)
1024 continue;
1025
1026 cx88_set_stereo(core, mode, 0);
1027 break;
1028 case WW_NONE:
1029 case WW_BTSC:
1030 case WW_EIAJ:
1031 case WW_I2SPT:
1032 case WW_FM:
1033 case WW_I2SADC:
1034 hw_autodetect:
1035
1036
1037
1038
1039 break;
1040 }
1041 }
1042
1043 dprintk("cx88: tvaudio thread exiting\n");
1044 return 0;
1045 }
1046 EXPORT_SYMBOL(cx88_audio_thread);