From f98c55ea18e87905bdf69eb4a187e94572ed9494 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Mon, 9 Jan 2006 15:25:18 -0200 Subject: [PATCH] V4L/DVB (3116): tda9887 improvements: better defaults, better configurability. - Set the tuner takeover point to 0x10 for NTSC/radio and 0x14 for PAL/SECAM. - Allow override through TDA9887_SET_CONFIG - PAL-N belongs with PAL-BG as does PAL-H. PAL-Nc belongs to PAL-M - Add SECAM-BGH - Set video freq to cVideoIF_38_90 for DK standards. - Add cTunerGainLow to radio, change deemphasis to 75 for mono. - Add ntsc module param for 'M' and 'J' (Japanese) standards. - Fix module handling for 2.4. - Now able to select all standards through pal/secam/ntsc module options Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tda9887.c | 164 +++++++++++++++++++++++++++------- include/media/tuner.h | 31 ++++--- 2 files changed, 150 insertions(+), 45 deletions(-) diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index ceaa29975c8e..32f133ed0b0b 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -114,6 +114,9 @@ static struct i2c_client client_template; #define cAudioGain0 0x00 // bit c7 #define cAudioGain6 0x80 // bit c7 +#define cTopMask 0x1f // bit c0:4 +#define cTopPalSecamDefault 0x14 // bit c0:4 +#define cTopNtscRadioDefault 0x10 // bit c0:4 //// third reg (e) #define cAudioIF_4_5 0x00 // bit e0:1 @@ -145,13 +148,15 @@ static struct i2c_client client_template; static struct tvnorm tvnorms[] = { { - .std = V4L2_STD_PAL_BG, - .name = "PAL-BG", + .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N, + .name = "PAL-BGHN", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_5_5 | + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_5_5 | cVideoIF_38_90 ), },{ .std = V4L2_STD_PAL_I, @@ -159,8 +164,10 @@ static struct tvnorm tvnorms[] = { .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_6_0 | + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_6_0 | cVideoIF_38_90 ), },{ .std = V4L2_STD_PAL_DK, @@ -168,23 +175,37 @@ static struct tvnorm tvnorms[] = { .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_6_5 | - cVideoIF_38_00 ), + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_6_5 | + cVideoIF_38_90 ), },{ - .std = V4L2_STD_PAL_M | V4L2_STD_PAL_N, - .name = "PAL-M/N", + .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc, + .name = "PAL-M/Nc", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis75 ), - .e = ( cAudioIF_4_5 | + cDeemphasis75 | + cTopNtscRadioDefault), + .e = ( cGating_36 | + cAudioIF_4_5 | cVideoIF_45_75 ), + },{ + .std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H, + .name = "SECAM-BGH", + .b = ( cPositiveAmTV | + cQSS ), + .c = ( cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_5_5 | + cVideoIF_38_90 ), },{ .std = V4L2_STD_SECAM_L, .name = "SECAM-L", .b = ( cPositiveAmTV | cQSS ), + .c = ( cTopPalSecamDefault), .e = ( cGating_36 | cAudioIF_6_5 | cVideoIF_38_90 ), @@ -194,6 +215,7 @@ static struct tvnorm tvnorms[] = { .b = ( cOutputPort2Inactive | cPositiveAmTV | cQSS ), + .c = ( cTopPalSecamDefault), .e = ( cGating_36 | cAudioIF_6_5 | cVideoIF_33_90 ), @@ -203,26 +225,30 @@ static struct tvnorm tvnorms[] = { .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), - .e = ( cAudioIF_6_5 | - cVideoIF_38_00 ), + cDeemphasis50 | + cTopPalSecamDefault), + .e = ( cGating_36 | + cAudioIF_6_5 | + cVideoIF_38_90 ), },{ .std = V4L2_STD_NTSC_M, .name = "NTSC-M", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis75 ), + cDeemphasis75 | + cTopNtscRadioDefault), .e = ( cGating_36 | cAudioIF_4_5 | cVideoIF_45_75 ), },{ .std = V4L2_STD_NTSC_M_JP, - .name = "NTSC-JP", + .name = "NTSC-M-JP", .b = ( cNegativeFmTV | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50 ), + cDeemphasis50 | + cTopNtscRadioDefault), .e = ( cGating_36 | cAudioIF_4_5 | cVideoIF_58_75 ), @@ -234,8 +260,10 @@ static struct tvnorm radio_stereo = { .b = ( cFmRadio | cQSS ), .c = ( cDeemphasisOFF | - cAudioGain6 ), - .e = ( cAudioIF_5_5 | + cAudioGain6 | + cTopNtscRadioDefault), + .e = ( cTunerGainLow | + cAudioIF_5_5 | cRadioIF_38_90 ), }; @@ -244,8 +272,10 @@ static struct tvnorm radio_mono = { .b = ( cFmRadio | cQSS ), .c = ( cDeemphasisON | - cDeemphasis50), - .e = ( cAudioIF_5_5 | + cDeemphasis75 | + cTopNtscRadioDefault), + .e = ( cTunerGainLow | + cAudioIF_5_5 | cRadioIF_38_90 ), }; @@ -408,7 +438,8 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) static unsigned int port1 = UNSET; static unsigned int port2 = UNSET; static unsigned int qss = UNSET; -static unsigned int adjust = 0x10; +static unsigned int adjust = UNSET; + module_param(port1, int, 0644); module_param(port2, int, 0644); module_param(qss, int, 0644); @@ -436,8 +467,10 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf) buf[1] &= ~cQSS; } - if (adjust >= 0x00 && adjust < 0x20) + if (adjust >= 0x00 && adjust < 0x20) { + buf[2] &= ~cTopMask; buf[2] |= adjust; + } return 0; } @@ -473,6 +506,10 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) break; } } + if (t->config & TDA9887_TOP_SET) { + buf[2] &= ~cTopMask; + buf[2] |= (t->config >> 8) & cTopMask; + } if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC)) buf[1] &= ~cQSS; return 0; @@ -480,10 +517,13 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) /* ---------------------------------------------------------------------- */ -static char pal[] = "-"; +static char pal[] = "--"; +static char secam[] = "--"; +static char ntsc[] = "-"; + module_param_string(pal, pal, sizeof(pal), 0644); -static char secam[] = "-"; module_param_string(secam, secam, sizeof(secam), 0644); +module_param_string(ntsc, ntsc, sizeof(ntsc), 0644); static int tda9887_fixup_std(struct tda9887 *t) { @@ -494,8 +534,17 @@ static int tda9887_fixup_std(struct tda9887 *t) case 'B': case 'g': case 'G': - tda9887_dbg("insmod fixup: PAL => PAL-BG\n"); - t->std = V4L2_STD_PAL_BG; + case 'h': + case 'H': + case 'n': + case 'N': + if (pal[1] == 'c' || pal[1] == 'C') { + tda9887_dbg("insmod fixup: PAL => PAL-Nc\n"); + t->std = V4L2_STD_PAL_Nc; + } else { + tda9887_dbg("insmod fixup: PAL => PAL-BGHN\n"); + t->std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N; + } break; case 'i': case 'I': @@ -509,6 +558,11 @@ static int tda9887_fixup_std(struct tda9887 *t) tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); t->std = V4L2_STD_PAL_DK; break; + case 'm': + case 'M': + tda9887_dbg("insmod fixup: PAL => PAL-M\n"); + t->std = V4L2_STD_PAL_M; + break; case '-': /* default parameter, do nothing */ break; @@ -519,6 +573,15 @@ static int tda9887_fixup_std(struct tda9887 *t) } if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { switch (secam[0]) { + case 'b': + case 'B': + case 'g': + case 'G': + case 'h': + case 'H': + tda9887_dbg("insmod fixup: SECAM => SECAM-BGH\n"); + t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H; + break; case 'd': case 'D': case 'k': @@ -528,8 +591,13 @@ static int tda9887_fixup_std(struct tda9887 *t) break; case 'l': case 'L': - tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); - t->std = V4L2_STD_SECAM_L; + if (secam[1] == 'c' || secam[1] == 'C') { + tda9887_dbg("insmod fixup: SECAM => SECAM-L'\n"); + t->std = V4L2_STD_SECAM_LC; + } else { + tda9887_dbg("insmod fixup: SECAM => SECAM-L\n"); + t->std = V4L2_STD_SECAM_L; + } break; case '-': /* default parameter, do nothing */ @@ -539,6 +607,26 @@ static int tda9887_fixup_std(struct tda9887 *t) break; } } + if ((t->std & V4L2_STD_NTSC) == V4L2_STD_NTSC) { + switch (ntsc[0]) { + case 'm': + case 'M': + tda9887_dbg("insmod fixup: NTSC => NTSC-M\n"); + t->std = V4L2_STD_NTSC_M; + break; + case 'j': + case 'J': + tda9887_dbg("insmod fixup: NTSC => NTSC_M_JP\n"); + t->std = V4L2_STD_NTSC_M_JP; + break; + case '-': + /* default parameter, do nothing */ + break; + default: + tda9887_info("ntsc= argument not recognised\n"); + break; + } + } return 0; } @@ -561,6 +649,19 @@ static int tda9887_configure(struct tda9887 *t) memset(t->data,0,sizeof(t->data)); tda9887_set_tvnorm(t,t->data); + /* A note on the port settings: + These settings tend to depend on the specifics of the board. + By default they are set to inactive (bit value 1) by this driver, + overwriting any changes made by the tvnorm. This means that it + is the responsibility of the module using the tda9887 to set + these values in case of changes in the tvnorm. + In many cases port 2 should be made active (0) when selecting + SECAM-L, and port 2 should remain inactive (1) for SECAM-L'. + + For the other standards the tda9887 application note says that + the ports should be set to active (0), but, again, that may + differ depending on the precise hardware configuration. + */ t->data[1] |= cOutputPort1Inactive; t->data[1] |= cOutputPort2Inactive; @@ -571,7 +672,6 @@ static int tda9887_configure(struct tda9887 *t) t->data[1] |= cForcedMuteAudioON; } - tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", t->data[1],t->data[2],t->data[3]); if (debug > 1) diff --git a/include/media/tuner.h b/include/media/tuner.h index e224722a7ff7..567f05549e3a 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -120,20 +120,25 @@ #define TDA9887_SET_CONFIG _IOW('t',5,int) /* tv card specific */ -# define TDA9887_PRESENT (1<<0) -# define TDA9887_PORT1_INACTIVE (1<<1) -# define TDA9887_PORT2_INACTIVE (1<<2) -# define TDA9887_QSS (1<<3) -# define TDA9887_INTERCARRIER (1<<4) -# define TDA9887_PORT1_ACTIVE (1<<5) -# define TDA9887_PORT2_ACTIVE (1<<6) -# define TDA9887_INTERCARRIER_NTSC (1<<7) +#define TDA9887_PRESENT (1<<0) +#define TDA9887_PORT1_INACTIVE (1<<1) +#define TDA9887_PORT2_INACTIVE (1<<2) +#define TDA9887_QSS (1<<3) +#define TDA9887_INTERCARRIER (1<<4) +#define TDA9887_PORT1_ACTIVE (1<<5) +#define TDA9887_PORT2_ACTIVE (1<<6) +#define TDA9887_INTERCARRIER_NTSC (1<<7) +/* Tuner takeover point adjustment, in dB, -16 <= top <= 15 */ +#define TDA9887_TOP_MASK (0x3f << 8) +#define TDA9887_TOP_SET (1 << 13) +#define TDA9887_TOP(top) (TDA9887_TOP_SET | (((16 + (top)) & 0x1f) << 8)) + /* config options */ -# define TDA9887_DEEMPHASIS_MASK (3<<16) -# define TDA9887_DEEMPHASIS_NONE (1<<16) -# define TDA9887_DEEMPHASIS_50 (2<<16) -# define TDA9887_DEEMPHASIS_75 (3<<16) -# define TDA9887_AUTOMUTE (1<<18) +#define TDA9887_DEEMPHASIS_MASK (3<<16) +#define TDA9887_DEEMPHASIS_NONE (1<<16) +#define TDA9887_DEEMPHASIS_50 (2<<16) +#define TDA9887_DEEMPHASIS_75 (3<<16) +#define TDA9887_AUTOMUTE (1<<18) #ifdef __KERNEL__