0001
0002
0003
0004
0005
0006
0007
0008 #include "ivtv-driver.h"
0009 #include "ivtv-i2c.h"
0010 #include "ivtv-ioctl.h"
0011 #include "ivtv-queue.h"
0012 #include "ivtv-cards.h"
0013 #include "ivtv-vbi.h"
0014
0015 static void ivtv_set_vps(struct ivtv *itv, int enabled)
0016 {
0017 struct v4l2_sliced_vbi_data data;
0018
0019 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
0020 return;
0021 data.id = V4L2_SLICED_VPS;
0022 data.field = 0;
0023 data.line = enabled ? 16 : 0;
0024 data.data[2] = itv->vbi.vps_payload.data[0];
0025 data.data[8] = itv->vbi.vps_payload.data[1];
0026 data.data[9] = itv->vbi.vps_payload.data[2];
0027 data.data[10] = itv->vbi.vps_payload.data[3];
0028 data.data[11] = itv->vbi.vps_payload.data[4];
0029 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
0030 }
0031
0032 static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
0033 {
0034 struct v4l2_sliced_vbi_data data;
0035
0036 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
0037 return;
0038 data.id = V4L2_SLICED_CAPTION_525;
0039 data.field = 0;
0040 data.line = (mode & 1) ? 21 : 0;
0041 data.data[0] = cc->odd[0];
0042 data.data[1] = cc->odd[1];
0043 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
0044 data.field = 1;
0045 data.line = (mode & 2) ? 21 : 0;
0046 data.data[0] = cc->even[0];
0047 data.data[1] = cc->even[1];
0048 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
0049 }
0050
0051 static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
0052 {
0053 struct v4l2_sliced_vbi_data data;
0054
0055 if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
0056 return;
0057
0058
0059
0060
0061
0062 if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
0063 enabled = 1;
0064 mode = 0x08;
0065 }
0066 data.id = V4L2_SLICED_WSS_625;
0067 data.field = 0;
0068 data.line = enabled ? 23 : 0;
0069 data.data[0] = mode & 0xff;
0070 data.data[1] = (mode >> 8) & 0xff;
0071 ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
0072 }
0073
0074 static int odd_parity(u8 c)
0075 {
0076 c ^= (c >> 4);
0077 c ^= (c >> 2);
0078 c ^= (c >> 1);
0079
0080 return c & 1;
0081 }
0082
0083 static void ivtv_write_vbi_line(struct ivtv *itv,
0084 const struct v4l2_sliced_vbi_data *d,
0085 struct vbi_cc *cc, int *found_cc)
0086 {
0087 struct vbi_info *vi = &itv->vbi;
0088
0089 if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
0090 if (d->field) {
0091 cc->even[0] = d->data[0];
0092 cc->even[1] = d->data[1];
0093 } else {
0094 cc->odd[0] = d->data[0];
0095 cc->odd[1] = d->data[1];
0096 }
0097 *found_cc = 1;
0098 } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
0099 struct vbi_vps vps;
0100
0101 vps.data[0] = d->data[2];
0102 vps.data[1] = d->data[8];
0103 vps.data[2] = d->data[9];
0104 vps.data[3] = d->data[10];
0105 vps.data[4] = d->data[11];
0106 if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
0107 vi->vps_payload = vps;
0108 set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
0109 }
0110 } else if (d->id == V4L2_SLICED_WSS_625 &&
0111 d->line == 23 && d->field == 0) {
0112 int wss = d->data[0] | d->data[1] << 8;
0113
0114 if (vi->wss_payload != wss) {
0115 vi->wss_payload = wss;
0116 set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
0117 }
0118 }
0119 }
0120
0121 static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
0122 {
0123 struct vbi_info *vi = &itv->vbi;
0124
0125 if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
0126 memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
0127 sizeof(struct vbi_cc));
0128 vi->cc_payload_idx++;
0129 set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
0130 }
0131 }
0132
0133 static void ivtv_write_vbi(struct ivtv *itv,
0134 const struct v4l2_sliced_vbi_data *sliced,
0135 size_t cnt)
0136 {
0137 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
0138 int found_cc = 0;
0139 size_t i;
0140
0141 for (i = 0; i < cnt; i++)
0142 ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
0143
0144 if (found_cc)
0145 ivtv_write_vbi_cc_lines(itv, &cc);
0146 }
0147
0148 ssize_t
0149 ivtv_write_vbi_from_user(struct ivtv *itv,
0150 const struct v4l2_sliced_vbi_data __user *sliced,
0151 size_t cnt)
0152 {
0153 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
0154 int found_cc = 0;
0155 size_t i;
0156 struct v4l2_sliced_vbi_data d;
0157 ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
0158
0159 for (i = 0; i < cnt; i++) {
0160 if (copy_from_user(&d, sliced + i,
0161 sizeof(struct v4l2_sliced_vbi_data))) {
0162 ret = -EFAULT;
0163 break;
0164 }
0165 ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
0166 }
0167
0168 if (found_cc)
0169 ivtv_write_vbi_cc_lines(itv, &cc);
0170
0171 return ret;
0172 }
0173
0174 static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
0175 {
0176 int line = 0;
0177 int i;
0178 u32 linemask[2] = { 0, 0 };
0179 unsigned short size;
0180 static const u8 mpeg_hdr_data[] = {
0181 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
0182 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
0183 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
0184 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
0185 };
0186 const int sd = sizeof(mpeg_hdr_data);
0187 int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
0188 u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
0189
0190 for (i = 0; i < lines; i++) {
0191 int f, l;
0192
0193 if (itv->vbi.sliced_data[i].id == 0)
0194 continue;
0195
0196 l = itv->vbi.sliced_data[i].line - 6;
0197 f = itv->vbi.sliced_data[i].field;
0198 if (f)
0199 l += 18;
0200 if (l < 32)
0201 linemask[0] |= (1 << l);
0202 else
0203 linemask[1] |= (1 << (l - 32));
0204 dst[sd + 12 + line * 43] =
0205 ivtv_service2vbi(itv->vbi.sliced_data[i].id);
0206 memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
0207 line++;
0208 }
0209 memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
0210 if (line == 36) {
0211
0212
0213
0214 memcpy(dst + sd, "ITV0", 4);
0215 memmove(dst + sd + 4, dst + sd + 12, line * 43);
0216 size = 4 + ((43 * line + 3) & ~3);
0217 } else {
0218 memcpy(dst + sd, "itv0", 4);
0219 cpu_to_le32s(&linemask[0]);
0220 cpu_to_le32s(&linemask[1]);
0221 memcpy(dst + sd + 4, &linemask[0], 8);
0222 size = 12 + ((43 * line + 3) & ~3);
0223 }
0224 dst[4+16] = (size + 10) >> 8;
0225 dst[5+16] = (size + 10) & 0xff;
0226 dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
0227 dst[10+16] = (pts_stamp >> 22) & 0xff;
0228 dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
0229 dst[12+16] = (pts_stamp >> 7) & 0xff;
0230 dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
0231 itv->vbi.sliced_mpeg_size[idx] = sd + size;
0232 }
0233
0234 static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
0235 {
0236 u32 linemask[2];
0237 int i, l, id2;
0238 int line = 0;
0239
0240 if (!memcmp(p, "itv0", 4)) {
0241 memcpy(linemask, p + 4, 8);
0242 p += 12;
0243 } else if (!memcmp(p, "ITV0", 4)) {
0244 linemask[0] = 0xffffffff;
0245 linemask[1] = 0xf;
0246 p += 4;
0247 } else {
0248
0249 linemask[0] = linemask[1] = 0;
0250 }
0251 for (i = 0; i < 36; i++) {
0252 int err = 0;
0253
0254 if (i < 32 && !(linemask[0] & (1 << i)))
0255 continue;
0256 if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
0257 continue;
0258 id2 = *p & 0xf;
0259 switch (id2) {
0260 case IVTV_SLICED_TYPE_TELETEXT_B:
0261 id2 = V4L2_SLICED_TELETEXT_B;
0262 break;
0263 case IVTV_SLICED_TYPE_CAPTION_525:
0264 id2 = V4L2_SLICED_CAPTION_525;
0265 err = !odd_parity(p[1]) || !odd_parity(p[2]);
0266 break;
0267 case IVTV_SLICED_TYPE_VPS:
0268 id2 = V4L2_SLICED_VPS;
0269 break;
0270 case IVTV_SLICED_TYPE_WSS_625:
0271 id2 = V4L2_SLICED_WSS_625;
0272 break;
0273 default:
0274 id2 = 0;
0275 break;
0276 }
0277 if (err == 0) {
0278 l = (i < 18) ? i + 6 : i - 18 + 6;
0279 itv->vbi.sliced_dec_data[line].line = l;
0280 itv->vbi.sliced_dec_data[line].field = i >= 18;
0281 itv->vbi.sliced_dec_data[line].id = id2;
0282 memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
0283 line++;
0284 }
0285 p += 43;
0286 }
0287 while (line < 36) {
0288 itv->vbi.sliced_dec_data[line].id = 0;
0289 itv->vbi.sliced_dec_data[line].line = 0;
0290 itv->vbi.sliced_dec_data[line].field = 0;
0291 line++;
0292 }
0293 return line * sizeof(itv->vbi.sliced_dec_data[0]);
0294 }
0295
0296
0297
0298
0299 static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
0300 {
0301 u32 line_size = itv->vbi.raw_decoder_line_size;
0302 u32 lines = itv->vbi.count;
0303 u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
0304 u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
0305 u8 *q = buf;
0306 u8 *p;
0307 int i;
0308
0309 for (i = 0; i < lines; i++) {
0310 p = buf + i * line_size;
0311
0312
0313 if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
0314 break;
0315 }
0316 memcpy(q, p + 4, line_size - 4);
0317 q += line_size - 4;
0318 }
0319 return lines * (line_size - 4);
0320 }
0321
0322
0323
0324
0325 static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
0326 {
0327 u32 line_size = itv->vbi.sliced_decoder_line_size;
0328 struct v4l2_decode_vbi_line vbi = {};
0329 int i;
0330 unsigned lines = 0;
0331
0332
0333 for (i = 0; i < size; i++, buf++) {
0334 if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
0335 break;
0336 }
0337
0338 size -= i;
0339 if (size < line_size) {
0340 return line;
0341 }
0342 for (i = 0; i < size / line_size; i++) {
0343 u8 *p = buf + i * line_size;
0344
0345
0346 if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
0347 continue;
0348 }
0349 vbi.p = p + 4;
0350 v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
0351 if (vbi.type && !(lines & (1 << vbi.line))) {
0352 lines |= 1 << vbi.line;
0353 itv->vbi.sliced_data[line].id = vbi.type;
0354 itv->vbi.sliced_data[line].field = vbi.is_second_field;
0355 itv->vbi.sliced_data[line].line = vbi.line;
0356 memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
0357 line++;
0358 }
0359 }
0360 return line;
0361 }
0362
0363 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
0364 u64 pts_stamp, int streamtype)
0365 {
0366 u8 *p = (u8 *) buf->buf;
0367 u32 size = buf->bytesused;
0368 int y;
0369
0370
0371 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
0372 u8 type;
0373
0374 ivtv_buf_swap(buf);
0375
0376 type = p[3];
0377
0378 size = buf->bytesused = compress_raw_buf(itv, p, size);
0379
0380
0381 if (type == itv->vbi.raw_decoder_sav_even_field) {
0382
0383
0384 p += size - 4;
0385 memcpy(p, &itv->vbi.frame, 4);
0386 itv->vbi.frame++;
0387 }
0388 return;
0389 }
0390
0391
0392 if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
0393 int lines;
0394
0395 ivtv_buf_swap(buf);
0396
0397
0398 lines = compress_sliced_buf(itv, 0, p, size / 2,
0399 itv->vbi.sliced_decoder_sav_odd_field);
0400
0401
0402
0403 lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
0404 itv->vbi.sliced_decoder_sav_even_field);
0405
0406 if (lines == 0) {
0407 itv->vbi.sliced_data[0].id = 0;
0408 itv->vbi.sliced_data[0].line = 0;
0409 itv->vbi.sliced_data[0].field = 0;
0410 lines = 1;
0411 }
0412 buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
0413 memcpy(p, &itv->vbi.sliced_data[0], size);
0414
0415 if (itv->vbi.insert_mpeg) {
0416 copy_vbi_data(itv, lines, pts_stamp);
0417 }
0418 itv->vbi.frame++;
0419 return;
0420 }
0421
0422
0423 if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
0424
0425
0426
0427
0428
0429
0430
0431 int offset = size & 3;
0432 int cnt;
0433
0434 if (offset) {
0435 p += 4 - offset;
0436 }
0437
0438 for (y = 0; y < size; y += 4) {
0439 swab32s((u32 *)(p + y));
0440 }
0441
0442 cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
0443 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
0444 buf->bytesused = cnt;
0445
0446 ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
0447 cnt / sizeof(itv->vbi.sliced_dec_data[0]));
0448 return;
0449 }
0450 }
0451
0452 void ivtv_disable_cc(struct ivtv *itv)
0453 {
0454 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
0455
0456 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
0457 ivtv_set_cc(itv, 0, &cc);
0458 itv->vbi.cc_payload_idx = 0;
0459 }
0460
0461
0462 void ivtv_vbi_work_handler(struct ivtv *itv)
0463 {
0464 struct vbi_info *vi = &itv->vbi;
0465 struct v4l2_sliced_vbi_data data;
0466 struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
0467
0468
0469 if (itv->output_mode == OUT_PASSTHROUGH) {
0470 if (itv->is_50hz) {
0471 data.id = V4L2_SLICED_WSS_625;
0472 data.field = 0;
0473
0474 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
0475 ivtv_set_wss(itv, 1, data.data[0] & 0xf);
0476 vi->wss_missing_cnt = 0;
0477 } else if (vi->wss_missing_cnt == 4) {
0478 ivtv_set_wss(itv, 1, 0x8);
0479 } else {
0480 vi->wss_missing_cnt++;
0481 }
0482 }
0483 else {
0484 int mode = 0;
0485
0486 data.id = V4L2_SLICED_CAPTION_525;
0487 data.field = 0;
0488 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
0489 mode |= 1;
0490 cc.odd[0] = data.data[0];
0491 cc.odd[1] = data.data[1];
0492 }
0493 data.field = 1;
0494 if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
0495 mode |= 2;
0496 cc.even[0] = data.data[0];
0497 cc.even[1] = data.data[1];
0498 }
0499 if (mode) {
0500 vi->cc_missing_cnt = 0;
0501 ivtv_set_cc(itv, mode, &cc);
0502 } else if (vi->cc_missing_cnt == 4) {
0503 ivtv_set_cc(itv, 0, &cc);
0504 } else {
0505 vi->cc_missing_cnt++;
0506 }
0507 }
0508 return;
0509 }
0510
0511 if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
0512 ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
0513 }
0514
0515 if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
0516 if (vi->cc_payload_idx == 0) {
0517 clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
0518 ivtv_set_cc(itv, 3, &cc);
0519 }
0520 while (vi->cc_payload_idx) {
0521 cc = vi->cc_payload[0];
0522
0523 memmove(vi->cc_payload, vi->cc_payload + 1,
0524 sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
0525 vi->cc_payload_idx--;
0526 if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
0527 continue;
0528
0529 ivtv_set_cc(itv, 3, &cc);
0530 break;
0531 }
0532 }
0533
0534 if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
0535 ivtv_set_vps(itv, 1);
0536 }
0537 }