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

V4L/DVB (10714): zoran et al: convert zoran i2c modules to V4L2.

The zoran i2c modules were still using V4L1 internally. Replace this
with V4L2. Also deleted saa7111.c and saa7114.c, we use saa7115.c instead.
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
[mchehab@redhat.com: fix v4l2_ctrl_query_fill_std merge conflict]
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 84c1b094
......@@ -307,38 +307,18 @@ config VIDEO_TCM825X
config VIDEO_SAA7110
tristate "Philips SAA7110 video decoder"
depends on VIDEO_V4L1 && I2C
depends on VIDEO_V4L2 && I2C
---help---
Support for the Philips SAA7110 video decoders.
To compile this driver as a module, choose M here: the
module will be called saa7110.
config VIDEO_SAA7111
tristate "Philips SAA7111 video decoder"
depends on VIDEO_V4L1 && I2C
---help---
Support for the Philips SAA711 video decoder.
To compile this driver as a module, choose M here: the
module will be called saa7111.
config VIDEO_SAA7114
tristate "Philips SAA7114 video decoder"
depends on VIDEO_V4L1 && I2C
---help---
Support for the Philips SAA7114 video decoder. This driver
is used only on Zoran driver and should be moved soon to
SAA711x module.
To compile this driver as a module, choose M here: the
module will be called saa7114.
config VIDEO_SAA711X
tristate "Philips SAA7113/4/5 video decoders"
tristate "Philips SAA7111/3/4/5 video decoders"
depends on VIDEO_V4L2 && I2C
---help---
Support for the Philips SAA7113/4/5 video decoders.
Support for the Philips SAA7111/3/4/5 video decoders.
To compile this driver as a module, choose M here: the
module will be called saa7115.
......@@ -639,7 +619,7 @@ config VIDEO_MXB
depends on PCI && VIDEO_V4L1 && I2C
select VIDEO_SAA7146_VV
select VIDEO_TUNER
select VIDEO_SAA7115 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO
......
......@@ -43,8 +43,6 @@ obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
obj-$(CONFIG_VIDEO_SAA7111) += saa7111.o
obj-$(CONFIG_VIDEO_SAA7114) += saa7114.o
obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
......
......@@ -52,9 +52,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
struct adv7170 {
unsigned char reg[128];
int norm;
v4l2_std_id norm;
int input;
int enable;
int bright;
int contrast;
int hue;
......@@ -62,7 +61,6 @@ struct adv7170 {
};
static char *inputs[] = { "pass_through", "play_back" };
static char *norms[] = { "PAL", "NTSC" };
/* ----------------------------------------------------------------------- */
......@@ -191,7 +189,7 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg)
struct adv7170 *encoder = i2c_get_clientdata(client);
switch (cmd) {
case 0:
case VIDIOC_INT_INIT:
#if 0
/* This is just for testing!!! */
adv7170_write_block(client, init_common,
......@@ -201,63 +199,47 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg)
#endif
break;
case ENCODER_GET_CAPABILITIES:
case VIDIOC_INT_S_STD_OUTPUT:
{
struct video_encoder_capability *cap = arg;
v4l2_std_id iarg = *(v4l2_std_id *) arg;
cap->flags = VIDEO_ENCODER_PAL |
VIDEO_ENCODER_NTSC;
cap->inputs = 2;
cap->outputs = 1;
break;
}
case ENCODER_SET_NORM:
{
int iarg = *(int *) arg;
v4l_dbg(1, debug, client, "set norm %d\n", iarg);
v4l_dbg(1, debug, client, "set norm %llx\n", iarg);
switch (iarg) {
case VIDEO_MODE_NTSC:
if (iarg & V4L2_STD_NTSC) {
adv7170_write_block(client, init_NTSC,
sizeof(init_NTSC));
if (encoder->input == 0)
adv7170_write(client, 0x02, 0x0e); // Enable genlock
adv7170_write(client, 0x07, TR0MODE | TR0RST);
adv7170_write(client, 0x07, TR0MODE);
break;
case VIDEO_MODE_PAL:
} else if (iarg & V4L2_STD_PAL) {
adv7170_write_block(client, init_PAL,
sizeof(init_PAL));
if (encoder->input == 0)
adv7170_write(client, 0x02, 0x0e); // Enable genlock
adv7170_write(client, 0x07, TR0MODE | TR0RST);
adv7170_write(client, 0x07, TR0MODE);
break;
default:
v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
} else {
v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg);
return -EINVAL;
}
v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
v4l_dbg(1, debug, client, "switched to %llx\n", iarg);
encoder->norm = iarg;
break;
}
case ENCODER_SET_INPUT:
case VIDIOC_INT_S_VIDEO_ROUTING:
{
int iarg = *(int *) arg;
struct v4l2_routing *route = arg;
/* RJ: *iarg = 0: input is from decoder
*iarg = 1: input is from ZR36060
*iarg = 2: color bar */
v4l_dbg(1, debug, client, "set input from %s\n",
iarg == 0 ? "decoder" : "ZR36060");
route->input == 0 ? "decoder" : "ZR36060");
switch (iarg) {
switch (route->input) {
case 0:
adv7170_write(client, 0x01, 0x20);
adv7170_write(client, 0x08, TR1CAPT); /* TR1 */
......@@ -277,30 +259,11 @@ static int adv7170_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
default:
v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
return -EINVAL;
}
v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
encoder->input = iarg;
break;
}
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
/* not much choice of outputs */
if (*iarg != 0) {
v4l_dbg(1, debug, client, "illegal input: %d\n", route->input);
return -EINVAL;
}
break;
}
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]);
encoder->input = route->input;
break;
}
......@@ -337,9 +300,8 @@ static int adv7170_probe(struct i2c_client *client,
encoder = kzalloc(sizeof(struct adv7170), GFP_KERNEL);
if (encoder == NULL)
return -ENOMEM;
encoder->norm = VIDEO_MODE_NTSC;
encoder->norm = V4L2_STD_NTSC;
encoder->input = 0;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
i = adv7170_write_block(client, init_NTSC, sizeof(init_NTSC));
......
......@@ -46,9 +46,8 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* ----------------------------------------------------------------------- */
struct adv7175 {
int norm;
v4l2_std_id norm;
int input;
int enable;
int bright;
int contrast;
int hue;
......@@ -59,7 +58,6 @@ struct adv7175 {
#define I2C_ADV7176 0x54
static char *inputs[] = { "pass_through", "play_back", "color_bar" };
static char *norms[] = { "PAL", "NTSC", "SECAM->PAL (may not work!)" };
/* ----------------------------------------------------------------------- */
......@@ -189,7 +187,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
struct adv7175 *encoder = i2c_get_clientdata(client);
switch (cmd) {
case 0:
case VIDIOC_INT_INIT:
/* This is just for testing!!! */
adv7175_write_block(client, init_common,
sizeof(init_common));
......@@ -197,42 +195,25 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
adv7175_write(client, 0x07, TR0MODE);
break;
case ENCODER_GET_CAPABILITIES:
case VIDIOC_INT_S_STD_OUTPUT:
{
struct video_encoder_capability *cap = arg;
v4l2_std_id iarg = *(v4l2_std_id *) arg;
cap->flags = VIDEO_ENCODER_PAL |
VIDEO_ENCODER_NTSC |
VIDEO_ENCODER_SECAM; /* well, hacky */
cap->inputs = 2;
cap->outputs = 1;
break;
}
case ENCODER_SET_NORM:
{
int iarg = *(int *) arg;
switch (iarg) {
case VIDEO_MODE_NTSC:
if (iarg & V4L2_STD_NTSC) {
adv7175_write_block(client, init_ntsc,
sizeof(init_ntsc));
if (encoder->input == 0)
adv7175_write(client, 0x0d, 0x4f); // Enable genlock
adv7175_write(client, 0x07, TR0MODE | TR0RST);
adv7175_write(client, 0x07, TR0MODE);
break;
case VIDEO_MODE_PAL:
} else if (iarg & V4L2_STD_PAL) {
adv7175_write_block(client, init_pal,
sizeof(init_pal));
if (encoder->input == 0)
adv7175_write(client, 0x0d, 0x4f); // Enable genlock
adv7175_write(client, 0x07, TR0MODE | TR0RST);
adv7175_write(client, 0x07, TR0MODE);
break;
case VIDEO_MODE_SECAM: // WARNING! ADV7176 does not support SECAM.
} else if (iarg & V4L2_STD_SECAM) {
/* This is an attempt to convert
* SECAM->PAL (typically it does not work
* due to genlock: when decoder is in SECAM
......@@ -245,33 +226,32 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
adv7175_write(client, 0x0d, 0x49); // Disable genlock
adv7175_write(client, 0x07, TR0MODE | TR0RST);
adv7175_write(client, 0x07, TR0MODE);
break;
default:
v4l_dbg(1, debug, client, "illegal norm: %d\n", iarg);
} else {
v4l_dbg(1, debug, client, "illegal norm: %llx\n", iarg);
return -EINVAL;
}
v4l_dbg(1, debug, client, "switched to %s\n", norms[iarg]);
v4l_dbg(1, debug, client, "switched to %llx\n", iarg);
encoder->norm = iarg;
break;
}
case ENCODER_SET_INPUT:
case VIDIOC_INT_S_VIDEO_ROUTING:
{
int iarg = *(int *) arg;
struct v4l2_routing *route = arg;
/* RJ: *iarg = 0: input is from SAA7110
*iarg = 1: input is from ZR36060
*iarg = 2: color bar */
switch (iarg) {
switch (route->input) {
case 0:
adv7175_write(client, 0x01, 0x00);
if (encoder->norm == VIDEO_MODE_NTSC)
if (encoder->norm & V4L2_STD_NTSC)
set_subcarrier_freq(client, 1);
adv7175_write(client, 0x0c, TR1CAPT); /* TR1 */
if (encoder->norm == VIDEO_MODE_SECAM)
if (encoder->norm & V4L2_STD_SECAM)
adv7175_write(client, 0x0d, 0x49); // Disable genlock
else
adv7175_write(client, 0x0d, 0x4f); // Enable genlock
......@@ -283,7 +263,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
case 1:
adv7175_write(client, 0x01, 0x00);
if (encoder->norm == VIDEO_MODE_NTSC)
if (encoder->norm & V4L2_STD_NTSC)
set_subcarrier_freq(client, 0);
adv7175_write(client, 0x0c, TR1PLAY); /* TR1 */
......@@ -296,7 +276,7 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
case 2:
adv7175_write(client, 0x01, 0x80);
if (encoder->norm == VIDEO_MODE_NTSC)
if (encoder->norm & V4L2_STD_NTSC)
set_subcarrier_freq(client, 0);
adv7175_write(client, 0x0d, 0x49);
......@@ -306,29 +286,11 @@ static int adv7175_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
default:
v4l_dbg(1, debug, client, "illegal input: %d\n", iarg);
v4l_dbg(1, debug, client, "illegal input: %d\n", route->input);
return -EINVAL;
}
v4l_dbg(1, debug, client, "switched to %s\n", inputs[iarg]);
encoder->input = iarg;
break;
}
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
/* not much choice of outputs */
if (*iarg != 0)
return -EINVAL;
break;
}
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
v4l_dbg(1, debug, client, "switched to %s\n", inputs[route->input]);
encoder->input = route->input;
break;
}
......@@ -369,9 +331,8 @@ static int adv7175_probe(struct i2c_client *client,
encoder = kzalloc(sizeof(struct adv7175), GFP_KERNEL);
if (encoder == NULL)
return -ENOMEM;
encoder->norm = VIDEO_MODE_PAL;
encoder->norm = V4L2_STD_NTSC;
encoder->input = 0;
encoder->enable = 1;
i2c_set_clientdata(client, encoder);
i = adv7175_write_block(client, init_common, sizeof(init_common));
......
......@@ -54,7 +54,7 @@ struct bt819 {
unsigned char reg[32];
int initialized;
int norm;
v4l2_std_id norm;
int input;
int enable;
int bright;
......@@ -178,7 +178,7 @@ static int bt819_init(struct i2c_client *client)
0x1a, 0x80, /* 0x1a ADC Interface */
};
struct timing *timing = &timing_data[decoder->norm];
struct timing *timing = &timing_data[(decoder->norm & V4L2_STD_525_60) ? 1 : 0];
init[0x03 * 2 - 1] =
(((timing->vdelay >> 8) & 0x03) << 6) |
......@@ -192,7 +192,7 @@ static int bt819_init(struct i2c_client *client)
init[0x08 * 2 - 1] = timing->hscale >> 8;
init[0x09 * 2 - 1] = timing->hscale & 0xff;
/* 0x15 in array is address 0x19 */
init[0x15 * 2 - 1] = (decoder->norm == 0) ? 115 : 93; /* Chroma burst delay */
init[0x15 * 2 - 1] = (decoder->norm & V4L2_STD_625_50) ? 115 : 93; /* Chroma burst delay */
/* reset */
bt819_write(client, 0x1f, 0x00);
mdelay(1);
......@@ -215,121 +215,93 @@ static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg)
}
switch (cmd) {
case 0:
case VIDIOC_INT_INIT:
/* This is just for testing!!! */
bt819_init(client);
break;
case DECODER_GET_CAPABILITIES:
{
struct video_decoder_capability *cap = arg;
cap->flags = VIDEO_DECODER_PAL |
VIDEO_DECODER_NTSC |
VIDEO_DECODER_AUTO |
VIDEO_DECODER_CCIR;
cap->inputs = 8;
cap->outputs = 1;
break;
}
case DECODER_GET_STATUS:
{
case VIDIOC_QUERYSTD:
case VIDIOC_INT_G_INPUT_STATUS: {
int *iarg = arg;
v4l2_std_id *istd = arg;
int status;
int res;
int res = V4L2_IN_ST_NO_SIGNAL;
v4l2_std_id std;
status = bt819_read(client, 0x00);
res = 0;
if ((status & 0x80))
res |= DECODER_STATUS_GOOD;
res = 0;
switch (decoder->norm) {
case VIDEO_MODE_NTSC:
res |= DECODER_STATUS_NTSC;
break;
case VIDEO_MODE_PAL:
res |= DECODER_STATUS_PAL;
break;
default:
case VIDEO_MODE_AUTO:
if ((status & 0x10))
res |= DECODER_STATUS_PAL;
else
res |= DECODER_STATUS_NTSC;
break;
}
res |= DECODER_STATUS_COLOR;
*iarg = res;
if ((status & 0x10))
std = V4L2_STD_PAL;
else
std = V4L2_STD_NTSC;
if (cmd == VIDIOC_QUERYSTD)
*istd = std;
else
*iarg = res;
v4l_dbg(1, debug, client, "get status %x\n", *iarg);
break;
}
case DECODER_SET_NORM:
case VIDIOC_S_STD:
{
int *iarg = arg;
v4l2_std_id *iarg = arg;
struct timing *timing = NULL;
v4l_dbg(1, debug, client, "set norm %x\n", *iarg);
v4l_dbg(1, debug, client, "set norm %llx\n", *iarg);
switch (*iarg) {
case VIDEO_MODE_NTSC:
if (*iarg & V4L2_STD_NTSC) {
bt819_setbit(client, 0x01, 0, 1);
bt819_setbit(client, 0x01, 1, 0);
bt819_setbit(client, 0x01, 5, 0);
bt819_write(client, 0x18, 0x68);
bt819_write(client, 0x19, 0x5d);
/* bt819_setbit(client, 0x1a, 5, 1); */
timing = &timing_data[VIDEO_MODE_NTSC];
break;
case VIDEO_MODE_PAL:
timing = &timing_data[1];
} else if (*iarg & V4L2_STD_PAL) {
bt819_setbit(client, 0x01, 0, 1);
bt819_setbit(client, 0x01, 1, 1);
bt819_setbit(client, 0x01, 5, 1);
bt819_write(client, 0x18, 0x7f);
bt819_write(client, 0x19, 0x72);
/* bt819_setbit(client, 0x1a, 5, 0); */
timing = &timing_data[VIDEO_MODE_PAL];
break;
case VIDEO_MODE_AUTO:
bt819_setbit(client, 0x01, 0, 0);
bt819_setbit(client, 0x01, 1, 0);
break;
default:
v4l_dbg(1, debug, client, "unsupported norm %x\n", *iarg);
timing = &timing_data[0];
} else {
v4l_dbg(1, debug, client, "unsupported norm %llx\n", *iarg);
return -EINVAL;
}
if (timing) {
bt819_write(client, 0x03,
(((timing->vdelay >> 8) & 0x03) << 6) |
(((timing->vactive >> 8) & 0x03) << 4) |
(((timing->hdelay >> 8) & 0x03) << 2) |
((timing->hactive >> 8) & 0x03) );
bt819_write(client, 0x04, timing->vdelay & 0xff);
bt819_write(client, 0x05, timing->vactive & 0xff);
bt819_write(client, 0x06, timing->hdelay & 0xff);
bt819_write(client, 0x07, timing->hactive & 0xff);
bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
bt819_write(client, 0x09, timing->hscale & 0xff);
}
/* case VIDEO_MODE_AUTO:
bt819_setbit(client, 0x01, 0, 0);
bt819_setbit(client, 0x01, 1, 0);*/
bt819_write(client, 0x03,
(((timing->vdelay >> 8) & 0x03) << 6) |
(((timing->vactive >> 8) & 0x03) << 4) |
(((timing->hdelay >> 8) & 0x03) << 2) |
((timing->hactive >> 8) & 0x03));
bt819_write(client, 0x04, timing->vdelay & 0xff);
bt819_write(client, 0x05, timing->vactive & 0xff);
bt819_write(client, 0x06, timing->hdelay & 0xff);
bt819_write(client, 0x07, timing->hactive & 0xff);
bt819_write(client, 0x08, (timing->hscale >> 8) & 0xff);
bt819_write(client, 0x09, timing->hscale & 0xff);
decoder->norm = *iarg;
break;
}
case DECODER_SET_INPUT:
case VIDIOC_INT_S_VIDEO_ROUTING:
{
int *iarg = arg;
struct v4l2_routing *route = arg;
v4l_dbg(1, debug, client, "set input %x\n", *iarg);
v4l_dbg(1, debug, client, "set input %x\n", route->input);
if (*iarg < 0 || *iarg > 7)
if (route->input < 0 || route->input > 7)
return -EINVAL;
if (decoder->input != *iarg) {
decoder->input = *iarg;
if (decoder->input != route->input) {
decoder->input = route->input;
/* select mode */
if (decoder->input == 0) {
bt819_setbit(client, 0x0b, 6, 0);
......@@ -342,75 +314,116 @@ static int bt819_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
}
case DECODER_SET_OUTPUT:
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
{
int *iarg = arg;
int enable = cmd == VIDIOC_STREAMON;
v4l_dbg(1, debug, client, "set output %x\n", *iarg);
v4l_dbg(1, debug, client, "enable output %x\n", enable);
/* not much choice of outputs */
if (*iarg != 0)
return -EINVAL;
if (decoder->enable != enable) {
decoder->enable = enable;
bt819_setbit(client, 0x16, 7, !enable);
}
break;
}
case DECODER_ENABLE_OUTPUT:
case VIDIOC_QUERYCTRL:
{
int *iarg = arg;
int enable = (*iarg != 0);
struct v4l2_queryctrl *qc = arg;
v4l_dbg(1, debug, client, "enable output %x\n", *iarg);
switch (qc->id) {
case V4L2_CID_BRIGHTNESS:
v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
break;
if (decoder->enable != enable) {
decoder->enable = enable;
bt819_setbit(client, 0x16, 7, !enable);
case V4L2_CID_CONTRAST:
v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
break;
case V4L2_CID_SATURATION:
v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
break;
case V4L2_CID_HUE:
v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
break;
default:
return -EINVAL;
}
break;
}
case DECODER_SET_PICTURE:
case VIDIOC_S_CTRL:
{
struct video_picture *pic = arg;
struct v4l2_control *ctrl = arg;
v4l_dbg(1, debug, client,
"set picture brightness %d contrast %d colour %d\n",
pic->brightness, pic->contrast, pic->colour);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
if (decoder->bright != ctrl->value) {
decoder->bright = ctrl->value;
bt819_write(client, 0x0a, decoder->bright);
}
break;
case V4L2_CID_CONTRAST:
if (decoder->contrast != ctrl->value) {
decoder->contrast = ctrl->value;
bt819_write(client, 0x0c,
decoder->contrast & 0xff);
bt819_setbit(client, 0x0b, 2,
((decoder->contrast >> 8) & 0x01));
}
break;
if (decoder->bright != pic->brightness) {
/* We want -128 to 127 we get 0-65535 */
decoder->bright = pic->brightness;
bt819_write(client, 0x0a,
(decoder->bright >> 8) - 128);
}
case V4L2_CID_SATURATION:
if (decoder->sat != ctrl->value) {
decoder->sat = ctrl->value;
bt819_write(client, 0x0d,
(decoder->sat >> 7) & 0xff);
bt819_setbit(client, 0x0b, 1,
((decoder->sat >> 15) & 0x01));
/* Ratio between U gain and V gain must stay the same as
the ratio between the default U and V gain values. */
temp = (decoder->sat * 180) / 254;
bt819_write(client, 0x0e, (temp >> 7) & 0xff);
bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
}
break;
if (decoder->contrast != pic->contrast) {
/* We want 0 to 511 we get 0-65535 */
decoder->contrast = pic->contrast;
bt819_write(client, 0x0c,
(decoder->contrast >> 7) & 0xff);
bt819_setbit(client, 0x0b, 2,
((decoder->contrast >> 15) & 0x01));
case V4L2_CID_HUE:
if (decoder->hue != ctrl->value) {
decoder->hue = ctrl->value;
bt819_write(client, 0x0f, decoder->hue);
}
break;
default:
return -EINVAL;
}
break;
}
if (decoder->sat != pic->colour) {
/* We want 0 to 511 we get 0-65535 */
decoder->sat = pic->colour;
bt819_write(client, 0x0d,
(decoder->sat >> 7) & 0xff);
bt819_setbit(client, 0x0b, 1,
((decoder->sat >> 15) & 0x01));
temp = (decoder->sat * 201) / 237;
bt819_write(client, 0x0e, (temp >> 7) & 0xff);
bt819_setbit(client, 0x0b, 0, (temp >> 15) & 0x01);
}
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue;
bt819_write(client, 0x0f,
128 - (decoder->hue >> 8));
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = decoder->bright;
break;
case V4L2_CID_CONTRAST:
ctrl->value = decoder->contrast;
break;
case V4L2_CID_SATURATION:
ctrl->value = decoder->sat;
break;
case V4L2_CID_HUE:
ctrl->value = decoder->hue;
break;
default:
return -EINVAL;
}
break;
}
......@@ -462,13 +475,13 @@ static int bt819_probe(struct i2c_client *client,
decoder = kzalloc(sizeof(struct bt819), GFP_KERNEL);
if (decoder == NULL)
return -ENOMEM;
decoder->norm = VIDEO_MODE_NTSC;
decoder->norm = V4L2_STD_NTSC;
decoder->input = 0;
decoder->enable = 1;
decoder->bright = 32768;
decoder->contrast = 32768;
decoder->hue = 32768;
decoder->sat = 32768;
decoder->bright = 0;
decoder->contrast = 0xd8; /* 100% of original signal */
decoder->hue = 0;
decoder->sat = 0xfe; /* 100% of original signal */
decoder->initialized = 0;
i2c_set_clientdata(client, decoder);
......
......@@ -55,8 +55,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
struct bt856 {
unsigned char reg[BT856_NR_REG];
int norm;
int enable;
v4l2_std_id norm;
};
/* ----------------------------------------------------------------------- */
......@@ -96,7 +95,7 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
struct bt856 *encoder = i2c_get_clientdata(client);
switch (cmd) {
case 0:
case VIDIOC_INT_INIT:
/* This is just for testing!!! */
v4l_dbg(1, debug, client, "init\n");
bt856_write(client, 0xdc, 0x18);
......@@ -107,15 +106,10 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
//bt856_setbit(client, 0xdc, 6, 0);
bt856_setbit(client, 0xdc, 4, 1);
switch (encoder->norm) {
case VIDEO_MODE_NTSC:
if (encoder->norm & V4L2_STD_NTSC)
bt856_setbit(client, 0xdc, 2, 0);
break;
case VIDEO_MODE_PAL:
else
bt856_setbit(client, 0xdc, 2, 1);
break;
}
bt856_setbit(client, 0xdc, 1, 1);
bt856_setbit(client, 0xde, 4, 0);
......@@ -124,38 +118,19 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
bt856_dump(client);
break;
case ENCODER_GET_CAPABILITIES:
case VIDIOC_INT_S_STD_OUTPUT:
{
struct video_encoder_capability *cap = arg;
v4l_dbg(1, debug, client, "get capabilities\n");
v4l2_std_id *iarg = arg;
cap->flags = VIDEO_ENCODER_PAL |
VIDEO_ENCODER_NTSC |
VIDEO_ENCODER_CCIR;
cap->inputs = 2;
cap->outputs = 1;
break;
}
case ENCODER_SET_NORM:
{
int *iarg = arg;
v4l_dbg(1, debug, client, "set norm %llx\n", *iarg);
v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
switch (*iarg) {
case VIDEO_MODE_NTSC:
if (*iarg & V4L2_STD_NTSC) {
bt856_setbit(client, 0xdc, 2, 0);
break;
case VIDEO_MODE_PAL:
} else if (*iarg & V4L2_STD_PAL) {
bt856_setbit(client, 0xdc, 2, 1);
bt856_setbit(client, 0xda, 0, 0);
//bt856_setbit(client, 0xda, 0, 1);
break;
default:
} else {
return -EINVAL;
}
encoder->norm = *iarg;
......@@ -164,16 +139,16 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
}
case ENCODER_SET_INPUT:
case VIDIOC_INT_S_VIDEO_ROUTING:
{
int *iarg = arg;
struct v4l2_routing *route = arg;
v4l_dbg(1, debug, client, "set input %d\n", *iarg);
v4l_dbg(1, debug, client, "set input %d\n", route->input);
/* We only have video bus.
* iarg = 0: input is from bt819
* iarg = 1: input is from ZR36060 */
switch (*iarg) {
* route->input= 0: input is from bt819
* route->input= 1: input is from ZR36060 */
switch (route->input) {
case 0:
bt856_setbit(client, 0xde, 4, 0);
bt856_setbit(client, 0xde, 3, 1);
......@@ -199,28 +174,6 @@ static int bt856_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
}
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
v4l_dbg(1, debug, client, "set output %d\n", *iarg);
/* not much choice of outputs */
if (*iarg != 0)
return -EINVAL;
break;
}
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
break;
}
default:
return -EINVAL;
}
......@@ -249,8 +202,7 @@ static int bt856_probe(struct i2c_client *client,
encoder = kzalloc(sizeof(struct bt856), GFP_KERNEL);
if (encoder == NULL)
return -ENOMEM;
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
encoder->norm = V4L2_STD_NTSC;
i2c_set_clientdata(client, encoder);
bt856_write(client, 0xdc, 0x18);
......@@ -261,16 +213,10 @@ static int bt856_probe(struct i2c_client *client,
//bt856_setbit(client, 0xdc, 6, 0);
bt856_setbit(client, 0xdc, 4, 1);
switch (encoder->norm) {
case VIDEO_MODE_NTSC:
if (encoder->norm & V4L2_STD_NTSC)
bt856_setbit(client, 0xdc, 2, 0);
break;
case VIDEO_MODE_PAL:
else
bt856_setbit(client, 0xdc, 2, 1);
break;
}
bt856_setbit(client, 0xdc, 1, 1);
bt856_setbit(client, 0xde, 4, 0);
......
......@@ -52,8 +52,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
struct bt866 {
u8 reg[256];
int norm;
int enable;
v4l2_std_id norm;
int bright;
int contrast;
int hue;
......@@ -94,44 +93,21 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
struct bt866 *encoder = i2c_get_clientdata(client);
switch (cmd) {
case ENCODER_GET_CAPABILITIES:
case VIDIOC_INT_S_STD_OUTPUT:
{
struct video_encoder_capability *cap = arg;
v4l2_std_id *iarg = arg;
v4l_dbg(1, debug, client, "get capabilities\n");
v4l_dbg(1, debug, client, "set norm %llx\n", *iarg);
cap->flags
= VIDEO_ENCODER_PAL
| VIDEO_ENCODER_NTSC
| VIDEO_ENCODER_CCIR;
cap->inputs = 2;
cap->outputs = 1;
break;
}
case ENCODER_SET_NORM:
{
int *iarg = arg;
v4l_dbg(1, debug, client, "set norm %d\n", *iarg);
switch (*iarg) {
case VIDEO_MODE_NTSC:
break;
case VIDEO_MODE_PAL:
break;
default:
if (!(*iarg & (V4L2_STD_NTSC | V4L2_STD_PAL)))
return -EINVAL;
}
encoder->norm = *iarg;
break;
}
case ENCODER_SET_INPUT:
case VIDIOC_INT_S_VIDEO_ROUTING:
{
int *iarg = arg;
struct v4l2_routing *route = arg;
static const __u8 init[] = {
0xc8, 0xcc, /* CRSCALE */
0xca, 0x91, /* CBSCALE */
......@@ -167,7 +143,7 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
val = encoder->reg[0xdc];
if (*iarg == 0)
if (route->input == 0)
val |= 0x40; /* CBSWAP */
else
val &= ~0x40; /* !CBSWAP */
......@@ -175,15 +151,15 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
bt866_write(client, 0xdc, val);
val = encoder->reg[0xcc];
if (*iarg == 2)
if (route->input == 2)
val |= 0x01; /* OSDBAR */
else
val &= ~0x01; /* !OSDBAR */
bt866_write(client, 0xcc, val);
v4l_dbg(1, debug, client, "set input %d\n", *iarg);
v4l_dbg(1, debug, client, "set input %d\n", route->input);
switch (*iarg) {
switch (route->input) {
case 0:
break;
case 1:
......@@ -194,27 +170,6 @@ static int bt866_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
}
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
v4l_dbg(1, debug, client, "set output %d\n", *iarg);
/* not much choice of outputs */
if (*iarg != 0)
return -EINVAL;
break;
}
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
v4l_dbg(1, debug, client, "enable output %d\n", encoder->enable);
break;
}
case 4711:
{
int *iarg = arg;
......
......@@ -201,7 +201,7 @@ struct ks0127 {
int format_height;
int cap_width;
int cap_height;
int norm;
v4l2_std_id norm;
int ks_type;
u8 regs[256];
};
......@@ -408,20 +408,22 @@ static void ks0127_reset(struct i2c_client *c)
static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
{
struct ks0127 *ks = i2c_get_clientdata(c);
struct v4l2_routing *route = arg;
int *iarg = (int *)arg;
v4l2_std_id *istd = arg;
int status;
if (!ks)
return -ENODEV;
switch (cmd) {
case DECODER_INIT:
v4l_dbg(1, debug, c, "DECODER_INIT\n");
case VIDIOC_INT_INIT:
v4l_dbg(1, debug, c, "VIDIOC_INT_INIT\n");
ks0127_reset(c);
break;
case DECODER_SET_INPUT:
switch(*iarg) {
case VIDIOC_INT_S_VIDEO_ROUTING:
switch (route->input) {
case KS_INPUT_COMPOSITE_1:
case KS_INPUT_COMPOSITE_2:
case KS_INPUT_COMPOSITE_3:
......@@ -429,7 +431,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
case KS_INPUT_COMPOSITE_5:
case KS_INPUT_COMPOSITE_6:
v4l_dbg(1, debug, c,
"DECODER_SET_INPUT %d: Composite\n", *iarg);
"VIDIOC_S_INPUT %d: Composite\n", *iarg);
/* autodetect 50/60 Hz */
ks0127_and_or(c, KS_CMDA, 0xfc, 0x00);
/* VSE=0 */
......@@ -463,7 +465,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
case KS_INPUT_SVIDEO_2:
case KS_INPUT_SVIDEO_3:
v4l_dbg(1, debug, c,
"DECODER_SET_INPUT %d: S-Video\n", *iarg);
"VIDIOC_S_INPUT %d: S-Video\n", *iarg);
/* autodetect 50/60 Hz */
ks0127_and_or(c, KS_CMDA, 0xfc, 0x00);
/* VSE=0 */
......@@ -495,9 +497,8 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
case KS_INPUT_YUV656:
v4l_dbg(1, debug, c,
"DECODER_SET_INPUT 15: YUV656\n");
if (ks->norm == VIDEO_MODE_NTSC ||
ks->norm == KS_STD_PAL_M)
"VIDIOC_S_INPUT 15: YUV656\n");
if (ks->norm & V4L2_STD_525_60)
/* force 60 Hz */
ks0127_and_or(c, KS_CMDA, 0xfc, 0x03);
else
......@@ -541,7 +542,7 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
default:
v4l_dbg(1, debug, c,
"DECODER_SET_INPUT: Unknown input %d\n", *iarg);
"VIDIOC_INT_S_VIDEO_ROUTING: Unknown input %d\n", route->input);
break;
}
......@@ -550,77 +551,37 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
ks0127_write(c, KS_DEMOD, reg_defaults[KS_DEMOD]);
break;
case DECODER_SET_OUTPUT:
switch(*iarg) {
case KS_OUTPUT_YUV656E:
v4l_dbg(1, debug, c,
"DECODER_SET_OUTPUT: OUTPUT_YUV656E (Missing)\n");
return -EINVAL;
case KS_OUTPUT_EXV:
v4l_dbg(1, debug, c,
"DECODER_SET_OUTPUT: OUTPUT_EXV\n");
ks0127_and_or(c, KS_OFMTA, 0xf0, 0x09);
break;
}
break;
case DECODER_SET_NORM: /* sam This block mixes old and new norm names... */
case VIDIOC_S_STD: /* sam This block mixes old and new norm names... */
/* Set to automatic SECAM/Fsc mode */
ks0127_and_or(c, KS_DEMOD, 0xf0, 0x00);
ks->norm = *iarg;
switch (*iarg) {
/* this is untested !! */
/* It just detects PAL_N/NTSC_M (no special frequencies) */
/* And you have to set the standard a second time afterwards */
case VIDEO_MODE_AUTO:
v4l_dbg(1, debug, c,
"DECODER_SET_NORM: AUTO\n");
ks->norm = *istd;
/* The chip determines the format */
/* based on the current field rate */
ks0127_and_or(c, KS_CMDA, 0xfc, 0x00);
ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
/* This is wrong for PAL ! As I said, */
/* you need to set the standard once again !! */
ks->format_height = 240;
ks->format_width = 704;
break;
case VIDEO_MODE_NTSC:
if (*istd & V4L2_STD_NTSC) {
v4l_dbg(1, debug, c,
"DECODER_SET_NORM: NTSC_M\n");
"VIDIOC_S_STD: NTSC_M\n");
ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
ks->format_height = 240;
ks->format_width = 704;
break;
case KS_STD_NTSC_N:
} else if (*istd & V4L2_STD_PAL_N) {
v4l_dbg(1, debug, c,
"KS0127_SET_NORM: NTSC_N (fixme)\n");
ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
ks->format_height = 240;
ks->format_width = 704;
break;
case VIDEO_MODE_PAL:
} else if (*istd & V4L2_STD_PAL) {
v4l_dbg(1, debug, c,
"DECODER_SET_NORM: PAL_N\n");
"VIDIOC_S_STD: PAL_N\n");
ks0127_and_or(c, KS_CHROMA, 0x9f, 0x20);
ks->format_height = 290;
ks->format_width = 704;
break;
case KS_STD_PAL_M:
} else if (*istd & V4L2_STD_PAL_M) {
v4l_dbg(1, debug, c,
"KS0127_SET_NORM: PAL_M (fixme)\n");
ks0127_and_or(c, KS_CHROMA, 0x9f, 0x40);
ks->format_height = 290;
ks->format_width = 704;
break;
case VIDEO_MODE_SECAM:
} else if (*istd & V4L2_STD_SECAM) {
v4l_dbg(1, debug, c,
"KS0127_SET_NORM: SECAM\n");
ks->format_height = 290;
......@@ -632,29 +593,34 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
schedule_timeout_interruptible(HZ/10+1);
/* did it autodetect? */
if (ks0127_read(c, KS_DEMOD) & 0x40)
break;
/* force to secam mode */
ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f);
break;
default:
if (!(ks0127_read(c, KS_DEMOD) & 0x40))
/* force to secam mode */
ks0127_and_or(c, KS_DEMOD, 0xf0, 0x0f);
} else {
v4l_dbg(1, debug, c,
"DECODER_SET_NORM: Unknown norm %d\n", *iarg);
break;
"VIDIOC_S_STD: Unknown norm %llx\n", *istd);
}
break;
case DECODER_SET_PICTURE:
case VIDIOC_QUERYCTRL:
{
return -EINVAL;
}
case VIDIOC_S_CTRL:
v4l_dbg(1, debug, c,
"DECODER_SET_PICTURE: not yet supported\n");
"VIDIOC_S_CTRL: not yet supported\n");
return -EINVAL;
/* sam todo: KS0127_SET_BRIGHTNESS: Merge into DECODER_SET_PICTURE */
/* sam todo: KS0127_SET_CONTRAST: Merge into DECODER_SET_PICTURE */
/* sam todo: KS0127_SET_HUE: Merge into DECODER_SET_PICTURE? */
/* sam todo: KS0127_SET_SATURATION: Merge into DECODER_SET_PICTURE */
case VIDIOC_G_CTRL:
v4l_dbg(1, debug, c,
"VIDIOC_G_CTRL: not yet supported\n");
return -EINVAL;
/* sam todo: KS0127_SET_BRIGHTNESS: Merge into VIDIOC_S_CTRL */
/* sam todo: KS0127_SET_CONTRAST: Merge into VIDIOC_S_CTRL */
/* sam todo: KS0127_SET_HUE: Merge into VIDIOC_S_CTRL? */
/* sam todo: KS0127_SET_SATURATION: Merge into VIDIOC_S_CTRL */
/* sam todo: KS0127_SET_AGC_MODE: */
/* sam todo: KS0127_SET_AGC: */
/* sam todo: KS0127_SET_CHROMA_MODE: */
......@@ -670,22 +636,21 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
/* sam todo: KS0127_SET_UNUSEV: */
/* sam todo: KS0127_SET_VSALIGN_MODE: */
case DECODER_ENABLE_OUTPUT:
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
{
int enable;
int enable = cmd == VIDIOC_STREAMON;
iarg = arg;
enable = (*iarg != 0);
if (enable) {
v4l_dbg(1, debug, c,
"DECODER_ENABLE_OUTPUT on\n");
"VIDIOC_STREAMON\n");
/* All output pins on */
ks0127_and_or(c, KS_OFMTA, 0xcf, 0x30);
/* Obey the OEN pin */
ks0127_and_or(c, KS_CDEM, 0x7f, 0x00);
} else {
v4l_dbg(1, debug, c,
"DECODER_ENABLE_OUTPUT off\n");
"VIDIOC_STREAMOFF\n");
/* Video output pins off */
ks0127_and_or(c, KS_OFMTA, 0xcf, 0x00);
/* Ignore the OEN pin */
......@@ -699,19 +664,26 @@ static int ks0127_command(struct i2c_client *c, unsigned cmd, void *arg)
/* sam todo: KS0127_SET_HEIGHT: */
/* sam todo: KS0127_SET_HSCALE: */
case DECODER_GET_STATUS:
v4l_dbg(1, debug, c, "DECODER_GET_STATUS\n");
*iarg = 0;
case VIDIOC_QUERYSTD:
case VIDIOC_INT_G_INPUT_STATUS: {
int stat = V4L2_IN_ST_NO_SIGNAL;
v4l2_std_id std = V4L2_STD_ALL;
v4l_dbg(1, debug, c, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n");
status = ks0127_read(c, KS_STAT);
if (!(status & 0x20)) /* NOVID not set */
*iarg = (*iarg | DECODER_STATUS_GOOD);
if ((status & 0x01)) /* CLOCK set */
*iarg = (*iarg | DECODER_STATUS_COLOR);
stat = 0;
if (!(status & 0x01)) /* CLOCK set */
stat |= V4L2_IN_ST_NO_COLOR;
if ((status & 0x08)) /* PALDET set */
*iarg = (*iarg | DECODER_STATUS_PAL);
std = V4L2_STD_PAL;
else
*iarg = (*iarg | DECODER_STATUS_NTSC);
std = V4L2_STD_NTSC;
if (cmd == VIDIOC_QUERYSTD)
*istd = std;
else
*iarg = stat;
break;
}
/* Catch any unknown command */
default:
......
......@@ -54,7 +54,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
struct saa7110 {
u8 reg[SAA7110_NR_REG];
int norm;
v4l2_std_id norm;
int input;
int enable;
int bright;
......@@ -176,7 +176,7 @@ static const unsigned char initseq[1 + SAA7110_NR_REG] = {
/* 0x30 */ 0x44, 0x71, 0x02, 0x8C, 0x02
};
static int determine_norm(struct i2c_client *client)
static v4l2_std_id determine_norm(struct i2c_client *client)
{
DEFINE_WAIT(wait);
struct saa7110 *decoder = i2c_get_clientdata(client);
......@@ -198,11 +198,11 @@ static int determine_norm(struct i2c_client *client)
if (status & 0x20) {
v4l_dbg(1, debug, client, "status=0x%02x (NTSC/no color)\n", status);
//saa7110_write(client,0x2E,0x81);
return VIDEO_MODE_NTSC;
return V4L2_STD_NTSC;
}
v4l_dbg(1, debug, client, "status=0x%02x (PAL/no color)\n", status);
//saa7110_write(client,0x2E,0x9A);
return VIDEO_MODE_PAL;
return V4L2_STD_PAL;
}
//saa7110_write(client,0x06,0x03);
if (status & 0x20) { /* 60Hz */
......@@ -211,7 +211,7 @@ static int determine_norm(struct i2c_client *client)
saa7110_write(client, 0x0F, 0x50);
saa7110_write(client, 0x11, 0x2C);
//saa7110_write(client,0x2E,0x81);
return VIDEO_MODE_NTSC;
return V4L2_STD_NTSC;
}
/* 50Hz -> PAL/SECAM */
......@@ -228,10 +228,10 @@ static int determine_norm(struct i2c_client *client)
if ((status & 0x03) == 0x01) {
v4l_dbg(1, debug, client, "status=0x%02x (SECAM)\n", status);
saa7110_write(client, 0x0D, 0x87);
return VIDEO_MODE_SECAM;
return V4L2_STD_SECAM;
}
v4l_dbg(1, debug, client, "status=0x%02x (PAL)\n", status);
return VIDEO_MODE_PAL;
return V4L2_STD_PAL;
}
static int
......@@ -240,112 +240,81 @@ saa7110_command (struct i2c_client *client,
void *arg)
{
struct saa7110 *decoder = i2c_get_clientdata(client);
struct v4l2_routing *route = arg;
v4l2_std_id std;
int v;
switch (cmd) {
case 0:
case VIDIOC_INT_INIT:
//saa7110_write_block(client, initseq, sizeof(initseq));
break;
case DECODER_GET_CAPABILITIES:
{
struct video_decoder_capability *dc = arg;
dc->flags =
VIDEO_DECODER_PAL | VIDEO_DECODER_NTSC |
VIDEO_DECODER_SECAM | VIDEO_DECODER_AUTO;
dc->inputs = SAA7110_MAX_INPUT;
dc->outputs = SAA7110_MAX_OUTPUT;
break;
}
case DECODER_GET_STATUS:
case VIDIOC_INT_G_INPUT_STATUS:
{
int res = V4L2_IN_ST_NO_SIGNAL;
int status;
int res = 0;
status = saa7110_read(client);
v4l_dbg(1, debug, client, "status=0x%02x norm=%d\n",
v4l_dbg(1, debug, client, "status=0x%02x norm=%llx\n",
status, decoder->norm);
if (!(status & 0x40))
res |= DECODER_STATUS_GOOD;
if (status & 0x03)
res |= DECODER_STATUS_COLOR;
res = 0;
if (!(status & 0x03))
res |= V4L2_IN_ST_NO_COLOR;
switch (decoder->norm) {
case VIDEO_MODE_NTSC:
res |= DECODER_STATUS_NTSC;
break;
case VIDEO_MODE_PAL:
res |= DECODER_STATUS_PAL;
break;
case VIDEO_MODE_SECAM:
res |= DECODER_STATUS_SECAM;
break;
}
*(int *) arg = res;
break;
}
case DECODER_SET_NORM:
v = *(int *) arg;
if (decoder->norm != v) {
decoder->norm = v;
case VIDIOC_QUERYSTD:
{
*(v4l2_std_id *)arg = determine_norm(client);
break;
}
case VIDIOC_S_STD:
std = *(v4l2_std_id *) arg;
if (decoder->norm != std) {
decoder->norm = std;
//saa7110_write(client, 0x06, 0x03);
switch (v) {
case VIDEO_MODE_NTSC:
if (std & V4L2_STD_NTSC) {
saa7110_write(client, 0x0D, 0x86);
saa7110_write(client, 0x0F, 0x50);
saa7110_write(client, 0x11, 0x2C);
//saa7110_write(client, 0x2E, 0x81);
v4l_dbg(1, debug, client, "switched to NTSC\n");
break;
case VIDEO_MODE_PAL:
} else if (std & V4L2_STD_PAL) {
saa7110_write(client, 0x0D, 0x86);
saa7110_write(client, 0x0F, 0x10);
saa7110_write(client, 0x11, 0x59);
//saa7110_write(client, 0x2E, 0x9A);
v4l_dbg(1, debug, client, "switched to PAL\n");
break;
case VIDEO_MODE_SECAM:
} else if (std & V4L2_STD_SECAM) {
saa7110_write(client, 0x0D, 0x87);
saa7110_write(client, 0x0F, 0x10);
saa7110_write(client, 0x11, 0x59);
//saa7110_write(client, 0x2E, 0x9A);
v4l_dbg(1, debug, client, "switched to SECAM\n");
break;
case VIDEO_MODE_AUTO:
v4l_dbg(1, debug, client, "switched to AUTO\n");
decoder->norm = determine_norm(client);
*(int *) arg = decoder->norm;
break;
default:
return -EPERM;
} else {
return -EINVAL;
}
}
break;
case DECODER_SET_INPUT:
v = *(int *) arg;
if (v < 0 || v >= SAA7110_MAX_INPUT) {
v4l_dbg(1, debug, client, "input=%d not available\n", v);
case VIDIOC_INT_S_VIDEO_ROUTING:
if (route->input < 0 || route->input >= SAA7110_MAX_INPUT) {
v4l_dbg(1, debug, client, "input=%d not available\n", route->input);
return -EINVAL;
}
if (decoder->input != v) {
saa7110_selmux(client, v);
v4l_dbg(1, debug, client, "switched to input=%d\n", v);
if (decoder->input != route->input) {
saa7110_selmux(client, route->input);
v4l_dbg(1, debug, client, "switched to input=%d\n", route->input);
}
break;
case DECODER_SET_OUTPUT:
v = *(int *) arg;
/* not much choice of outputs */
if (v != 0)
return -EINVAL;
break;
case DECODER_ENABLE_OUTPUT:
v = *(int *) arg;
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
v = cmd == VIDIOC_STREAMON;
if (decoder->enable != v) {
decoder->enable = v;
saa7110_write(client, 0x0E, v ? 0x18 : 0x80);
......@@ -353,46 +322,81 @@ saa7110_command (struct i2c_client *client,
}
break;
case DECODER_SET_PICTURE:
case VIDIOC_QUERYCTRL:
{
struct video_picture *pic = arg;
if (decoder->bright != pic->brightness) {
/* We want 0 to 255 we get 0-65535 */
decoder->bright = pic->brightness;
saa7110_write(client, 0x19, decoder->bright >> 8);
}
if (decoder->contrast != pic->contrast) {
/* We want 0 to 127 we get 0-65535 */
decoder->contrast = pic->contrast;
saa7110_write(client, 0x13,
decoder->contrast >> 9);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 127 we get 0-65535 */
decoder->sat = pic->colour;
saa7110_write(client, 0x12, decoder->sat >> 9);
struct v4l2_queryctrl *qc = arg;
switch (qc->id) {
case V4L2_CID_BRIGHTNESS:
return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
case V4L2_CID_CONTRAST:
case V4L2_CID_SATURATION:
return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
case V4L2_CID_HUE:
return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
default:
return -EINVAL;
}
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue;
saa7110_write(client, 0x07,
(decoder->hue >> 8) - 128);
break;
}
case VIDIOC_G_CTRL:
{
struct v4l2_control *ctrl = arg;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = decoder->bright;
break;
case V4L2_CID_CONTRAST:
ctrl->value = decoder->contrast;
break;
case V4L2_CID_SATURATION:
ctrl->value = decoder->sat;
break;
case V4L2_CID_HUE:
ctrl->value = decoder->hue;
break;
default:
return -EINVAL;
}
break;
}
case DECODER_DUMP:
if (!debug)
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
if (decoder->bright != ctrl->value) {
decoder->bright = ctrl->value;
saa7110_write(client, 0x19, decoder->bright);
}
break;
for (v = 0; v < SAA7110_NR_REG; v += 16) {
int j;
v4l_dbg(1, debug, client, "%02x:", v);
for (j = 0; j < 16 && v + j < SAA7110_NR_REG; j++)
printk(KERN_CONT " %02x", decoder->reg[v + j]);
printk(KERN_CONT "\n");
case V4L2_CID_CONTRAST:
if (decoder->contrast != ctrl->value) {
decoder->contrast = ctrl->value;
saa7110_write(client, 0x13, decoder->contrast);
}
break;
case V4L2_CID_SATURATION:
if (decoder->sat != ctrl->value) {
decoder->sat = ctrl->value;
saa7110_write(client, 0x12, decoder->sat);
}
break;
case V4L2_CID_HUE:
if (decoder->hue != ctrl->value) {
decoder->hue = ctrl->value;
saa7110_write(client, 0x07, decoder->hue);
}
break;
default:
return -EINVAL;
}
break;
}
default:
v4l_dbg(1, debug, client, "unknown command %08x\n", cmd);
......@@ -429,7 +433,7 @@ static int saa7110_probe(struct i2c_client *client,
decoder = kzalloc(sizeof(struct saa7110), GFP_KERNEL);
if (!decoder)
return -ENOMEM;
decoder->norm = VIDEO_MODE_PAL;
decoder->norm = V4L2_STD_PAL;
decoder->input = 0;
decoder->enable = 1;
decoder->bright = 32768;
......
/*
* saa7111 - Philips SAA7111A video decoder driver version 0.0.3
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
*
* Slight changes for video timing and attachment output by
* Wolfgang Scherr <scherr@net4you.net>
*
* Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
* - moved over to linux>=2.4.x i2c protocol (1/1/2003)
*
* Changes by Michael Hunold <michael@mihu.de>
* - implemented DECODER_SET_GPIO, DECODER_INIT, DECODER_SET_VBI_BYPASS
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_decoder.h>
#include <media/v4l2-common.h>
#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Philips SAA7111 video decoder driver");
MODULE_AUTHOR("Dave Perks");
MODULE_LICENSE("GPL");
static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* ----------------------------------------------------------------------- */
#define SAA7111_NR_REG 0x18
struct saa7111 {
unsigned char reg[SAA7111_NR_REG];
int norm;
int input;
int enable;
};
/* ----------------------------------------------------------------------- */
static inline int saa7111_write(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
decoder->reg[reg] = value;
return i2c_smbus_write_byte_data(client, reg, value);
}
static inline void saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
if (decoder->reg[reg] != value) {
decoder->reg[reg] = value;
i2c_smbus_write_byte_data(client, reg, value);
}
}
static int saa7111_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
/* the saa7111 has an autoincrement function, use it if
* the adapter understands raw I2C */
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
/* do raw I2C, not smbus compatible */
struct saa7111 *decoder = i2c_get_clientdata(client);
u8 block_data[32];
int block_len;
while (len >= 2) {
block_len = 0;
block_data[block_len++] = reg = data[0];
do {
block_data[block_len++] =
decoder->reg[reg++] = data[1];
len -= 2;
data += 2;
} while (len >= 2 && data[0] == reg && block_len < 32);
ret = i2c_master_send(client, block_data, block_len);
if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
ret = saa7111_write(client, reg, *data++);
if (ret < 0)
break;
len -= 2;
}
}
return ret;
}
static int saa7111_init_decoder(struct i2c_client *client,
struct video_decoder_init *init)
{
return saa7111_write_block(client, init->data, init->len);
}
static inline int saa7111_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
/* ----------------------------------------------------------------------- */
static const unsigned char saa7111_i2c_init[] = {
0x00, 0x00, /* 00 - ID byte */
0x01, 0x00, /* 01 - reserved */
/*front end */
0x02, 0xd0, /* 02 - FUSE=3, GUDL=2, MODE=0 */
0x03, 0x23, /* 03 - HLNRS=0, VBSL=1, WPOFF=0,
* HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
0x04, 0x00, /* 04 - GAI1=256 */
0x05, 0x00, /* 05 - GAI2=256 */
/* decoder */
0x06, 0xf3, /* 06 - HSB at 13(50Hz) / 17(60Hz)
* pixels after end of last line */
/*0x07, 0x13, * 07 - HSS at 113(50Hz) / 117(60Hz) pixels
* after end of last line */
0x07, 0xe8, /* 07 - HSS seems to be needed to
* work with NTSC, too */
0x08, 0xc8, /* 08 - AUFD=1, FSEL=1, EXFIL=0,
* VTRC=1, HPLL=0, VNOI=0 */
0x09, 0x01, /* 09 - BYPS=0, PREF=0, BPSS=0,
* VBLB=0, UPTCV=0, APER=1 */
0x0a, 0x80, /* 0a - BRIG=128 */
0x0b, 0x47, /* 0b - CONT=1.109 */
0x0c, 0x40, /* 0c - SATN=1.0 */
0x0d, 0x00, /* 0d - HUE=0 */
0x0e, 0x01, /* 0e - CDTO=0, CSTD=0, DCCF=0,
* FCTC=0, CHBW=1 */
0x0f, 0x00, /* 0f - reserved */
0x10, 0x48, /* 10 - OFTS=1, HDEL=0, VRLN=1, YDEL=0 */
0x11, 0x1c, /* 11 - GPSW=0, CM99=0, FECO=0, COMPO=1,
* OEYC=1, OEHV=1, VIPB=0, COLO=0 */
0x12, 0x00, /* 12 - output control 2 */
0x13, 0x00, /* 13 - output control 3 */
0x14, 0x00, /* 14 - reserved */
0x15, 0x00, /* 15 - VBI */
0x16, 0x00, /* 16 - VBI */
0x17, 0x00, /* 17 - VBI */
};
static int saa7111_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
switch (cmd) {
case 0:
break;
case DECODER_INIT:
{
struct video_decoder_init *init = arg;
struct video_decoder_init vdi;
if (NULL != init)
return saa7111_init_decoder(client, init);
vdi.data = saa7111_i2c_init;
vdi.len = sizeof(saa7111_i2c_init);
return saa7111_init_decoder(client, &vdi);
}
case DECODER_DUMP:
{
int i;
for (i = 0; i < SAA7111_NR_REG; i += 16) {
int j;
v4l_info(client, "%03x", i);
for (j = 0; j < 16 && i + j < SAA7111_NR_REG; ++j) {
printk(KERN_CONT " %02x",
saa7111_read(client, i + j));
}
printk(KERN_CONT "\n");
}
break;
}
case DECODER_GET_CAPABILITIES:
{
struct video_decoder_capability *cap = arg;
cap->flags = VIDEO_DECODER_PAL |
VIDEO_DECODER_NTSC |
VIDEO_DECODER_SECAM |
VIDEO_DECODER_AUTO |
VIDEO_DECODER_CCIR;
cap->inputs = 8;
cap->outputs = 1;
break;
}
case DECODER_GET_STATUS:
{
int *iarg = arg;
int status;
int res;
status = saa7111_read(client, 0x1f);
v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
res = 0;
if ((status & (1 << 6)) == 0) {
res |= DECODER_STATUS_GOOD;
}
switch (decoder->norm) {
case VIDEO_MODE_NTSC:
res |= DECODER_STATUS_NTSC;
break;
case VIDEO_MODE_PAL:
res |= DECODER_STATUS_PAL;
break;
case VIDEO_MODE_SECAM:
res |= DECODER_STATUS_SECAM;
break;
default:
case VIDEO_MODE_AUTO:
if ((status & (1 << 5)) != 0) {
res |= DECODER_STATUS_NTSC;
} else {
res |= DECODER_STATUS_PAL;
}
break;
}
if ((status & (1 << 0)) != 0) {
res |= DECODER_STATUS_COLOR;
}
*iarg = res;
break;
}
case DECODER_SET_GPIO:
{
int *iarg = arg;
if (0 != *iarg) {
saa7111_write(client, 0x11,
(decoder->reg[0x11] | 0x80));
} else {
saa7111_write(client, 0x11,
(decoder->reg[0x11] & 0x7f));
}
break;
}
case DECODER_SET_VBI_BYPASS:
{
int *iarg = arg;
if (0 != *iarg) {
saa7111_write(client, 0x13,
(decoder->reg[0x13] & 0xf0) | 0x0a);
} else {
saa7111_write(client, 0x13,
(decoder->reg[0x13] & 0xf0));
}
break;
}
case DECODER_SET_NORM:
{
int *iarg = arg;
switch (*iarg) {
case VIDEO_MODE_NTSC:
saa7111_write(client, 0x08,
(decoder->reg[0x08] & 0x3f) | 0x40);
saa7111_write(client, 0x0e,
(decoder->reg[0x0e] & 0x8f));
break;
case VIDEO_MODE_PAL:
saa7111_write(client, 0x08,
(decoder->reg[0x08] & 0x3f) | 0x00);
saa7111_write(client, 0x0e,
(decoder->reg[0x0e] & 0x8f));
break;
case VIDEO_MODE_SECAM:
saa7111_write(client, 0x08,
(decoder->reg[0x08] & 0x3f) | 0x00);
saa7111_write(client, 0x0e,
(decoder->reg[0x0e] & 0x8f) | 0x50);
break;
case VIDEO_MODE_AUTO:
saa7111_write(client, 0x08,
(decoder->reg[0x08] & 0x3f) | 0x80);
saa7111_write(client, 0x0e,
(decoder->reg[0x0e] & 0x8f));
break;
default:
return -EINVAL;
}
decoder->norm = *iarg;
break;
}
case DECODER_SET_INPUT:
{
int *iarg = arg;
if (*iarg < 0 || *iarg > 7) {
return -EINVAL;
}
if (decoder->input != *iarg) {
decoder->input = *iarg;
/* select mode */
saa7111_write(client, 0x02,
(decoder->
reg[0x02] & 0xf8) | decoder->input);
/* bypass chrominance trap for modes 4..7 */
saa7111_write(client, 0x09,
(decoder->
reg[0x09] & 0x7f) | ((decoder->
input >
3) ? 0x80 :
0));
}
break;
}
case DECODER_SET_OUTPUT:
{
int *iarg = arg;
/* not much choice of outputs */
if (*iarg != 0) {
return -EINVAL;
}
break;
}
case DECODER_ENABLE_OUTPUT:
{
int *iarg = arg;
int enable = (*iarg != 0);
if (decoder->enable != enable) {
decoder->enable = enable;
/* RJ: If output should be disabled (for
* playing videos), we also need a open PLL.
* The input is set to 0 (where no input
* source is connected), although this
* is not necessary.
*
* If output should be enabled, we have to
* reverse the above.
*/
if (decoder->enable) {
saa7111_write(client, 0x02,
(decoder->
reg[0x02] & 0xf8) |
decoder->input);
saa7111_write(client, 0x08,
(decoder->reg[0x08] & 0xfb));
saa7111_write(client, 0x11,
(decoder->
reg[0x11] & 0xf3) | 0x0c);
} else {
saa7111_write(client, 0x02,
(decoder->reg[0x02] & 0xf8));
saa7111_write(client, 0x08,
(decoder->
reg[0x08] & 0xfb) | 0x04);
saa7111_write(client, 0x11,
(decoder->reg[0x11] & 0xf3));
}
}
break;
}
case DECODER_SET_PICTURE:
{
struct video_picture *pic = arg;
/* We want 0 to 255 we get 0-65535 */
saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
/* We want 0 to 127 we get 0-65535 */
saa7111_write(client, 0x0b, pic->contrast >> 9);
/* We want 0 to 127 we get 0-65535 */
saa7111_write(client, 0x0c, pic->colour >> 9);
/* We want -128 to 127 we get 0-65535 */
saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
break;
}
default:
return -EINVAL;
}
return 0;
}
/* ----------------------------------------------------------------------- */
static unsigned short normal_i2c[] = { 0x48 >> 1, I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
static int saa7111_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int i;
struct saa7111 *decoder;
struct video_decoder_init vdi;
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(struct saa7111), GFP_KERNEL);
if (decoder == NULL) {
kfree(client);
return -ENOMEM;
}
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0;
decoder->enable = 1;
i2c_set_clientdata(client, decoder);
vdi.data = saa7111_i2c_init;
vdi.len = sizeof(saa7111_i2c_init);
i = saa7111_init_decoder(client, &vdi);
if (i < 0) {
v4l_dbg(1, debug, client, "init status %d\n", i);
} else {
v4l_dbg(1, debug, client, "revision %x\n",
saa7111_read(client, 0x00) >> 4);
}
return 0;
}
static int saa7111_remove(struct i2c_client *client)
{
kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
static const struct i2c_device_id saa7111_id[] = {
{ "saa7111_old", 0 }, /* "saa7111" maps to the saa7115 driver */
{ }
};
MODULE_DEVICE_TABLE(i2c, saa7111_id);
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "saa7111",
.driverid = I2C_DRIVERID_SAA7111A,
.command = saa7111_command,
.probe = saa7111_probe,
.remove = saa7111_remove,
.id_table = saa7111_id,
};
/*
* saa7114 - Philips SAA7114H video decoder driver version 0.0.1
*
* Copyright (C) 2002 Maxim Yevtyushkin <max@linuxmedialabs.com>
*
* Based on saa7111 driver by Dave Perks
*
* Copyright (C) 1998 Dave Perks <dperks@ibm.net>
*
* Slight changes for video timing and attachment output by
* Wolfgang Scherr <scherr@net4you.net>
*
* Changes by Ronald Bultje <rbultje@ronald.bitfreak.net>
* - moved over to linux>=2.4.x i2c protocol (1/1/2003)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/types.h>
#include <linux/ioctl.h>
#include <asm/uaccess.h>
#include <linux/i2c.h>
#include <linux/i2c-id.h>
#include <linux/videodev.h>
#include <linux/video_decoder.h>
#include <media/v4l2-common.h>
#include <media/v4l2-i2c-drv-legacy.h>
MODULE_DESCRIPTION("Philips SAA7114H video decoder driver");
MODULE_AUTHOR("Maxim Yevtyushkin");
MODULE_LICENSE("GPL");
static int debug;
module_param(debug, int, 0);
MODULE_PARM_DESC(debug, "Debug level (0-1)");
/* ----------------------------------------------------------------------- */
struct saa7114 {
unsigned char reg[0xf0 * 2];
int norm;
int input;
int enable;
int bright;
int contrast;
int hue;
int sat;
int playback;
};
#define I2C_DELAY 10
//#define SAA_7114_NTSC_HSYNC_START (-3)
//#define SAA_7114_NTSC_HSYNC_STOP (-18)
#define SAA_7114_NTSC_HSYNC_START (-17)
#define SAA_7114_NTSC_HSYNC_STOP (-32)
//#define SAA_7114_NTSC_HOFFSET (5)
#define SAA_7114_NTSC_HOFFSET (6)
#define SAA_7114_NTSC_VOFFSET (10)
#define SAA_7114_NTSC_WIDTH (720)
#define SAA_7114_NTSC_HEIGHT (250)
#define SAA_7114_SECAM_HSYNC_START (-17)
#define SAA_7114_SECAM_HSYNC_STOP (-32)
#define SAA_7114_SECAM_HOFFSET (2)
#define SAA_7114_SECAM_VOFFSET (10)
#define SAA_7114_SECAM_WIDTH (720)
#define SAA_7114_SECAM_HEIGHT (300)
#define SAA_7114_PAL_HSYNC_START (-17)
#define SAA_7114_PAL_HSYNC_STOP (-32)
#define SAA_7114_PAL_HOFFSET (2)
#define SAA_7114_PAL_VOFFSET (10)
#define SAA_7114_PAL_WIDTH (720)
#define SAA_7114_PAL_HEIGHT (300)
#define SAA_7114_VERTICAL_CHROMA_OFFSET 0 //0x50504040
#define SAA_7114_VERTICAL_LUMA_OFFSET 0
#define REG_ADDR(x) (((x) << 1) + 1)
#define LOBYTE(x) ((unsigned char)((x) & 0xff))
#define HIBYTE(x) ((unsigned char)(((x) >> 8) & 0xff))
#define LOWORD(x) ((unsigned short int)((x) & 0xffff))
#define HIWORD(x) ((unsigned short int)(((x) >> 16) & 0xffff))
/* ----------------------------------------------------------------------- */
static inline int saa7114_write(struct i2c_client *client, u8 reg, u8 value)
{
return i2c_smbus_write_byte_data(client, reg, value);
}
static int saa7114_write_block(struct i2c_client *client, const u8 *data, unsigned int len)
{
int ret = -1;
u8 reg;
/* the saa7114 has an autoincrement function, use it if
* the adapter understands raw I2C */
if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
/* do raw I2C, not smbus compatible */
u8 block_data[32];
int block_len;
while (len >= 2) {
block_len = 0;
block_data[block_len++] = reg = data[0];
do {
block_data[block_len++] = data[1];
reg++;
len -= 2;
data += 2;
} while (len >= 2 && data[0] == reg && block_len < 32);
ret = i2c_master_send(client, block_data, block_len);
if (ret < 0)
break;
}
} else {
/* do some slow I2C emulation kind of thing */
while (len >= 2) {
reg = *data++;
ret = saa7114_write(client, reg, *data++);
if (ret < 0)
break;
len -= 2;
}
}
return ret;
}
static inline int saa7114_read(struct i2c_client *client, u8 reg)
{
return i2c_smbus_read_byte_data(client, reg);
}
/* ----------------------------------------------------------------------- */
// initially set NTSC, composite
static const unsigned char init[] = {
0x00, 0x00, /* 00 - ID byte , chip version,
* read only */
0x01, 0x08, /* 01 - X,X,X,X, IDEL3 to IDEL0 -
* horizontal increment delay,
* recommended position */
0x02, 0x00, /* 02 - FUSE=3, GUDL=2, MODE=0 ;
* input control */
0x03, 0x10, /* 03 - HLNRS=0, VBSL=1, WPOFF=0,
* HOLDG=0, GAFIX=0, GAI1=256, GAI2=256 */
0x04, 0x90, /* 04 - GAI1=256 */
0x05, 0x90, /* 05 - GAI2=256 */
0x06, SAA_7114_NTSC_HSYNC_START, /* 06 - HSB: hsync start,
* depends on the video standard */
0x07, SAA_7114_NTSC_HSYNC_STOP, /* 07 - HSS: hsync stop, depends
*on the video standard */
0x08, 0xb8, /* 08 - AUFD=1, FSEL=1, EXFIL=0, VTRC=1,
* HPLL: free running in playback, locked
* in capture, VNOI=0 */
0x09, 0x80, /* 09 - BYPS=0, PREF=0, BPSS=0, VBLB=0,
* UPTCV=0, APER=1; depends from input */
0x0a, 0x80, /* 0a - BRIG=128 */
0x0b, 0x44, /* 0b - CONT=1.109 */
0x0c, 0x40, /* 0c - SATN=1.0 */
0x0d, 0x00, /* 0d - HUE=0 */
0x0e, 0x84, /* 0e - CDTO, CSTD2 to 0, DCVF, FCTC,
* CCOMB; depends from video standard */
0x0f, 0x24, /* 0f - ACGC,CGAIN6 to CGAIN0; depends
* from video standard */
0x10, 0x03, /* 10 - OFFU1 to 0, OFFV1 to 0, CHBW,
* LCBW2 to 0 */
0x11, 0x59, /* 11 - COLO, RTP1, HEDL1 to 0, RTP0,
* YDEL2 to 0 */
0x12, 0xc9, /* 12 - RT signal control RTSE13 to 10
* and 03 to 00 */
0x13, 0x80, /* 13 - RT/X port output control */
0x14, 0x00, /* 14 - analog, ADC, compatibility control */
0x15, 0x00, /* 15 - VGATE start FID change */
0x16, 0xfe, /* 16 - VGATE stop */
0x17, 0x00, /* 17 - Misc., VGATE MSBs */
0x18, 0x40, /* RAWG */
0x19, 0x80, /* RAWO */
0x1a, 0x00,
0x1b, 0x00,
0x1c, 0x00,
0x1d, 0x00,
0x1e, 0x00,
0x1f, 0x00, /* status byte, read only */
0x20, 0x00, /* video decoder reserved part */
0x21, 0x00,
0x22, 0x00,
0x23, 0x00,
0x24, 0x00,
0x25, 0x00,
0x26, 0x00,
0x27, 0x00,
0x28, 0x00,
0x29, 0x00,
0x2a, 0x00,
0x2b, 0x00,
0x2c, 0x00,
0x2d, 0x00,
0x2e, 0x00,
0x2f, 0x00,
0x30, 0xbc, /* audio clock generator */
0x31, 0xdf,
0x32, 0x02,
0x33, 0x00,
0x34, 0xcd,
0x35, 0xcc,
0x36, 0x3a,
0x37, 0x00,
0x38, 0x03,
0x39, 0x10,
0x3a, 0x00,
0x3b, 0x00,
0x3c, 0x00,
0x3d, 0x00,
0x3e, 0x00,
0x3f, 0x00,
0x40, 0x00, /* VBI data slicer */
0x41, 0xff,
0x42, 0xff,
0x43, 0xff,
0x44, 0xff,
0x45, 0xff,
0x46, 0xff,
0x47, 0xff,
0x48, 0xff,
0x49, 0xff,
0x4a, 0xff,
0x4b, 0xff,
0x4c, 0xff,
0x4d, 0xff,
0x4e, 0xff,
0x4f, 0xff,
0x50, 0xff,
0x51, 0xff,
0x52, 0xff,
0x53, 0xff,
0x54, 0xff,
0x55, 0xff,
0x56, 0xff,
0x57, 0xff,
0x58, 0x40, // framing code
0x59, 0x47, // horizontal offset
0x5a, 0x06, // vertical offset
0x5b, 0x83, // field offset
0x5c, 0x00, // reserved
0x5d, 0x3e, // header and data
0x5e, 0x00, // sliced data
0x5f, 0x00, // reserved
0x60, 0x00, /* video decoder reserved part */
0x61, 0x00,
0x62, 0x00,
0x63, 0x00,
0x64, 0x00,
0x65, 0x00,
0x66, 0x00,
0x67, 0x00,
0x68, 0x00,
0x69, 0x00,
0x6a, 0x00,
0x6b, 0x00,
0x6c, 0x00,
0x6d, 0x00,
0x6e, 0x00,
0x6f, 0x00,
0x70, 0x00, /* video decoder reserved part */
0x71, 0x00,
0x72, 0x00,
0x73, 0x00,
0x74, 0x00,
0x75, 0x00,
0x76, 0x00,
0x77, 0x00,
0x78, 0x00,
0x79, 0x00,
0x7a, 0x00,
0x7b, 0x00,
0x7c, 0x00,
0x7d, 0x00,
0x7e, 0x00,
0x7f, 0x00,
0x80, 0x00, /* X-port, I-port and scaler */
0x81, 0x00,
0x82, 0x00,
0x83, 0x00,
0x84, 0xc5,
0x85, 0x0d, // hsync and vsync ?
0x86, 0x40,
0x87, 0x01,
0x88, 0x00,
0x89, 0x00,
0x8a, 0x00,
0x8b, 0x00,
0x8c, 0x00,
0x8d, 0x00,
0x8e, 0x00,
0x8f, 0x00,
0x90, 0x03, /* Task A definition */
0x91, 0x08,
0x92, 0x00,
0x93, 0x40,
0x94, 0x00, // window settings
0x95, 0x00,
0x96, 0x00,
0x97, 0x00,
0x98, 0x00,
0x99, 0x00,
0x9a, 0x00,
0x9b, 0x00,
0x9c, 0x00,
0x9d, 0x00,
0x9e, 0x00,
0x9f, 0x00,
0xa0, 0x01, /* horizontal integer prescaling ratio */
0xa1, 0x00, /* horizontal prescaler accumulation
* sequence length */
0xa2, 0x00, /* UV FIR filter, Y FIR filter, prescaler
* DC gain */
0xa3, 0x00,
0xa4, 0x80, // luminance brightness
0xa5, 0x40, // luminance gain
0xa6, 0x40, // chrominance saturation
0xa7, 0x00,
0xa8, 0x00, // horizontal luminance scaling increment
0xa9, 0x04,
0xaa, 0x00, // horizontal luminance phase offset
0xab, 0x00,
0xac, 0x00, // horizontal chrominance scaling increment
0xad, 0x02,
0xae, 0x00, // horizontal chrominance phase offset
0xaf, 0x00,
0xb0, 0x00, // vertical luminance scaling increment
0xb1, 0x04,
0xb2, 0x00, // vertical chrominance scaling increment
0xb3, 0x04,
0xb4, 0x00,
0xb5, 0x00,
0xb6, 0x00,
0xb7, 0x00,
0xb8, 0x00,
0xb9, 0x00,
0xba, 0x00,
0xbb, 0x00,
0xbc, 0x00,
0xbd, 0x00,
0xbe, 0x00,
0xbf, 0x00,
0xc0, 0x02, // Task B definition
0xc1, 0x08,
0xc2, 0x00,
0xc3, 0x40,
0xc4, 0x00, // window settings
0xc5, 0x00,
0xc6, 0x00,
0xc7, 0x00,
0xc8, 0x00,
0xc9, 0x00,
0xca, 0x00,
0xcb, 0x00,
0xcc, 0x00,
0xcd, 0x00,
0xce, 0x00,
0xcf, 0x00,
0xd0, 0x01, // horizontal integer prescaling ratio
0xd1, 0x00, // horizontal prescaler accumulation sequence length
0xd2, 0x00, // UV FIR filter, Y FIR filter, prescaler DC gain
0xd3, 0x00,
0xd4, 0x80, // luminance brightness
0xd5, 0x40, // luminance gain
0xd6, 0x40, // chrominance saturation
0xd7, 0x00,
0xd8, 0x00, // horizontal luminance scaling increment
0xd9, 0x04,
0xda, 0x00, // horizontal luminance phase offset
0xdb, 0x00,
0xdc, 0x00, // horizontal chrominance scaling increment
0xdd, 0x02,
0xde, 0x00, // horizontal chrominance phase offset
0xdf, 0x00,
0xe0, 0x00, // vertical luminance scaling increment
0xe1, 0x04,
0xe2, 0x00, // vertical chrominance scaling increment
0xe3, 0x04,
0xe4, 0x00,
0xe5, 0x00,
0xe6, 0x00,
0xe7, 0x00,
0xe8, 0x00,
0xe9, 0x00,
0xea, 0x00,
0xeb, 0x00,
0xec, 0x00,
0xed, 0x00,
0xee, 0x00,
0xef, 0x00
};
static int saa7114_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct saa7114 *decoder = i2c_get_clientdata(client);
switch (cmd) {
case 0:
//dprintk(1, KERN_INFO "%s: writing init\n", I2C_NAME(client));
//saa7114_write_block(client, init, sizeof(init));
break;
case DECODER_DUMP:
{
int i;
if (!debug)
break;
v4l_info(client, "decoder dump\n");
for (i = 0; i < 32; i += 16) {
int j;
v4l_info(client, "%03x", i);
for (j = 0; j < 16; ++j) {
printk(KERN_CONT " %02x",
saa7114_read(client, i + j));
}
printk(KERN_CONT "\n");
}
break;
}
case DECODER_GET_CAPABILITIES:
{
struct video_decoder_capability *cap = arg;
v4l_dbg(1, debug, client, "get capabilities\n");
cap->flags = VIDEO_DECODER_PAL |
VIDEO_DECODER_NTSC |
VIDEO_DECODER_AUTO |
VIDEO_DECODER_CCIR;
cap->inputs = 8;
cap->outputs = 1;
break;
}
case DECODER_GET_STATUS:
{
int *iarg = arg;
int status;
int res;
status = saa7114_read(client, 0x1f);
v4l_dbg(1, debug, client, "status: 0x%02x\n", status);
res = 0;
if ((status & (1 << 6)) == 0) {
res |= DECODER_STATUS_GOOD;
}
switch (decoder->norm) {
case VIDEO_MODE_NTSC:
res |= DECODER_STATUS_NTSC;
break;
case VIDEO_MODE_PAL:
res |= DECODER_STATUS_PAL;
break;
case VIDEO_MODE_SECAM:
res |= DECODER_STATUS_SECAM;
break;
default:
case VIDEO_MODE_AUTO:
if ((status & (1 << 5)) != 0) {
res |= DECODER_STATUS_NTSC;
} else {
res |= DECODER_STATUS_PAL;
}
break;
}
if ((status & (1 << 0)) != 0) {
res |= DECODER_STATUS_COLOR;
}
*iarg = res;
break;
}
case DECODER_SET_NORM:
{
int *iarg = arg;
short int hoff = 0, voff = 0, w = 0, h = 0;
v4l_dbg(1, debug, client, "set norm\n");
switch (*iarg) {
case VIDEO_MODE_NTSC:
v4l_dbg(1, debug, client, "NTSC\n");
decoder->reg[REG_ADDR(0x06)] =
SAA_7114_NTSC_HSYNC_START;
decoder->reg[REG_ADDR(0x07)] =
SAA_7114_NTSC_HSYNC_STOP;
decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
decoder->reg[REG_ADDR(0x0e)] = 0x85;
decoder->reg[REG_ADDR(0x0f)] = 0x24;
hoff = SAA_7114_NTSC_HOFFSET;
voff = SAA_7114_NTSC_VOFFSET;
w = SAA_7114_NTSC_WIDTH;
h = SAA_7114_NTSC_HEIGHT;
break;
case VIDEO_MODE_PAL:
v4l_dbg(1, debug, client, "PAL\n");
decoder->reg[REG_ADDR(0x06)] =
SAA_7114_PAL_HSYNC_START;
decoder->reg[REG_ADDR(0x07)] =
SAA_7114_PAL_HSYNC_STOP;
decoder->reg[REG_ADDR(0x08)] = decoder->playback ? 0x7c : 0xb8; // PLL free when playback, PLL close when capture
decoder->reg[REG_ADDR(0x0e)] = 0x81;
decoder->reg[REG_ADDR(0x0f)] = 0x24;
hoff = SAA_7114_PAL_HOFFSET;
voff = SAA_7114_PAL_VOFFSET;
w = SAA_7114_PAL_WIDTH;
h = SAA_7114_PAL_HEIGHT;
break;
default:
v4l_dbg(1, debug, client, "Unknown video mode\n");
return -EINVAL;
}
decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low
decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high
decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low
decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high
decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low
decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high
decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low
decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high
decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low
decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high
decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low
decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high
decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low
decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high
decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low
decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high
decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low
decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high
decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low
decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high
decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low
decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high
decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low
decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high
saa7114_write(client, 0x80, 0x06); // i-port and scaler back end clock selection, task A&B off
saa7114_write(client, 0x88, 0xd8); // sw reset scaler
saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
saa7114_write_block(client, decoder->reg + (0x06 << 1),
3 << 1);
saa7114_write_block(client, decoder->reg + (0x0e << 1),
2 << 1);
saa7114_write_block(client, decoder->reg + (0x5a << 1),
2 << 1);
saa7114_write_block(client, decoder->reg + (0x94 << 1),
(0x9f + 1 - 0x94) << 1);
saa7114_write_block(client, decoder->reg + (0xc4 << 1),
(0xcf + 1 - 0xc4) << 1);
saa7114_write(client, 0x88, 0xd8); // sw reset scaler
saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
saa7114_write(client, 0x80, 0x36); // i-port and scaler back end clock selection
decoder->norm = *iarg;
break;
}
case DECODER_SET_INPUT:
{
int *iarg = arg;
v4l_dbg(1, debug, client, "set input (%d)\n", *iarg);
if (*iarg < 0 || *iarg > 7) {
return -EINVAL;
}
if (decoder->input != *iarg) {
v4l_dbg(1, debug, client, "now setting %s input\n",
*iarg >= 6 ? "S-Video" : "Composite");
decoder->input = *iarg;
/* select mode */
decoder->reg[REG_ADDR(0x02)] =
(decoder->
reg[REG_ADDR(0x02)] & 0xf0) | (decoder->
input <
6 ? 0x0 : 0x9);
saa7114_write(client, 0x02,
decoder->reg[REG_ADDR(0x02)]);
/* bypass chrominance trap for modes 6..9 */
decoder->reg[REG_ADDR(0x09)] =
(decoder->
reg[REG_ADDR(0x09)] & 0x7f) | (decoder->
input <
6 ? 0x0 :
0x80);
saa7114_write(client, 0x09,
decoder->reg[REG_ADDR(0x09)]);
decoder->reg[REG_ADDR(0x0e)] =
decoder->input <
6 ? decoder->
reg[REG_ADDR(0x0e)] | 1 : decoder->
reg[REG_ADDR(0x0e)] & ~1;
saa7114_write(client, 0x0e,
decoder->reg[REG_ADDR(0x0e)]);
}
break;
}
case DECODER_SET_OUTPUT:
{
int *iarg = arg;
v4l_dbg(1, debug, client, "set output\n");
/* not much choice of outputs */
if (*iarg != 0) {
return -EINVAL;
}
break;
}
case DECODER_ENABLE_OUTPUT:
{
int *iarg = arg;
int enable = (*iarg != 0);
v4l_dbg(1, debug, client, "%s output\n",
enable ? "enable" : "disable");
decoder->playback = !enable;
if (decoder->enable != enable) {
decoder->enable = enable;
/* RJ: If output should be disabled (for
* playing videos), we also need a open PLL.
* The input is set to 0 (where no input
* source is connected), although this
* is not necessary.
*
* If output should be enabled, we have to
* reverse the above.
*/
if (decoder->enable) {
decoder->reg[REG_ADDR(0x08)] = 0xb8;
decoder->reg[REG_ADDR(0x12)] = 0xc9;
decoder->reg[REG_ADDR(0x13)] = 0x80;
decoder->reg[REG_ADDR(0x87)] = 0x01;
} else {
decoder->reg[REG_ADDR(0x08)] = 0x7c;
decoder->reg[REG_ADDR(0x12)] = 0x00;
decoder->reg[REG_ADDR(0x13)] = 0x00;
decoder->reg[REG_ADDR(0x87)] = 0x00;
}
saa7114_write_block(client,
decoder->reg + (0x12 << 1),
2 << 1);
saa7114_write(client, 0x08,
decoder->reg[REG_ADDR(0x08)]);
saa7114_write(client, 0x87,
decoder->reg[REG_ADDR(0x87)]);
saa7114_write(client, 0x88, 0xd8); // sw reset scaler
saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
saa7114_write(client, 0x80, 0x36);
}
break;
}
case DECODER_SET_PICTURE:
{
struct video_picture *pic = arg;
v4l_dbg(1, debug, client,
"decoder set picture bright=%d contrast=%d saturation=%d hue=%d\n",
pic->brightness, pic->contrast, pic->colour, pic->hue);
if (decoder->bright != pic->brightness) {
/* We want 0 to 255 we get 0-65535 */
decoder->bright = pic->brightness;
saa7114_write(client, 0x0a, decoder->bright >> 8);
}
if (decoder->contrast != pic->contrast) {
/* We want 0 to 127 we get 0-65535 */
decoder->contrast = pic->contrast;
saa7114_write(client, 0x0b,
decoder->contrast >> 9);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 127 we get 0-65535 */
decoder->sat = pic->colour;
saa7114_write(client, 0x0c, decoder->sat >> 9);
}
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue;
saa7114_write(client, 0x0d,
(decoder->hue - 32768) >> 8);
}
break;
}
default:
return -EINVAL;
}
return 0;
}
/* ----------------------------------------------------------------------- */
static unsigned short normal_i2c[] = { 0x42 >> 1, 0x40 >> 1, I2C_CLIENT_END };
I2C_CLIENT_INSMOD;
static int saa7114_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int i, err[30];
short int hoff = SAA_7114_NTSC_HOFFSET;
short int voff = SAA_7114_NTSC_VOFFSET;
short int w = SAA_7114_NTSC_WIDTH;
short int h = SAA_7114_NTSC_HEIGHT;
struct saa7114 *decoder;
/* Check if the adapter supports the needed features */
if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
v4l_info(client, "chip found @ 0x%x (%s)\n",
client->addr << 1, client->adapter->name);
decoder = kzalloc(sizeof(struct saa7114), GFP_KERNEL);
if (decoder == NULL)
return -ENOMEM;
decoder->norm = VIDEO_MODE_NTSC;
decoder->input = -1;
decoder->enable = 1;
decoder->bright = 32768;
decoder->contrast = 32768;
decoder->hue = 32768;
decoder->sat = 32768;
decoder->playback = 0; // initially capture mode useda
i2c_set_clientdata(client, decoder);
memcpy(decoder->reg, init, sizeof(init));
decoder->reg[REG_ADDR(0x94)] = LOBYTE(hoff); // hoffset low
decoder->reg[REG_ADDR(0x95)] = HIBYTE(hoff) & 0x0f; // hoffset high
decoder->reg[REG_ADDR(0x96)] = LOBYTE(w); // width low
decoder->reg[REG_ADDR(0x97)] = HIBYTE(w) & 0x0f; // width high
decoder->reg[REG_ADDR(0x98)] = LOBYTE(voff); // voffset low
decoder->reg[REG_ADDR(0x99)] = HIBYTE(voff) & 0x0f; // voffset high
decoder->reg[REG_ADDR(0x9a)] = LOBYTE(h + 2); // height low
decoder->reg[REG_ADDR(0x9b)] = HIBYTE(h + 2) & 0x0f; // height high
decoder->reg[REG_ADDR(0x9c)] = LOBYTE(w); // out width low
decoder->reg[REG_ADDR(0x9d)] = HIBYTE(w) & 0x0f; // out width high
decoder->reg[REG_ADDR(0x9e)] = LOBYTE(h); // out height low
decoder->reg[REG_ADDR(0x9f)] = HIBYTE(h) & 0x0f; // out height high
decoder->reg[REG_ADDR(0xc4)] = LOBYTE(hoff); // hoffset low
decoder->reg[REG_ADDR(0xc5)] = HIBYTE(hoff) & 0x0f; // hoffset high
decoder->reg[REG_ADDR(0xc6)] = LOBYTE(w); // width low
decoder->reg[REG_ADDR(0xc7)] = HIBYTE(w) & 0x0f; // width high
decoder->reg[REG_ADDR(0xc8)] = LOBYTE(voff); // voffset low
decoder->reg[REG_ADDR(0xc9)] = HIBYTE(voff) & 0x0f; // voffset high
decoder->reg[REG_ADDR(0xca)] = LOBYTE(h + 2); // height low
decoder->reg[REG_ADDR(0xcb)] = HIBYTE(h + 2) & 0x0f; // height high
decoder->reg[REG_ADDR(0xcc)] = LOBYTE(w); // out width low
decoder->reg[REG_ADDR(0xcd)] = HIBYTE(w) & 0x0f; // out width high
decoder->reg[REG_ADDR(0xce)] = LOBYTE(h); // out height low
decoder->reg[REG_ADDR(0xcf)] = HIBYTE(h) & 0x0f; // out height high
decoder->reg[REG_ADDR(0xb8)] =
LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xb9)] =
HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xba)] =
LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xbb)] =
HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xbc)] =
LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0xbd)] =
HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0xbe)] =
LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0xbf)] =
HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0xe8)] =
LOBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xe9)] =
HIBYTE(LOWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xea)] =
LOBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xeb)] =
HIBYTE(HIWORD(SAA_7114_VERTICAL_CHROMA_OFFSET));
decoder->reg[REG_ADDR(0xec)] =
LOBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0xed)] =
HIBYTE(LOWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0xee)] =
LOBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0xef)] =
HIBYTE(HIWORD(SAA_7114_VERTICAL_LUMA_OFFSET));
decoder->reg[REG_ADDR(0x13)] = 0x80; // RTC0 on
decoder->reg[REG_ADDR(0x87)] = 0x01; // I-Port
decoder->reg[REG_ADDR(0x12)] = 0xc9; // RTS0
decoder->reg[REG_ADDR(0x02)] = 0xc0; // set composite1 input, aveasy
decoder->reg[REG_ADDR(0x09)] = 0x00; // chrominance trap
decoder->reg[REG_ADDR(0x0e)] |= 1; // combfilter on
v4l_dbg(1, debug, client, "starting init\n");
err[0] =
saa7114_write_block(client, decoder->reg + (0x20 << 1),
0x10 << 1);
err[1] =
saa7114_write_block(client, decoder->reg + (0x30 << 1),
0x10 << 1);
err[2] =
saa7114_write_block(client, decoder->reg + (0x63 << 1),
(0x7f + 1 - 0x63) << 1);
err[3] =
saa7114_write_block(client, decoder->reg + (0x89 << 1),
6 << 1);
err[4] =
saa7114_write_block(client, decoder->reg + (0xb8 << 1),
8 << 1);
err[5] =
saa7114_write_block(client, decoder->reg + (0xe8 << 1),
8 << 1);
for (i = 0; i <= 5; i++) {
if (err[i] < 0) {
v4l_dbg(1, debug, client,
"init error %d at stage %d, leaving attach.\n",
i, err[i]);
kfree(decoder);
return -EIO;
}
}
for (i = 6; i < 8; i++) {
v4l_dbg(1, debug, client,
"reg[0x%02x] = 0x%02x (0x%02x)\n",
i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
v4l_dbg(1, debug, client,
"performing decoder reset sequence\n");
err[6] = saa7114_write(client, 0x80, 0x06); // i-port and scaler backend clock selection, task A&B off
err[7] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
err[8] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
for (i = 6; i <= 8; i++) {
if (err[i] < 0) {
v4l_dbg(1, debug, client,
"init error %d at stage %d, leaving attach.\n",
i, err[i]);
kfree(decoder);
return -EIO;
}
}
v4l_dbg(1, debug, client, "performing the rest of init\n");
err[9] = saa7114_write(client, 0x01, decoder->reg[REG_ADDR(0x01)]);
err[10] = saa7114_write_block(client, decoder->reg + (0x03 << 1), (0x1e + 1 - 0x03) << 1); // big seq
err[11] = saa7114_write_block(client, decoder->reg + (0x40 << 1), (0x5f + 1 - 0x40) << 1); // slicer
err[12] = saa7114_write_block(client, decoder->reg + (0x81 << 1), 2 << 1); // ?
err[13] = saa7114_write_block(client, decoder->reg + (0x83 << 1), 5 << 1); // ?
err[14] = saa7114_write_block(client, decoder->reg + (0x90 << 1), 4 << 1); // Task A
err[15] =
saa7114_write_block(client, decoder->reg + (0x94 << 1),
12 << 1);
err[16] =
saa7114_write_block(client, decoder->reg + (0xa0 << 1),
8 << 1);
err[17] =
saa7114_write_block(client, decoder->reg + (0xa8 << 1),
8 << 1);
err[18] =
saa7114_write_block(client, decoder->reg + (0xb0 << 1),
8 << 1);
err[19] = saa7114_write_block(client, decoder->reg + (0xc0 << 1), 4 << 1); // Task B
err[15] =
saa7114_write_block(client, decoder->reg + (0xc4 << 1),
12 << 1);
err[16] =
saa7114_write_block(client, decoder->reg + (0xd0 << 1),
8 << 1);
err[17] =
saa7114_write_block(client, decoder->reg + (0xd8 << 1),
8 << 1);
err[18] =
saa7114_write_block(client, decoder->reg + (0xe0 << 1),
8 << 1);
for (i = 9; i <= 18; i++) {
if (err[i] < 0) {
v4l_dbg(1, debug, client,
"init error %d at stage %d, leaving attach.\n",
i, err[i]);
kfree(decoder);
return -EIO;
}
}
for (i = 6; i < 8; i++) {
v4l_dbg(1, debug, client,
"reg[0x%02x] = 0x%02x (0x%02x)\n",
i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
for (i = 0x11; i <= 0x13; i++) {
v4l_dbg(1, debug, client,
"reg[0x%02x] = 0x%02x (0x%02x)\n",
i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
v4l_dbg(1, debug, client, "setting video input\n");
err[19] =
saa7114_write(client, 0x02, decoder->reg[REG_ADDR(0x02)]);
err[20] =
saa7114_write(client, 0x09, decoder->reg[REG_ADDR(0x09)]);
err[21] =
saa7114_write(client, 0x0e, decoder->reg[REG_ADDR(0x0e)]);
for (i = 19; i <= 21; i++) {
if (err[i] < 0) {
v4l_dbg(1, debug, client,
"init error %d at stage %d, leaving attach.\n",
i, err[i]);
kfree(decoder);
return -EIO;
}
}
v4l_dbg(1, debug, client, "performing decoder reset sequence\n");
err[22] = saa7114_write(client, 0x88, 0xd8); // sw reset scaler
err[23] = saa7114_write(client, 0x88, 0xf8); // sw reset scaler release
err[24] = saa7114_write(client, 0x80, 0x36); // i-port and scaler backend clock selection, task A&B off
for (i = 22; i <= 24; i++) {
if (err[i] < 0) {
v4l_dbg(1, debug, client,
"init error %d at stage %d, leaving attach.\n",
i, err[i]);
kfree(decoder);
return -EIO;
}
}
err[25] = saa7114_write(client, 0x06, init[REG_ADDR(0x06)]);
err[26] = saa7114_write(client, 0x07, init[REG_ADDR(0x07)]);
err[27] = saa7114_write(client, 0x10, init[REG_ADDR(0x10)]);
v4l_dbg(1, debug, client, "chip version %x, decoder status 0x%02x\n",
saa7114_read(client, 0x00) >> 4,
saa7114_read(client, 0x1f));
v4l_dbg(1, debug, client,
"power save control: 0x%02x, scaler status: 0x%02x\n",
saa7114_read(client, 0x88),
saa7114_read(client, 0x8f));
for (i = 0x94; i < 0x96; i++) {
v4l_dbg(1, debug, client,
"reg[0x%02x] = 0x%02x (0x%02x)\n",
i, saa7114_read(client, i),
decoder->reg[REG_ADDR(i)]);
}
//i = saa7114_write_block(client, init, sizeof(init));
return 0;
}
static int saa7114_remove(struct i2c_client *client)
{
kfree(i2c_get_clientdata(client));
return 0;
}
/* ----------------------------------------------------------------------- */
static const struct i2c_device_id saa7114_id[] = {
{ "saa7114_old", 0 }, /* "saa7114" maps to the saa7115 driver */
{ }
};
MODULE_DEVICE_TABLE(i2c, saa7114_id);
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "saa7114",
.driverid = I2C_DRIVERID_SAA7114,
.command = saa7114_command,
.probe = saa7114_probe,
.remove = saa7114_remove,
.id_table = saa7114_id,
};
......@@ -49,8 +49,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
struct saa7185 {
unsigned char reg[128];
int norm;
int enable;
v4l2_std_id norm;
int bright;
int contrast;
int hue;
......@@ -218,68 +217,43 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg)
struct saa7185 *encoder = i2c_get_clientdata(client);
switch (cmd) {
case 0:
case VIDIOC_INT_INIT:
saa7185_write_block(client, init_common,
sizeof(init_common));
switch (encoder->norm) {
case VIDEO_MODE_NTSC:
if (encoder->norm & V4L2_STD_NTSC)
saa7185_write_block(client, init_ntsc,
sizeof(init_ntsc));
break;
case VIDEO_MODE_PAL:
else
saa7185_write_block(client, init_pal,
sizeof(init_pal));
break;
}
break;
case ENCODER_GET_CAPABILITIES:
{
struct video_encoder_capability *cap = arg;
cap->flags =
VIDEO_ENCODER_PAL | VIDEO_ENCODER_NTSC |
VIDEO_ENCODER_SECAM | VIDEO_ENCODER_CCIR;
cap->inputs = 1;
cap->outputs = 1;
break;
}
case ENCODER_SET_NORM:
case VIDIOC_INT_S_STD_OUTPUT:
{
int *iarg = arg;
v4l2_std_id *iarg = arg;
//saa7185_write_block(client, init_common, sizeof(init_common));
switch (*iarg) {
case VIDEO_MODE_NTSC:
if (*iarg & V4L2_STD_NTSC)
saa7185_write_block(client, init_ntsc,
sizeof(init_ntsc));
break;
case VIDEO_MODE_PAL:
else if (*iarg & V4L2_STD_PAL)
saa7185_write_block(client, init_pal,
sizeof(init_pal));
break;
case VIDEO_MODE_SECAM:
default:
else
return -EINVAL;
}
encoder->norm = *iarg;
break;
}
case ENCODER_SET_INPUT:
case VIDIOC_INT_S_VIDEO_ROUTING:
{
int *iarg = arg;
struct v4l2_routing *route = arg;
/* RJ: *iarg = 0: input is from SA7111
*iarg = 1: input is from ZR36060 */
/* RJ: route->input = 0: input is from SA7111
route->input = 1: input is from ZR36060 */
switch (*iarg) {
switch (route->input) {
case 0:
/* turn off colorbar */
saa7185_write(client, 0x3a, 0x0f);
......@@ -315,27 +289,6 @@ static int saa7185_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
}
case ENCODER_SET_OUTPUT:
{
int *iarg = arg;
/* not much choice of outputs */
if (*iarg != 0)
return -EINVAL;
break;
}
case ENCODER_ENABLE_OUTPUT:
{
int *iarg = arg;
encoder->enable = !!*iarg;
saa7185_write(client, 0x61,
(encoder->reg[0x61] & 0xbf) |
(encoder->enable ? 0x00 : 0x40));
break;
}
default:
return -EINVAL;
}
......@@ -365,8 +318,7 @@ static int saa7185_probe(struct i2c_client *client,
encoder = kzalloc(sizeof(struct saa7185), GFP_KERNEL);
if (encoder == NULL)
return -ENOMEM;
encoder->norm = VIDEO_MODE_NTSC;
encoder->enable = 1;
encoder->norm = V4L2_STD_NTSC;
i2c_set_clientdata(client, encoder);
i = saa7185_write_block(client, init_common, sizeof(init_common));
......
......@@ -27,6 +27,7 @@
#include <media/v4l2-common.h>
#include <media/v4l2-i2c-drv-legacy.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <linux/video_decoder.h>
MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
......@@ -44,7 +45,7 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
struct vpx3220 {
unsigned char reg[255];
int norm;
v4l2_std_id norm;
int input;
int enable;
int bright;
......@@ -259,79 +260,41 @@ static const unsigned short init_fp[] = {
0x4b, 0x298, /* PLL gain */
};
static void vpx3220_dump_i2c(struct i2c_client *client)
{
int len = sizeof(init_common);
const unsigned char *data = init_common;
while (len > 1) {
v4l_dbg(1, debug, client, "i2c reg 0x%02x data 0x%02x\n",
*data, vpx3220_read(client, *data));
data += 2;
len -= 2;
}
}
static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
{
struct vpx3220 *decoder = i2c_get_clientdata(client);
switch (cmd) {
case 0:
case VIDIOC_INT_INIT:
{
vpx3220_write_block(client, init_common,
sizeof(init_common));
vpx3220_write_fp_block(client, init_fp,
sizeof(init_fp) >> 1);
switch (decoder->norm) {
case VIDEO_MODE_NTSC:
if (decoder->norm & V4L2_STD_NTSC) {
vpx3220_write_fp_block(client, init_ntsc,
sizeof(init_ntsc) >> 1);
break;
case VIDEO_MODE_PAL:
} else if (decoder->norm & V4L2_STD_PAL) {
vpx3220_write_fp_block(client, init_pal,
sizeof(init_pal) >> 1);
break;
case VIDEO_MODE_SECAM:
} else if (decoder->norm & V4L2_STD_SECAM) {
vpx3220_write_fp_block(client, init_secam,
sizeof(init_secam) >> 1);
break;
default:
} else {
vpx3220_write_fp_block(client, init_pal,
sizeof(init_pal) >> 1);
break;
}
break;
}
case DECODER_DUMP:
{
vpx3220_dump_i2c(client);
break;
}
case DECODER_GET_CAPABILITIES:
{
struct video_decoder_capability *cap = arg;
v4l_dbg(1, debug, client, "DECODER_GET_CAPABILITIES\n");
cap->flags = VIDEO_DECODER_PAL |
VIDEO_DECODER_NTSC |
VIDEO_DECODER_SECAM |
VIDEO_DECODER_AUTO |
VIDEO_DECODER_CCIR;
cap->inputs = 3;
cap->outputs = 1;
break;
}
case DECODER_GET_STATUS:
case VIDIOC_QUERYSTD:
case VIDIOC_INT_G_INPUT_STATUS:
{
int res = 0, status;
int res = V4L2_IN_ST_NO_SIGNAL, status;
v4l2_std_id std = 0;
v4l_dbg(1, debug, client, "DECODER_GET_STATUS\n");
v4l_dbg(1, debug, client, "VIDIOC_QUERYSTD/VIDIOC_INT_G_INPUT_STATUS\n");
status = vpx3220_fp_read(client, 0x0f3);
......@@ -341,35 +304,38 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
return status;
if ((status & 0x20) == 0) {
res |= DECODER_STATUS_GOOD | DECODER_STATUS_COLOR;
res = 0;
switch (status & 0x18) {
case 0x00:
case 0x10:
case 0x14:
case 0x18:
res |= DECODER_STATUS_PAL;
std = V4L2_STD_PAL;
break;
case 0x08:
res |= DECODER_STATUS_SECAM;
std = V4L2_STD_SECAM;
break;
case 0x04:
case 0x0c:
case 0x1c:
res |= DECODER_STATUS_NTSC;
std = V4L2_STD_NTSC;
break;
}
}
*(int *) arg = res;
if (cmd == VIDIOC_QUERYSTD)
*(v4l2_std_id *)arg = std;
else
*(int *)arg = res;
break;
}
case DECODER_SET_NORM:
case VIDIOC_S_STD:
{
int *iarg = arg, data;
v4l2_std_id *iarg = arg;
int temp_input;
/* Here we back up the input selection because it gets
......@@ -377,36 +343,23 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
choosen video norm */
temp_input = vpx3220_fp_read(client, 0xf2);
v4l_dbg(1, debug, client, "DECODER_SET_NORM %d\n", *iarg);
switch (*iarg) {
case VIDEO_MODE_NTSC:
v4l_dbg(1, debug, client, "VIDIOC_S_STD %llx\n", *iarg);
if (*iarg & V4L2_STD_NTSC) {
vpx3220_write_fp_block(client, init_ntsc,
sizeof(init_ntsc) >> 1);
v4l_dbg(1, debug, client, "norm switched to NTSC\n");
break;
case VIDEO_MODE_PAL:
} else if (*iarg & V4L2_STD_PAL) {
vpx3220_write_fp_block(client, init_pal,
sizeof(init_pal) >> 1);
v4l_dbg(1, debug, client, "norm switched to PAL\n");
break;
case VIDEO_MODE_SECAM:
} else if (*iarg & V4L2_STD_SECAM) {
vpx3220_write_fp_block(client, init_secam,
sizeof(init_secam) >> 1);
v4l_dbg(1, debug, client, "norm switched to SECAM\n");
break;
case VIDEO_MODE_AUTO:
/* FIXME This is only preliminary support */
data = vpx3220_fp_read(client, 0xf2) & 0x20;
vpx3220_fp_write(client, 0xf2, 0x00c0 | data);
v4l_dbg(1, debug, client, "norm switched to AUTO\n");
break;
default:
} else {
return -EINVAL;
}
decoder->norm = *iarg;
/* And here we set the backed up video input again */
......@@ -415,9 +368,10 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
break;
}
case DECODER_SET_INPUT:
case VIDIOC_INT_S_VIDEO_ROUTING:
{
int *iarg = arg, data;
struct v4l2_routing *route = arg;
int data;
/* RJ: *iarg = 0: ST8 (PCTV) input
*iarg = 1: COMPOSITE input
......@@ -429,73 +383,117 @@ static int vpx3220_command(struct i2c_client *client, unsigned cmd, void *arg)
{0x0e, 1}
};
if (*iarg < 0 || *iarg > 2)
if (route->input < 0 || route->input > 2)
return -EINVAL;
v4l_dbg(1, debug, client, "input switched to %s\n", inputs[*iarg]);
v4l_dbg(1, debug, client, "input switched to %s\n", inputs[route->input]);
vpx3220_write(client, 0x33, input[*iarg][0]);
vpx3220_write(client, 0x33, input[route->input][0]);
data = vpx3220_fp_read(client, 0xf2) & ~(0x0020);
if (data < 0)
return data;
/* 0x0010 is required to latch the setting */
vpx3220_fp_write(client, 0xf2,
data | (input[*iarg][1] << 5) | 0x0010);
data | (input[route->input][1] << 5) | 0x0010);
udelay(10);
break;
}
case DECODER_SET_OUTPUT:
case VIDIOC_STREAMON:
case VIDIOC_STREAMOFF:
{
int *iarg = arg;
int on = cmd == VIDIOC_STREAMON;
v4l_dbg(1, debug, client, "VIDIOC_STREAM%s\n", on ? "ON" : "OFF");
/* not much choice of outputs */
if (*iarg != 0) {
return -EINVAL;
}
vpx3220_write(client, 0xf2, (on ? 0x1b : 0x00));
break;
}
case DECODER_ENABLE_OUTPUT:
case VIDIOC_QUERYCTRL:
{
int *iarg = arg;
struct v4l2_queryctrl *qc = arg;
v4l_dbg(1, debug, client, "DECODER_ENABLE_OUTPUT %d\n", *iarg);
switch (qc->id) {
case V4L2_CID_BRIGHTNESS:
v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
break;
case V4L2_CID_CONTRAST:
v4l2_ctrl_query_fill(qc, 0, 63, 1, 32);
break;
case V4L2_CID_SATURATION:
v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048);
break;
vpx3220_write(client, 0xf2, (*iarg ? 0x1b : 0x00));
case V4L2_CID_HUE:
v4l2_ctrl_query_fill(qc, -512, 511, 1, 0);
break;
default:
return -EINVAL;
}
break;
}
case DECODER_SET_PICTURE:
case VIDIOC_G_CTRL:
{
struct video_picture *pic = arg;
struct v4l2_control *ctrl = arg;
if (decoder->bright != pic->brightness) {
/* We want -128 to 128 we get 0-65535 */
decoder->bright = pic->brightness;
vpx3220_write(client, 0xe6,
(decoder->bright - 32768) >> 8);
}
if (decoder->contrast != pic->contrast) {
/* We want 0 to 64 we get 0-65535 */
/* Bit 7 and 8 is for noise shaping */
decoder->contrast = pic->contrast;
vpx3220_write(client, 0xe7,
(decoder->contrast >> 10) + 192);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 4096 we get 0-65535 */
decoder->sat = pic->colour;
vpx3220_fp_write(client, 0xa0,
decoder->sat >> 4);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = decoder->bright;
break;
case V4L2_CID_CONTRAST:
ctrl->value = decoder->contrast;
break;
case V4L2_CID_SATURATION:
ctrl->value = decoder->sat;
break;
case V4L2_CID_HUE:
ctrl->value = decoder->hue;
break;
default:
return -EINVAL;
}
if (decoder->hue != pic->hue) {
/* We want -512 to 512 we get 0-65535 */
decoder->hue = pic->hue;
vpx3220_fp_write(client, 0x1c,
((decoder->hue - 32768) >> 6) & 0xFFF);
break;
}
case VIDIOC_S_CTRL:
{
struct v4l2_control *ctrl = arg;
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
if (decoder->bright != ctrl->value) {
decoder->bright = ctrl->value;
vpx3220_write(client, 0xe6, decoder->bright);
}
break;
case V4L2_CID_CONTRAST:
if (decoder->contrast != ctrl->value) {
/* Bit 7 and 8 is for noise shaping */
decoder->contrast = ctrl->value;
vpx3220_write(client, 0xe7,
decoder->contrast + 192);
}
break;
case V4L2_CID_SATURATION:
if (decoder->sat != ctrl->value) {
decoder->sat = ctrl->value;
vpx3220_fp_write(client, 0xa0, decoder->sat);
}
break;
case V4L2_CID_HUE:
if (decoder->hue != ctrl->value) {
decoder->hue = ctrl->value;
vpx3220_fp_write(client, 0x1c, decoder->hue);
}
break;
default:
return -EINVAL;
}
break;
}
......@@ -541,7 +539,7 @@ static int vpx3220_probe(struct i2c_client *client,
decoder = kzalloc(sizeof(struct vpx3220), GFP_KERNEL);
if (decoder == NULL)
return -ENOMEM;
decoder->norm = VIDEO_MODE_PAL;
decoder->norm = V4L2_STD_PAL;
decoder->input = 0;
decoder->enable = 1;
decoder->bright = 32768;
......
......@@ -32,7 +32,7 @@ config VIDEO_ZORAN_ZR36060
config VIDEO_ZORAN_BUZ
tristate "Iomega Buz support"
depends on VIDEO_ZORAN_ZR36060
select VIDEO_SAA7111 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
help
Support for the Iomega Buz MJPEG capture/playback card.
......@@ -58,7 +58,7 @@ config VIDEO_ZORAN_LML33
config VIDEO_ZORAN_LML33R10
tristate "Linux Media Labs LML33R10 support"
depends on VIDEO_ZORAN_ZR36060
select VIDEO_SAA7114 if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
help
support for the Linux Media Labs LML33R10 MJPEG capture/playback
......
......@@ -352,7 +352,7 @@ struct card_info {
char name[32];
} input[BUZ_MAX_INPUT];
int norms;
v4l2_std_id norms;
struct tvnorm *tvn[3]; /* supported TV norms */
u32 jpeg_int; /* JPEG interrupt */
......@@ -401,8 +401,8 @@ struct zoran {
spinlock_t spinlock; /* Spinlock */
/* Video for Linux parameters */
int input, norm; /* card's norm and input - norm=VIDEO_MODE_* */
int hue, saturation, contrast, brightness; /* Current picture params */
int input; /* card's norm and input - norm=VIDEO_MODE_* */
v4l2_std_id norm;
struct video_buffer buffer; /* Current buffer params */
struct zoran_overlay_settings overlay_settings;
u32 *overlay_mask; /* overlay mask */
......
......@@ -340,11 +340,8 @@ i2cid_to_modulename (u16 i2c_id)
case I2C_DRIVERID_SAA7110:
name = "saa7110";
break;
case I2C_DRIVERID_SAA7111A:
name = "saa7111";
break;
case I2C_DRIVERID_SAA7114:
name = "saa7114";
case I2C_DRIVERID_SAA711X:
name = "saa7115";
break;
case I2C_DRIVERID_SAA7185B:
name = "saa7185";
......@@ -439,7 +436,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 2, "S-Video" },
{ 0, "Internal/comp" }
},
.norms = 3,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
.tvn = {
&f50sqpixel_dc10,
&f60sqpixel_dc10,
......@@ -467,7 +464,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 7, "S-Video" },
{ 5, "Internal/comp" }
},
.norms = 3,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
.tvn = {
&f50sqpixel,
&f60sqpixel,
......@@ -494,7 +491,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 7, "S-Video" },
{ 5, "Internal/comp" }
},
.norms = 3,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
.tvn = {
&f50sqpixel,
&f60sqpixel,
......@@ -523,7 +520,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 2, "S-Video" },
{ 0, "Internal/comp" }
},
.norms = 3,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
.tvn = {
&f50sqpixel_dc10,
&f60sqpixel_dc10,
......@@ -552,7 +549,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 2, "S-Video" },
{ 0, "Internal/comp" }
},
.norms = 3,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
.tvn = {
&f50sqpixel_dc10,
&f60sqpixel_dc10,
......@@ -579,7 +576,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 0, "Composite" },
{ 7, "S-Video" }
},
.norms = 2,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL,
.tvn = {
&f50ccir601_lml33,
&f60ccir601_lml33,
......@@ -597,7 +594,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
}, {
.type = LML33R10,
.name = "LML33R10",
.i2c_decoder = I2C_DRIVERID_SAA7114,
.i2c_decoder = I2C_DRIVERID_SAA711X,
.i2c_encoder = I2C_DRIVERID_ADV7170,
.video_codec = CODEC_TYPE_ZR36060,
......@@ -606,7 +603,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 0, "Composite" },
{ 7, "S-Video" }
},
.norms = 2,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL,
.tvn = {
&f50ccir601_lm33r10,
&f60ccir601_lm33r10,
......@@ -624,7 +621,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
}, {
.type = BUZ,
.name = "Buz",
.i2c_decoder = I2C_DRIVERID_SAA7111A,
.i2c_decoder = I2C_DRIVERID_SAA711X,
.i2c_encoder = I2C_DRIVERID_SAA7185B,
.video_codec = CODEC_TYPE_ZR36060,
......@@ -633,7 +630,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{ 3, "Composite" },
{ 7, "S-Video" }
},
.norms = 3,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL|V4L2_STD_SECAM,
.tvn = {
&f50ccir601,
&f60ccir601,
......@@ -670,7 +667,7 @@ static struct card_info zoran_cards[NUM_CARDS] __devinitdata = {
{10, "S-Video 3" },
{15, "YCbCr" }
},
.norms = 2,
.norms = V4L2_STD_NTSC|V4L2_STD_PAL,
.tvn = {
&f50ccir601_avs6eyes,
&f60ccir601_avs6eyes,
......@@ -1086,8 +1083,6 @@ static int __devinit
zr36057_init (struct zoran *zr)
{
int j, err;
int two = 2;
int zero = 0;
dprintk(1,
KERN_INFO
......@@ -1113,14 +1108,23 @@ zr36057_init (struct zoran *zr)
if (default_norm < VIDEO_MODE_PAL &&
default_norm > VIDEO_MODE_SECAM)
default_norm = VIDEO_MODE_PAL;
zr->norm = default_norm;
if (!(zr->timing = zr->card.tvn[zr->norm])) {
if (default_norm == VIDEO_MODE_PAL) {
zr->norm = V4L2_STD_PAL;
zr->timing = zr->card.tvn[0];
} else if (default_norm == VIDEO_MODE_NTSC) {
zr->norm = V4L2_STD_NTSC;
zr->timing = zr->card.tvn[1];
} else {
zr->norm = V4L2_STD_SECAM;
zr->timing = zr->card.tvn[2];
}
if (zr->timing == NULL) {
dprintk(1,
KERN_WARNING
"%s: zr36057_init() - default TV standard not supported by hardware. PAL will be used.\n",
ZR_DEVNAME(zr));
zr->norm = VIDEO_MODE_PAL;
zr->timing = zr->card.tvn[zr->norm];
zr->norm = V4L2_STD_PAL;
zr->timing = zr->card.tvn[0];
}
if (default_input > zr->card.inputs-1) {
......@@ -1132,12 +1136,6 @@ zr36057_init (struct zoran *zr)
}
zr->input = default_input;
/* Should the following be reset at every open ? */
zr->hue = 32768;
zr->contrast = 32768;
zr->saturation = 32768;
zr->brightness = 32768;
/* default setup (will be repeated at every open) */
zoran_open_init_params(zr);
......@@ -1173,8 +1171,10 @@ zr36057_init (struct zoran *zr)
detect_guest_activity(zr);
test_interrupts(zr);
if (!pass_through) {
decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
encoder_command(zr, ENCODER_SET_INPUT, &two);
struct v4l2_routing route = { 2, 0 };
decoder_command(zr, VIDIOC_STREAMOFF, 0);
encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
}
zr->zoran_proc = NULL;
......
......@@ -37,6 +37,8 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/videodev.h>
#include <linux/videodev2.h>
#include <media/v4l2-common.h>
#include <linux/spinlock.h>
#include <linux/sem.h>
......@@ -312,9 +314,9 @@ zr36057_adjust_vfe (struct zoran *zr,
case BUZ_MODE_MOTION_COMPRESS:
case BUZ_MODE_IDLE:
default:
if (zr->norm == VIDEO_MODE_NTSC ||
if ((zr->norm & V4L2_STD_NTSC) ||
(zr->card.type == LML33R10 &&
zr->norm == VIDEO_MODE_PAL))
(zr->norm & V4L2_STD_PAL)))
btand(~ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
else
btor(ZR36057_VFESPFR_ExtFl, ZR36057_VFESPFR);
......@@ -355,14 +357,6 @@ zr36057_set_vfe (struct zoran *zr,
dprintk(2, KERN_INFO "%s: set_vfe() - width = %d, height = %d\n",
ZR_DEVNAME(zr), video_width, video_height);
if (zr->norm != VIDEO_MODE_PAL &&
zr->norm != VIDEO_MODE_NTSC &&
zr->norm != VIDEO_MODE_SECAM) {
dprintk(1,
KERN_ERR "%s: set_vfe() - norm = %d not valid\n",
ZR_DEVNAME(zr), zr->norm);
return;
}
if (video_width < BUZ_MIN_WIDTH ||
video_height < BUZ_MIN_HEIGHT ||
video_width > Wa || video_height > Ha) {
......@@ -426,7 +420,7 @@ zr36057_set_vfe (struct zoran *zr,
* we get the correct colors when uncompressing to the screen */
//reg |= ZR36057_VFESPFR_VCLKPol; /**/
/* RJ: Don't know if that is needed for NTSC also */
if (zr->norm != VIDEO_MODE_NTSC)
if (!(zr->norm & V4L2_STD_NTSC))
reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang
reg |= ZR36057_VFESPFR_TopField;
if (HorDcm >= 48) {
......@@ -981,11 +975,10 @@ void
zr36057_enable_jpg (struct zoran *zr,
enum zoran_codec_mode mode)
{
static int zero;
static int one = 1;
struct vfe_settings cap;
int field_size =
zr->jpg_buffers.buffer_size / zr->jpg_settings.field_per_buff;
struct v4l2_routing route = { 0, 0 };
zr->codec_mode = mode;
......@@ -1007,8 +1000,9 @@ zr36057_enable_jpg (struct zoran *zr,
* the video bus direction set to input.
*/
set_videobus_dir(zr, 0);
decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
encoder_command(zr, ENCODER_SET_INPUT, &zero);
decoder_command(zr, VIDIOC_STREAMON, 0);
route.input = 0;
encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
/* Take the JPEG codec and the VFE out of sleep */
jpeg_codec_sleep(zr, 0);
......@@ -1054,9 +1048,10 @@ zr36057_enable_jpg (struct zoran *zr,
/* In motion decompression mode, the decoder output must be disabled, and
* the video bus direction set to output.
*/
decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
decoder_command(zr, VIDIOC_STREAMOFF, 0);
set_videobus_dir(zr, 1);
encoder_command(zr, ENCODER_SET_INPUT, &one);
route.input = 1;
encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
/* Take the JPEG codec and the VFE out of sleep */
jpeg_codec_sleep(zr, 0);
......@@ -1100,8 +1095,9 @@ zr36057_enable_jpg (struct zoran *zr,
jpeg_codec_sleep(zr, 1);
zr36057_adjust_vfe(zr, mode);
decoder_command(zr, DECODER_ENABLE_OUTPUT, &one);
encoder_command(zr, ENCODER_SET_INPUT, &zero);
decoder_command(zr, VIDIOC_STREAMON, 0);
route.input = 0;
encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
dprintk(2, KERN_INFO "%s: enable_jpg(IDLE)\n", ZR_DEVNAME(zr));
break;
......@@ -1211,17 +1207,17 @@ zoran_reap_stat_com (struct zoran *zr)
static void zoran_restart(struct zoran *zr)
{
/* Now the stat_comm buffer is ready for restart */
int status, mode;
int status = 0, mode;
if (zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) {
decoder_command(zr, DECODER_GET_STATUS, &status);
decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status);
mode = CODEC_DO_COMPRESSION;
} else {
status = 0;
status = V4L2_IN_ST_NO_SIGNAL;
mode = CODEC_DO_EXPANSION;
}
if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS ||
(status & DECODER_STATUS_GOOD)) {
!(status & V4L2_IN_ST_NO_SIGNAL)) {
/********** RESTART code *************/
jpeg_codec_reset(zr);
zr->codec->set_mode(zr->codec, mode);
......@@ -1582,7 +1578,7 @@ zoran_set_pci_master (struct zoran *zr,
void
zoran_init_hardware (struct zoran *zr)
{
int j, zero = 0;
struct v4l2_routing route = { 0, 0 };
/* Enable bus-mastering */
zoran_set_pci_master(zr, 1);
......@@ -1592,15 +1588,16 @@ zoran_init_hardware (struct zoran *zr)
zr->card.init(zr);
}
j = zr->card.input[zr->input].muxsel;
route.input = zr->card.input[zr->input].muxsel;
decoder_command(zr, 0, NULL);
decoder_command(zr, DECODER_SET_NORM, &zr->norm);
decoder_command(zr, DECODER_SET_INPUT, &j);
decoder_command(zr, VIDIOC_INT_INIT, NULL);
decoder_command(zr, VIDIOC_S_STD, &zr->norm);
decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
encoder_command(zr, 0, NULL);
encoder_command(zr, ENCODER_SET_NORM, &zr->norm);
encoder_command(zr, ENCODER_SET_INPUT, &zero);
encoder_command(zr, VIDIOC_INT_INIT, NULL);
encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &zr->norm);
route.input = 0;
encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
/* toggle JPEG codec sleep to sync PLL */
jpeg_codec_sleep(zr, 1);
......@@ -1674,7 +1671,7 @@ decoder_command (struct zoran *zr,
return -EIO;
if (zr->card.type == LML33 &&
(cmd == DECODER_SET_NORM || cmd == DECODER_SET_INPUT)) {
(cmd == VIDIOC_S_STD || cmd == VIDIOC_INT_S_VIDEO_ROUTING)) {
int res;
// Bt819 needs to reset its FIFO buffer using #FRST pin and
......
......@@ -1145,9 +1145,10 @@ zoran_close(struct file *file)
zoran_set_pci_master(zr, 0);
if (!pass_through) { /* Switch to color bar */
int zero = 0, two = 2;
decoder_command(zr, DECODER_ENABLE_OUTPUT, &zero);
encoder_command(zr, ENCODER_SET_INPUT, &two);
struct v4l2_routing route = { 2, 0 };
decoder_command(zr, VIDIOC_STREAMOFF, 0);
encoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
}
}
......@@ -1569,9 +1570,9 @@ zoran_v4l2_buffer_status (struct file *file,
static int
zoran_set_norm (struct zoran *zr,
int norm) /* VIDEO_MODE_* */
v4l2_std_id norm)
{
int norm_encoder, on;
int on;
if (zr->v4l_buffers.active != ZORAN_FREE ||
zr->jpg_buffers.active != ZORAN_FREE) {
......@@ -1598,52 +1599,42 @@ zoran_set_norm (struct zoran *zr,
}
}
if (norm != VIDEO_MODE_AUTO &&
(norm < 0 || norm >= zr->card.norms ||
!zr->card.tvn[norm])) {
if (!(norm & zr->card.norms)) {
dprintk(1,
KERN_ERR "%s: set_norm() - unsupported norm %d\n",
KERN_ERR "%s: set_norm() - unsupported norm %llx\n",
ZR_DEVNAME(zr), norm);
return -EINVAL;
}
if (norm == VIDEO_MODE_AUTO) {
int status;
if (norm == V4L2_STD_ALL) {
int status = 0;
v4l2_std_id std = 0;
/* if we have autodetect, ... */
struct video_decoder_capability caps;
decoder_command(zr, DECODER_GET_CAPABILITIES, &caps);
if (!(caps.flags & VIDEO_DECODER_AUTO)) {
dprintk(1, KERN_ERR "%s: norm=auto unsupported\n",
ZR_DEVNAME(zr));
return -EINVAL;
}
decoder_command(zr, DECODER_SET_NORM, &norm);
decoder_command(zr, VIDIOC_QUERYSTD, &std);
decoder_command(zr, VIDIOC_S_STD, &std);
/* let changes come into effect */
ssleep(2);
decoder_command(zr, DECODER_GET_STATUS, &status);
if (!(status & DECODER_STATUS_GOOD)) {
decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status);
if (status & V4L2_IN_ST_NO_SIGNAL) {
dprintk(1,
KERN_ERR
"%s: set_norm() - no norm detected\n",
ZR_DEVNAME(zr));
/* reset norm */
decoder_command(zr, DECODER_SET_NORM, &zr->norm);
decoder_command(zr, VIDIOC_S_STD, &zr->norm);
return -EIO;
}
if (status & DECODER_STATUS_NTSC)
norm = VIDEO_MODE_NTSC;
else if (status & DECODER_STATUS_SECAM)
norm = VIDEO_MODE_SECAM;
else
norm = VIDEO_MODE_PAL;
norm = std;
}
zr->timing = zr->card.tvn[norm];
norm_encoder = norm;
if (norm & V4L2_STD_SECAM)
zr->timing = zr->card.tvn[2];
else if (norm & V4L2_STD_NTSC)
zr->timing = zr->card.tvn[1];
else
zr->timing = zr->card.tvn[0];
/* We switch overlay off and on since a change in the
* norm needs different VFE settings */
......@@ -1651,8 +1642,8 @@ zoran_set_norm (struct zoran *zr,
if (on)
zr36057_overlay(zr, 0);
decoder_command(zr, DECODER_SET_NORM, &norm);
encoder_command(zr, ENCODER_SET_NORM, &norm_encoder);
decoder_command(zr, VIDIOC_S_STD, &norm);
encoder_command(zr, VIDIOC_INT_S_STD_OUTPUT, &norm);
if (on)
zr36057_overlay(zr, 1);
......@@ -1667,7 +1658,7 @@ static int
zoran_set_input (struct zoran *zr,
int input)
{
int realinput;
struct v4l2_routing route = { 0, 0 };
if (input == zr->input) {
return 0;
......@@ -1690,10 +1681,10 @@ zoran_set_input (struct zoran *zr,
return -EINVAL;
}
realinput = zr->card.input[input].muxsel;
route.input = zr->card.input[input].muxsel;
zr->input = input;
decoder_command(zr, DECODER_SET_INPUT, &realinput);
decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
return 0;
}
......@@ -1722,7 +1713,13 @@ static long zoran_default(struct file *file, void *__fh, int cmd, void *arg)
mutex_lock(&zr->resource_lock);
bparams->norm = zr->norm;
if (zr->norm & V4L2_STD_NTSC)
bparams->norm = VIDEO_MODE_NTSC;
else if (zr->norm & V4L2_STD_PAL)
bparams->norm = VIDEO_MODE_PAL;
else
bparams->norm = VIDEO_MODE_SECAM;
bparams->input = zr->input;
bparams->decimation = fh->jpg_settings.decimation;
......@@ -1905,7 +1902,9 @@ jpgreqbuf_unlock_and_return:
case BUZIOC_G_STATUS:
{
struct zoran_status *bstat = arg;
int norm, input, status, res = 0;
struct v4l2_routing route = { 0, 0 };
int status = 0, res = 0;
v4l2_std_id norm;
dprintk(3, KERN_DEBUG "%s: BUZIOC_G_STATUS\n", ZR_DEVNAME(zr));
......@@ -1917,8 +1916,7 @@ jpgreqbuf_unlock_and_return:
return -EINVAL;
}
input = zr->card.input[bstat->input].muxsel;
norm = VIDEO_MODE_AUTO;
route.input = zr->card.input[bstat->input].muxsel;
mutex_lock(&zr->resource_lock);
......@@ -1931,34 +1929,33 @@ jpgreqbuf_unlock_and_return:
goto gstat_unlock_and_return;
}
decoder_command(zr, DECODER_SET_INPUT, &input);
decoder_command(zr, DECODER_SET_NORM, &norm);
decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
/* sleep 1 second */
ssleep(1);
/* Get status of video decoder */
decoder_command(zr, DECODER_GET_STATUS, &status);
decoder_command(zr, VIDIOC_QUERYSTD, &norm);
decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &status);
/* restore previous input and norm */
input = zr->card.input[zr->input].muxsel;
decoder_command(zr, DECODER_SET_INPUT, &input);
decoder_command(zr, DECODER_SET_NORM, &zr->norm);
route.input = zr->card.input[zr->input].muxsel;
decoder_command(zr, VIDIOC_INT_S_VIDEO_ROUTING, &route);
gstat_unlock_and_return:
mutex_unlock(&zr->resource_lock);
if (!res) {
bstat->signal =
(status & DECODER_STATUS_GOOD) ? 1 : 0;
if (status & DECODER_STATUS_NTSC)
(status & V4L2_IN_ST_NO_SIGNAL) ? 0 : 1;
if (norm & V4L2_STD_NTSC)
bstat->norm = VIDEO_MODE_NTSC;
else if (status & DECODER_STATUS_SECAM)
else if (norm & V4L2_STD_SECAM)
bstat->norm = VIDEO_MODE_SECAM;
else
bstat->norm = VIDEO_MODE_PAL;
bstat->color =
(status & DECODER_STATUS_COLOR) ? 1 : 0;
(status & V4L2_IN_ST_NO_COLOR) ? 0 : 1;
}
return res;
......@@ -2867,37 +2864,15 @@ strmoff_unlock_and_return:
static int zoran_queryctrl(struct file *file, void *__fh,
struct v4l2_queryctrl *ctrl)
{
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
/* we only support hue/saturation/contrast/brightness */
if (ctrl->id < V4L2_CID_BRIGHTNESS ||
ctrl->id > V4L2_CID_HUE)
return -EINVAL;
else {
int id = ctrl->id;
memset(ctrl, 0, sizeof(*ctrl));
ctrl->id = id;
}
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
strncpy(ctrl->name, "Brightness", sizeof(ctrl->name)-1);
break;
case V4L2_CID_CONTRAST:
strncpy(ctrl->name, "Contrast", sizeof(ctrl->name)-1);
break;
case V4L2_CID_SATURATION:
strncpy(ctrl->name, "Saturation", sizeof(ctrl->name)-1);
break;
case V4L2_CID_HUE:
strncpy(ctrl->name, "Hue", sizeof(ctrl->name)-1);
break;
}
ctrl->minimum = 0;
ctrl->maximum = 65535;
ctrl->step = 1;
ctrl->default_value = 32768;
ctrl->type = V4L2_CTRL_TYPE_INTEGER;
ctrl->flags = V4L2_CTRL_FLAG_SLIDER;
decoder_command(zr, VIDIOC_QUERYCTRL, ctrl);
return 0;
}
......@@ -2913,20 +2888,7 @@ static int zoran_g_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl
return -EINVAL;
mutex_lock(&zr->resource_lock);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
ctrl->value = zr->brightness;
break;
case V4L2_CID_CONTRAST:
ctrl->value = zr->contrast;
break;
case V4L2_CID_SATURATION:
ctrl->value = zr->saturation;
break;
case V4L2_CID_HUE:
ctrl->value = zr->hue;
break;
}
decoder_command(zr, VIDIOC_G_CTRL, ctrl);
mutex_unlock(&zr->resource_lock);
return 0;
......@@ -2936,42 +2898,14 @@ static int zoran_s_ctrl(struct file *file, void *__fh, struct v4l2_control *ctrl
{
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
struct video_picture pict;
/* we only support hue/saturation/contrast/brightness */
if (ctrl->id < V4L2_CID_BRIGHTNESS ||
ctrl->id > V4L2_CID_HUE)
return -EINVAL;
if (ctrl->value < 0 || ctrl->value > 65535) {
dprintk(1, KERN_ERR
"%s: VIDIOC_S_CTRL - invalid value %d for id=%d\n",
ZR_DEVNAME(zr), ctrl->value, ctrl->id);
return -EINVAL;
}
mutex_lock(&zr->resource_lock);
switch (ctrl->id) {
case V4L2_CID_BRIGHTNESS:
zr->brightness = ctrl->value;
break;
case V4L2_CID_CONTRAST:
zr->contrast = ctrl->value;
break;
case V4L2_CID_SATURATION:
zr->saturation = ctrl->value;
break;
case V4L2_CID_HUE:
zr->hue = ctrl->value;
break;
}
pict.brightness = zr->brightness;
pict.contrast = zr->contrast;
pict.colour = zr->saturation;
pict.hue = zr->hue;
decoder_command(zr, DECODER_SET_PICTURE, &pict);
decoder_command(zr, VIDIOC_S_CTRL, ctrl);
mutex_unlock(&zr->resource_lock);
return 0;
......@@ -2981,24 +2915,10 @@ static int zoran_g_std(struct file *file, void *__fh, v4l2_std_id *std)
{
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
int norm;
mutex_lock(&zr->resource_lock);
norm = zr->norm;
*std = zr->norm;
mutex_unlock(&zr->resource_lock);
switch (norm) {
case VIDEO_MODE_PAL:
*std = V4L2_STD_PAL;
break;
case VIDEO_MODE_NTSC:
*std = V4L2_STD_NTSC;
break;
case VIDEO_MODE_SECAM:
*std = V4L2_STD_SECAM;
break;
}
return 0;
}
......@@ -3006,25 +2926,10 @@ static int zoran_s_std(struct file *file, void *__fh, v4l2_std_id *std)
{
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
int norm = -1, res = 0;
if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL))
norm = VIDEO_MODE_PAL;
else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC))
norm = VIDEO_MODE_NTSC;
else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM))
norm = VIDEO_MODE_SECAM;
else if (*std == V4L2_STD_ALL)
norm = VIDEO_MODE_AUTO;
else {
dprintk(1, KERN_ERR
"%s: VIDIOC_S_STD - invalid norm 0x%llx\n",
ZR_DEVNAME(zr), (unsigned long long)*std);
return -EINVAL;
}
int res = 0;
mutex_lock(&zr->resource_lock);
res = zoran_set_norm(zr, norm);
res = zoran_set_norm(zr, *std);
if (res)
goto sstd_unlock_and_return;
......@@ -3039,7 +2944,6 @@ static int zoran_enum_input(struct file *file, void *__fh,
{
struct zoran_fh *fh = __fh;
struct zoran *zr = fh->zr;
int status;
if (inp->index < 0 || inp->index >= zr->card.inputs)
return -EINVAL;
......@@ -3056,16 +2960,8 @@ static int zoran_enum_input(struct file *file, void *__fh,
/* Get status of video decoder */
mutex_lock(&zr->resource_lock);
decoder_command(zr, DECODER_GET_STATUS, &status);
decoder_command(zr, VIDIOC_INT_G_INPUT_STATUS, &inp->status);
mutex_unlock(&zr->resource_lock);
if (!(status & DECODER_STATUS_GOOD)) {
inp->status |= V4L2_IN_ST_NO_POWER;
inp->status |= V4L2_IN_ST_NO_SIGNAL;
}
if (!(status & DECODER_STATUS_COLOR))
inp->status |= V4L2_IN_ST_NO_COLOR;
return 0;
}
......
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