📄 tvaudio.c
字号:
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)) { printk("tvaudio: found tda9874%s.\n", (dic == 0x11) ? "a":"h"); tda9874a_dic = dic; /* remember device id. */ return 1; } return 0; /* not found */}static int tda9874a_initialize(struct CHIPSTATE *chip){ if (tda9874a_SIF > 2) tda9874a_SIF = 1; if (tda9874a_STD >= 8) tda9874a_STD = 0; if(tda9874a_AMSEL > 1) tda9874a_AMSEL = 0; if(tda9874a_SIF == 1) tda9874a_GCONR = 0xc0; /* sound IF input 1 */ else tda9874a_GCONR = 0xc1; /* sound IF input 2 */ tda9874a_ESP = tda9874a_STD; tda9874a_mode = (tda9874a_STD < 5) ? 0 : 1; if(tda9874a_AMSEL == 0) tda9874a_NCONR = 0x01; /* auto-mute: analog mono input */ else tda9874a_NCONR = 0x05; /* auto-mute: 1st carrier FM or AM */ 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_CH1 0xCE /* audio channel 1 (mute off) - "linear stereo" mode */#define TDA8425_S1_CH2 0xCF /* audio channel 2 (mute off) - "linear stereo" mode */#define TDA8425_S1_MU 0x20 /* mute bit */#define TDA8425_S1_STEREO 0x18 /* stereo bits */#define TDA8425_S1_STEREO_SPATIAL 0x18 /* spatial stereo */#define TDA8425_S1_STEREO_LINEAR 0x08 /* linear stereo */#define TDA8425_S1_STEREO_PSEUDO 0x10 /* pseudo stereo */#define TDA8425_S1_STEREO_MONO 0x00 /* forced mono */#define TDA8425_S1_ML 0x06 /* language selector */#define TDA8425_S1_ML_SOUND_A 0x02 /* sound a */#define TDA8425_S1_ML_SOUND_B 0x04 /* sound b */#define TDA8425_S1_ML_STEREO 0x06 /* stereo */#define TDA8425_S1_IS 0x01 /* channel selector */static int tda8425_shift10(int val) { return (val >> 10) | 0xc0; }static int tda8425_shift12(int val) { return (val >> 12) | 0xf0; }static int tda8425_initialize(struct CHIPSTATE *chip){ struct CHIPDESC *desc = chiplist + chip->type; int inputmap[8] = { /* tuner */ TDA8425_S1_CH2, /* radio */ TDA8425_S1_CH1, /* extern */ TDA8425_S1_CH1, /* intern */ TDA8425_S1_OFF, /* off */ TDA8425_S1_OFF, /* on */ TDA8425_S1_CH2}; if (chip->c.adapter->id == (I2C_ALGO_BIT | I2C_HW_B_RIVA)) { memcpy (desc->inputmap, inputmap, sizeof (inputmap)); } return 0;}static void tda8425_setmode(struct CHIPSTATE *chip, int mode){ int s1 = chip->shadow.bytes[TDA8425_S1+1] & 0xe1; if (mode & VIDEO_SOUND_LANG1) { s1 |= TDA8425_S1_ML_SOUND_A; s1 |= TDA8425_S1_STEREO_PSEUDO; } else if (mode & VIDEO_SOUND_LANG2) { s1 |= TDA8425_S1_ML_SOUND_B; s1 |= TDA8425_S1_STEREO_PSEUDO; } else { s1 |= TDA8425_S1_ML_STEREO; if (mode & VIDEO_SOUND_MONO) s1 |= TDA8425_S1_STEREO_MONO; if (mode & VIDEO_SOUND_STEREO) s1 |= TDA8425_S1_STEREO_SPATIAL; } chip_write(chip,TDA8425_S1,s1);}/* ---------------------------------------------------------------------- *//* 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 - defines+functions for TA8874Z */// write 1st byte#define TA8874Z_LED_STE 0x80#define TA8874Z_LED_BIL 0x40#define TA8874Z_LED_EXT 0x20#define TA8874Z_MONO_SET 0x10#define TA8874Z_MUTE 0x08#define TA8874Z_F_MONO 0x04#define TA8874Z_MODE_SUB 0x02#define TA8874Z_MODE_MAIN 0x01// write 2nd byte//#define TA8874Z_TI 0x80 // test mode#define TA8874Z_SEPARATION 0x3f#define TA8874Z_SEPARATION_DEFAULT 0x10// read#define TA8874Z_B1 0x80#define TA8874Z_B0 0x40#define TA8874Z_CHAG_FLAG 0x20// B1 B0// mono L H// stereo L L// BIL H Lstatic int ta8874z_getmode(struct CHIPSTATE *chip){ int val, mode; val = chip_read(chip); mode = VIDEO_SOUND_MONO; if (val & TA8874Z_B1){ mode |= VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; }else if (!(val & TA8874Z_B0)){ mode |= VIDEO_SOUND_STEREO; } //dprintk ("ta8874z_getmode(): raw chip read: 0x%02x, return: 0x%02x\n", val, mode); return mode;}static audiocmd ta8874z_stereo = { 2, {0, TA8874Z_SEPARATION_DEFAULT}};static audiocmd ta8874z_mono = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}};static audiocmd ta8874z_main = {2, { 0, TA8874Z_SEPARATION_DEFAULT}};static audiocmd ta8874z_sub = {2, { TA8874Z_MODE_SUB, TA8874Z_SEPARATION_DEFAULT}};static void ta8874z_setmode(struct CHIPSTATE *chip, int mode){ int update = 1; audiocmd *t = NULL; dprintk("ta8874z_setmode(): mode: 0x%02x\n", mode); switch(mode){ case VIDEO_SOUND_MONO: t = &ta8874z_mono; break; case VIDEO_SOUND_STEREO: t = &ta8874z_stereo; break; case VIDEO_SOUND_LANG1: t = &ta8874z_main; break; case VIDEO_SOUND_LANG2: t = &ta8874z_sub; break; default: update = 0; } if(update) chip_cmd(chip, "TA8874Z", t);}static int ta8874z_checkit(struct CHIPSTATE *chip){ int rc; rc = chip_read(chip); return ((rc & 0x1f) == 0x1f) ? 1 : 0;}/* ---------------------------------------------------------------------- *//* 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; // address clash with msp34xxint tea6420 = 1;int pic16c54 = 1;int ta8874z = 0; // address clash with tda9840MODULE_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");MODULE_PARM(ta8874z,"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, }, { .name = "tda9874h/a", .id = I2C_DRIVERID_TDA9874,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -