Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003     Vertical Blank Interval support functions
0004     Copyright (C) 2004-2007  Hans Verkuil <hverkuil@xs4all.nl>
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     /* When using a 50 Hz system, always turn on the
0058        wide screen signal with 4x3 ratio as the default.
0059        Turning this signal on and off can confuse certain
0060        TVs. As far as I can tell there is no reason not to
0061        transmit this signal. */
0062     if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
0063         enabled = 1;
0064         mode = 0x08;  /* 4x3 full format */
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);   /* start of vbi 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         /* All lines are used, so there is no space for the linemask
0212            (the max size of the VBI data is 36 * 43 + 4 bytes).
0213            So in this case we use the magic number 'ITV0'. */
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         /* unknown VBI data, convert to empty VBI frame */
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 /* Compress raw VBI format, removes leading SAV codes and surplus space after the
0297    field.
0298    Returns new compressed size. */
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         /* Look for SAV code */
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 /* Compressed VBI format, all found sliced blocks put next to one another
0324    Returns new compressed size */
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     /* find the first valid line */
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         /* Look for SAV code  */
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     /* Raw VBI data */
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         /* second field of the frame? */
0381         if (type == itv->vbi.raw_decoder_sav_even_field) {
0382             /* Dirty hack needed for backwards
0383                compatibility of old VBI software. */
0384             p += size - 4;
0385             memcpy(p, &itv->vbi.frame, 4);
0386             itv->vbi.frame++;
0387         }
0388         return;
0389     }
0390 
0391     /* Sliced VBI data with data insertion */
0392     if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
0393         int lines;
0394 
0395         ivtv_buf_swap(buf);
0396 
0397         /* first field */
0398         lines = compress_sliced_buf(itv, 0, p, size / 2,
0399             itv->vbi.sliced_decoder_sav_odd_field);
0400         /* second field */
0401         /* experimentation shows that the second half does not always begin
0402            at the exact address. So start a bit earlier (hence 32). */
0403         lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
0404             itv->vbi.sliced_decoder_sav_even_field);
0405         /* always return at least one empty line */
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     /* Sliced VBI re-inserted from an MPEG stream */
0423     if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
0424         /* If the size is not 4-byte aligned, then the starting address
0425            for the swapping is also shifted. After swapping the data the
0426            real start address of the VBI data is exactly 4 bytes after the
0427            original start. It's a bit fiddly but it works like a charm.
0428            Non-4-byte alignment happens when an lseek is done on the input
0429            mpeg file to a non-4-byte aligned position. So on arrival here
0430            the VBI data is also non-4-byte aligned. */
0431         int offset = size & 3;
0432         int cnt;
0433 
0434         if (offset) {
0435             p += 4 - offset;
0436         }
0437         /* Swap Buffer */
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     /* Lock */
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);  /* 4x3 full format */
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 }