diff options
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/cx18/cx18-av-audio.c | 120 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.c | 29 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-core.h | 9 | ||||
-rw-r--r-- | drivers/media/video/cx18/cx18-av-vbi.c | 325 |
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 | ||
467 | int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg) | 467 | int 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: | 493 | int 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 | ||
517 | int 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 | ||
416 | static 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 | |||
423 | static 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 | |||
429 | static void input_change(struct cx18 *cx) | 416 | static 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 | ||
857 | static int cx18_av_s_fmt(struct v4l2_subdev *sd, struct v4l2_format *fmt) | 838 | static 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 */ |
358 | int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg); | 358 | int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl); |
359 | int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl); | ||
360 | int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq); | ||
359 | void cx18_av_audio_set_path(struct cx18 *cx); | 361 | void cx18_av_audio_set_path(struct cx18 *cx); |
360 | 362 | ||
361 | /* ----------------------------------------------------------------------- */ | 363 | /* ----------------------------------------------------------------------- */ |
362 | /* cx18_av-vbi.c */ | 364 | /* cx18_av-vbi.c */ |
363 | int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg); | 365 | int cx18_av_decode_vbi_line(struct v4l2_subdev *sd, |
366 | struct v4l2_decode_vbi_line *vbi); | ||
367 | int cx18_av_vbi_g_fmt(struct cx18 *cx, struct v4l2_format *fmt); | ||
368 | int 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 | ||
132 | int cx18_av_vbi(struct cx18 *cx, unsigned int cmd, void *arg) | 132 | int 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++) | 176 | int 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 | |||
263 | int 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 | } |