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

V4L/DVB (9827): saa7127: convert to v4l2_subdev.

Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 9415f4b2
...@@ -53,7 +53,7 @@ ...@@ -53,7 +53,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/videodev2.h> #include <linux/videodev2.h>
#include <media/v4l2-common.h> #include <media/v4l2-device.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
#include <media/v4l2-i2c-drv.h> #include <media/v4l2-i2c-drv.h>
#include <media/saa7127.h> #include <media/saa7127.h>
...@@ -231,6 +231,7 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = { ...@@ -231,6 +231,7 @@ static struct i2c_reg_value saa7127_init_config_50hz[] = {
*/ */
struct saa7127_state { struct saa7127_state {
struct v4l2_subdev sd;
v4l2_std_id std; v4l2_std_id std;
u32 ident; u32 ident;
enum saa7127_input_type input_type; enum saa7127_input_type input_type;
...@@ -250,6 +251,11 @@ struct saa7127_state { ...@@ -250,6 +251,11 @@ struct saa7127_state {
u8 reg_61; u8 reg_61;
}; };
static inline struct saa7127_state *to_state(struct v4l2_subdev *sd)
{
return container_of(sd, struct saa7127_state, sd);
}
static const char * const output_strs[] = static const char * const output_strs[] =
{ {
"S-Video + Composite", "S-Video + Composite",
...@@ -281,32 +287,35 @@ static const char * const wss_strs[] = { ...@@ -281,32 +287,35 @@ static const char * const wss_strs[] = {
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_read(struct i2c_client *client, u8 reg) static int saa7127_read(struct v4l2_subdev *sd, u8 reg)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
return i2c_smbus_read_byte_data(client, reg); return i2c_smbus_read_byte_data(client, reg);
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_write(struct i2c_client *client, u8 reg, u8 val) static int saa7127_write(struct v4l2_subdev *sd, u8 reg, u8 val)
{ {
struct i2c_client *client = v4l2_get_subdevdata(sd);
int i; int i;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
if (i2c_smbus_write_byte_data(client, reg, val) == 0) if (i2c_smbus_write_byte_data(client, reg, val) == 0)
return 0; return 0;
} }
v4l_err(client, "I2C Write Problem\n"); v4l2_err(sd, "I2C Write Problem\n");
return -1; return -1;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_write_inittab(struct i2c_client *client, static int saa7127_write_inittab(struct v4l2_subdev *sd,
const struct i2c_reg_value *regs) const struct i2c_reg_value *regs)
{ {
while (regs->reg != 0) { while (regs->reg != 0) {
saa7127_write(client, regs->reg, regs->value); saa7127_write(sd, regs->reg, regs->value);
regs++; regs++;
} }
return 0; return 0;
...@@ -314,16 +323,16 @@ static int saa7127_write_inittab(struct i2c_client *client, ...@@ -314,16 +323,16 @@ static int saa7127_write_inittab(struct i2c_client *client,
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
int enable = (data->line != 0); int enable = (data->line != 0);
if (enable && (data->field != 0 || data->line != 16)) if (enable && (data->field != 0 || data->line != 16))
return -EINVAL; return -EINVAL;
if (state->vps_enable != enable) { if (state->vps_enable != enable) {
v4l_dbg(1, debug, client, "Turn VPS Signal %s\n", enable ? "on" : "off"); v4l2_dbg(1, debug, sd, "Turn VPS Signal %s\n", enable ? "on" : "off");
saa7127_write(client, 0x54, enable << 7); saa7127_write(sd, 0x54, enable << 7);
state->vps_enable = enable; state->vps_enable = enable;
} }
if (!enable) if (!enable)
...@@ -334,91 +343,91 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat ...@@ -334,91 +343,91 @@ static int saa7127_set_vps(struct i2c_client *client, struct v4l2_sliced_vbi_dat
state->vps_data[2] = data->data[9]; state->vps_data[2] = data->data[9];
state->vps_data[3] = data->data[10]; state->vps_data[3] = data->data[10];
state->vps_data[4] = data->data[11]; state->vps_data[4] = data->data[11];
v4l_dbg(1, debug, client, "Set VPS data %02x %02x %02x %02x %02x\n", v4l2_dbg(1, debug, sd, "Set VPS data %02x %02x %02x %02x %02x\n",
state->vps_data[0], state->vps_data[1], state->vps_data[0], state->vps_data[1],
state->vps_data[2], state->vps_data[3], state->vps_data[2], state->vps_data[3],
state->vps_data[4]); state->vps_data[4]);
saa7127_write(client, 0x55, state->vps_data[0]); saa7127_write(sd, 0x55, state->vps_data[0]);
saa7127_write(client, 0x56, state->vps_data[1]); saa7127_write(sd, 0x56, state->vps_data[1]);
saa7127_write(client, 0x57, state->vps_data[2]); saa7127_write(sd, 0x57, state->vps_data[2]);
saa7127_write(client, 0x58, state->vps_data[3]); saa7127_write(sd, 0x58, state->vps_data[3]);
saa7127_write(client, 0x59, state->vps_data[4]); saa7127_write(sd, 0x59, state->vps_data[4]);
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_cc(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) static int saa7127_set_cc(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
u16 cc = data->data[1] << 8 | data->data[0]; u16 cc = data->data[1] << 8 | data->data[0];
int enable = (data->line != 0); int enable = (data->line != 0);
if (enable && (data->field != 0 || data->line != 21)) if (enable && (data->field != 0 || data->line != 21))
return -EINVAL; return -EINVAL;
if (state->cc_enable != enable) { if (state->cc_enable != enable) {
v4l_dbg(1, debug, client, v4l2_dbg(1, debug, sd,
"Turn CC %s\n", enable ? "on" : "off"); "Turn CC %s\n", enable ? "on" : "off");
saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
(state->xds_enable << 7) | (enable << 6) | 0x11); (state->xds_enable << 7) | (enable << 6) | 0x11);
state->cc_enable = enable; state->cc_enable = enable;
} }
if (!enable) if (!enable)
return 0; return 0;
v4l_dbg(2, debug, client, "CC data: %04x\n", cc); v4l2_dbg(2, debug, sd, "CC data: %04x\n", cc);
saa7127_write(client, SAA7127_REG_LINE_21_ODD_0, cc & 0xff); saa7127_write(sd, SAA7127_REG_LINE_21_ODD_0, cc & 0xff);
saa7127_write(client, SAA7127_REG_LINE_21_ODD_1, cc >> 8); saa7127_write(sd, SAA7127_REG_LINE_21_ODD_1, cc >> 8);
state->cc_data = cc; state->cc_data = cc;
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_xds(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) static int saa7127_set_xds(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
u16 xds = data->data[1] << 8 | data->data[0]; u16 xds = data->data[1] << 8 | data->data[0];
int enable = (data->line != 0); int enable = (data->line != 0);
if (enable && (data->field != 1 || data->line != 21)) if (enable && (data->field != 1 || data->line != 21))
return -EINVAL; return -EINVAL;
if (state->xds_enable != enable) { if (state->xds_enable != enable) {
v4l_dbg(1, debug, client, "Turn XDS %s\n", enable ? "on" : "off"); v4l2_dbg(1, debug, sd, "Turn XDS %s\n", enable ? "on" : "off");
saa7127_write(client, SAA7127_REG_CLOSED_CAPTION, saa7127_write(sd, SAA7127_REG_CLOSED_CAPTION,
(enable << 7) | (state->cc_enable << 6) | 0x11); (enable << 7) | (state->cc_enable << 6) | 0x11);
state->xds_enable = enable; state->xds_enable = enable;
} }
if (!enable) if (!enable)
return 0; return 0;
v4l_dbg(2, debug, client, "XDS data: %04x\n", xds); v4l2_dbg(2, debug, sd, "XDS data: %04x\n", xds);
saa7127_write(client, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff); saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_0, xds & 0xff);
saa7127_write(client, SAA7127_REG_LINE_21_EVEN_1, xds >> 8); saa7127_write(sd, SAA7127_REG_LINE_21_EVEN_1, xds >> 8);
state->xds_data = xds; state->xds_data = xds;
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_data *data) static int saa7127_set_wss(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
int enable = (data->line != 0); int enable = (data->line != 0);
if (enable && (data->field != 0 || data->line != 23)) if (enable && (data->field != 0 || data->line != 23))
return -EINVAL; return -EINVAL;
if (state->wss_enable != enable) { if (state->wss_enable != enable) {
v4l_dbg(1, debug, client, "Turn WSS %s\n", enable ? "on" : "off"); v4l2_dbg(1, debug, sd, "Turn WSS %s\n", enable ? "on" : "off");
saa7127_write(client, 0x27, enable << 7); saa7127_write(sd, 0x27, enable << 7);
state->wss_enable = enable; state->wss_enable = enable;
} }
if (!enable) if (!enable)
return 0; return 0;
saa7127_write(client, 0x26, data->data[0]); saa7127_write(sd, 0x26, data->data[0]);
saa7127_write(client, 0x27, 0x80 | (data->data[1] & 0x3f)); saa7127_write(sd, 0x27, 0x80 | (data->data[1] & 0x3f));
v4l_dbg(1, debug, client, v4l2_dbg(1, debug, sd,
"WSS mode: %s\n", wss_strs[data->data[0] & 0xf]); "WSS mode: %s\n", wss_strs[data->data[0] & 0xf]);
state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0]; state->wss_mode = (data->data[1] & 0x3f) << 8 | data->data[0];
return 0; return 0;
...@@ -426,18 +435,18 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat ...@@ -426,18 +435,18 @@ static int saa7127_set_wss(struct i2c_client *client, struct v4l2_sliced_vbi_dat
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_video_enable(struct i2c_client *client, int enable) static int saa7127_set_video_enable(struct v4l2_subdev *sd, int enable)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
if (enable) { if (enable) {
v4l_dbg(1, debug, client, "Enable Video Output\n"); v4l2_dbg(1, debug, sd, "Enable Video Output\n");
saa7127_write(client, 0x2d, state->reg_2d); saa7127_write(sd, 0x2d, state->reg_2d);
saa7127_write(client, 0x61, state->reg_61); saa7127_write(sd, 0x61, state->reg_61);
} else { } else {
v4l_dbg(1, debug, client, "Disable Video Output\n"); v4l2_dbg(1, debug, sd, "Disable Video Output\n");
saa7127_write(client, 0x2d, (state->reg_2d & 0xf0)); saa7127_write(sd, 0x2d, (state->reg_2d & 0xf0));
saa7127_write(client, 0x61, (state->reg_61 | 0xc0)); saa7127_write(sd, 0x61, (state->reg_61 | 0xc0));
} }
state->video_enable = enable; state->video_enable = enable;
return 0; return 0;
...@@ -445,32 +454,32 @@ static int saa7127_set_video_enable(struct i2c_client *client, int enable) ...@@ -445,32 +454,32 @@ static int saa7127_set_video_enable(struct i2c_client *client, int enable)
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_std(struct i2c_client *client, v4l2_std_id std) static int saa7127_set_std(struct v4l2_subdev *sd, v4l2_std_id std)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
const struct i2c_reg_value *inittab; const struct i2c_reg_value *inittab;
if (std & V4L2_STD_525_60) { if (std & V4L2_STD_525_60) {
v4l_dbg(1, debug, client, "Selecting 60 Hz video Standard\n"); v4l2_dbg(1, debug, sd, "Selecting 60 Hz video Standard\n");
inittab = saa7127_init_config_60hz; inittab = saa7127_init_config_60hz;
state->reg_61 = SAA7127_60HZ_DAC_CONTROL; state->reg_61 = SAA7127_60HZ_DAC_CONTROL;
} else { } else {
v4l_dbg(1, debug, client, "Selecting 50 Hz video Standard\n"); v4l2_dbg(1, debug, sd, "Selecting 50 Hz video Standard\n");
inittab = saa7127_init_config_50hz; inittab = saa7127_init_config_50hz;
state->reg_61 = SAA7127_50HZ_DAC_CONTROL; state->reg_61 = SAA7127_50HZ_DAC_CONTROL;
} }
/* Write Table */ /* Write Table */
saa7127_write_inittab(client, inittab); saa7127_write_inittab(sd, inittab);
state->std = std; state->std = std;
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_output_type(struct i2c_client *client, int output) static int saa7127_set_output_type(struct v4l2_subdev *sd, int output)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
switch (output) { switch (output) {
case SAA7127_OUTPUT_TYPE_RGB: case SAA7127_OUTPUT_TYPE_RGB:
...@@ -506,83 +515,77 @@ static int saa7127_set_output_type(struct i2c_client *client, int output) ...@@ -506,83 +515,77 @@ static int saa7127_set_output_type(struct i2c_client *client, int output)
default: default:
return -EINVAL; return -EINVAL;
} }
v4l_dbg(1, debug, client, v4l2_dbg(1, debug, sd,
"Selecting %s output type\n", output_strs[output]); "Selecting %s output type\n", output_strs[output]);
/* Configure Encoder */ /* Configure Encoder */
saa7127_write(client, 0x2d, state->reg_2d); saa7127_write(sd, 0x2d, state->reg_2d);
saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
state->output_type = output; state->output_type = output;
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_set_input_type(struct i2c_client *client, int input) static int saa7127_set_input_type(struct v4l2_subdev *sd, int input)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
switch (input) { switch (input) {
case SAA7127_INPUT_TYPE_NORMAL: /* avia */ case SAA7127_INPUT_TYPE_NORMAL: /* avia */
v4l_dbg(1, debug, client, "Selecting Normal Encoder Input\n"); v4l2_dbg(1, debug, sd, "Selecting Normal Encoder Input\n");
state->reg_3a_cb = 0; state->reg_3a_cb = 0;
break; break;
case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */ case SAA7127_INPUT_TYPE_TEST_IMAGE: /* color bar */
v4l_dbg(1, debug, client, "Selecting Color Bar generator\n"); v4l2_dbg(1, debug, sd, "Selecting Color Bar generator\n");
state->reg_3a_cb = 0x80; state->reg_3a_cb = 0x80;
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
saa7127_write(client, 0x3a, state->reg_3a | state->reg_3a_cb); saa7127_write(sd, 0x3a, state->reg_3a | state->reg_3a_cb);
state->input_type = input; state->input_type = input;
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static int saa7127_command(struct i2c_client *client, static int saa7127_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
unsigned int cmd, void *arg)
{ {
struct saa7127_state *state = i2c_get_clientdata(client); struct saa7127_state *state = to_state(sd);
struct v4l2_format *fmt = arg;
struct v4l2_routing *route = arg;
switch (cmd) {
case VIDIOC_INT_S_STD_OUTPUT:
if (state->std == *(v4l2_std_id *)arg)
break;
return saa7127_set_std(client, *(v4l2_std_id *)arg);
case VIDIOC_INT_G_STD_OUTPUT: if (state->std == std)
*(v4l2_std_id *)arg = state->std; return 0;
break; return saa7127_set_std(sd, std);
}
case VIDIOC_INT_G_VIDEO_ROUTING:
route->input = state->input_type;
route->output = state->output_type;
break;
case VIDIOC_INT_S_VIDEO_ROUTING: static int saa7127_s_routing(struct v4l2_subdev *sd, const struct v4l2_routing *route)
{ {
struct saa7127_state *state = to_state(sd);
int rc = 0; int rc = 0;
if (state->input_type != route->input) if (state->input_type != route->input)
rc = saa7127_set_input_type(client, route->input); rc = saa7127_set_input_type(sd, route->input);
if (rc == 0 && state->output_type != route->output) if (rc == 0 && state->output_type != route->output)
rc = saa7127_set_output_type(client, route->output); rc = saa7127_set_output_type(sd, route->output);
return rc; return rc;
} }
case VIDIOC_STREAMON: static int saa7127_s_stream(struct v4l2_subdev *sd, int enable)
case VIDIOC_STREAMOFF: {
if (state->video_enable == (cmd == VIDIOC_STREAMON)) struct saa7127_state *state = to_state(sd);
break;
return saa7127_set_video_enable(client, cmd == VIDIOC_STREAMON); if (state->video_enable == enable)
return 0;
return saa7127_set_video_enable(sd, enable);
}
static int saa7127_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
{
struct saa7127_state *state = to_state(sd);
case VIDIOC_G_FMT:
if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE) if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
return -EINVAL; return -EINVAL;
...@@ -599,72 +602,108 @@ static int saa7127_command(struct i2c_client *client, ...@@ -599,72 +602,108 @@ static int saa7127_command(struct i2c_client *client,
(state->vps_enable ? V4L2_SLICED_VPS : 0) | (state->vps_enable ? V4L2_SLICED_VPS : 0) |
(state->wss_enable ? V4L2_SLICED_WSS_625 : 0) | (state->wss_enable ? V4L2_SLICED_WSS_625 : 0) |
(state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0); (state->cc_enable ? V4L2_SLICED_CAPTION_525 : 0);
break; return 0;
}
case VIDIOC_LOG_STATUS: static int saa7127_s_vbi_data(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *data)
v4l_info(client, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz"); {
v4l_info(client, "Input: %s\n", state->input_type ? "color bars" : "normal"); switch (data->id) {
v4l_info(client, "Output: %s\n", state->video_enable ? case V4L2_SLICED_WSS_625:
output_strs[state->output_type] : "disabled"); return saa7127_set_wss(sd, data);
v4l_info(client, "WSS: %s\n", state->wss_enable ? case V4L2_SLICED_VPS:
wss_strs[state->wss_mode] : "disabled"); return saa7127_set_vps(sd, data);
v4l_info(client, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled"); case V4L2_SLICED_CAPTION_525:
v4l_info(client, "CC: %s\n", state->cc_enable ? "enabled" : "disabled"); if (data->field == 0)
break; return saa7127_set_cc(sd, data);
return saa7127_set_xds(sd, data);
default:
return -EINVAL;
}
return 0;
}
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
case VIDIOC_DBG_G_REGISTER: static int saa7127_g_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
case VIDIOC_DBG_S_REGISTER: {
{ struct i2c_client *client = v4l2_get_subdevdata(sd);
struct v4l2_register *reg = arg;
if (!v4l2_chip_match_i2c_client(client, if (!v4l2_chip_match_i2c_client(client,
reg->match_type, reg->match_chip)) reg->match_type, reg->match_chip))
return -EINVAL; return -EINVAL;
if (!capable(CAP_SYS_ADMIN)) if (!capable(CAP_SYS_ADMIN))
return -EPERM; return -EPERM;
if (cmd == VIDIOC_DBG_G_REGISTER) reg->val = saa7127_read(sd, reg->reg & 0xff);
reg->val = saa7127_read(client, reg->reg & 0xff); return 0;
else }
saa7127_write(client, reg->reg & 0xff, reg->val & 0xff);
break;
}
#endif
case VIDIOC_INT_S_VBI_DATA: static int saa7127_s_register(struct v4l2_subdev *sd, struct v4l2_register *reg)
{ {
struct v4l2_sliced_vbi_data *data = arg; struct i2c_client *client = v4l2_get_subdevdata(sd);
switch (data->id) { if (!v4l2_chip_match_i2c_client(client,
case V4L2_SLICED_WSS_625: reg->match_type, reg->match_chip))
return saa7127_set_wss(client, data);
case V4L2_SLICED_VPS:
return saa7127_set_vps(client, data);
case V4L2_SLICED_CAPTION_525:
if (data->field == 0)
return saa7127_set_cc(client, data);
return saa7127_set_xds(client, data);
default:
return -EINVAL; return -EINVAL;
} if (!capable(CAP_SYS_ADMIN))
break; return -EPERM;
} saa7127_write(sd, reg->reg & 0xff, reg->val & 0xff);
return 0;
}
#endif
case VIDIOC_G_CHIP_IDENT: static int saa7127_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_chip_ident *chip)
return v4l2_chip_ident_i2c_client(client, arg, state->ident, 0); {
struct saa7127_state *state = to_state(sd);
struct i2c_client *client = v4l2_get_subdevdata(sd);
default: return v4l2_chip_ident_i2c_client(client, chip, state->ident, 0);
return -EINVAL; }
}
static int saa7127_log_status(struct v4l2_subdev *sd)
{
struct saa7127_state *state = to_state(sd);
v4l2_info(sd, "Standard: %s\n", (state->std & V4L2_STD_525_60) ? "60 Hz" : "50 Hz");
v4l2_info(sd, "Input: %s\n", state->input_type ? "color bars" : "normal");
v4l2_info(sd, "Output: %s\n", state->video_enable ?
output_strs[state->output_type] : "disabled");
v4l2_info(sd, "WSS: %s\n", state->wss_enable ?
wss_strs[state->wss_mode] : "disabled");
v4l2_info(sd, "VPS: %s\n", state->vps_enable ? "enabled" : "disabled");
v4l2_info(sd, "CC: %s\n", state->cc_enable ? "enabled" : "disabled");
return 0; return 0;
} }
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
static const struct v4l2_subdev_core_ops saa7127_core_ops = {
.log_status = saa7127_log_status,
.g_chip_ident = saa7127_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = saa7127_g_register,
.s_register = saa7127_s_register,
#endif
};
static const struct v4l2_subdev_video_ops saa7127_video_ops = {
.s_vbi_data = saa7127_s_vbi_data,
.g_fmt = saa7127_g_fmt,
.s_std_output = saa7127_s_std_output,
.s_routing = saa7127_s_routing,
.s_stream = saa7127_s_stream,
};
static const struct v4l2_subdev_ops saa7127_ops = {
.core = &saa7127_core_ops,
.video = &saa7127_video_ops,
};
/* ----------------------------------------------------------------------- */
static int saa7127_probe(struct i2c_client *client, static int saa7127_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct saa7127_state *state; struct saa7127_state *state;
struct v4l2_subdev *sd;
struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */ struct v4l2_sliced_vbi_data vbi = { 0, 0, 0, 0 }; /* set to disabled */
/* Check if the adapter supports the needed features */ /* Check if the adapter supports the needed features */
...@@ -674,40 +713,42 @@ static int saa7127_probe(struct i2c_client *client, ...@@ -674,40 +713,42 @@ static int saa7127_probe(struct i2c_client *client,
v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n", v4l_dbg(1, debug, client, "detecting saa7127 client on address 0x%x\n",
client->addr << 1); client->addr << 1);
state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL);
if (state == NULL)
return -ENOMEM;
sd = &state->sd;
v4l2_i2c_subdev_init(sd, client, &saa7127_ops);
/* First test register 0: Bits 5-7 are a version ID (should be 0), /* First test register 0: Bits 5-7 are a version ID (should be 0),
and bit 2 should also be 0. and bit 2 should also be 0.
This is rather general, so the second test is more specific and This is rather general, so the second test is more specific and
looks at the 'ending point of burst in clock cycles' which is looks at the 'ending point of burst in clock cycles' which is
0x1d after a reset and not expected to ever change. */ 0x1d after a reset and not expected to ever change. */
if ((saa7127_read(client, 0) & 0xe4) != 0 || if ((saa7127_read(sd, 0) & 0xe4) != 0 ||
(saa7127_read(client, 0x29) & 0x3f) != 0x1d) { (saa7127_read(sd, 0x29) & 0x3f) != 0x1d) {
v4l_dbg(1, debug, client, "saa7127 not found\n"); v4l2_dbg(1, debug, sd, "saa7127 not found\n");
kfree(state);
return -ENODEV; return -ENODEV;
} }
state = kzalloc(sizeof(struct saa7127_state), GFP_KERNEL);
if (state == NULL)
return -ENOMEM;
i2c_set_clientdata(client, state);
/* Configure Encoder */ /* Configure Encoder */
v4l_dbg(1, debug, client, "Configuring encoder\n"); v4l2_dbg(1, debug, sd, "Configuring encoder\n");
saa7127_write_inittab(client, saa7127_init_config_common); saa7127_write_inittab(sd, saa7127_init_config_common);
saa7127_set_std(client, V4L2_STD_NTSC); saa7127_set_std(sd, V4L2_STD_NTSC);
saa7127_set_output_type(client, SAA7127_OUTPUT_TYPE_BOTH); saa7127_set_output_type(sd, SAA7127_OUTPUT_TYPE_BOTH);
saa7127_set_vps(client, &vbi); saa7127_set_vps(sd, &vbi);
saa7127_set_wss(client, &vbi); saa7127_set_wss(sd, &vbi);
saa7127_set_cc(client, &vbi); saa7127_set_cc(sd, &vbi);
saa7127_set_xds(client, &vbi); saa7127_set_xds(sd, &vbi);
if (test_image == 1) if (test_image == 1)
/* The Encoder has an internal Colorbar generator */ /* The Encoder has an internal Colorbar generator */
/* This can be used for debugging */ /* This can be used for debugging */
saa7127_set_input_type(client, SAA7127_INPUT_TYPE_TEST_IMAGE); saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_TEST_IMAGE);
else else
saa7127_set_input_type(client, SAA7127_INPUT_TYPE_NORMAL); saa7127_set_input_type(sd, SAA7127_INPUT_TYPE_NORMAL);
saa7127_set_video_enable(client, 1); saa7127_set_video_enable(sd, 1);
if (id->driver_data) { /* Chip type is already known */ if (id->driver_data) { /* Chip type is already known */
state->ident = id->driver_data; state->ident = id->driver_data;
...@@ -715,10 +756,10 @@ static int saa7127_probe(struct i2c_client *client, ...@@ -715,10 +756,10 @@ static int saa7127_probe(struct i2c_client *client,
int read_result; int read_result;
/* Detect if it's an saa7129 */ /* Detect if it's an saa7129 */
read_result = saa7127_read(client, SAA7129_REG_FADE_KEY_COL2); read_result = saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2);
saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, 0xaa); saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2, 0xaa);
if (saa7127_read(client, SAA7129_REG_FADE_KEY_COL2) == 0xaa) { if (saa7127_read(sd, SAA7129_REG_FADE_KEY_COL2) == 0xaa) {
saa7127_write(client, SAA7129_REG_FADE_KEY_COL2, saa7127_write(sd, SAA7129_REG_FADE_KEY_COL2,
read_result); read_result);
state->ident = V4L2_IDENT_SAA7129; state->ident = V4L2_IDENT_SAA7129;
strlcpy(client->name, "saa7129", I2C_NAME_SIZE); strlcpy(client->name, "saa7129", I2C_NAME_SIZE);
...@@ -728,10 +769,10 @@ static int saa7127_probe(struct i2c_client *client, ...@@ -728,10 +769,10 @@ static int saa7127_probe(struct i2c_client *client,
} }
} }
v4l_info(client, "%s found @ 0x%x (%s)\n", client->name, v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
client->addr << 1, client->adapter->name); client->addr << 1, client->adapter->name);
if (state->ident == V4L2_IDENT_SAA7129) if (state->ident == V4L2_IDENT_SAA7129)
saa7127_write_inittab(client, saa7129_init_config_extra); saa7127_write_inittab(sd, saa7129_init_config_extra);
return 0; return 0;
} }
...@@ -739,9 +780,12 @@ static int saa7127_probe(struct i2c_client *client, ...@@ -739,9 +780,12 @@ static int saa7127_probe(struct i2c_client *client,
static int saa7127_remove(struct i2c_client *client) static int saa7127_remove(struct i2c_client *client)
{ {
struct v4l2_subdev *sd = i2c_get_clientdata(client);
v4l2_device_unregister_subdev(sd);
/* Turn off TV output */ /* Turn off TV output */
saa7127_set_video_enable(client, 0); saa7127_set_video_enable(sd, 0);
kfree(i2c_get_clientdata(client)); kfree(to_state(sd));
return 0; return 0;
} }
...@@ -760,7 +804,6 @@ MODULE_DEVICE_TABLE(i2c, saa7127_id); ...@@ -760,7 +804,6 @@ MODULE_DEVICE_TABLE(i2c, saa7127_id);
static struct v4l2_i2c_driver_data v4l2_i2c_data = { static struct v4l2_i2c_driver_data v4l2_i2c_data = {
.name = "saa7127", .name = "saa7127",
.driverid = I2C_DRIVERID_SAA7127, .driverid = I2C_DRIVERID_SAA7127,
.command = saa7127_command,
.probe = saa7127_probe, .probe = saa7127_probe,
.remove = saa7127_remove, .remove = saa7127_remove,
.id_table = saa7127_id, .id_table = saa7127_id,
......
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