aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media')
-rw-r--r--drivers/media/video/cx18/cx18-av-audio.c120
-rw-r--r--drivers/media/video/cx18/cx18-av-core.c29
-rw-r--r--drivers/media/video/cx18/cx18-av-core.h9
-rw-r--r--drivers/media/video/cx18/cx18-av-vbi.c325
4 files changed, 228 insertions, 255 deletions
diff --git a/drivers/media/video/cx18/cx18-av-audio.c b/drivers/media/video/cx18/cx18-av-audio.c
index a2f0ad570434..9e30983f2ff6 100644
--- a/drivers/media/video/cx18/cx18-av-audio.c
+++ b/drivers/media/video/cx18/cx18-av-audio.c
@@ -464,82 +464,76 @@ static void set_mute(struct cx18 *cx, int mute)
464 } 464 }
465} 465}
466 466
467int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg) 467int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
468{ 468{
469 struct cx18 *cx = v4l2_get_subdevdata(sd);
469 struct cx18_av_state *state = &cx->av_state; 470 struct cx18_av_state *state = &cx->av_state;
470 struct v4l2_control *ctrl = arg;
471 int retval; 471 int retval;
472 u8 v;
472 473
473 switch (cmd) { 474 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
474 case VIDIOC_INT_AUDIO_CLOCK_FREQ: 475 v = cx18_av_read(cx, 0x803) & ~0x10;
475 { 476 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
476 u8 v; 477 cx18_av_write(cx, 0x8d3, 0x1f);
477 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 478 }
478 v = cx18_av_read(cx, 0x803) & ~0x10; 479 v = cx18_av_read(cx, 0x810) | 0x1;
479 cx18_av_write_expect(cx, 0x803, v, v, 0x1f); 480 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
480 cx18_av_write(cx, 0x8d3, 0x1f);
481 }
482 v = cx18_av_read(cx, 0x810) | 0x1;
483 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
484 481
485 retval = set_audclk_freq(cx, *(u32 *)arg); 482 retval = set_audclk_freq(cx, freq);
486 483
487 v = cx18_av_read(cx, 0x810) & ~0x1; 484 v = cx18_av_read(cx, 0x810) & ~0x1;
488 cx18_av_write_expect(cx, 0x810, v, v, 0x0f); 485 cx18_av_write_expect(cx, 0x810, v, v, 0x0f);
489 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) { 486 if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
490 v = cx18_av_read(cx, 0x803) | 0x10; 487 v = cx18_av_read(cx, 0x803) | 0x10;
491 cx18_av_write_expect(cx, 0x803, v, v, 0x1f); 488 cx18_av_write_expect(cx, 0x803, v, v, 0x1f);
492 }
493 return retval;
494 } 489 }
490 return retval;
491}
495 492
496 case VIDIOC_G_CTRL: 493int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
497 switch (ctrl->id) { 494{
498 case V4L2_CID_AUDIO_VOLUME: 495 switch (ctrl->id) {
499 ctrl->value = get_volume(cx); 496 case V4L2_CID_AUDIO_VOLUME:
500 break; 497 ctrl->value = get_volume(cx);
501 case V4L2_CID_AUDIO_BASS:
502 ctrl->value = get_bass(cx);
503 break;
504 case V4L2_CID_AUDIO_TREBLE:
505 ctrl->value = get_treble(cx);
506 break;
507 case V4L2_CID_AUDIO_BALANCE:
508 ctrl->value = get_balance(cx);
509 break;
510 case V4L2_CID_AUDIO_MUTE:
511 ctrl->value = get_mute(cx);
512 break;
513 default:
514 return -EINVAL;
515 }
516 break; 498 break;
517 499 case V4L2_CID_AUDIO_BASS:
518 case VIDIOC_S_CTRL: 500 ctrl->value = get_bass(cx);
519 switch (ctrl->id) { 501 break;
520 case V4L2_CID_AUDIO_VOLUME: 502 case V4L2_CID_AUDIO_TREBLE:
521 set_volume(cx, ctrl->value); 503 ctrl->value = get_treble(cx);
522 break; 504 break;
523 case V4L2_CID_AUDIO_BASS: 505 case V4L2_CID_AUDIO_BALANCE:
524 set_bass(cx, ctrl->value); 506 ctrl->value = get_balance(cx);
525 break; 507 break;
526 case V4L2_CID_AUDIO_TREBLE: 508 case V4L2_CID_AUDIO_MUTE:
527 set_treble(cx, ctrl->value); 509 ctrl->value = get_mute(cx);
528 break;
529 case V4L2_CID_AUDIO_BALANCE:
530 set_balance(cx, ctrl->value);
531 break;
532 case V4L2_CID_AUDIO_MUTE:
533 set_mute(cx, ctrl->value);
534 break;
535 default:
536 return -EINVAL;
537 }
538 break; 510 break;
539
540 default: 511 default:
541 return -EINVAL; 512 return -EINVAL;
542 } 513 }
514 return 0;
515}
543 516
517int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
518{
519 switch (ctrl->id) {
520 case V4L2_CID_AUDIO_VOLUME:
521 set_volume(cx, ctrl->value);
522 break;
523 case V4L2_CID_AUDIO_BASS:
524 set_bass(cx, ctrl->value);
525 break;
526 case V4L2_CID_AUDIO_TREBLE:
527 set_treble(cx, ctrl->value);
528 break;
529 case V4L2_CID_AUDIO_BALANCE:
530 set_balance(cx, ctrl->value);
531 break;
532 case V4L2_CID_AUDIO_MUTE:
533 set_mute(cx, ctrl->value);
534 break;
535 default:
536 return -EINVAL;
537 }
544 return 0; 538 return 0;
545} 539}
diff --git a/drivers/media/video/cx18/cx18-av-core.c b/drivers/media/video/cx18/cx18-av-core.c
index 21f4be8393b7..f4dd9d78eb3d 100644
--- a/drivers/media/video/cx18/cx18-av-core.c
+++ b/drivers/media/video/cx18/cx18-av-core.c
@@ -413,19 +413,6 @@ void cx18_av_std_setup(struct cx18 *cx)
413 cx18_av_write(cx, 0x47f, state->slicer_line_delay); 413 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
414} 414}
415 415
416static int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
417 struct v4l2_decode_vbi_line *vbi_line)
418{
419 struct cx18 *cx = v4l2_get_subdevdata(sd);
420 return cx18_av_vbi(cx, VIDIOC_INT_DECODE_VBI_LINE, vbi_line);
421}
422
423static int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
424{
425 struct cx18 *cx = v4l2_get_subdevdata(sd);
426 return cx18_av_audio(cx, VIDIOC_INT_AUDIO_CLOCK_FREQ, &freq);
427}
428
429static void input_change(struct cx18 *cx) 416static void input_change(struct cx18 *cx)
430{ 417{
431 struct cx18_av_state *state = &cx->av_state; 418 struct cx18_av_state *state = &cx->av_state;
@@ -772,7 +759,7 @@ static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
772 case V4L2_CID_AUDIO_TREBLE: 759 case V4L2_CID_AUDIO_TREBLE:
773 case V4L2_CID_AUDIO_BALANCE: 760 case V4L2_CID_AUDIO_BALANCE:
774 case V4L2_CID_AUDIO_MUTE: 761 case V4L2_CID_AUDIO_MUTE:
775 return cx18_av_audio(cx, VIDIOC_S_CTRL, ctrl); 762 return cx18_av_audio_s_ctrl(cx, ctrl);
776 763
777 default: 764 default:
778 return -EINVAL; 765 return -EINVAL;
@@ -802,7 +789,7 @@ static int cx18_av_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
802 case V4L2_CID_AUDIO_TREBLE: 789 case V4L2_CID_AUDIO_TREBLE:
803 case V4L2_CID_AUDIO_BALANCE: 790 case V4L2_CID_AUDIO_BALANCE:
804 case V4L2_CID_AUDIO_MUTE: 791 case V4L2_CID_AUDIO_MUTE:
805 return cx18_av_audio(cx, VIDIOC_G_CTRL, ctrl); 792 return cx18_av_audio_g_ctrl(cx, ctrl);
806 default: 793 default:
807 return -EINVAL; 794 return -EINVAL;
808 } 795 }
@@ -845,13 +832,7 @@ static int cx18_av_g_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
845{ 832{
846 struct cx18 *cx = v4l2_get_subdevdata(sd); 833 struct cx18 *cx = v4l2_get_subdevdata(sd);
847 834
848 switch (fmt->type) { 835 return cx18_av_vbi_g_fmt(cx, fmt);
849 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
850 return cx18_av_vbi(cx, VIDIOC_G_FMT, fmt);
851 default:
852 return -EINVAL;
853 }
854 return 0;
855} 836}
856 837
857static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) 838static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
@@ -925,10 +906,10 @@ static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt)
925 break; 906 break;
926 907
927 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE: 908 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
928 return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt); 909 return cx18_av_vbi_s_fmt(cx, fmt);
929 910
930 case V4L2_BUF_TYPE_VBI_CAPTURE: 911 case V4L2_BUF_TYPE_VBI_CAPTURE:
931 return cx18_av_vbi(cx, VIDIOC_S_FMT, fmt); 912 return cx18_av_vbi_s_fmt(cx, fmt);
932 913
933 default: 914 default:
934 return -EINVAL; 915 return -EINVAL;
diff --git a/drivers/media/video/cx18/cx18-av-core.h b/drivers/media/video/cx18/cx18-av-core.h
index 2687a2c91ddd..c458120e8c90 100644
--- a/drivers/media/video/cx18/cx18-av-core.h
+++ b/drivers/media/video/cx18/cx18-av-core.h
@@ -355,11 +355,16 @@ int cx18_av_loadfw(struct cx18 *cx);
355 355
356/* ----------------------------------------------------------------------- */ 356/* ----------------------------------------------------------------------- */
357/* cx18_av-audio.c */ 357/* cx18_av-audio.c */
358int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg); 358int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl);
359int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl);
360int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
359void cx18_av_audio_set_path(struct cx18 *cx); 361void cx18_av_audio_set_path(struct cx18 *cx);
360 362
361/* ----------------------------------------------------------------------- */ 363/* ----------------------------------------------------------------------- */
362/* cx18_av-vbi.c */ 364/* cx18_av-vbi.c */
363int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg); 365int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
366 struct v4l2_decode_vbi_line *vbi);
367int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt);
368int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt);
364 369
365#endif 370#endif
diff --git a/drivers/media/video/cx18/cx18-av-vbi.c b/drivers/media/video/cx18/cx18-av-vbi.c
index 27699839b80d..23b31670bf1d 100644
--- a/drivers/media/video/cx18/cx18-av-vbi.c
+++ b/drivers/media/video/cx18/cx18-av-vbi.c
@@ -129,196 +129,189 @@ static int decode_vps(u8 *dst, u8 *p)
129 return err & 0xf0; 129 return err & 0xf0;
130} 130}
131 131
132int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) 132int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt)
133{ 133{
134 struct cx18_av_state *state = &cx->av_state; 134 struct cx18_av_state *state = &cx->av_state;
135 struct v4l2_format *fmt;
136 struct v4l2_sliced_vbi_format *svbi; 135 struct v4l2_sliced_vbi_format *svbi;
136 static const u16 lcr2vbi[] = {
137 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */
138 0, V4L2_SLICED_WSS_625, 0, /* 4 */
139 V4L2_SLICED_CAPTION_525, /* 6 */
140 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */
141 0, 0, 0, 0
142 };
143 int is_pal = !(state->std & V4L2_STD_525_60);
144 int i;
137 145
138 switch (cmd) { 146 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
139 case VIDIOC_G_FMT: 147 return -EINVAL;
140 { 148 svbi = &fmt->fmt.sliced;
141 static u16 lcr2vbi[] = { 149 memset(svbi, 0, sizeof(*svbi));
142 0, V4L2_SLICED_TELETEXT_B, 0, /* 1 */ 150 /* we're done if raw VBI is active */
143 0, V4L2_SLICED_WSS_625, 0, /* 4 */ 151 if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
144 V4L2_SLICED_CAPTION_525, /* 6 */ 152 return 0;
145 0, 0, V4L2_SLICED_VPS, 0, 0, /* 9 */ 153
146 0, 0, 0, 0 154 if (is_pal) {
147 }; 155 for (i = 7; i <= 23; i++) {
148 int is_pal = !(state->std & V4L2_STD_525_60); 156 u8 v = cx18_av_read(cx, 0x424 + i - 7);
149 int i;
150
151 fmt = arg;
152 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE)
153 return -EINVAL;
154 svbi = &fmt->fmt.sliced;
155 memset(svbi, 0, sizeof(*svbi));
156 /* we're done if raw VBI is active */
157 if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
158 break;
159
160 if (is_pal) {
161 for (i = 7; i <= 23; i++) {
162 u8 v = cx18_av_read(cx, 0x424 + i - 7);
163
164 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
165 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
166 svbi->service_set |= svbi->service_lines[0][i] |
167 svbi->service_lines[1][i];
168 }
169 } else {
170 for (i = 10; i <= 21; i++) {
171 u8 v = cx18_av_read(cx, 0x424 + i - 10);
172
173 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
174 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
175 svbi->service_set |= svbi->service_lines[0][i] |
176 svbi->service_lines[1][i];
177 }
178 }
179 break;
180 }
181 157
182 case VIDIOC_S_FMT: 158 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
183 { 159 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
184 int is_pal = !(state->std & V4L2_STD_525_60); 160 svbi->service_set |= svbi->service_lines[0][i] |
185 int i, x; 161 svbi->service_lines[1][i];
186 u8 lcr[24];
187
188 fmt = arg;
189 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
190 fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
191 return -EINVAL;
192 svbi = &fmt->fmt.sliced;
193 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
194 /* raw VBI */
195 memset(svbi, 0, sizeof(*svbi));
196
197 /* Setup standard */
198 cx18_av_std_setup(cx);
199
200 /* VBI Offset */
201 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
202 cx18_av_write(cx, 0x404, 0x2e);
203 break;
204 } 162 }
163 } else {
164 for (i = 10; i <= 21; i++) {
165 u8 v = cx18_av_read(cx, 0x424 + i - 10);
166
167 svbi->service_lines[0][i] = lcr2vbi[v >> 4];
168 svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
169 svbi->service_set |= svbi->service_lines[0][i] |
170 svbi->service_lines[1][i];
171 }
172 }
173 return 0;
174}
205 175
206 for (x = 0; x <= 23; x++) 176int cx18_av_vbi_s_fmt(struct cx18 *cx, struct v4l2_format *fmt)
207 lcr[x] = 0x00; 177{
178 struct cx18_av_state *state = &cx->av_state;
179 struct v4l2_sliced_vbi_format *svbi;
180 int is_pal = !(state->std & V4L2_STD_525_60);
181 int i, x;
182 u8 lcr[24];
183
184 if (fmt->type != V4L2_BUF_TYPE_SLICED_VBI_CAPTURE &&
185 fmt->type != V4L2_BUF_TYPE_VBI_CAPTURE)
186 return -EINVAL;
187 svbi = &fmt->fmt.sliced;
188 if (fmt->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
189 /* raw VBI */
190 memset(svbi, 0, sizeof(*svbi));
208 191
209 /* Setup standard */ 192 /* Setup standard */
210 cx18_av_std_setup(cx); 193 cx18_av_std_setup(cx);
211 194
212 /* Sliced VBI */ 195 /* VBI Offset */
213 cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
214 cx18_av_write(cx, 0x406, 0x13);
215 cx18_av_write(cx, 0x47f, state->slicer_line_delay); 196 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
197 cx18_av_write(cx, 0x404, 0x2e);
198 return 0;
199 }
216 200
217 /* Force impossible lines to 0 */ 201 for (x = 0; x <= 23; x++)
218 if (is_pal) { 202 lcr[x] = 0x00;
219 for (i = 0; i <= 6; i++) 203
220 svbi->service_lines[0][i] = 204 /* Setup standard */
221 svbi->service_lines[1][i] = 0; 205 cx18_av_std_setup(cx);
222 } else { 206
223 for (i = 0; i <= 9; i++) 207 /* Sliced VBI */
224 svbi->service_lines[0][i] = 208 cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
225 svbi->service_lines[1][i] = 0; 209 cx18_av_write(cx, 0x406, 0x13);
226 210 cx18_av_write(cx, 0x47f, state->slicer_line_delay);
227 for (i = 22; i <= 23; i++) 211
228 svbi->service_lines[0][i] = 212 /* Force impossible lines to 0 */
229 svbi->service_lines[1][i] = 0; 213 if (is_pal) {
230 } 214 for (i = 0; i <= 6; i++)
215 svbi->service_lines[0][i] =
216 svbi->service_lines[1][i] = 0;
217 } else {
218 for (i = 0; i <= 9; i++)
219 svbi->service_lines[0][i] =
220 svbi->service_lines[1][i] = 0;
221
222 for (i = 22; i <= 23; i++)
223 svbi->service_lines[0][i] =
224 svbi->service_lines[1][i] = 0;
225 }
231 226
232 /* Build register values for requested service lines */ 227 /* Build register values for requested service lines */
233 for (i = 7; i <= 23; i++) { 228 for (i = 7; i <= 23; i++) {
234 for (x = 0; x <= 1; x++) { 229 for (x = 0; x <= 1; x++) {
235 switch (svbi->service_lines[1-x][i]) { 230 switch (svbi->service_lines[1-x][i]) {
236 case V4L2_SLICED_TELETEXT_B: 231 case V4L2_SLICED_TELETEXT_B:
237 lcr[i] |= 1 << (4 * x); 232 lcr[i] |= 1 << (4 * x);
238 break; 233 break;
239 case V4L2_SLICED_WSS_625: 234 case V4L2_SLICED_WSS_625:
240 lcr[i] |= 4 << (4 * x); 235 lcr[i] |= 4 << (4 * x);
241 break; 236 break;
242 case V4L2_SLICED_CAPTION_525: 237 case V4L2_SLICED_CAPTION_525:
243 lcr[i] |= 6 << (4 * x); 238 lcr[i] |= 6 << (4 * x);
244 break; 239 break;
245 case V4L2_SLICED_VPS: 240 case V4L2_SLICED_VPS:
246 lcr[i] |= 9 << (4 * x); 241 lcr[i] |= 9 << (4 * x);
247 break; 242 break;
248 }
249 } 243 }
250 } 244 }
245 }
251 246
252 if (is_pal) { 247 if (is_pal) {
253 for (x = 1, i = 0x424; i <= 0x434; i++, x++) 248 for (x = 1, i = 0x424; i <= 0x434; i++, x++)
254 cx18_av_write(cx, i, lcr[6 + x]); 249 cx18_av_write(cx, i, lcr[6 + x]);
255 } else { 250 } else {
256 for (x = 1, i = 0x424; i <= 0x430; i++, x++) 251 for (x = 1, i = 0x424; i <= 0x430; i++, x++)
257 cx18_av_write(cx, i, lcr[9 + x]); 252 cx18_av_write(cx, i, lcr[9 + x]);
258 for (i = 0x431; i <= 0x434; i++) 253 for (i = 0x431; i <= 0x434; i++)
259 cx18_av_write(cx, i, 0); 254 cx18_av_write(cx, i, 0);
260 } 255 }
261 256
262 cx18_av_write(cx, 0x43c, 0x16); 257 cx18_av_write(cx, 0x43c, 0x16);
263 /* FIXME - should match vblank set in cx18_av_std_setup() */ 258 /* FIXME - should match vblank set in cx18_av_std_setup() */
264 cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26); 259 cx18_av_write(cx, 0x474, is_pal ? 0x2a : 26);
265 break; 260 return 0;
261}
262
263int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
264 struct v4l2_decode_vbi_line *vbi)
265{
266 struct cx18 *cx = v4l2_get_subdevdata(sd);
267 struct cx18_av_state *state = &cx->av_state;
268 struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
269 u8 *p;
270 int did, sdid, l, err = 0;
271
272 /*
273 * Check for the ancillary data header for sliced VBI
274 */
275 if (anc->preamble[0] ||
276 anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
277 (anc->did != sliced_vbi_did[0] &&
278 anc->did != sliced_vbi_did[1])) {
279 vbi->line = vbi->type = 0;
280 return 0;
266 } 281 }
267 282
268 case VIDIOC_INT_DECODE_VBI_LINE: 283 did = anc->did;
269 { 284 sdid = anc->sdid & 0xf;
270 struct v4l2_decode_vbi_line *vbi = arg; 285 l = anc->idid[0] & 0x3f;
271 u8 *p; 286 l += state->slicer_line_offset;
272 struct vbi_anc_data *anc = (struct vbi_anc_data *) vbi->p; 287 p = anc->payload;
273 int did, sdid, l, err = 0;
274
275 /*
276 * Check for the ancillary data header for sliced VBI
277 */
278 if (anc->preamble[0] ||
279 anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
280 (anc->did != sliced_vbi_did[0] &&
281 anc->did != sliced_vbi_did[1])) {
282 vbi->line = vbi->type = 0;
283 break;
284 }
285 288
286 did = anc->did; 289 /* Decode the SDID set by the slicer */
287 sdid = anc->sdid & 0xf; 290 switch (sdid) {
288 l = anc->idid[0] & 0x3f; 291 case 1:
289 l += state->slicer_line_offset; 292 sdid = V4L2_SLICED_TELETEXT_B;
290 p = anc->payload; 293 break;
291 294 case 4:
292 /* Decode the SDID set by the slicer */ 295 sdid = V4L2_SLICED_WSS_625;
293 switch (sdid) { 296 break;
294 case 1: 297 case 6:
295 sdid = V4L2_SLICED_TELETEXT_B; 298 sdid = V4L2_SLICED_CAPTION_525;
296 break; 299 err = !odd_parity(p[0]) || !odd_parity(p[1]);
297 case 4: 300 break;
298 sdid = V4L2_SLICED_WSS_625; 301 case 9:
299 break; 302 sdid = V4L2_SLICED_VPS;
300 case 6: 303 if (decode_vps(p, p) != 0)
301 sdid = V4L2_SLICED_CAPTION_525;
302 err = !odd_parity(p[0]) || !odd_parity(p[1]);
303 break;
304 case 9:
305 sdid = V4L2_SLICED_VPS;
306 if (decode_vps(p, p) != 0)
307 err = 1;
308 break;
309 default:
310 sdid = 0;
311 err = 1; 304 err = 1;
312 break;
313 }
314
315 vbi->type = err ? 0 : sdid;
316 vbi->line = err ? 0 : l;
317 vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
318 vbi->p = p;
319 break; 305 break;
320 } 306 default:
307 sdid = 0;
308 err = 1;
309 break;
321 } 310 }
322 311
312 vbi->type = err ? 0 : sdid;
313 vbi->line = err ? 0 : l;
314 vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
315 vbi->p = p;
323 return 0; 316 return 0;
324} 317}