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

V4L/DVB (7344): cx25840: better PAL-M and NTSC-KR handling

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@infradead.org>
parent 2fd3c14c
...@@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client) ...@@ -352,7 +352,7 @@ static void cx23885_initialize(struct i2c_client *client)
static void input_change(struct i2c_client *client) static void input_change(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 = state->std;
/* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */ /* Follow step 8c and 8d of section 3.16 in the cx25840 datasheet */
if (std & V4L2_STD_SECAM) { if (std & V4L2_STD_SECAM) {
...@@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp ...@@ -523,32 +523,34 @@ static int set_input(struct i2c_client *client, enum cx25840_video_input vid_inp
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) static int set_v4lstd(struct i2c_client *client)
{ {
u8 fmt=0; /* zero is autodetect */ struct cx25840_state *state = i2c_get_clientdata(client);
u8 fmt = 0; /* zero is autodetect */
u8 pal_m = 0;
/* First tests should be against specific std */ /* First tests should be against specific std */
if (std == V4L2_STD_NTSC_M_JP) { if (state->std == V4L2_STD_NTSC_M_JP) {
fmt=0x2; fmt = 0x2;
} else if (std == V4L2_STD_NTSC_443) { } else if (state->std == V4L2_STD_NTSC_443) {
fmt=0x3; fmt = 0x3;
} else if (std == V4L2_STD_PAL_M) { } else if (state->std == V4L2_STD_PAL_M) {
fmt=0x5; pal_m = 1;
} else if (std == V4L2_STD_PAL_N) { fmt = 0x5;
fmt=0x6; } else if (state->std == V4L2_STD_PAL_N) {
} else if (std == V4L2_STD_PAL_Nc) { fmt = 0x6;
fmt=0x7; } else if (state->std == V4L2_STD_PAL_Nc) {
} else if (std == V4L2_STD_PAL_60) { fmt = 0x7;
fmt=0x8; } else if (state->std == V4L2_STD_PAL_60) {
fmt = 0x8;
} else { } else {
/* Then, test against generic ones */ /* Then, test against generic ones */
if (std & V4L2_STD_NTSC) { if (state->std & V4L2_STD_NTSC)
fmt=0x1; fmt = 0x1;
} else if (std & V4L2_STD_PAL) { else if (state->std & V4L2_STD_PAL)
fmt=0x4; fmt = 0x4;
} else if (std & V4L2_STD_SECAM) { else if (state->std & V4L2_STD_SECAM)
fmt=0xc; fmt = 0xc;
}
} }
v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt); v4l_dbg(1, cx25840_debug, client, "changing video std to fmt %i\n",fmt);
...@@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std) ...@@ -563,42 +565,13 @@ static int set_v4lstd(struct i2c_client *client, v4l2_std_id std)
cx25840_and_or(client, 0x47b, ~6, 0); cx25840_and_or(client, 0x47b, ~6, 0);
} }
cx25840_and_or(client, 0x400, ~0xf, fmt); cx25840_and_or(client, 0x400, ~0xf, fmt);
cx25840_and_or(client, 0x403, ~0x3, pal_m);
cx25840_vbi_setup(client); cx25840_vbi_setup(client);
if (!state->is_cx25836)
input_change(client);
return 0; return 0;
} }
v4l2_std_id cx25840_get_v4lstd(struct i2c_client * client)
{
struct cx25840_state *state = i2c_get_clientdata(client);
/* check VID_FMT_SEL first */
u8 fmt = cx25840_read(client, 0x400) & 0xf;
if (!fmt) {
/* check AFD_FMT_STAT if set to autodetect */
fmt = cx25840_read(client, 0x40d) & 0xf;
}
switch (fmt) {
case 0x1:
{
/* if the audio std is A2-M, then this is the South Korean
NTSC standard */
if (!state->is_cx25836 && cx25840_read(client, 0x805) == 2)
return V4L2_STD_NTSC_M_KR;
return V4L2_STD_NTSC_M;
}
case 0x2: return V4L2_STD_NTSC_M_JP;
case 0x3: return V4L2_STD_NTSC_443;
case 0x4: return V4L2_STD_PAL;
case 0x5: return V4L2_STD_PAL_M;
case 0x6: return V4L2_STD_PAL_N;
case 0x7: return V4L2_STD_PAL_Nc;
case 0x8: return V4L2_STD_PAL_60;
case 0xc: return V4L2_STD_SECAM;
default: return V4L2_STD_UNKNOWN;
}
}
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl) static int set_v4lctrl(struct i2c_client *client, struct v4l2_control *ctrl)
...@@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) ...@@ -718,9 +691,10 @@ static int get_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt) static int set_v4lfmt(struct i2c_client *client, struct v4l2_format *fmt)
{ {
struct cx25840_state *state = i2c_get_clientdata(client);
struct v4l2_pix_format *pix; struct v4l2_pix_format *pix;
int HSC, VSC, Vsrc, Hsrc, filter, Vlines; int HSC, VSC, Vsrc, Hsrc, filter, Vlines;
int is_50Hz = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); int is_50Hz = !(state->std & V4L2_STD_525_60);
switch (fmt->type) { switch (fmt->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE: case V4L2_BUF_TYPE_VIDEO_CAPTURE:
...@@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -1096,12 +1070,15 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
} }
case VIDIOC_G_STD: case VIDIOC_G_STD:
*(v4l2_std_id *)arg = cx25840_get_v4lstd(client); *(v4l2_std_id *)arg = state->std;
break; break;
case VIDIOC_S_STD: case VIDIOC_S_STD:
if (state->radio == 0 && state->std == *(v4l2_std_id *)arg)
return 0;
state->radio = 0; state->radio = 0;
return set_v4lstd(client, *(v4l2_std_id *)arg); state->std = *(v4l2_std_id *)arg;
return set_v4lstd(client);
case AUDC_SET_RADIO: case AUDC_SET_RADIO:
state->radio = 1; state->radio = 1;
......
...@@ -38,6 +38,7 @@ struct cx25840_state { ...@@ -38,6 +38,7 @@ struct cx25840_state {
struct i2c_client *c; struct i2c_client *c;
int pvr150_workaround; int pvr150_workaround;
int radio; int radio;
v4l2_std_id std;
enum cx25840_video_input vid_input; enum cx25840_video_input vid_input;
enum cx25840_audio_input aud_input; enum cx25840_audio_input aud_input;
u32 audclk_freq; u32 audclk_freq;
...@@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value); ...@@ -60,7 +61,6 @@ int cx25840_write4(struct i2c_client *client, u16 addr, u32 value);
u8 cx25840_read(struct i2c_client *client, u16 addr); u8 cx25840_read(struct i2c_client *client, u16 addr);
u32 cx25840_read4(struct i2c_client *client, u16 addr); u32 cx25840_read4(struct i2c_client *client, u16 addr);
int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value); int cx25840_and_or(struct i2c_client *client, u16 addr, unsigned mask, u8 value);
v4l2_std_id cx25840_get_v4lstd(struct i2c_client *client);
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
/* cx25850-firmware.c */ /* cx25850-firmware.c */
......
...@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p) ...@@ -85,7 +85,7 @@ static int decode_vps(u8 * dst, u8 * p)
void cx25840_vbi_setup(struct i2c_client *client) 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 = state->std;
int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation; int hblank,hactive,burst,vblank,vactive,sc,vblank656,src_decimation;
int luma_lpf,uv_lpf, comb; int luma_lpf,uv_lpf, comb;
u32 pll_int,pll_frac,pll_post; u32 pll_int,pll_frac,pll_post;
...@@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -242,7 +242,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg)
0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
0, 0, 0, 0 0, 0, 0, 0
}; };
int is_pal = !(cx25840_get_v4lstd(client) & V4L2_STD_525_60); int is_pal = !(state->std & V4L2_STD_525_60);
int i; int i;
fmt = arg; fmt = arg;
...@@ -279,7 +279,7 @@ int cx25840_vbi(struct i2c_client *client, unsigned int cmd, void *arg) ...@@ -279,7 +279,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_525_60); int is_pal = !(state->std & 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