Commit 839e4a4a authored by Mauro Carvalho Chehab's avatar Mauro Carvalho Chehab

V4L/DVB (4067): Fixed cx25840 to work with PAL/M

Sub-carrier frequency for PAL/M is slicely different than NTSC/M.
Without this patch, colors don't work on PAL/M.
Setting method also improved to allow other video standards to be included.
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent c820cc45
...@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); ...@@ -46,7 +46,7 @@ MODULE_LICENSE("GPL");
static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END }; static unsigned short normal_i2c[] = { 0x88 >> 1, I2C_CLIENT_END };
static int cx25840_debug; int cx25840_debug;
module_param_named(debug,cx25840_debug, int, 0644); module_param_named(debug,cx25840_debug, int, 0644);
...@@ -251,17 +251,7 @@ static void input_change(struct i2c_client *client) ...@@ -251,17 +251,7 @@ static void input_change(struct i2c_client *client)
cx25840_and_or(client, 0x401, ~0x60, 0); cx25840_and_or(client, 0x401, ~0x60, 0);
cx25840_and_or(client, 0x401, ~0x60, 0x60); cx25840_and_or(client, 0x401, ~0x60, 0x60);
/* Note: perhaps V4L2_STD_PAL_M should be handled as V4L2_STD_NTSC if (std & V4L2_STD_525_60) {
instead of V4L2_STD_PAL. Someone needs to test this. */
if (std & V4L2_STD_PAL) {
/* Follow tuner change procedure for PAL */
cx25840_write(client, 0x808, 0xff);
cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_SECAM) {
/* Select autodetect for SECAM */
cx25840_write(client, 0x808, 0xff);
cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_NTSC) {
/* Certain Hauppauge PVR150 models have a hardware bug /* Certain Hauppauge PVR150 models have a hardware bug
that causes audio to drop out. For these models the that causes audio to drop out. For these models the
audio standard must be set explicitly. audio standard must be set explicitly.
...@@ -280,6 +270,14 @@ static void input_change(struct i2c_client *client) ...@@ -280,6 +270,14 @@ static void input_change(struct i2c_client *client)
cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6); cx25840_write(client, 0x808, hw_fix ? 0x1f : 0xf6);
} }
cx25840_write(client, 0x80b, 0x00); cx25840_write(client, 0x80b, 0x00);
} else if (std & V4L2_STD_PAL) {
/* Follow tuner change procedure for PAL */
cx25840_write(client, 0x808, 0xff);
cx25840_write(client, 0x80b, 0x10);
} else if (std & V4L2_STD_SECAM) {
/* Select autodetect for SECAM */
cx25840_write(client, 0x808, 0xff);
cx25840_write(client, 0x80b, 0x10);
} }
if (cx25840_read(client, 0x803) & 0x10) { if (cx25840_read(client, 0x803) & 0x10) {
...@@ -387,6 +385,8 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) ...@@ -387,6 +385,8 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
} }
} }
v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
/* Follow step 9 of section 3.16 in the cx25840 datasheet. /* Follow step 9 of section 3.16 in the cx25840 datasheet.
Without this PAL may display a vertical ghosting effect. Without this PAL may display a vertical ghosting effect.
This happens for example with the Yuan MPC622. */ This happens for example with the Yuan MPC622. */
......
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <linux/i2c.h> #include <linux/i2c.h>
extern int cx25840_debug;
/* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is /* ENABLE_PVR150_WORKAROUND activates a workaround for a hardware bug that is
present in Hauppauge PVR-150 (and possibly PVR-500) cards that have present in Hauppauge PVR-150 (and possibly PVR-500) cards that have
certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The certain NTSC tuners (tveeprom tuner model numbers 85, 99 and 112). The
......
...@@ -86,61 +86,130 @@ void cx25840_vbi_setup(struct i2c_client *client) ...@@ -86,61 +86,130 @@ void cx25840_vbi_setup(struct i2c_client *client)
{ {
struct cx25840_state *state = i2c_get_clientdata(client); struct cx25840_state *state = i2c_get_clientdata(client);
v4l2_std_id std = cx25840_get_v4lstd(client); v4l2_std_id std = cx25840_get_v4lstd(client);
int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
int luma_lpf,uv_lpf, comb;
u32 pll_int,pll_frac,pll_post;
/* datasheet startup, step 8d */
if (std & ~V4L2_STD_NTSC) { if (std & ~V4L2_STD_NTSC) {
/* datasheet startup, step 8d */
cx25840_write(client, 0x49f, 0x11); cx25840_write(client, 0x49f, 0x11);
} else {
cx25840_write(client, 0x49f, 0x14);
}
cx25840_write(client, 0x470, 0x84); if (std & V4L2_STD_625_50) {
cx25840_write(client, 0x471, 0x00); hblank=0x084;
cx25840_write(client, 0x472, 0x2d); hactive=0x2d0;
cx25840_write(client, 0x473, 0x5d); burst=0x5d;
vblank=0x024;
cx25840_write(client, 0x474, 0x24); vactive=0x244;
cx25840_write(client, 0x475, 0x40); vblank656=0x28;
cx25840_write(client, 0x476, 0x24); src_decimation=0x21f;
cx25840_write(client, 0x477, 0x28);
cx25840_write(client, 0x478, 0x1f);
cx25840_write(client, 0x479, 0x02);
luma_lpf=2;
if (std & V4L2_STD_SECAM) { if (std & V4L2_STD_SECAM) {
cx25840_write(client, 0x47a, 0x80); uv_lpf=0;
cx25840_write(client, 0x47b, 0x00); comb=0;
cx25840_write(client, 0x47c, 0x5f); sc=0x0a425f;
cx25840_write(client, 0x47d, 0x42);
} else { } else {
cx25840_write(client, 0x47a, 0x90); uv_lpf=1;
cx25840_write(client, 0x47b, 0x20); comb=0x20;
cx25840_write(client, 0x47c, 0x63); sc=0x0a8263;
cx25840_write(client, 0x47d, 0x82);
} }
cx25840_write(client, 0x47e, 0x0a);
cx25840_write(client, 0x47f, 0x01);
state->vbi_line_offset = 5;
} else { } else {
/* datasheet startup, step 8d */ hactive=720;
cx25840_write(client, 0x49f, 0x14); hblank=122;
vactive=487;
luma_lpf=1;
uv_lpf=1;
src_decimation=0x21f;
if (std == V4L2_STD_PAL_M) {
vblank=20;
vblank656=24;
burst=0x61;
comb=0x20;
sc=555452;
} else {
vblank=26;
vblank656=26;
burst=0x5b;
comb=0x66;
sc=556063;
}
}
/* DEBUG: Displays configured PLL frequency */
pll_int=cx25840_read(client, 0x108);
pll_frac=cx25840_read4(client, 0x10c)&0x1ffffff;
pll_post=cx25840_read(client, 0x109);
v4l_dbg(1, cx25840_debug, client,
"PLL regs = int: %u, frac: %u, post: %u\n",
pll_int,pll_frac,pll_post);
if (pll_post) {
int fin, fsc;
int pll= (28636363L*((((u64)pll_int)<<25L)+pll_frac)) >>25L;
pll/=pll_post;
v4l_dbg(1, cx25840_debug, client, "PLL = %d.%06d MHz\n",
pll/1000000, pll%1000000);
v4l_dbg(1, cx25840_debug, client, "PLL/8 = %d.%06d MHz\n",
pll/8000000, (pll/8)%1000000);
fin=((u64)src_decimation*pll)>>12;
v4l_dbg(1, cx25840_debug, client, "ADC Sampling freq = "
"%d.%06d MHz\n",
fin/1000000,fin%1000000);
fsc= (((u64)sc)*pll) >> 24L;
v4l_dbg(1, cx25840_debug, client, "Chroma sub-carrier freq = "
"%d.%06d MHz\n",
fsc/1000000,fsc%1000000);
v4l_dbg(1, cx25840_debug, client, "hblank %i, hactive %i, "
"vblank %i , vactive %i, vblank656 %i, src_dec %i,"
"burst 0x%02x, luma_lpf %i, uv_lpf %i, comb 0x%02x,"
" sc 0x%06x\n",
hblank, hactive, vblank, vactive, vblank656,
src_decimation, burst, luma_lpf, uv_lpf, comb, sc);
}
/* Sets horizontal blanking delay and active lines */
cx25840_write(client, 0x470, hblank);
cx25840_write(client, 0x471, 0xff&(((hblank>>8)&0x3)|(hactive <<4)));
cx25840_write(client, 0x472, hactive>>4);
/* Sets burst gate delay */
cx25840_write(client, 0x473, burst);
cx25840_write(client, 0x470, 0x7a); /* Sets vertical blanking delay and active duration */
cx25840_write(client, 0x471, 0x00); cx25840_write(client, 0x474, vblank);
cx25840_write(client, 0x472, 0x2d); cx25840_write(client, 0x475, 0xff&(((vblank>>8)&0x3)|(vactive <<4)));
cx25840_write(client, 0x473, 0x5b); cx25840_write(client, 0x476, vactive>>4);
cx25840_write(client, 0x477, vblank656);
cx25840_write(client, 0x474, 0x1a); /* Sets src decimation rate */
cx25840_write(client, 0x475, 0x70); cx25840_write(client, 0x478, 0xff&src_decimation);
cx25840_write(client, 0x476, 0x1e); cx25840_write(client, 0x479, 0xff&(src_decimation>>8));
cx25840_write(client, 0x477, 0x1e);
cx25840_write(client, 0x478, 0x1f); /* Sets Luma and UV Low pass filters */
cx25840_write(client, 0x479, 0x02); cx25840_write(client, 0x47a, luma_lpf<<6|((uv_lpf<<4)&0x30));
cx25840_write(client, 0x47a, 0x50);
cx25840_write(client, 0x47b, 0x66);
cx25840_write(client, 0x47c, 0x1f); /* Enables comb filters */
cx25840_write(client, 0x47d, 0x7c); cx25840_write(client, 0x47b, comb);
cx25840_write(client, 0x47e, 0x08);
/* Sets SC Step*/
cx25840_write(client, 0x47c, sc);
cx25840_write(client, 0x47d, 0xff&sc>>8);
cx25840_write(client, 0x47e, 0xff&sc>>16);
/* Sets VBI parameters */
if (std & V4L2_STD_625_50) {
cx25840_write(client, 0x47f, 0x01);
state->vbi_line_offset = 5;
} else {
cx25840_write(client, 0x47f, 0x00); cx25840_write(client, 0x47f, 0x00);
state->vbi_line_offset = 8; state->vbi_line_offset = 8;
} }
...@@ -186,7 +255,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -186,7 +255,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
case VIDIOC_S_FMT: case VIDIOC_S_FMT:
{ {
int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_NTSC); int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60);
int vbi_offset = is_pal ? 1 : 0; int vbi_offset = is_pal ? 1 : 0;
int i, x; int i, x;
u8 lcr[24]; u8 lcr[24];
......
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