media: cx25840: add pin to pad mapping and output format configuration
This commit adds pin to pad mapping and output format configuration support in CX2584x-series chips to cx25840 driver. This functionality is then used to allow disabling ivtv-specific hacks and configuration values (called a "generic mode"), so cx25840 driver can be used for other devices not needing them without risking compatibility problems. Signed-off-by: Maciej S. Szmigiero <mail@maciej.szmigiero.name> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
parent
763549a3cf
commit
e81a9076b4
|
@ -21,6 +21,9 @@
|
||||||
* CX23888 DIF support for the HVR1850
|
* CX23888 DIF support for the HVR1850
|
||||||
* Copyright (C) 2011 Steven Toth <stoth@kernellabs.com>
|
* Copyright (C) 2011 Steven Toth <stoth@kernellabs.com>
|
||||||
*
|
*
|
||||||
|
* CX2584x pin to pad mapping and output format configuration support are
|
||||||
|
* Copyright (C) 2011 Maciej S. Szmigiero <mail@maciej.szmigiero.name>
|
||||||
|
*
|
||||||
* This program is free software; you can redistribute it and/or
|
* This program is free software; you can redistribute it and/or
|
||||||
* modify it under the terms of the GNU General Public License
|
* modify it under the terms of the GNU General Public License
|
||||||
* as published by the Free Software Foundation; either version 2
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
@ -316,6 +319,217 @@ static int cx23885_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u8 cx25840_function_to_pad(struct i2c_client *client, u8 function)
|
||||||
|
{
|
||||||
|
if (function > CX25840_PAD_VRESET) {
|
||||||
|
v4l_err(client, "invalid function %u, assuming default\n",
|
||||||
|
(unsigned int)function);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void cx25840_set_invert(u8 *pinctrl3, u8 *voutctrl4, u8 function,
|
||||||
|
u8 pin, bool invert)
|
||||||
|
{
|
||||||
|
switch (function) {
|
||||||
|
case CX25840_PAD_IRQ_N:
|
||||||
|
if (invert)
|
||||||
|
*pinctrl3 &= ~2;
|
||||||
|
else
|
||||||
|
*pinctrl3 |= 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PAD_ACTIVE:
|
||||||
|
if (invert)
|
||||||
|
*voutctrl4 |= BIT(2);
|
||||||
|
else
|
||||||
|
*voutctrl4 &= ~BIT(2);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PAD_VACTIVE:
|
||||||
|
if (invert)
|
||||||
|
*voutctrl4 |= BIT(5);
|
||||||
|
else
|
||||||
|
*voutctrl4 &= ~BIT(5);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PAD_CBFLAG:
|
||||||
|
if (invert)
|
||||||
|
*voutctrl4 |= BIT(4);
|
||||||
|
else
|
||||||
|
*voutctrl4 &= ~BIT(4);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PAD_VRESET:
|
||||||
|
if (invert)
|
||||||
|
*voutctrl4 |= BIT(0);
|
||||||
|
else
|
||||||
|
*voutctrl4 &= ~BIT(0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function != CX25840_PAD_DEFAULT)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch (pin) {
|
||||||
|
case CX25840_PIN_DVALID_PRGM0:
|
||||||
|
if (invert)
|
||||||
|
*voutctrl4 |= BIT(6);
|
||||||
|
else
|
||||||
|
*voutctrl4 &= ~BIT(6);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PIN_HRESET_PRGM2:
|
||||||
|
if (invert)
|
||||||
|
*voutctrl4 |= BIT(1);
|
||||||
|
else
|
||||||
|
*voutctrl4 &= ~BIT(1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cx25840_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
|
||||||
|
struct v4l2_subdev_io_pin_config *p)
|
||||||
|
{
|
||||||
|
struct i2c_client *client = v4l2_get_subdevdata(sd);
|
||||||
|
unsigned int i;
|
||||||
|
u8 pinctrl[6], pinconf[10], voutctrl4;
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
pinctrl[i] = cx25840_read(client, 0x114 + i);
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
pinconf[i] = cx25840_read(client, 0x11c + i);
|
||||||
|
|
||||||
|
voutctrl4 = cx25840_read(client, 0x407);
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
u8 strength = p[i].strength;
|
||||||
|
|
||||||
|
if (strength != CX25840_PIN_DRIVE_SLOW &&
|
||||||
|
strength != CX25840_PIN_DRIVE_MEDIUM &&
|
||||||
|
strength != CX25840_PIN_DRIVE_FAST) {
|
||||||
|
|
||||||
|
v4l_err(client,
|
||||||
|
"invalid drive speed for pin %u (%u), assuming fast\n",
|
||||||
|
(unsigned int)p[i].pin,
|
||||||
|
(unsigned int)strength);
|
||||||
|
|
||||||
|
strength = CX25840_PIN_DRIVE_FAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (p[i].pin) {
|
||||||
|
case CX25840_PIN_DVALID_PRGM0:
|
||||||
|
if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE))
|
||||||
|
pinctrl[0] &= ~BIT(6);
|
||||||
|
else
|
||||||
|
pinctrl[0] |= BIT(6);
|
||||||
|
|
||||||
|
pinconf[3] &= 0xf0;
|
||||||
|
pinconf[3] |= cx25840_function_to_pad(client,
|
||||||
|
p[i].function);
|
||||||
|
|
||||||
|
cx25840_set_invert(&pinctrl[3], &voutctrl4,
|
||||||
|
p[i].function,
|
||||||
|
CX25840_PIN_DVALID_PRGM0,
|
||||||
|
p[i].flags &
|
||||||
|
BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW));
|
||||||
|
|
||||||
|
pinctrl[4] &= ~(3 << 2); /* CX25840_PIN_DRIVE_MEDIUM */
|
||||||
|
switch (strength) {
|
||||||
|
case CX25840_PIN_DRIVE_SLOW:
|
||||||
|
pinctrl[4] |= 1 << 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PIN_DRIVE_FAST:
|
||||||
|
pinctrl[4] |= 2 << 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PIN_HRESET_PRGM2:
|
||||||
|
if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE))
|
||||||
|
pinctrl[1] &= ~BIT(0);
|
||||||
|
else
|
||||||
|
pinctrl[1] |= BIT(0);
|
||||||
|
|
||||||
|
pinconf[4] &= 0xf0;
|
||||||
|
pinconf[4] |= cx25840_function_to_pad(client,
|
||||||
|
p[i].function);
|
||||||
|
|
||||||
|
cx25840_set_invert(&pinctrl[3], &voutctrl4,
|
||||||
|
p[i].function,
|
||||||
|
CX25840_PIN_HRESET_PRGM2,
|
||||||
|
p[i].flags &
|
||||||
|
BIT(V4L2_SUBDEV_IO_PIN_ACTIVE_LOW));
|
||||||
|
|
||||||
|
pinctrl[4] &= ~(3 << 2); /* CX25840_PIN_DRIVE_MEDIUM */
|
||||||
|
switch (strength) {
|
||||||
|
case CX25840_PIN_DRIVE_SLOW:
|
||||||
|
pinctrl[4] |= 1 << 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PIN_DRIVE_FAST:
|
||||||
|
pinctrl[4] |= 2 << 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PIN_PLL_CLK_PRGM7:
|
||||||
|
if (p[i].flags & BIT(V4L2_SUBDEV_IO_PIN_DISABLE))
|
||||||
|
pinctrl[2] &= ~BIT(2);
|
||||||
|
else
|
||||||
|
pinctrl[2] |= BIT(2);
|
||||||
|
|
||||||
|
switch (p[i].function) {
|
||||||
|
case CX25840_PAD_XTI_X5_DLL:
|
||||||
|
pinconf[6] = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PAD_AUX_PLL:
|
||||||
|
pinconf[6] = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PAD_VID_PLL:
|
||||||
|
pinconf[6] = 5;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_PAD_XTI:
|
||||||
|
pinconf[6] = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
pinconf[6] = 3;
|
||||||
|
pinconf[6] |=
|
||||||
|
cx25840_function_to_pad(client,
|
||||||
|
p[i].function)
|
||||||
|
<< 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
v4l_err(client, "invalid or unsupported pin %u\n",
|
||||||
|
(unsigned int)p[i].pin);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cx25840_write(client, 0x407, voutctrl4);
|
||||||
|
|
||||||
|
for (i = 0; i < 6; i++)
|
||||||
|
cx25840_write(client, 0x114 + i, pinctrl[i]);
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
cx25840_write(client, 0x11c + i, pinconf[i]);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
|
static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
|
||||||
struct v4l2_subdev_io_pin_config *pincfg)
|
struct v4l2_subdev_io_pin_config *pincfg)
|
||||||
{
|
{
|
||||||
|
@ -323,6 +537,8 @@ static int common_s_io_pin_config(struct v4l2_subdev *sd, size_t n,
|
||||||
|
|
||||||
if (is_cx2388x(state))
|
if (is_cx2388x(state))
|
||||||
return cx23885_s_io_pin_config(sd, n, pincfg);
|
return cx23885_s_io_pin_config(sd, n, pincfg);
|
||||||
|
else if (is_cx2584x(state))
|
||||||
|
return cx25840_s_io_pin_config(sd, n, pincfg);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,6 +605,91 @@ static void cx25840_work_handler(struct work_struct *work)
|
||||||
wake_up(&state->fw_wait);
|
wake_up(&state->fw_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_SET_BIT(state, opt_msk, voc, idx, bit, oneval) \
|
||||||
|
do { \
|
||||||
|
if ((state)->vid_config & (opt_msk)) { \
|
||||||
|
if (((state)->vid_config & (opt_msk)) == \
|
||||||
|
(oneval)) \
|
||||||
|
(voc)[idx] |= BIT(bit); \
|
||||||
|
else \
|
||||||
|
(voc)[idx] &= ~BIT(bit); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* apply current vconfig to hardware regs */
|
||||||
|
static void cx25840_vconfig_apply(struct i2c_client *client)
|
||||||
|
{
|
||||||
|
struct cx25840_state *state = to_state(i2c_get_clientdata(client));
|
||||||
|
u8 voutctrl[3];
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
voutctrl[i] = cx25840_read(client, 0x404 + i);
|
||||||
|
|
||||||
|
if (state->vid_config & CX25840_VCONFIG_FMT_MASK)
|
||||||
|
voutctrl[0] &= ~3;
|
||||||
|
switch (state->vid_config & CX25840_VCONFIG_FMT_MASK) {
|
||||||
|
case CX25840_VCONFIG_FMT_BT656:
|
||||||
|
voutctrl[0] |= 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_VCONFIG_FMT_VIP11:
|
||||||
|
voutctrl[0] |= 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_VCONFIG_FMT_VIP2:
|
||||||
|
voutctrl[0] |= 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_VCONFIG_FMT_BT601:
|
||||||
|
/* zero */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_RES_MASK, voutctrl,
|
||||||
|
0, 2, CX25840_VCONFIG_RES_10BIT);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VBIRAW_MASK, voutctrl,
|
||||||
|
0, 3, CX25840_VCONFIG_VBIRAW_ENABLED);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ANCDATA_MASK, voutctrl,
|
||||||
|
0, 4, CX25840_VCONFIG_ANCDATA_ENABLED);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_TASKBIT_MASK, voutctrl,
|
||||||
|
0, 5, CX25840_VCONFIG_TASKBIT_ONE);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_ACTIVE_MASK, voutctrl,
|
||||||
|
1, 2, CX25840_VCONFIG_ACTIVE_HORIZONTAL);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VALID_MASK, voutctrl,
|
||||||
|
1, 3, CX25840_VCONFIG_VALID_ANDACTIVE);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_HRESETW_MASK, voutctrl,
|
||||||
|
1, 4, CX25840_VCONFIG_HRESETW_PIXCLK);
|
||||||
|
|
||||||
|
if (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK)
|
||||||
|
voutctrl[1] &= ~(3 << 6);
|
||||||
|
switch (state->vid_config & CX25840_VCONFIG_CLKGATE_MASK) {
|
||||||
|
case CX25840_VCONFIG_CLKGATE_VALID:
|
||||||
|
voutctrl[1] |= 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_VCONFIG_CLKGATE_VALIDACTIVE:
|
||||||
|
voutctrl[1] |= 3;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CX25840_VCONFIG_CLKGATE_NONE:
|
||||||
|
/* zero */
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_DCMODE_MASK, voutctrl,
|
||||||
|
2, 0, CX25840_VCONFIG_DCMODE_BYTES);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_IDID0S_MASK, voutctrl,
|
||||||
|
2, 1, CX25840_VCONFIG_IDID0S_LINECNT);
|
||||||
|
CX25840_VCONFIG_SET_BIT(state, CX25840_VCONFIG_VIPCLAMP_MASK, voutctrl,
|
||||||
|
2, 4, CX25840_VCONFIG_VIPCLAMP_ENABLED);
|
||||||
|
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
cx25840_write(client, 0x404 + i, voutctrl[i]);
|
||||||
|
}
|
||||||
|
|
||||||
static void cx25840_initialize(struct i2c_client *client)
|
static void cx25840_initialize(struct i2c_client *client)
|
||||||
{
|
{
|
||||||
DEFINE_WAIT(wait);
|
DEFINE_WAIT(wait);
|
||||||
|
@ -455,6 +756,9 @@ static void cx25840_initialize(struct i2c_client *client)
|
||||||
/* (re)set input */
|
/* (re)set input */
|
||||||
set_input(client, state->vid_input, state->aud_input);
|
set_input(client, state->vid_input, state->aud_input);
|
||||||
|
|
||||||
|
if (state->generic_mode)
|
||||||
|
cx25840_vconfig_apply(client);
|
||||||
|
|
||||||
/* start microcontroller */
|
/* start microcontroller */
|
||||||
cx25840_and_or(client, 0x803, ~0x10, 0x10);
|
cx25840_and_or(client, 0x803, ~0x10, 0x10);
|
||||||
}
|
}
|
||||||
|
@ -809,13 +1113,20 @@ void cx25840_std_setup(struct i2c_client *client)
|
||||||
else
|
else
|
||||||
cx25840_write(client, 0x49f, 0x14);
|
cx25840_write(client, 0x49f, 0x14);
|
||||||
|
|
||||||
|
/* generic mode uses the values that the chip autoconfig would set */
|
||||||
if (std & V4L2_STD_625_50) {
|
if (std & V4L2_STD_625_50) {
|
||||||
hblank = 132;
|
hblank = 132;
|
||||||
hactive = 720;
|
hactive = 720;
|
||||||
burst = 93;
|
burst = 93;
|
||||||
|
if (state->generic_mode) {
|
||||||
|
vblank = 34;
|
||||||
|
vactive = 576;
|
||||||
|
vblank656 = 38;
|
||||||
|
} else {
|
||||||
vblank = 36;
|
vblank = 36;
|
||||||
vactive = 580;
|
vactive = 580;
|
||||||
vblank656 = 40;
|
vblank656 = 40;
|
||||||
|
}
|
||||||
src_decimation = 0x21f;
|
src_decimation = 0x21f;
|
||||||
luma_lpf = 2;
|
luma_lpf = 2;
|
||||||
|
|
||||||
|
@ -824,6 +1135,10 @@ void cx25840_std_setup(struct i2c_client *client)
|
||||||
comb = 0;
|
comb = 0;
|
||||||
sc = 0x0a425f;
|
sc = 0x0a425f;
|
||||||
} else if (std == V4L2_STD_PAL_Nc) {
|
} else if (std == V4L2_STD_PAL_Nc) {
|
||||||
|
if (state->generic_mode) {
|
||||||
|
burst = 95;
|
||||||
|
luma_lpf = 1;
|
||||||
|
}
|
||||||
uv_lpf = 1;
|
uv_lpf = 1;
|
||||||
comb = 0x20;
|
comb = 0x20;
|
||||||
sc = 556453;
|
sc = 556453;
|
||||||
|
@ -838,12 +1153,19 @@ void cx25840_std_setup(struct i2c_client *client)
|
||||||
vactive = 487;
|
vactive = 487;
|
||||||
luma_lpf = 1;
|
luma_lpf = 1;
|
||||||
uv_lpf = 1;
|
uv_lpf = 1;
|
||||||
|
if (state->generic_mode) {
|
||||||
|
vblank = 20;
|
||||||
|
vblank656 = 24;
|
||||||
|
}
|
||||||
|
|
||||||
src_decimation = 0x21f;
|
src_decimation = 0x21f;
|
||||||
if (std == V4L2_STD_PAL_60) {
|
if (std == V4L2_STD_PAL_60) {
|
||||||
|
if (!state->generic_mode) {
|
||||||
vblank = 26;
|
vblank = 26;
|
||||||
vblank656 = 26;
|
vblank656 = 26;
|
||||||
burst = 0x5b;
|
burst = 0x5b;
|
||||||
|
} else
|
||||||
|
burst = 0x59;
|
||||||
luma_lpf = 2;
|
luma_lpf = 2;
|
||||||
comb = 0x20;
|
comb = 0x20;
|
||||||
sc = 688739;
|
sc = 688739;
|
||||||
|
@ -854,8 +1176,10 @@ void cx25840_std_setup(struct i2c_client *client)
|
||||||
comb = 0x20;
|
comb = 0x20;
|
||||||
sc = 555452;
|
sc = 555452;
|
||||||
} else {
|
} else {
|
||||||
|
if (!state->generic_mode) {
|
||||||
vblank = 26;
|
vblank = 26;
|
||||||
vblank656 = 26;
|
vblank656 = 26;
|
||||||
|
}
|
||||||
burst = 0x5b;
|
burst = 0x5b;
|
||||||
comb = 0x66;
|
comb = 0x66;
|
||||||
sc = 556063;
|
sc = 556063;
|
||||||
|
@ -1403,7 +1727,9 @@ static int cx25840_set_fmt(struct v4l2_subdev *sd,
|
||||||
Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
|
Hsrc |= (cx25840_read(client, 0x471) & 0xf0) >> 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
Vlines = fmt->height + (is_50Hz ? 4 : 7);
|
Vlines = fmt->height;
|
||||||
|
if (!state->generic_mode)
|
||||||
|
Vlines += is_50Hz ? 4 : 7;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We keep 1 margin for the Vsrc < Vlines check since the
|
* We keep 1 margin for the Vsrc < Vlines check since the
|
||||||
|
@ -1647,8 +1973,71 @@ static void log_audio_status(struct i2c_client *client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_OPTION(state, cfg_in, opt_msk) \
|
||||||
|
do { \
|
||||||
|
if ((cfg_in) & (opt_msk)) { \
|
||||||
|
(state)->vid_config &= ~(opt_msk); \
|
||||||
|
(state)->vid_config |= (cfg_in) & (opt_msk); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/* apply incoming options to the current vconfig */
|
||||||
|
static void cx25840_vconfig_add(struct cx25840_state *state, u32 cfg_in)
|
||||||
|
{
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_FMT_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_RES_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VBIRAW_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ANCDATA_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_TASKBIT_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_ACTIVE_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VALID_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_HRESETW_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_CLKGATE_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_DCMODE_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_IDID0S_MASK);
|
||||||
|
CX25840_VCONFIG_OPTION(state, cfg_in, CX25840_VCONFIG_VIPCLAMP_MASK);
|
||||||
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initializes the device in the generic mode.
|
||||||
|
* For cx2584x chips also adds additional video output settings provided
|
||||||
|
* in @val parameter (CX25840_VCONFIG_*).
|
||||||
|
*
|
||||||
|
* The generic mode disables some of the ivtv-related hacks in this driver.
|
||||||
|
* For cx2584x chips it also enables setting video output configuration while
|
||||||
|
* setting it according to datasheet defaults by default.
|
||||||
|
*/
|
||||||
|
static int cx25840_init(struct v4l2_subdev *sd, u32 val)
|
||||||
|
{
|
||||||
|
struct cx25840_state *state = to_state(sd);
|
||||||
|
|
||||||
|
state->generic_mode = true;
|
||||||
|
|
||||||
|
if (is_cx2584x(state)) {
|
||||||
|
/* set datasheet video output defaults */
|
||||||
|
state->vid_config = CX25840_VCONFIG_FMT_BT656 |
|
||||||
|
CX25840_VCONFIG_RES_8BIT |
|
||||||
|
CX25840_VCONFIG_VBIRAW_DISABLED |
|
||||||
|
CX25840_VCONFIG_ANCDATA_ENABLED |
|
||||||
|
CX25840_VCONFIG_TASKBIT_ONE |
|
||||||
|
CX25840_VCONFIG_ACTIVE_HORIZONTAL |
|
||||||
|
CX25840_VCONFIG_VALID_NORMAL |
|
||||||
|
CX25840_VCONFIG_HRESETW_NORMAL |
|
||||||
|
CX25840_VCONFIG_CLKGATE_NONE |
|
||||||
|
CX25840_VCONFIG_DCMODE_DWORDS |
|
||||||
|
CX25840_VCONFIG_IDID0S_NORMAL |
|
||||||
|
CX25840_VCONFIG_VIPCLAMP_DISABLED;
|
||||||
|
|
||||||
|
/* add additional settings */
|
||||||
|
cx25840_vconfig_add(state, val);
|
||||||
|
} else /* TODO: generic mode needs to be developed for other chips */
|
||||||
|
WARN_ON(1);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
|
static int cx25840_reset(struct v4l2_subdev *sd, u32 val)
|
||||||
{
|
{
|
||||||
struct cx25840_state *state = to_state(sd);
|
struct cx25840_state *state = to_state(sd);
|
||||||
|
@ -1860,6 +2249,11 @@ static int cx25840_s_video_routing(struct v4l2_subdev *sd,
|
||||||
if (is_cx23888(state))
|
if (is_cx23888(state))
|
||||||
cx23888_std_setup(client);
|
cx23888_std_setup(client);
|
||||||
|
|
||||||
|
if (is_cx2584x(state) && state->generic_mode && config) {
|
||||||
|
cx25840_vconfig_add(state, config);
|
||||||
|
cx25840_vconfig_apply(client);
|
||||||
|
}
|
||||||
|
|
||||||
return set_input(client, input, state->aud_input);
|
return set_input(client, input, state->aud_input);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5067,6 +5461,8 @@ static const struct v4l2_ctrl_ops cx25840_ctrl_ops = {
|
||||||
static const struct v4l2_subdev_core_ops cx25840_core_ops = {
|
static const struct v4l2_subdev_core_ops cx25840_core_ops = {
|
||||||
.log_status = cx25840_log_status,
|
.log_status = cx25840_log_status,
|
||||||
.reset = cx25840_reset,
|
.reset = cx25840_reset,
|
||||||
|
/* calling the (optional) init op will turn on the generic mode */
|
||||||
|
.init = cx25840_init,
|
||||||
.load_fw = cx25840_load_fw,
|
.load_fw = cx25840_load_fw,
|
||||||
.s_io_pin_config = common_s_io_pin_config,
|
.s_io_pin_config = common_s_io_pin_config,
|
||||||
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
#ifdef CONFIG_VIDEO_ADV_DEBUG
|
||||||
|
|
|
@ -53,10 +53,15 @@ enum cx25840_media_pads {
|
||||||
* @mute: audio mute V4L2 control (non-cx2583x devices only)
|
* @mute: audio mute V4L2 control (non-cx2583x devices only)
|
||||||
* @pvr150_workaround: whether we enable workaround for Hauppauge PVR150
|
* @pvr150_workaround: whether we enable workaround for Hauppauge PVR150
|
||||||
* hardware bug (audio dropping out)
|
* hardware bug (audio dropping out)
|
||||||
|
* @generic_mode: whether we disable ivtv-specific hacks
|
||||||
|
* this mode gets turned on when the bridge driver calls
|
||||||
|
* cx25840 subdevice init core op
|
||||||
* @radio: set if we are currently in the radio mode, otherwise
|
* @radio: set if we are currently in the radio mode, otherwise
|
||||||
* the current mode is non-radio (that is, video)
|
* the current mode is non-radio (that is, video)
|
||||||
* @std: currently set video standard
|
* @std: currently set video standard
|
||||||
* @vid_input: currently set video input
|
* @vid_input: currently set video input
|
||||||
|
* @vid_config: currently set video output configuration
|
||||||
|
* only used in the generic mode
|
||||||
* @aud_input: currently set audio input
|
* @aud_input: currently set audio input
|
||||||
* @audclk_freq: currently set audio sample rate
|
* @audclk_freq: currently set audio sample rate
|
||||||
* @audmode: currently set audio mode (when in non-radio mode)
|
* @audmode: currently set audio mode (when in non-radio mode)
|
||||||
|
@ -83,9 +88,11 @@ struct cx25840_state {
|
||||||
struct v4l2_ctrl *mute;
|
struct v4l2_ctrl *mute;
|
||||||
};
|
};
|
||||||
int pvr150_workaround;
|
int pvr150_workaround;
|
||||||
|
bool generic_mode;
|
||||||
int radio;
|
int radio;
|
||||||
v4l2_std_id std;
|
v4l2_std_id std;
|
||||||
enum cx25840_video_input vid_input;
|
enum cx25840_video_input vid_input;
|
||||||
|
u32 vid_config;
|
||||||
enum cx25840_audio_input aud_input;
|
enum cx25840_audio_input aud_input;
|
||||||
u32 audclk_freq;
|
u32 audclk_freq;
|
||||||
int audmode;
|
int audmode;
|
||||||
|
@ -118,6 +125,14 @@ static inline bool is_cx2583x(struct cx25840_state *state)
|
||||||
state->id == CX25837;
|
state->id == CX25837;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool is_cx2584x(struct cx25840_state *state)
|
||||||
|
{
|
||||||
|
return state->id == CX25840 ||
|
||||||
|
state->id == CX25841 ||
|
||||||
|
state->id == CX25842 ||
|
||||||
|
state->id == CX25843;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool is_cx231xx(struct cx25840_state *state)
|
static inline bool is_cx231xx(struct cx25840_state *state)
|
||||||
{
|
{
|
||||||
return state->id == CX2310X_AV;
|
return state->id == CX2310X_AV;
|
||||||
|
|
|
@ -95,6 +95,7 @@ int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
|
||||||
memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
|
memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
|
||||||
svbi->service_set = 0;
|
svbi->service_set = 0;
|
||||||
/* we're done if raw VBI is active */
|
/* we're done if raw VBI is active */
|
||||||
|
/* TODO: this will have to be changed for generic_mode VBI */
|
||||||
if ((cx25840_read(client, 0x404) & 0x10) == 0)
|
if ((cx25840_read(client, 0x404) & 0x10) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
@ -137,6 +138,7 @@ int cx25840_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
|
||||||
cx25840_write(client, 0x54f, vbi_offset);
|
cx25840_write(client, 0x54f, vbi_offset);
|
||||||
else
|
else
|
||||||
cx25840_write(client, 0x47f, vbi_offset);
|
cx25840_write(client, 0x47f, vbi_offset);
|
||||||
|
/* TODO: this will have to be changed for generic_mode VBI */
|
||||||
cx25840_write(client, 0x404, 0x2e);
|
cx25840_write(client, 0x404, 0x2e);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -157,6 +159,7 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
|
||||||
cx25840_std_setup(client);
|
cx25840_std_setup(client);
|
||||||
|
|
||||||
/* Sliced VBI */
|
/* Sliced VBI */
|
||||||
|
/* TODO: this will have to be changed for generic_mode VBI */
|
||||||
cx25840_write(client, 0x404, 0x32); /* Ancillary data */
|
cx25840_write(client, 0x404, 0x32); /* Ancillary data */
|
||||||
cx25840_write(client, 0x406, 0x13);
|
cx25840_write(client, 0x406, 0x13);
|
||||||
if (is_cx23888(state))
|
if (is_cx23888(state))
|
||||||
|
@ -211,6 +214,7 @@ int cx25840_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
|
||||||
}
|
}
|
||||||
|
|
||||||
cx25840_write(client, state->vbi_regs_offset + 0x43c, 0x16);
|
cx25840_write(client, state->vbi_regs_offset + 0x43c, 0x16);
|
||||||
|
/* TODO: this will have to be changed for generic_mode VBI */
|
||||||
if (is_cx23888(state))
|
if (is_cx23888(state))
|
||||||
cx25840_write(client, 0x428, is_pal ? 0x2a : 0x22);
|
cx25840_write(client, 0x428, is_pal ? 0x2a : 0x22);
|
||||||
else
|
else
|
||||||
|
|
|
@ -82,6 +82,81 @@ enum cx25840_video_input {
|
||||||
CX25840_DIF_ON = 0x80000400,
|
CX25840_DIF_ON = 0x80000400,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The defines below are used to set the chip video output settings
|
||||||
|
* in the generic mode that can be enabled by calling the subdevice
|
||||||
|
* init core op.
|
||||||
|
*
|
||||||
|
* The requested settings can be passed to the init core op as
|
||||||
|
* @val parameter and to the s_routing video op as @config parameter.
|
||||||
|
*
|
||||||
|
* For details please refer to the section 3.7 Video Output Formatting and
|
||||||
|
* to Video Out Control 1 to 4 registers in the section 5.6 Video Decoder Core
|
||||||
|
* of the chip datasheet.
|
||||||
|
*/
|
||||||
|
#define CX25840_VCONFIG_FMT_SHIFT 0
|
||||||
|
#define CX25840_VCONFIG_FMT_MASK GENMASK(2, 0)
|
||||||
|
#define CX25840_VCONFIG_FMT_BT601 BIT(0)
|
||||||
|
#define CX25840_VCONFIG_FMT_BT656 BIT(1)
|
||||||
|
#define CX25840_VCONFIG_FMT_VIP11 GENMASK(1, 0)
|
||||||
|
#define CX25840_VCONFIG_FMT_VIP2 BIT(2)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_RES_SHIFT 3
|
||||||
|
#define CX25840_VCONFIG_RES_MASK GENMASK(4, 3)
|
||||||
|
#define CX25840_VCONFIG_RES_8BIT BIT(3)
|
||||||
|
#define CX25840_VCONFIG_RES_10BIT BIT(4)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_VBIRAW_SHIFT 5
|
||||||
|
#define CX25840_VCONFIG_VBIRAW_MASK GENMASK(6, 5)
|
||||||
|
#define CX25840_VCONFIG_VBIRAW_DISABLED BIT(5)
|
||||||
|
#define CX25840_VCONFIG_VBIRAW_ENABLED BIT(6)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_ANCDATA_SHIFT 7
|
||||||
|
#define CX25840_VCONFIG_ANCDATA_MASK GENMASK(8, 7)
|
||||||
|
#define CX25840_VCONFIG_ANCDATA_DISABLED BIT(7)
|
||||||
|
#define CX25840_VCONFIG_ANCDATA_ENABLED BIT(8)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_TASKBIT_SHIFT 9
|
||||||
|
#define CX25840_VCONFIG_TASKBIT_MASK GENMASK(10, 9)
|
||||||
|
#define CX25840_VCONFIG_TASKBIT_ZERO BIT(9)
|
||||||
|
#define CX25840_VCONFIG_TASKBIT_ONE BIT(10)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_ACTIVE_SHIFT 11
|
||||||
|
#define CX25840_VCONFIG_ACTIVE_MASK GENMASK(12, 11)
|
||||||
|
#define CX25840_VCONFIG_ACTIVE_COMPOSITE BIT(11)
|
||||||
|
#define CX25840_VCONFIG_ACTIVE_HORIZONTAL BIT(12)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_VALID_SHIFT 13
|
||||||
|
#define CX25840_VCONFIG_VALID_MASK GENMASK(14, 13)
|
||||||
|
#define CX25840_VCONFIG_VALID_NORMAL BIT(13)
|
||||||
|
#define CX25840_VCONFIG_VALID_ANDACTIVE BIT(14)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_HRESETW_SHIFT 15
|
||||||
|
#define CX25840_VCONFIG_HRESETW_MASK GENMASK(16, 15)
|
||||||
|
#define CX25840_VCONFIG_HRESETW_NORMAL BIT(15)
|
||||||
|
#define CX25840_VCONFIG_HRESETW_PIXCLK BIT(16)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_CLKGATE_SHIFT 17
|
||||||
|
#define CX25840_VCONFIG_CLKGATE_MASK GENMASK(18, 17)
|
||||||
|
#define CX25840_VCONFIG_CLKGATE_NONE BIT(17)
|
||||||
|
#define CX25840_VCONFIG_CLKGATE_VALID BIT(18)
|
||||||
|
#define CX25840_VCONFIG_CLKGATE_VALIDACTIVE GENMASK(18, 17)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_DCMODE_SHIFT 19
|
||||||
|
#define CX25840_VCONFIG_DCMODE_MASK GENMASK(20, 19)
|
||||||
|
#define CX25840_VCONFIG_DCMODE_DWORDS BIT(19)
|
||||||
|
#define CX25840_VCONFIG_DCMODE_BYTES BIT(20)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_IDID0S_SHIFT 21
|
||||||
|
#define CX25840_VCONFIG_IDID0S_MASK GENMASK(22, 21)
|
||||||
|
#define CX25840_VCONFIG_IDID0S_NORMAL BIT(21)
|
||||||
|
#define CX25840_VCONFIG_IDID0S_LINECNT BIT(22)
|
||||||
|
|
||||||
|
#define CX25840_VCONFIG_VIPCLAMP_SHIFT 23
|
||||||
|
#define CX25840_VCONFIG_VIPCLAMP_MASK GENMASK(24, 23)
|
||||||
|
#define CX25840_VCONFIG_VIPCLAMP_ENABLED BIT(23)
|
||||||
|
#define CX25840_VCONFIG_VIPCLAMP_DISABLED BIT(24)
|
||||||
|
|
||||||
enum cx25840_audio_input {
|
enum cx25840_audio_input {
|
||||||
/* Audio inputs: serial or In4-In8 */
|
/* Audio inputs: serial or In4-In8 */
|
||||||
CX25840_AUDIO_SERIAL,
|
CX25840_AUDIO_SERIAL,
|
||||||
|
@ -109,7 +184,7 @@ enum cx25840_io_pin {
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cx25840_io_pad {
|
enum cx25840_io_pad {
|
||||||
/* Output pads */
|
/* Output pads, these must match the actual chip register values */
|
||||||
CX25840_PAD_DEFAULT = 0,
|
CX25840_PAD_DEFAULT = 0,
|
||||||
CX25840_PAD_ACTIVE,
|
CX25840_PAD_ACTIVE,
|
||||||
CX25840_PAD_VACTIVE,
|
CX25840_PAD_VACTIVE,
|
||||||
|
|
Loading…
Reference in New Issue