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

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

parent 2fd3c14c
Loading
Loading
Loading
Loading
+34 −57
Original line number Original line Diff line number Diff line
@@ -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,33 +523,35 @@ 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)
{
{
	struct cx25840_state *state = i2c_get_clientdata(client);
	u8 fmt = 0; 	/* zero is autodetect */
	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) {
		pal_m = 1;
		fmt = 0x5;
		fmt = 0x5;
	} else if (std == V4L2_STD_PAL_N) {
	} else if (state->std == V4L2_STD_PAL_N) {
		fmt = 0x6;
		fmt = 0x6;
	} else if (std == V4L2_STD_PAL_Nc) {
	} else if (state->std == V4L2_STD_PAL_Nc) {
		fmt = 0x7;
		fmt = 0x7;
	} else if (std == V4L2_STD_PAL_60) {
	} else if (state->std == V4L2_STD_PAL_60) {
		fmt = 0x8;
		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)
		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)


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,
	}
	}


	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;
+1 −1
Original line number Original line Diff line number Diff line
@@ -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);
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                                                      */
+3 −3
Original line number Original line Diff line number Diff line
@@ -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)
			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)


	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];