Commit 32cd527f authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB: v4l: move vbi-specific video ops to a new vbi ops struct

Only a relatively small number of video receivers and transmitters actually
support VBI. So start moving the vbi specific ops to an ops struct of their
own.
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent b26d6e21
...@@ -1403,17 +1403,21 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = { ...@@ -1403,17 +1403,21 @@ static const struct v4l2_subdev_audio_ops cx18_av_audio_ops = {
static const struct v4l2_subdev_video_ops cx18_av_video_ops = { static const struct v4l2_subdev_video_ops cx18_av_video_ops = {
.s_routing = cx18_av_s_video_routing, .s_routing = cx18_av_s_video_routing,
.decode_vbi_line = cx18_av_decode_vbi_line,
.s_stream = cx18_av_s_stream, .s_stream = cx18_av_s_stream,
.g_fmt = cx18_av_g_fmt, .g_fmt = cx18_av_g_fmt,
.s_fmt = cx18_av_s_fmt, .s_fmt = cx18_av_s_fmt,
}; };
static const struct v4l2_subdev_vbi_ops cx18_av_vbi_ops = {
.decode_vbi_line = cx18_av_decode_vbi_line,
};
static const struct v4l2_subdev_ops cx18_av_ops = { static const struct v4l2_subdev_ops cx18_av_ops = {
.core = &cx18_av_general_ops, .core = &cx18_av_general_ops,
.tuner = &cx18_av_tuner_ops, .tuner = &cx18_av_tuner_ops,
.audio = &cx18_av_audio_ops, .audio = &cx18_av_audio_ops,
.video = &cx18_av_video_ops, .video = &cx18_av_video_ops,
.vbi = &cx18_av_vbi_ops,
}; };
int cx18_av_probe(struct cx18 *cx) int cx18_av_probe(struct cx18 *cx)
......
...@@ -174,7 +174,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size, ...@@ -174,7 +174,7 @@ static u32 compress_sliced_buf(struct cx18 *cx, u8 *buf, u32 size,
p[3] != sliced_vbi_eav_rp[1])) p[3] != sliced_vbi_eav_rp[1]))
continue; continue;
vbi.p = p + 4; vbi.p = p + 4;
v4l2_subdev_call(cx->sd_av, video, decode_vbi_line, &vbi); v4l2_subdev_call(cx->sd_av, vbi, decode_vbi_line, &vbi);
if (vbi.type) { if (vbi.type) {
cx->vbi.sliced_data[line].id = vbi.type; cx->vbi.sliced_data[line].id = vbi.type;
cx->vbi.sliced_data[line].field = vbi.is_second_field; cx->vbi.sliced_data[line].field = vbi.is_second_field;
......
...@@ -1635,15 +1635,19 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = { ...@@ -1635,15 +1635,19 @@ static const struct v4l2_subdev_video_ops cx25840_video_ops = {
.s_routing = cx25840_s_video_routing, .s_routing = cx25840_s_video_routing,
.g_fmt = cx25840_g_fmt, .g_fmt = cx25840_g_fmt,
.s_fmt = cx25840_s_fmt, .s_fmt = cx25840_s_fmt,
.decode_vbi_line = cx25840_decode_vbi_line,
.s_stream = cx25840_s_stream, .s_stream = cx25840_s_stream,
}; };
static const struct v4l2_subdev_vbi_ops cx25840_vbi_ops = {
.decode_vbi_line = cx25840_decode_vbi_line,
};
static const struct v4l2_subdev_ops cx25840_ops = { static const struct v4l2_subdev_ops cx25840_ops = {
.core = &cx25840_core_ops, .core = &cx25840_core_ops,
.tuner = &cx25840_tuner_ops, .tuner = &cx25840_tuner_ops,
.audio = &cx25840_audio_ops, .audio = &cx25840_audio_ops,
.video = &cx25840_video_ops, .video = &cx25840_video_ops,
.vbi = &cx25840_vbi_ops,
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
...@@ -38,7 +38,7 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled) ...@@ -38,7 +38,7 @@ static void ivtv_set_vps(struct ivtv *itv, int enabled)
data.data[9] = itv->vbi.vps_payload.data[2]; data.data[9] = itv->vbi.vps_payload.data[2];
data.data[10] = itv->vbi.vps_payload.data[3]; data.data[10] = itv->vbi.vps_payload.data[3];
data.data[11] = itv->vbi.vps_payload.data[4]; data.data[11] = itv->vbi.vps_payload.data[4];
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
} }
static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
...@@ -52,12 +52,12 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc) ...@@ -52,12 +52,12 @@ static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
data.line = (mode & 1) ? 21 : 0; data.line = (mode & 1) ? 21 : 0;
data.data[0] = cc->odd[0]; data.data[0] = cc->odd[0];
data.data[1] = cc->odd[1]; data.data[1] = cc->odd[1];
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
data.field = 1; data.field = 1;
data.line = (mode & 2) ? 21 : 0; data.line = (mode & 2) ? 21 : 0;
data.data[0] = cc->even[0]; data.data[0] = cc->even[0];
data.data[1] = cc->even[1]; data.data[1] = cc->even[1];
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
} }
static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
...@@ -80,7 +80,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode) ...@@ -80,7 +80,7 @@ static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
data.line = enabled ? 23 : 0; data.line = enabled ? 23 : 0;
data.data[0] = mode & 0xff; data.data[0] = mode & 0xff;
data.data[1] = (mode >> 8) & 0xff; data.data[1] = (mode >> 8) & 0xff;
ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_vbi_data, &data); ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
} }
static int odd_parity(u8 c) static int odd_parity(u8 c)
...@@ -316,7 +316,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 ...@@ -316,7 +316,7 @@ static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8
continue; continue;
} }
vbi.p = p + 4; vbi.p = p + 4;
v4l2_subdev_call(itv->sd_video, video, decode_vbi_line, &vbi); v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
if (vbi.type && !(lines & (1 << vbi.line))) { if (vbi.type && !(lines & (1 << vbi.line))) {
lines |= 1 << vbi.line; lines |= 1 << vbi.line;
itv->vbi.sliced_data[line].id = vbi.type; itv->vbi.sliced_data[line].id = vbi.type;
...@@ -440,7 +440,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv) ...@@ -440,7 +440,7 @@ void ivtv_vbi_work_handler(struct ivtv *itv)
data.id = V4L2_SLICED_WSS_625; data.id = V4L2_SLICED_WSS_625;
data.field = 0; data.field = 0;
if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
ivtv_set_wss(itv, 1, data.data[0] & 0xf); ivtv_set_wss(itv, 1, data.data[0] & 0xf);
vi->wss_missing_cnt = 0; vi->wss_missing_cnt = 0;
} else if (vi->wss_missing_cnt == 4) { } else if (vi->wss_missing_cnt == 4) {
...@@ -454,13 +454,13 @@ void ivtv_vbi_work_handler(struct ivtv *itv) ...@@ -454,13 +454,13 @@ void ivtv_vbi_work_handler(struct ivtv *itv)
data.id = V4L2_SLICED_CAPTION_525; data.id = V4L2_SLICED_CAPTION_525;
data.field = 0; data.field = 0;
if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
mode |= 1; mode |= 1;
cc.odd[0] = data.data[0]; cc.odd[0] = data.data[0];
cc.odd[1] = data.data[1]; cc.odd[1] = data.data[1];
} }
data.field = 1; data.field = 1;
if (v4l2_subdev_call(itv->sd_video, video, g_vbi_data, &data) == 0) { if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
mode |= 2; mode |= 2;
cc.even[0] = data.data[0]; cc.even[0] = data.data[0];
cc.even[1] = data.data[1]; cc.even[1] = data.data[1];
......
...@@ -1550,18 +1550,22 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = { ...@@ -1550,18 +1550,22 @@ static const struct v4l2_subdev_video_ops saa711x_video_ops = {
.s_crystal_freq = saa711x_s_crystal_freq, .s_crystal_freq = saa711x_s_crystal_freq,
.g_fmt = saa711x_g_fmt, .g_fmt = saa711x_g_fmt,
.s_fmt = saa711x_s_fmt, .s_fmt = saa711x_s_fmt,
.g_vbi_data = saa711x_g_vbi_data,
.decode_vbi_line = saa711x_decode_vbi_line,
.s_stream = saa711x_s_stream, .s_stream = saa711x_s_stream,
.querystd = saa711x_querystd, .querystd = saa711x_querystd,
.g_input_status = saa711x_g_input_status, .g_input_status = saa711x_g_input_status,
}; };
static const struct v4l2_subdev_vbi_ops saa711x_vbi_ops = {
.g_vbi_data = saa711x_g_vbi_data,
.decode_vbi_line = saa711x_decode_vbi_line,
};
static const struct v4l2_subdev_ops saa711x_ops = { static const struct v4l2_subdev_ops saa711x_ops = {
.core = &saa711x_core_ops, .core = &saa711x_core_ops,
.tuner = &saa711x_tuner_ops, .tuner = &saa711x_tuner_ops,
.audio = &saa711x_audio_ops, .audio = &saa711x_audio_ops,
.video = &saa711x_video_ops, .video = &saa711x_video_ops,
.vbi = &saa711x_vbi_ops,
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
...@@ -727,16 +727,20 @@ static const struct v4l2_subdev_core_ops saa7127_core_ops = { ...@@ -727,16 +727,20 @@ static const struct v4l2_subdev_core_ops saa7127_core_ops = {
}; };
static const struct v4l2_subdev_video_ops saa7127_video_ops = { static const struct v4l2_subdev_video_ops saa7127_video_ops = {
.s_vbi_data = saa7127_s_vbi_data,
.g_fmt = saa7127_g_fmt, .g_fmt = saa7127_g_fmt,
.s_std_output = saa7127_s_std_output, .s_std_output = saa7127_s_std_output,
.s_routing = saa7127_s_routing, .s_routing = saa7127_s_routing,
.s_stream = saa7127_s_stream, .s_stream = saa7127_s_stream,
}; };
static const struct v4l2_subdev_vbi_ops saa7127_vbi_ops = {
.s_vbi_data = saa7127_s_vbi_data,
};
static const struct v4l2_subdev_ops saa7127_ops = { static const struct v4l2_subdev_ops saa7127_ops = {
.core = &saa7127_core_ops, .core = &saa7127_core_ops,
.video = &saa7127_video_ops, .video = &saa7127_video_ops,
.vbi = &saa7127_vbi_ops,
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
...@@ -1046,6 +1046,9 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = { ...@@ -1046,6 +1046,9 @@ static const struct v4l2_subdev_video_ops tvp5150_video_ops = {
.s_routing = tvp5150_s_routing, .s_routing = tvp5150_s_routing,
.g_fmt = tvp5150_g_fmt, .g_fmt = tvp5150_g_fmt,
.s_fmt = tvp5150_s_fmt, .s_fmt = tvp5150_s_fmt,
};
static const struct v4l2_subdev_vbi_ops tvp5150_vbi_ops = {
.g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap, .g_sliced_vbi_cap = tvp5150_g_sliced_vbi_cap,
}; };
...@@ -1053,6 +1056,7 @@ static const struct v4l2_subdev_ops tvp5150_ops = { ...@@ -1053,6 +1056,7 @@ static const struct v4l2_subdev_ops tvp5150_ops = {
.core = &tvp5150_core_ops, .core = &tvp5150_core_ops,
.tuner = &tvp5150_tuner_ops, .tuner = &tvp5150_tuner_ops,
.video = &tvp5150_video_ops, .video = &tvp5150_video_ops,
.vbi = &tvp5150_vbi_ops,
}; };
......
...@@ -184,28 +184,6 @@ struct v4l2_subdev_audio_ops { ...@@ -184,28 +184,6 @@ struct v4l2_subdev_audio_ops {
}; };
/* /*
decode_vbi_line: video decoders that support sliced VBI need to implement
this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the
start of the VBI data that was generated by the decoder. The driver
then parses the sliced VBI data and sets the other fields in the
struct accordingly. The pointer p is updated to point to the start of
the payload which can be copied verbatim into the data field of the
v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the
type field is set to 0 on return.
s_vbi_data: used to generate VBI signals on a video signal.
v4l2_sliced_vbi_data is filled with the data packets that should be
output. Note that if you set the line field to 0, then that VBI signal
is disabled. If no valid VBI data was found, then the type field is
set to 0 on return.
g_vbi_data: used to obtain the sliced VBI packet from a readback register.
Not all video decoders support this. If no data is available because
the readback register contains invalid or erroneous data -EIO is
returned. Note that you must fill in the 'id' member and the 'field'
member (to determine whether CC data from the first or second field
should be obtained).
s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
video input devices. video input devices.
...@@ -243,10 +221,6 @@ struct v4l2_subdev_audio_ops { ...@@ -243,10 +221,6 @@ struct v4l2_subdev_audio_ops {
struct v4l2_subdev_video_ops { struct v4l2_subdev_video_ops {
int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config); int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags); int (*s_crystal_freq)(struct v4l2_subdev *sd, u32 freq, u32 flags);
int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);
int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);
int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);
int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);
int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std); int (*s_std_output)(struct v4l2_subdev *sd, v4l2_std_id std);
int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std); int (*querystd)(struct v4l2_subdev *sd, v4l2_std_id *std);
int (*g_input_status)(struct v4l2_subdev *sd, u32 *status); int (*g_input_status)(struct v4l2_subdev *sd, u32 *status);
...@@ -280,6 +254,36 @@ struct v4l2_subdev_video_ops { ...@@ -280,6 +254,36 @@ struct v4l2_subdev_video_ops {
struct v4l2_mbus_framefmt *fmt); struct v4l2_mbus_framefmt *fmt);
}; };
/*
decode_vbi_line: video decoders that support sliced VBI need to implement
this ioctl. Field p of the v4l2_sliced_vbi_line struct is set to the
start of the VBI data that was generated by the decoder. The driver
then parses the sliced VBI data and sets the other fields in the
struct accordingly. The pointer p is updated to point to the start of
the payload which can be copied verbatim into the data field of the
v4l2_sliced_vbi_data struct. If no valid VBI data was found, then the
type field is set to 0 on return.
s_vbi_data: used to generate VBI signals on a video signal.
v4l2_sliced_vbi_data is filled with the data packets that should be
output. Note that if you set the line field to 0, then that VBI signal
is disabled. If no valid VBI data was found, then the type field is
set to 0 on return.
g_vbi_data: used to obtain the sliced VBI packet from a readback register.
Not all video decoders support this. If no data is available because
the readback register contains invalid or erroneous data -EIO is
returned. Note that you must fill in the 'id' member and the 'field'
member (to determine whether CC data from the first or second field
should be obtained).
*/
struct v4l2_subdev_vbi_ops {
int (*decode_vbi_line)(struct v4l2_subdev *sd, struct v4l2_decode_vbi_line *vbi_line);
int (*s_vbi_data)(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_data *vbi_data);
int (*g_vbi_data)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_data *vbi_data);
int (*g_sliced_vbi_cap)(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_cap *cap);
};
/** /**
* struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations * struct v4l2_subdev_sensor_ops - v4l2-subdev sensor operations
* @g_skip_top_lines: number of lines at the top of the image to be skipped. * @g_skip_top_lines: number of lines at the top of the image to be skipped.
...@@ -379,6 +383,7 @@ struct v4l2_subdev_ops { ...@@ -379,6 +383,7 @@ struct v4l2_subdev_ops {
const struct v4l2_subdev_tuner_ops *tuner; const struct v4l2_subdev_tuner_ops *tuner;
const struct v4l2_subdev_audio_ops *audio; const struct v4l2_subdev_audio_ops *audio;
const struct v4l2_subdev_video_ops *video; const struct v4l2_subdev_video_ops *video;
const struct v4l2_subdev_vbi_ops *vbi;
const struct v4l2_subdev_ir_ops *ir; const struct v4l2_subdev_ir_ops *ir;
const struct v4l2_subdev_sensor_ops *sensor; const struct v4l2_subdev_sensor_ops *sensor;
}; };
......
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