root/drivers/media/pci/ivtv/ivtv-vbi.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ivtv_set_vps
  2. ivtv_set_cc
  3. ivtv_set_wss
  4. odd_parity
  5. ivtv_write_vbi_line
  6. ivtv_write_vbi_cc_lines
  7. ivtv_write_vbi
  8. ivtv_write_vbi_from_user
  9. copy_vbi_data
  10. ivtv_convert_ivtv_vbi
  11. compress_raw_buf
  12. compress_sliced_buf
  13. ivtv_process_vbi_data
  14. ivtv_disable_cc
  15. ivtv_vbi_work_handler

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3     Vertical Blank Interval support functions
   4     Copyright (C) 2004-2007  Hans Verkuil <hverkuil@xs4all.nl>
   5 
   6  */
   7 
   8 #include "ivtv-driver.h"
   9 #include "ivtv-i2c.h"
  10 #include "ivtv-ioctl.h"
  11 #include "ivtv-queue.h"
  12 #include "ivtv-cards.h"
  13 #include "ivtv-vbi.h"
  14 
  15 static void ivtv_set_vps(struct ivtv *itv, int enabled)
  16 {
  17         struct v4l2_sliced_vbi_data data;
  18 
  19         if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
  20                 return;
  21         data.id = V4L2_SLICED_VPS;
  22         data.field = 0;
  23         data.line = enabled ? 16 : 0;
  24         data.data[2] = itv->vbi.vps_payload.data[0];
  25         data.data[8] = itv->vbi.vps_payload.data[1];
  26         data.data[9] = itv->vbi.vps_payload.data[2];
  27         data.data[10] = itv->vbi.vps_payload.data[3];
  28         data.data[11] = itv->vbi.vps_payload.data[4];
  29         ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
  30 }
  31 
  32 static void ivtv_set_cc(struct ivtv *itv, int mode, const struct vbi_cc *cc)
  33 {
  34         struct v4l2_sliced_vbi_data data;
  35 
  36         if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
  37                 return;
  38         data.id = V4L2_SLICED_CAPTION_525;
  39         data.field = 0;
  40         data.line = (mode & 1) ? 21 : 0;
  41         data.data[0] = cc->odd[0];
  42         data.data[1] = cc->odd[1];
  43         ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
  44         data.field = 1;
  45         data.line = (mode & 2) ? 21 : 0;
  46         data.data[0] = cc->even[0];
  47         data.data[1] = cc->even[1];
  48         ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
  49 }
  50 
  51 static void ivtv_set_wss(struct ivtv *itv, int enabled, int mode)
  52 {
  53         struct v4l2_sliced_vbi_data data;
  54 
  55         if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
  56                 return;
  57         /* When using a 50 Hz system, always turn on the
  58            wide screen signal with 4x3 ratio as the default.
  59            Turning this signal on and off can confuse certain
  60            TVs. As far as I can tell there is no reason not to
  61            transmit this signal. */
  62         if ((itv->std_out & V4L2_STD_625_50) && !enabled) {
  63                 enabled = 1;
  64                 mode = 0x08;  /* 4x3 full format */
  65         }
  66         data.id = V4L2_SLICED_WSS_625;
  67         data.field = 0;
  68         data.line = enabled ? 23 : 0;
  69         data.data[0] = mode & 0xff;
  70         data.data[1] = (mode >> 8) & 0xff;
  71         ivtv_call_hw(itv, IVTV_HW_SAA7127, vbi, s_vbi_data, &data);
  72 }
  73 
  74 static int odd_parity(u8 c)
  75 {
  76         c ^= (c >> 4);
  77         c ^= (c >> 2);
  78         c ^= (c >> 1);
  79 
  80         return c & 1;
  81 }
  82 
  83 static void ivtv_write_vbi_line(struct ivtv *itv,
  84                                 const struct v4l2_sliced_vbi_data *d,
  85                                 struct vbi_cc *cc, int *found_cc)
  86 {
  87         struct vbi_info *vi = &itv->vbi;
  88 
  89         if (d->id == V4L2_SLICED_CAPTION_525 && d->line == 21) {
  90                 if (d->field) {
  91                         cc->even[0] = d->data[0];
  92                         cc->even[1] = d->data[1];
  93                 } else {
  94                         cc->odd[0] = d->data[0];
  95                         cc->odd[1] = d->data[1];
  96                 }
  97                 *found_cc = 1;
  98         } else if (d->id == V4L2_SLICED_VPS && d->line == 16 && d->field == 0) {
  99                 struct vbi_vps vps;
 100 
 101                 vps.data[0] = d->data[2];
 102                 vps.data[1] = d->data[8];
 103                 vps.data[2] = d->data[9];
 104                 vps.data[3] = d->data[10];
 105                 vps.data[4] = d->data[11];
 106                 if (memcmp(&vps, &vi->vps_payload, sizeof(vps))) {
 107                         vi->vps_payload = vps;
 108                         set_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags);
 109                 }
 110         } else if (d->id == V4L2_SLICED_WSS_625 &&
 111                    d->line == 23 && d->field == 0) {
 112                 int wss = d->data[0] | d->data[1] << 8;
 113 
 114                 if (vi->wss_payload != wss) {
 115                         vi->wss_payload = wss;
 116                         set_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags);
 117                 }
 118         }
 119 }
 120 
 121 static void ivtv_write_vbi_cc_lines(struct ivtv *itv, const struct vbi_cc *cc)
 122 {
 123         struct vbi_info *vi = &itv->vbi;
 124 
 125         if (vi->cc_payload_idx < ARRAY_SIZE(vi->cc_payload)) {
 126                 memcpy(&vi->cc_payload[vi->cc_payload_idx], cc,
 127                        sizeof(struct vbi_cc));
 128                 vi->cc_payload_idx++;
 129                 set_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
 130         }
 131 }
 132 
 133 static void ivtv_write_vbi(struct ivtv *itv,
 134                            const struct v4l2_sliced_vbi_data *sliced,
 135                            size_t cnt)
 136 {
 137         struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
 138         int found_cc = 0;
 139         size_t i;
 140 
 141         for (i = 0; i < cnt; i++)
 142                 ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
 143 
 144         if (found_cc)
 145                 ivtv_write_vbi_cc_lines(itv, &cc);
 146 }
 147 
 148 ssize_t
 149 ivtv_write_vbi_from_user(struct ivtv *itv,
 150                          const struct v4l2_sliced_vbi_data __user *sliced,
 151                          size_t cnt)
 152 {
 153         struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
 154         int found_cc = 0;
 155         size_t i;
 156         struct v4l2_sliced_vbi_data d;
 157         ssize_t ret = cnt * sizeof(struct v4l2_sliced_vbi_data);
 158 
 159         for (i = 0; i < cnt; i++) {
 160                 if (copy_from_user(&d, sliced + i,
 161                                    sizeof(struct v4l2_sliced_vbi_data))) {
 162                         ret = -EFAULT;
 163                         break;
 164                 }
 165                 ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
 166         }
 167 
 168         if (found_cc)
 169                 ivtv_write_vbi_cc_lines(itv, &cc);
 170 
 171         return ret;
 172 }
 173 
 174 static void copy_vbi_data(struct ivtv *itv, int lines, u32 pts_stamp)
 175 {
 176         int line = 0;
 177         int i;
 178         u32 linemask[2] = { 0, 0 };
 179         unsigned short size;
 180         static const u8 mpeg_hdr_data[] = {
 181                 0x00, 0x00, 0x01, 0xba, 0x44, 0x00, 0x0c, 0x66,
 182                 0x24, 0x01, 0x01, 0xd1, 0xd3, 0xfa, 0xff, 0xff,
 183                 0x00, 0x00, 0x01, 0xbd, 0x00, 0x1a, 0x84, 0x80,
 184                 0x07, 0x21, 0x00, 0x5d, 0x63, 0xa7, 0xff, 0xff
 185         };
 186         const int sd = sizeof(mpeg_hdr_data);   /* start of vbi data */
 187         int idx = itv->vbi.frame % IVTV_VBI_FRAMES;
 188         u8 *dst = &itv->vbi.sliced_mpeg_data[idx][0];
 189 
 190         for (i = 0; i < lines; i++) {
 191                 int f, l;
 192 
 193                 if (itv->vbi.sliced_data[i].id == 0)
 194                         continue;
 195 
 196                 l = itv->vbi.sliced_data[i].line - 6;
 197                 f = itv->vbi.sliced_data[i].field;
 198                 if (f)
 199                         l += 18;
 200                 if (l < 32)
 201                         linemask[0] |= (1 << l);
 202                 else
 203                         linemask[1] |= (1 << (l - 32));
 204                 dst[sd + 12 + line * 43] =
 205                         ivtv_service2vbi(itv->vbi.sliced_data[i].id);
 206                 memcpy(dst + sd + 12 + line * 43 + 1, itv->vbi.sliced_data[i].data, 42);
 207                 line++;
 208         }
 209         memcpy(dst, mpeg_hdr_data, sizeof(mpeg_hdr_data));
 210         if (line == 36) {
 211                 /* All lines are used, so there is no space for the linemask
 212                    (the max size of the VBI data is 36 * 43 + 4 bytes).
 213                    So in this case we use the magic number 'ITV0'. */
 214                 memcpy(dst + sd, "ITV0", 4);
 215                 memmove(dst + sd + 4, dst + sd + 12, line * 43);
 216                 size = 4 + ((43 * line + 3) & ~3);
 217         } else {
 218                 memcpy(dst + sd, "itv0", 4);
 219                 cpu_to_le32s(&linemask[0]);
 220                 cpu_to_le32s(&linemask[1]);
 221                 memcpy(dst + sd + 4, &linemask[0], 8);
 222                 size = 12 + ((43 * line + 3) & ~3);
 223         }
 224         dst[4+16] = (size + 10) >> 8;
 225         dst[5+16] = (size + 10) & 0xff;
 226         dst[9+16] = 0x21 | ((pts_stamp >> 29) & 0x6);
 227         dst[10+16] = (pts_stamp >> 22) & 0xff;
 228         dst[11+16] = 1 | ((pts_stamp >> 14) & 0xff);
 229         dst[12+16] = (pts_stamp >> 7) & 0xff;
 230         dst[13+16] = 1 | ((pts_stamp & 0x7f) << 1);
 231         itv->vbi.sliced_mpeg_size[idx] = sd + size;
 232 }
 233 
 234 static int ivtv_convert_ivtv_vbi(struct ivtv *itv, u8 *p)
 235 {
 236         u32 linemask[2];
 237         int i, l, id2;
 238         int line = 0;
 239 
 240         if (!memcmp(p, "itv0", 4)) {
 241                 memcpy(linemask, p + 4, 8);
 242                 p += 12;
 243         } else if (!memcmp(p, "ITV0", 4)) {
 244                 linemask[0] = 0xffffffff;
 245                 linemask[1] = 0xf;
 246                 p += 4;
 247         } else {
 248                 /* unknown VBI data, convert to empty VBI frame */
 249                 linemask[0] = linemask[1] = 0;
 250         }
 251         for (i = 0; i < 36; i++) {
 252                 int err = 0;
 253 
 254                 if (i < 32 && !(linemask[0] & (1 << i)))
 255                         continue;
 256                 if (i >= 32 && !(linemask[1] & (1 << (i - 32))))
 257                         continue;
 258                 id2 = *p & 0xf;
 259                 switch (id2) {
 260                 case IVTV_SLICED_TYPE_TELETEXT_B:
 261                         id2 = V4L2_SLICED_TELETEXT_B;
 262                         break;
 263                 case IVTV_SLICED_TYPE_CAPTION_525:
 264                         id2 = V4L2_SLICED_CAPTION_525;
 265                         err = !odd_parity(p[1]) || !odd_parity(p[2]);
 266                         break;
 267                 case IVTV_SLICED_TYPE_VPS:
 268                         id2 = V4L2_SLICED_VPS;
 269                         break;
 270                 case IVTV_SLICED_TYPE_WSS_625:
 271                         id2 = V4L2_SLICED_WSS_625;
 272                         break;
 273                 default:
 274                         id2 = 0;
 275                         break;
 276                 }
 277                 if (err == 0) {
 278                         l = (i < 18) ? i + 6 : i - 18 + 6;
 279                         itv->vbi.sliced_dec_data[line].line = l;
 280                         itv->vbi.sliced_dec_data[line].field = i >= 18;
 281                         itv->vbi.sliced_dec_data[line].id = id2;
 282                         memcpy(itv->vbi.sliced_dec_data[line].data, p + 1, 42);
 283                         line++;
 284                 }
 285                 p += 43;
 286         }
 287         while (line < 36) {
 288                 itv->vbi.sliced_dec_data[line].id = 0;
 289                 itv->vbi.sliced_dec_data[line].line = 0;
 290                 itv->vbi.sliced_dec_data[line].field = 0;
 291                 line++;
 292         }
 293         return line * sizeof(itv->vbi.sliced_dec_data[0]);
 294 }
 295 
 296 /* Compress raw VBI format, removes leading SAV codes and surplus space after the
 297    field.
 298    Returns new compressed size. */
 299 static u32 compress_raw_buf(struct ivtv *itv, u8 *buf, u32 size)
 300 {
 301         u32 line_size = itv->vbi.raw_decoder_line_size;
 302         u32 lines = itv->vbi.count;
 303         u8 sav1 = itv->vbi.raw_decoder_sav_odd_field;
 304         u8 sav2 = itv->vbi.raw_decoder_sav_even_field;
 305         u8 *q = buf;
 306         u8 *p;
 307         int i;
 308 
 309         for (i = 0; i < lines; i++) {
 310                 p = buf + i * line_size;
 311 
 312                 /* Look for SAV code */
 313                 if (p[0] != 0xff || p[1] || p[2] || (p[3] != sav1 && p[3] != sav2)) {
 314                         break;
 315                 }
 316                 memcpy(q, p + 4, line_size - 4);
 317                 q += line_size - 4;
 318         }
 319         return lines * (line_size - 4);
 320 }
 321 
 322 
 323 /* Compressed VBI format, all found sliced blocks put next to one another
 324    Returns new compressed size */
 325 static u32 compress_sliced_buf(struct ivtv *itv, u32 line, u8 *buf, u32 size, u8 sav)
 326 {
 327         u32 line_size = itv->vbi.sliced_decoder_line_size;
 328         struct v4l2_decode_vbi_line vbi;
 329         int i;
 330         unsigned lines = 0;
 331 
 332         /* find the first valid line */
 333         for (i = 0; i < size; i++, buf++) {
 334                 if (buf[0] == 0xff && !buf[1] && !buf[2] && buf[3] == sav)
 335                         break;
 336         }
 337 
 338         size -= i;
 339         if (size < line_size) {
 340                 return line;
 341         }
 342         for (i = 0; i < size / line_size; i++) {
 343                 u8 *p = buf + i * line_size;
 344 
 345                 /* Look for SAV code  */
 346                 if (p[0] != 0xff || p[1] || p[2] || p[3] != sav) {
 347                         continue;
 348                 }
 349                 vbi.p = p + 4;
 350                 v4l2_subdev_call(itv->sd_video, vbi, decode_vbi_line, &vbi);
 351                 if (vbi.type && !(lines & (1 << vbi.line))) {
 352                         lines |= 1 << vbi.line;
 353                         itv->vbi.sliced_data[line].id = vbi.type;
 354                         itv->vbi.sliced_data[line].field = vbi.is_second_field;
 355                         itv->vbi.sliced_data[line].line = vbi.line;
 356                         memcpy(itv->vbi.sliced_data[line].data, vbi.p, 42);
 357                         line++;
 358                 }
 359         }
 360         return line;
 361 }
 362 
 363 void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
 364                            u64 pts_stamp, int streamtype)
 365 {
 366         u8 *p = (u8 *) buf->buf;
 367         u32 size = buf->bytesused;
 368         int y;
 369 
 370         /* Raw VBI data */
 371         if (streamtype == IVTV_ENC_STREAM_TYPE_VBI && ivtv_raw_vbi(itv)) {
 372                 u8 type;
 373 
 374                 ivtv_buf_swap(buf);
 375 
 376                 type = p[3];
 377 
 378                 size = buf->bytesused = compress_raw_buf(itv, p, size);
 379 
 380                 /* second field of the frame? */
 381                 if (type == itv->vbi.raw_decoder_sav_even_field) {
 382                         /* Dirty hack needed for backwards
 383                            compatibility of old VBI software. */
 384                         p += size - 4;
 385                         memcpy(p, &itv->vbi.frame, 4);
 386                         itv->vbi.frame++;
 387                 }
 388                 return;
 389         }
 390 
 391         /* Sliced VBI data with data insertion */
 392         if (streamtype == IVTV_ENC_STREAM_TYPE_VBI) {
 393                 int lines;
 394 
 395                 ivtv_buf_swap(buf);
 396 
 397                 /* first field */
 398                 lines = compress_sliced_buf(itv, 0, p, size / 2,
 399                         itv->vbi.sliced_decoder_sav_odd_field);
 400                 /* second field */
 401                 /* experimentation shows that the second half does not always begin
 402                    at the exact address. So start a bit earlier (hence 32). */
 403                 lines = compress_sliced_buf(itv, lines, p + size / 2 - 32, size / 2 + 32,
 404                         itv->vbi.sliced_decoder_sav_even_field);
 405                 /* always return at least one empty line */
 406                 if (lines == 0) {
 407                         itv->vbi.sliced_data[0].id = 0;
 408                         itv->vbi.sliced_data[0].line = 0;
 409                         itv->vbi.sliced_data[0].field = 0;
 410                         lines = 1;
 411                 }
 412                 buf->bytesused = size = lines * sizeof(itv->vbi.sliced_data[0]);
 413                 memcpy(p, &itv->vbi.sliced_data[0], size);
 414 
 415                 if (itv->vbi.insert_mpeg) {
 416                         copy_vbi_data(itv, lines, pts_stamp);
 417                 }
 418                 itv->vbi.frame++;
 419                 return;
 420         }
 421 
 422         /* Sliced VBI re-inserted from an MPEG stream */
 423         if (streamtype == IVTV_DEC_STREAM_TYPE_VBI) {
 424                 /* If the size is not 4-byte aligned, then the starting address
 425                    for the swapping is also shifted. After swapping the data the
 426                    real start address of the VBI data is exactly 4 bytes after the
 427                    original start. It's a bit fiddly but it works like a charm.
 428                    Non-4-byte alignment happens when an lseek is done on the input
 429                    mpeg file to a non-4-byte aligned position. So on arrival here
 430                    the VBI data is also non-4-byte aligned. */
 431                 int offset = size & 3;
 432                 int cnt;
 433 
 434                 if (offset) {
 435                         p += 4 - offset;
 436                 }
 437                 /* Swap Buffer */
 438                 for (y = 0; y < size; y += 4) {
 439                        swab32s((u32 *)(p + y));
 440                 }
 441 
 442                 cnt = ivtv_convert_ivtv_vbi(itv, p + offset);
 443                 memcpy(buf->buf, itv->vbi.sliced_dec_data, cnt);
 444                 buf->bytesused = cnt;
 445 
 446                 ivtv_write_vbi(itv, itv->vbi.sliced_dec_data,
 447                                cnt / sizeof(itv->vbi.sliced_dec_data[0]));
 448                 return;
 449         }
 450 }
 451 
 452 void ivtv_disable_cc(struct ivtv *itv)
 453 {
 454         struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
 455 
 456         clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
 457         ivtv_set_cc(itv, 0, &cc);
 458         itv->vbi.cc_payload_idx = 0;
 459 }
 460 
 461 
 462 void ivtv_vbi_work_handler(struct ivtv *itv)
 463 {
 464         struct vbi_info *vi = &itv->vbi;
 465         struct v4l2_sliced_vbi_data data;
 466         struct vbi_cc cc = { .odd = { 0x80, 0x80 }, .even = { 0x80, 0x80 } };
 467 
 468         /* Lock */
 469         if (itv->output_mode == OUT_PASSTHROUGH) {
 470                 if (itv->is_50hz) {
 471                         data.id = V4L2_SLICED_WSS_625;
 472                         data.field = 0;
 473 
 474                         if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
 475                                 ivtv_set_wss(itv, 1, data.data[0] & 0xf);
 476                                 vi->wss_missing_cnt = 0;
 477                         } else if (vi->wss_missing_cnt == 4) {
 478                                 ivtv_set_wss(itv, 1, 0x8);  /* 4x3 full format */
 479                         } else {
 480                                 vi->wss_missing_cnt++;
 481                         }
 482                 }
 483                 else {
 484                         int mode = 0;
 485 
 486                         data.id = V4L2_SLICED_CAPTION_525;
 487                         data.field = 0;
 488                         if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
 489                                 mode |= 1;
 490                                 cc.odd[0] = data.data[0];
 491                                 cc.odd[1] = data.data[1];
 492                         }
 493                         data.field = 1;
 494                         if (v4l2_subdev_call(itv->sd_video, vbi, g_vbi_data, &data) == 0) {
 495                                 mode |= 2;
 496                                 cc.even[0] = data.data[0];
 497                                 cc.even[1] = data.data[1];
 498                         }
 499                         if (mode) {
 500                                 vi->cc_missing_cnt = 0;
 501                                 ivtv_set_cc(itv, mode, &cc);
 502                         } else if (vi->cc_missing_cnt == 4) {
 503                                 ivtv_set_cc(itv, 0, &cc);
 504                         } else {
 505                                 vi->cc_missing_cnt++;
 506                         }
 507                 }
 508                 return;
 509         }
 510 
 511         if (test_and_clear_bit(IVTV_F_I_UPDATE_WSS, &itv->i_flags)) {
 512                 ivtv_set_wss(itv, 1, vi->wss_payload & 0xf);
 513         }
 514 
 515         if (test_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags)) {
 516                 if (vi->cc_payload_idx == 0) {
 517                         clear_bit(IVTV_F_I_UPDATE_CC, &itv->i_flags);
 518                         ivtv_set_cc(itv, 3, &cc);
 519                 }
 520                 while (vi->cc_payload_idx) {
 521                         cc = vi->cc_payload[0];
 522 
 523                         memmove(vi->cc_payload, vi->cc_payload + 1,
 524                                         sizeof(vi->cc_payload) - sizeof(vi->cc_payload[0]));
 525                         vi->cc_payload_idx--;
 526                         if (vi->cc_payload_idx && cc.odd[0] == 0x80 && cc.odd[1] == 0x80)
 527                                 continue;
 528 
 529                         ivtv_set_cc(itv, 3, &cc);
 530                         break;
 531                 }
 532         }
 533 
 534         if (test_and_clear_bit(IVTV_F_I_UPDATE_VPS, &itv->i_flags)) {
 535                 ivtv_set_vps(itv, 1);
 536         }
 537 }

/* [<][>][^][v][top][bottom][index][help] */