Commit f98c55ea authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

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: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@brturbo.com.br>
parent a82c51d5
...@@ -114,6 +114,9 @@ static struct i2c_client client_template; ...@@ -114,6 +114,9 @@ static struct i2c_client client_template;
#define cAudioGain0 0x00 // bit c7 #define cAudioGain0 0x00 // bit c7
#define cAudioGain6 0x80 // 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) //// third reg (e)
#define cAudioIF_4_5 0x00 // bit e0:1 #define cAudioIF_4_5 0x00 // bit e0:1
...@@ -145,13 +148,15 @@ static struct i2c_client client_template; ...@@ -145,13 +148,15 @@ static struct i2c_client client_template;
static struct tvnorm tvnorms[] = { static struct tvnorm tvnorms[] = {
{ {
.std = V4L2_STD_PAL_BG, .std = V4L2_STD_PAL_BG | V4L2_STD_PAL_H | V4L2_STD_PAL_N,
.name = "PAL-BG", .name = "PAL-BGHN",
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis50 ), cDeemphasis50 |
.e = ( cAudioIF_5_5 | cTopPalSecamDefault),
.e = ( cGating_36 |
cAudioIF_5_5 |
cVideoIF_38_90 ), cVideoIF_38_90 ),
},{ },{
.std = V4L2_STD_PAL_I, .std = V4L2_STD_PAL_I,
...@@ -159,8 +164,10 @@ static struct tvnorm tvnorms[] = { ...@@ -159,8 +164,10 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis50 ), cDeemphasis50 |
.e = ( cAudioIF_6_0 | cTopPalSecamDefault),
.e = ( cGating_36 |
cAudioIF_6_0 |
cVideoIF_38_90 ), cVideoIF_38_90 ),
},{ },{
.std = V4L2_STD_PAL_DK, .std = V4L2_STD_PAL_DK,
...@@ -168,23 +175,37 @@ static struct tvnorm tvnorms[] = { ...@@ -168,23 +175,37 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis50 ), cDeemphasis50 |
.e = ( cAudioIF_6_5 | cTopPalSecamDefault),
cVideoIF_38_00 ), .e = ( cGating_36 |
cAudioIF_6_5 |
cVideoIF_38_90 ),
},{ },{
.std = V4L2_STD_PAL_M | V4L2_STD_PAL_N, .std = V4L2_STD_PAL_M | V4L2_STD_PAL_Nc,
.name = "PAL-M/N", .name = "PAL-M/Nc",
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis75 ), cDeemphasis75 |
.e = ( cAudioIF_4_5 | cTopNtscRadioDefault),
.e = ( cGating_36 |
cAudioIF_4_5 |
cVideoIF_45_75 ), 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, .std = V4L2_STD_SECAM_L,
.name = "SECAM-L", .name = "SECAM-L",
.b = ( cPositiveAmTV | .b = ( cPositiveAmTV |
cQSS ), cQSS ),
.c = ( cTopPalSecamDefault),
.e = ( cGating_36 | .e = ( cGating_36 |
cAudioIF_6_5 | cAudioIF_6_5 |
cVideoIF_38_90 ), cVideoIF_38_90 ),
...@@ -194,6 +215,7 @@ static struct tvnorm tvnorms[] = { ...@@ -194,6 +215,7 @@ static struct tvnorm tvnorms[] = {
.b = ( cOutputPort2Inactive | .b = ( cOutputPort2Inactive |
cPositiveAmTV | cPositiveAmTV |
cQSS ), cQSS ),
.c = ( cTopPalSecamDefault),
.e = ( cGating_36 | .e = ( cGating_36 |
cAudioIF_6_5 | cAudioIF_6_5 |
cVideoIF_33_90 ), cVideoIF_33_90 ),
...@@ -203,26 +225,30 @@ static struct tvnorm tvnorms[] = { ...@@ -203,26 +225,30 @@ static struct tvnorm tvnorms[] = {
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis50 ), cDeemphasis50 |
.e = ( cAudioIF_6_5 | cTopPalSecamDefault),
cVideoIF_38_00 ), .e = ( cGating_36 |
cAudioIF_6_5 |
cVideoIF_38_90 ),
},{ },{
.std = V4L2_STD_NTSC_M, .std = V4L2_STD_NTSC_M,
.name = "NTSC-M", .name = "NTSC-M",
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis75 ), cDeemphasis75 |
cTopNtscRadioDefault),
.e = ( cGating_36 | .e = ( cGating_36 |
cAudioIF_4_5 | cAudioIF_4_5 |
cVideoIF_45_75 ), cVideoIF_45_75 ),
},{ },{
.std = V4L2_STD_NTSC_M_JP, .std = V4L2_STD_NTSC_M_JP,
.name = "NTSC-JP", .name = "NTSC-M-JP",
.b = ( cNegativeFmTV | .b = ( cNegativeFmTV |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis50 ), cDeemphasis50 |
cTopNtscRadioDefault),
.e = ( cGating_36 | .e = ( cGating_36 |
cAudioIF_4_5 | cAudioIF_4_5 |
cVideoIF_58_75 ), cVideoIF_58_75 ),
...@@ -234,8 +260,10 @@ static struct tvnorm radio_stereo = { ...@@ -234,8 +260,10 @@ static struct tvnorm radio_stereo = {
.b = ( cFmRadio | .b = ( cFmRadio |
cQSS ), cQSS ),
.c = ( cDeemphasisOFF | .c = ( cDeemphasisOFF |
cAudioGain6 ), cAudioGain6 |
.e = ( cAudioIF_5_5 | cTopNtscRadioDefault),
.e = ( cTunerGainLow |
cAudioIF_5_5 |
cRadioIF_38_90 ), cRadioIF_38_90 ),
}; };
...@@ -244,8 +272,10 @@ static struct tvnorm radio_mono = { ...@@ -244,8 +272,10 @@ static struct tvnorm radio_mono = {
.b = ( cFmRadio | .b = ( cFmRadio |
cQSS ), cQSS ),
.c = ( cDeemphasisON | .c = ( cDeemphasisON |
cDeemphasis50), cDeemphasis75 |
.e = ( cAudioIF_5_5 | cTopNtscRadioDefault),
.e = ( cTunerGainLow |
cAudioIF_5_5 |
cRadioIF_38_90 ), cRadioIF_38_90 ),
}; };
...@@ -408,7 +438,8 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf) ...@@ -408,7 +438,8 @@ static int tda9887_set_tvnorm(struct tda9887 *t, char *buf)
static unsigned int port1 = UNSET; static unsigned int port1 = UNSET;
static unsigned int port2 = UNSET; static unsigned int port2 = UNSET;
static unsigned int qss = UNSET; static unsigned int qss = UNSET;
static unsigned int adjust = 0x10; static unsigned int adjust = UNSET;
module_param(port1, int, 0644); module_param(port1, int, 0644);
module_param(port2, int, 0644); module_param(port2, int, 0644);
module_param(qss, int, 0644); module_param(qss, int, 0644);
...@@ -436,8 +467,10 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf) ...@@ -436,8 +467,10 @@ static int tda9887_set_insmod(struct tda9887 *t, char *buf)
buf[1] &= ~cQSS; buf[1] &= ~cQSS;
} }
if (adjust >= 0x00 && adjust < 0x20) if (adjust >= 0x00 && adjust < 0x20) {
buf[2] &= ~cTopMask;
buf[2] |= adjust; buf[2] |= adjust;
}
return 0; return 0;
} }
...@@ -473,6 +506,10 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) ...@@ -473,6 +506,10 @@ static int tda9887_set_config(struct tda9887 *t, char *buf)
break; 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)) if ((t->config & TDA9887_INTERCARRIER_NTSC) && (t->std & V4L2_STD_NTSC))
buf[1] &= ~cQSS; buf[1] &= ~cQSS;
return 0; return 0;
...@@ -480,10 +517,13 @@ static int tda9887_set_config(struct tda9887 *t, char *buf) ...@@ -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); module_param_string(pal, pal, sizeof(pal), 0644);
static char secam[] = "-";
module_param_string(secam, secam, sizeof(secam), 0644); module_param_string(secam, secam, sizeof(secam), 0644);
module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
static int tda9887_fixup_std(struct tda9887 *t) static int tda9887_fixup_std(struct tda9887 *t)
{ {
...@@ -494,8 +534,17 @@ static int tda9887_fixup_std(struct tda9887 *t) ...@@ -494,8 +534,17 @@ static int tda9887_fixup_std(struct tda9887 *t)
case 'B': case 'B':
case 'g': case 'g':
case 'G': case 'G':
tda9887_dbg("insmod fixup: PAL => PAL-BG\n"); case 'h':
t->std = V4L2_STD_PAL_BG; 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; break;
case 'i': case 'i':
case 'I': case 'I':
...@@ -509,6 +558,11 @@ static int tda9887_fixup_std(struct tda9887 *t) ...@@ -509,6 +558,11 @@ static int tda9887_fixup_std(struct tda9887 *t)
tda9887_dbg("insmod fixup: PAL => PAL-DK\n"); tda9887_dbg("insmod fixup: PAL => PAL-DK\n");
t->std = V4L2_STD_PAL_DK; t->std = V4L2_STD_PAL_DK;
break; break;
case 'm':
case 'M':
tda9887_dbg("insmod fixup: PAL => PAL-M\n");
t->std = V4L2_STD_PAL_M;
break;
case '-': case '-':
/* default parameter, do nothing */ /* default parameter, do nothing */
break; break;
...@@ -519,6 +573,15 @@ static int tda9887_fixup_std(struct tda9887 *t) ...@@ -519,6 +573,15 @@ static int tda9887_fixup_std(struct tda9887 *t)
} }
if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) { if ((t->std & V4L2_STD_SECAM) == V4L2_STD_SECAM) {
switch (secam[0]) { 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 'D': case 'D':
case 'k': case 'k':
...@@ -528,8 +591,13 @@ static int tda9887_fixup_std(struct tda9887 *t) ...@@ -528,8 +591,13 @@ static int tda9887_fixup_std(struct tda9887 *t)
break; break;
case 'l': case 'l':
case 'L': case '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"); tda9887_dbg("insmod fixup: SECAM => SECAM-L\n");
t->std = V4L2_STD_SECAM_L; t->std = V4L2_STD_SECAM_L;
}
break; break;
case '-': case '-':
/* default parameter, do nothing */ /* default parameter, do nothing */
...@@ -539,6 +607,26 @@ static int tda9887_fixup_std(struct tda9887 *t) ...@@ -539,6 +607,26 @@ static int tda9887_fixup_std(struct tda9887 *t)
break; 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; return 0;
} }
...@@ -561,6 +649,19 @@ static int tda9887_configure(struct tda9887 *t) ...@@ -561,6 +649,19 @@ static int tda9887_configure(struct tda9887 *t)
memset(t->data,0,sizeof(t->data)); memset(t->data,0,sizeof(t->data));
tda9887_set_tvnorm(t,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] |= cOutputPort1Inactive;
t->data[1] |= cOutputPort2Inactive; t->data[1] |= cOutputPort2Inactive;
...@@ -571,7 +672,6 @@ static int tda9887_configure(struct tda9887 *t) ...@@ -571,7 +672,6 @@ static int tda9887_configure(struct tda9887 *t)
t->data[1] |= cForcedMuteAudioON; t->data[1] |= cForcedMuteAudioON;
} }
tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
t->data[1],t->data[2],t->data[3]); t->data[1],t->data[2],t->data[3]);
if (debug > 1) if (debug > 1)
......
...@@ -120,20 +120,25 @@ ...@@ -120,20 +120,25 @@
#define TDA9887_SET_CONFIG _IOW('t',5,int) #define TDA9887_SET_CONFIG _IOW('t',5,int)
/* tv card specific */ /* tv card specific */
# define TDA9887_PRESENT (1<<0) #define TDA9887_PRESENT (1<<0)
# define TDA9887_PORT1_INACTIVE (1<<1) #define TDA9887_PORT1_INACTIVE (1<<1)
# define TDA9887_PORT2_INACTIVE (1<<2) #define TDA9887_PORT2_INACTIVE (1<<2)
# define TDA9887_QSS (1<<3) #define TDA9887_QSS (1<<3)
# define TDA9887_INTERCARRIER (1<<4) #define TDA9887_INTERCARRIER (1<<4)
# define TDA9887_PORT1_ACTIVE (1<<5) #define TDA9887_PORT1_ACTIVE (1<<5)
# define TDA9887_PORT2_ACTIVE (1<<6) #define TDA9887_PORT2_ACTIVE (1<<6)
# define TDA9887_INTERCARRIER_NTSC (1<<7) #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 */ /* config options */
# define TDA9887_DEEMPHASIS_MASK (3<<16) #define TDA9887_DEEMPHASIS_MASK (3<<16)
# define TDA9887_DEEMPHASIS_NONE (1<<16) #define TDA9887_DEEMPHASIS_NONE (1<<16)
# define TDA9887_DEEMPHASIS_50 (2<<16) #define TDA9887_DEEMPHASIS_50 (2<<16)
# define TDA9887_DEEMPHASIS_75 (3<<16) #define TDA9887_DEEMPHASIS_75 (3<<16)
# define TDA9887_AUTOMUTE (1<<18) #define TDA9887_AUTOMUTE (1<<18)
#ifdef __KERNEL__ #ifdef __KERNEL__
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment