📄 tvaudio.c
字号:
static int tda9874a_NCONR = 0x01; /* default NICAM config.: AMSEL=0,AMUTE=1 */static int tda9874a_ESP = 0x07; /* default standard: NICAM D/K */static int tda9874a_dic = -1; /* device id. code *//* insmod options for tda9874a */static int tda9874a_SIF = -1;static int tda9874a_AMSEL = -1;static int tda9874a_STD = -1;MODULE_PARM(tda9874a_SIF,"i");MODULE_PARM(tda9874a_AMSEL,"i");MODULE_PARM(tda9874a_STD,"i");/* * initialization table for tda9874 decoder: * - carrier 1 freq. registers (3 bytes) * - carrier 2 freq. registers (3 bytes) * - demudulator config register * - FM de-emphasis register (slow identification mode) * Note: frequency registers must be written in single i2c transfer. */static struct tda9874a_MODES { char *name; audiocmd cmd;} tda9874a_modelist[9] = { { "A2, B/G", { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x77,0xA0,0x00, 0x00,0x00 }} }, { "A2, M (Korea)", { 9, { TDA9874A_C1FRA, 0x5D,0xC0,0x00, 0x62,0x6A,0xAA, 0x20,0x22 }} }, { "A2, D/K (1)", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x82,0x60,0x00, 0x00,0x00 }} }, { "A2, D/K (2)", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x8C,0x75,0x55, 0x00,0x00 }} }, { "A2, D/K (3)", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x77,0xA0,0x00, 0x00,0x00 }} }, { "NICAM, I", { 9, { TDA9874A_C1FRA, 0x7D,0x00,0x00, 0x88,0x8A,0xAA, 0x08,0x33 }} }, { "NICAM, B/G", { 9, { TDA9874A_C1FRA, 0x72,0x95,0x55, 0x79,0xEA,0xAA, 0x08,0x33 }} }, { "NICAM, D/K", /* default */ { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x08,0x33 }} }, { "NICAM, L", { 9, { TDA9874A_C1FRA, 0x87,0x6A,0xAA, 0x79,0xEA,0xAA, 0x09,0x33 }} }};static int tda9874a_setup(struct CHIPSTATE *chip){ chip_write(chip, TDA9874A_AGCGR, 0x00); /* 0 dB */ chip_write(chip, TDA9874A_GCONR, tda9874a_GCONR); chip_write(chip, TDA9874A_MSR, (tda9874a_mode) ? 0x03:0x02); if(tda9874a_dic == 0x11) { chip_write(chip, TDA9874A_FMMR, 0x80); } else { /* dic == 0x07 */ chip_cmd(chip,"tda9874_modelist",&tda9874a_modelist[tda9874a_STD].cmd); chip_write(chip, TDA9874A_FMMR, 0x00); } chip_write(chip, TDA9874A_C1OLAR, 0x00); /* 0 dB */ chip_write(chip, TDA9874A_C2OLAR, 0x00); /* 0 dB */ chip_write(chip, TDA9874A_NCONR, tda9874a_NCONR); chip_write(chip, TDA9874A_NOLAR, 0x00); /* 0 dB */ /* Note: If signal quality is poor you may want to change NICAM */ /* error limit registers (NLELR and NUELR) to some greater values. */ /* Then the sound would remain stereo, but won't be so clear. */ chip_write(chip, TDA9874A_NLELR, 0x14); /* default */ chip_write(chip, TDA9874A_NUELR, 0x50); /* default */ if(tda9874a_dic == 0x11) { chip_write(chip, TDA9874A_AMCONR, 0xf9); chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80); chip_write(chip, TDA9874A_AOSR, 0x80); chip_write(chip, TDA9874A_MDACOSR, (tda9874a_mode) ? 0x82:0x80); chip_write(chip, TDA9874A_ESP, tda9874a_ESP); } else { /* dic == 0x07 */ chip_write(chip, TDA9874A_AMCONR, 0xfb); chip_write(chip, TDA9874A_SDACOSR, (tda9874a_mode) ? 0x81:0x80); chip_write(chip, TDA9874A_AOSR, 0x00); // or 0x10 } dprintk("tda9874a_setup(): %s [0x%02X].\n", tda9874a_modelist[tda9874a_STD].name,tda9874a_STD); return 1;}static int tda9874a_getmode(struct CHIPSTATE *chip){ int dsr,nsr,mode; int necr; /* just for debugging */ mode = VIDEO_SOUND_MONO; if(-1 == (dsr = chip_read2(chip,TDA9874A_DSR))) return mode; if(-1 == (nsr = chip_read2(chip,TDA9874A_NSR))) return mode; if(-1 == (necr = chip_read2(chip,TDA9874A_NECR))) return mode; /* need to store dsr/nsr somewhere */ chip->shadow.bytes[MAXREGS-2] = dsr; chip->shadow.bytes[MAXREGS-1] = nsr; if(tda9874a_mode) { /* Note: DSR.RSSF and DSR.AMSTAT bits are also checked. * If NICAM auto-muting is enabled, DSR.AMSTAT=1 indicates * that sound has (temporarily) switched from NICAM to * mono FM (or AM) on 1st sound carrier due to high NICAM bit * error count. So in fact there is no stereo in this case :-( * But changing the mode to VIDEO_SOUND_MONO would switch * external 4052 multiplexer in audio_hook(). */#if 0 if((nsr & 0x02) && !(dsr & 0x10)) /* NSR.S/MB=1 and DSR.AMSTAT=0 */ mode |= VIDEO_SOUND_STEREO;#else if(nsr & 0x02) /* NSR.S/MB=1 */ mode |= VIDEO_SOUND_STEREO;#endif if(nsr & 0x01) /* NSR.D/SB=1 */ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; } else { if(dsr & 0x02) /* DSR.IDSTE=1 */ mode |= VIDEO_SOUND_STEREO; if(dsr & 0x04) /* DSR.IDDUA=1 */ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; } dprintk("tda9874a_getmode(): DSR=0x%X, NSR=0x%X, NECR=0x%X, return: %d.\n", dsr, nsr, necr, mode); return mode;}static void tda9874a_setmode(struct CHIPSTATE *chip, int mode){ /* Disable/enable NICAM auto-muting (based on DSR.RSSF status bit). */ /* If auto-muting is disabled, we can hear a signal of degrading quality. */ if(tda9874a_mode) { if(chip->shadow.bytes[MAXREGS-2] & 0x20) /* DSR.RSSF=1 */ tda9874a_NCONR &= 0xfe; /* enable */ else tda9874a_NCONR |= 0x01; /* disable */ chip_write(chip, TDA9874A_NCONR, tda9874a_NCONR); } /* Note: TDA9874A supports automatic FM dematrixing (FMMR register) * and has auto-select function for audio output (AOSR register). * Old TDA9874H doesn't support these features. * TDA9874A also has additional mono output pin (OUTM), which * on same (all?) tv-cards is not used, anyway (as well as MONOIN). */ if(tda9874a_dic == 0x11) { int aosr = 0x80; int mdacosr = (tda9874a_mode) ? 0x82:0x80; switch(mode) { case VIDEO_SOUND_MONO: case VIDEO_SOUND_STEREO: break; case VIDEO_SOUND_LANG1: aosr = 0x80; /* auto-select, dual A/A */ mdacosr = (tda9874a_mode) ? 0x82:0x80; break; case VIDEO_SOUND_LANG2: aosr = 0xa0; /* auto-select, dual B/B */ mdacosr = (tda9874a_mode) ? 0x83:0x81; break; default: chip->mode = 0; return; } chip_write(chip, TDA9874A_AOSR, aosr); chip_write(chip, TDA9874A_MDACOSR, mdacosr); dprintk("tda9874a_setmode(): req. mode %d; AOSR=0x%X, MDACOSR=0x%X.\n", mode, aosr, mdacosr); } else { /* dic == 0x07 */ int fmmr,aosr; switch(mode) { case VIDEO_SOUND_MONO: fmmr = 0x00; /* mono */ aosr = 0x10; /* A/A */ break; case VIDEO_SOUND_STEREO: if(tda9874a_mode) { fmmr = 0x00; aosr = 0x00; /* handled by NICAM auto-mute */ } else { fmmr = (tda9874a_ESP == 1) ? 0x05 : 0x04; /* stereo */ aosr = 0x00; } break; case VIDEO_SOUND_LANG1: fmmr = 0x02; /* dual */ aosr = 0x10; /* dual A/A */ break; case VIDEO_SOUND_LANG2: fmmr = 0x02; /* dual */ aosr = 0x20; /* dual B/B */ break; default: chip->mode = 0; return; } chip_write(chip, TDA9874A_FMMR, fmmr); chip_write(chip, TDA9874A_AOSR, aosr); dprintk("tda9874a_setmode(): req. mode %d; FMMR=0x%X, AOSR=0x%X.\n", mode, fmmr, aosr); }}static int tda9874a_checkit(struct CHIPSTATE *chip){ int dic,sic; /* device id. and software id. codes */ if(-1 == (dic = chip_read2(chip,TDA9874A_DIC))) return 0; if(-1 == (sic = chip_read2(chip,TDA9874A_SIC))) return 0; dprintk("tda9874a_checkit(): DIC=0x%X, SIC=0x%X.\n", dic, sic); if((dic == 0x11)||(dic == 0x07)) { dprintk("tvaudio: found tda9874%s.\n",(dic == 0x11) ? "a (new)":"h (old)"); tda9874a_dic = dic; /* remember device id. */ return 1; } return 0; /* not found */}static int tda9874a_initialize(struct CHIPSTATE *chip){ if(tda9874a_SIF != -1) { if(tda9874a_SIF == 1) tda9874a_GCONR = 0xc0; /* sound IF input 1 */ else if(tda9874a_SIF == 2) tda9874a_GCONR = 0xc1; /* sound IF input 2 */ else printk(KERN_WARNING "tda9874a: SIF parameter must be 1 or 2.\n"); } if(tda9874a_STD != -1) { if((tda9874a_STD >= 0)&&(tda9874a_STD <= 8)) { tda9874a_ESP = tda9874a_STD; tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1; } else { printk(KERN_WARNING "tda9874a: STD parameter must be between 0 and 8.\n"); } } if(tda9874a_AMSEL != -1) { if(tda9874a_AMSEL == 0) tda9874a_NCONR = 0x01; /* auto-mute: analog mono input */ else if(tda9874a_AMSEL == 1) tda9874a_NCONR = 0x05; /* auto-mute: 1st carrier FM or AM */ else printk(KERN_WARNING "tda9874a: AMSEL parameter must be 0 or 1.\n"); } tda9874a_setup(chip); return 0;}/* ---------------------------------------------------------------------- *//* audio chip descriptions - defines+functions for tea6420 */#define TEA6300_VL 0x00 /* volume left */#define TEA6300_VR 0x01 /* volume right */#define TEA6300_BA 0x02 /* bass */#define TEA6300_TR 0x03 /* treble */#define TEA6300_FA 0x04 /* fader control */#define TEA6300_S 0x05 /* switch register */ /* values for those registers: */#define TEA6300_S_SA 0x01 /* stereo A input */#define TEA6300_S_SB 0x02 /* stereo B */#define TEA6300_S_SC 0x04 /* stereo C */#define TEA6300_S_GMU 0x80 /* general mute */#define TEA6420_S_SA 0x00 /* stereo A input */#define TEA6420_S_SB 0x01 /* stereo B */#define TEA6420_S_SC 0x02 /* stereo C */#define TEA6420_S_SD 0x03 /* stereo D */#define TEA6420_S_SE 0x04 /* stereo E */#define TEA6420_S_GMU 0x05 /* general mute */static int tea6300_shift10(int val) { return val >> 10; }static int tea6300_shift12(int val) { return val >> 12; }/* ---------------------------------------------------------------------- *//* audio chip descriptions - defines+functions for tda8425 */#define TDA8425_VL 0x00 /* volume left */#define TDA8425_VR 0x01 /* volume right */#define TDA8425_BA 0x02 /* bass */#define TDA8425_TR 0x03 /* treble */#define TDA8425_S1 0x08 /* switch functions */ /* values for those registers: */#define TDA8425_S1_OFF 0xEE /* audio off (mute on) */#define TDA8425_S1_ON 0xCE /* audio on (mute off) - "linear stereo" mode */static int tda8425_shift10(int val) { return val >> 10 | 0xc0; }static int tda8425_shift12(int val) { return val >> 12 | 0xf0; }/* ---------------------------------------------------------------------- *//* audio chip descriptions - defines+functions for pic16c54 (PV951) *//* the registers of 16C54, I2C sub address. */#define PIC16C54_REG_KEY_CODE 0x01 /* Not use. */#define PIC16C54_REG_MISC 0x02/* bit definition of the RESET register, I2C data. */#define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ /* code of remote controller */#define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */#define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */#define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */#define PIC16C54_MISC_SND_MUTE 0x10 /* bit 4, Mute Audio(Line-in and Tuner) */#define PIC16C54_MISC_SND_NOTMUTE 0x20 /* bit 5 */#define PIC16C54_MISC_SWITCH_TUNER 0x40 /* bit 6 , Switch to Line-in */#define PIC16C54_MISC_SWITCH_LINE 0x80 /* bit 7 , Switch to Tuner *//* ---------------------------------------------------------------------- *//* audio chip descriptions - struct CHIPDESC *//* insmod options to enable/disable individual audio chips */int tda8425 = 1;int tda9840 = 1;int tda9850 = 1;int tda9855 = 1;int tda9873 = 1;int tda9874a = 1;int tea6300 = 0;int tea6420 = 1;int pic16c54 = 1;MODULE_PARM(tda8425,"i");MODULE_PARM(tda9840,"i");MODULE_PARM(tda9850,"i");MODULE_PARM(tda9855,"i");MODULE_PARM(tda9873,"i");MODULE_PARM(tda9874a,"i");MODULE_PARM(tea6300,"i");MODULE_PARM(tea6420,"i");MODULE_PARM(pic16c54,"i");static struct CHIPDESC chiplist[] = { { name: "tda9840", id: I2C_DRIVERID_TDA9840, insmodopt: &tda9840, addr_lo: I2C_TDA9840 >> 1, addr_hi: I2C_TDA9840 >> 1, registers: 5, getmode: tda9840_getmode, setmode: tda9840_setmode, checkmode: generic_checkmode, init: { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN /* ,TDA9840_SW, TDA9840_MONO */} } }, { name: "tda9873h", id: I2C_DRIVERID_TDA9873, checkit: tda9873_checkit, insmodopt: &tda9873, addr_lo: I2C_TDA985x_L >> 1, addr_hi: I2C_TDA985x_H >> 1, registers: 3, flags: CHIP_HAS_INPUTSEL, getmode: tda9873_getmode, setmode: tda9873_setmode, checkmode: generic_checkmode, init: { 4, { TDA9873_SW, 0xa4, 0x06, 0x03 } }, inputreg: TDA9873_SW, inputmute: TDA9873_MUTE | TDA9873_AUTOMUTE, inputmap: {0xa0, 0xa2, 0xa0, 0xa0, 0xc0}, inputmask: TDA9873_INP_MASK | TDA9873_MUTE | TDA9873_AUTOMUTE }, {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -