linux/drivers/media/pci/cx18/cx18-av-vbi.c
<<
>>
Prefs
   1/*
   2 *  cx18 ADEC VBI functions
   3 *
   4 *  Derived from cx25840-vbi.c
   5 *
   6 *  Copyright (C) 2007  Hans Verkuil <hverkuil@xs4all.nl>
   7 *
   8 *  This program is free software; you can redistribute it and/or
   9 *  modify it under the terms of the GNU General Public License
  10 *  as published by the Free Software Foundation; either version 2
  11 *  of the License, or (at your option) any later version.
  12 *
  13 *  This program is distributed in the hope that it will be useful,
  14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 *  GNU General Public License for more details.
  17 *
  18 *  You should have received a copy of the GNU General Public License
  19 *  along with this program; if not, write to the Free Software
  20 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  21 *  02110-1301, USA.
  22 */
  23
  24
  25#include "cx18-driver.h"
  26
  27/*
  28 * For sliced VBI output, we set up to use VIP-1.1, 8-bit mode,
  29 * NN counts 1 byte Dwords, an IDID with the VBI line # in it.
  30 * Thus, according to the VIP-2 Spec, our VBI ancillary data lines
  31 * (should!) look like:
  32 *      4 byte EAV code:          0xff 0x00 0x00 0xRP
  33 *      unknown number of possible idle bytes
  34 *      3 byte Anc data preamble: 0x00 0xff 0xff
  35 *      1 byte data identifier:   ne010iii (parity bits, 010, DID bits)
  36 *      1 byte secondary data id: nessssss (parity bits, SDID bits)
  37 *      1 byte data word count:   necccccc (parity bits, NN Dword count)
  38 *      2 byte Internal DID:      VBI-line-# 0x80
  39 *      NN data bytes
  40 *      1 byte checksum
  41 *      Fill bytes needed to fil out to 4*NN bytes of payload
  42 *
  43 * The RP codes for EAVs when in VIP-1.1 mode, not in raw mode, &
  44 * in the vertical blanking interval are:
  45 *      0xb0 (Task         0 VerticalBlank HorizontalBlank 0 0 0 0)
  46 *      0xf0 (Task EvenField VerticalBlank HorizontalBlank 0 0 0 0)
  47 *
  48 * Since the V bit is only allowed to toggle in the EAV RP code, just
  49 * before the first active region line and for active lines, they are:
  50 *      0x90 (Task         0 0 HorizontalBlank 0 0 0 0)
  51 *      0xd0 (Task EvenField 0 HorizontalBlank 0 0 0 0)
  52 *
  53 * The user application DID bytes we care about are:
  54 *      0x91 (1 0 010        0 !ActiveLine AncDataPresent)
  55 *      0x55 (0 1 010 2ndField !ActiveLine AncDataPresent)
  56 *
  57 */
  58static const u8 sliced_vbi_did[2] = { 0x91, 0x55 };
  59
  60struct vbi_anc_data {
  61        /* u8 eav[4]; */
  62        /* u8 idle[]; Variable number of idle bytes */
  63        u8 preamble[3];
  64        u8 did;
  65        u8 sdid;
  66        u8 data_count;
  67        u8 idid[2];
  68        u8 payload[1]; /* data_count of payload */
  69        /* u8 checksum; */
  70        /* u8 fill[]; Variable number of fill bytes */
  71};
  72
  73static int odd_parity(u8 c)
  74{
  75        c ^= (c >> 4);
  76        c ^= (c >> 2);
  77        c ^= (c >> 1);
  78
  79        return c & 1;
  80}
  81
  82static int decode_vps(u8 *dst, u8 *p)
  83{
  84        static const u8 biphase_tbl[] = {
  85                0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
  86                0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
  87                0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
  88                0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
  89                0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
  90                0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
  91                0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
  92                0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
  93                0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
  94                0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
  95                0xc3, 0x4b, 0x43, 0xc3, 0x87, 0x0f, 0x07, 0x87,
  96                0x83, 0x0b, 0x03, 0x83, 0xc3, 0x4b, 0x43, 0xc3,
  97                0xc1, 0x49, 0x41, 0xc1, 0x85, 0x0d, 0x05, 0x85,
  98                0x81, 0x09, 0x01, 0x81, 0xc1, 0x49, 0x41, 0xc1,
  99                0xe1, 0x69, 0x61, 0xe1, 0xa5, 0x2d, 0x25, 0xa5,
 100                0xa1, 0x29, 0x21, 0xa1, 0xe1, 0x69, 0x61, 0xe1,
 101                0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
 102                0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
 103                0xc2, 0x4a, 0x42, 0xc2, 0x86, 0x0e, 0x06, 0x86,
 104                0x82, 0x0a, 0x02, 0x82, 0xc2, 0x4a, 0x42, 0xc2,
 105                0xc0, 0x48, 0x40, 0xc0, 0x84, 0x0c, 0x04, 0x84,
 106                0x80, 0x08, 0x00, 0x80, 0xc0, 0x48, 0x40, 0xc0,
 107                0xe0, 0x68, 0x60, 0xe0, 0xa4, 0x2c, 0x24, 0xa4,
 108                0xa0, 0x28, 0x20, 0xa0, 0xe0, 0x68, 0x60, 0xe0,
 109                0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
 110                0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
 111                0xd2, 0x5a, 0x52, 0xd2, 0x96, 0x1e, 0x16, 0x96,
 112                0x92, 0x1a, 0x12, 0x92, 0xd2, 0x5a, 0x52, 0xd2,
 113                0xd0, 0x58, 0x50, 0xd0, 0x94, 0x1c, 0x14, 0x94,
 114                0x90, 0x18, 0x10, 0x90, 0xd0, 0x58, 0x50, 0xd0,
 115                0xf0, 0x78, 0x70, 0xf0, 0xb4, 0x3c, 0x34, 0xb4,
 116                0xb0, 0x38, 0x30, 0xb0, 0xf0, 0x78, 0x70, 0xf0,
 117        };
 118
 119        u8 c, err = 0;
 120        int i;
 121
 122        for (i = 0; i < 2 * 13; i += 2) {
 123                err |= biphase_tbl[p[i]] | biphase_tbl[p[i + 1]];
 124                c = (biphase_tbl[p[i + 1]] & 0xf) |
 125                    ((biphase_tbl[p[i]] & 0xf) << 4);
 126                dst[i / 2] = c;
 127        }
 128
 129        return err & 0xf0;
 130}
 131
 132int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
 133{
 134        struct cx18 *cx = v4l2_get_subdevdata(sd);
 135        struct cx18_av_state *state = &cx->av_state;
 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;
 145
 146        memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
 147        svbi->service_set = 0;
 148
 149        /* we're done if raw VBI is active */
 150        if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
 151                return 0;
 152
 153        if (is_pal) {
 154                for (i = 7; i <= 23; i++) {
 155                        u8 v = cx18_av_read(cx, 0x424 + i - 7);
 156
 157                        svbi->service_lines[0][i] = lcr2vbi[v >> 4];
 158                        svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
 159                        svbi->service_set |= svbi->service_lines[0][i] |
 160                                svbi->service_lines[1][i];
 161                }
 162        } else {
 163                for (i = 10; i <= 21; i++) {
 164                        u8 v = cx18_av_read(cx, 0x424 + i - 10);
 165
 166                        svbi->service_lines[0][i] = lcr2vbi[v >> 4];
 167                        svbi->service_lines[1][i] = lcr2vbi[v & 0xf];
 168                        svbi->service_set |= svbi->service_lines[0][i] |
 169                                svbi->service_lines[1][i];
 170                }
 171        }
 172        return 0;
 173}
 174
 175int cx18_av_s_raw_fmt(struct v4l2_subdev *sd, struct v4l2_vbi_format *fmt)
 176{
 177        struct cx18 *cx = v4l2_get_subdevdata(sd);
 178        struct cx18_av_state *state = &cx->av_state;
 179
 180        /* Setup standard */
 181        cx18_av_std_setup(cx);
 182
 183        /* VBI Offset */
 184        cx18_av_write(cx, 0x47f, state->slicer_line_delay);
 185        cx18_av_write(cx, 0x404, 0x2e);
 186        return 0;
 187}
 188
 189int cx18_av_s_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *svbi)
 190{
 191        struct cx18 *cx = v4l2_get_subdevdata(sd);
 192        struct cx18_av_state *state = &cx->av_state;
 193        int is_pal = !(state->std & V4L2_STD_525_60);
 194        int i, x;
 195        u8 lcr[24];
 196
 197        for (x = 0; x <= 23; x++)
 198                lcr[x] = 0x00;
 199
 200        /* Setup standard */
 201        cx18_av_std_setup(cx);
 202
 203        /* Sliced VBI */
 204        cx18_av_write(cx, 0x404, 0x32); /* Ancillary data */
 205        cx18_av_write(cx, 0x406, 0x13);
 206        cx18_av_write(cx, 0x47f, state->slicer_line_delay);
 207
 208        /* Force impossible lines to 0 */
 209        if (is_pal) {
 210                for (i = 0; i <= 6; i++)
 211                        svbi->service_lines[0][i] =
 212                                svbi->service_lines[1][i] = 0;
 213        } else {
 214                for (i = 0; i <= 9; i++)
 215                        svbi->service_lines[0][i] =
 216                                svbi->service_lines[1][i] = 0;
 217
 218                for (i = 22; i <= 23; i++)
 219                        svbi->service_lines[0][i] =
 220                                svbi->service_lines[1][i] = 0;
 221        }
 222
 223        /* Build register values for requested service lines */
 224        for (i = 7; i <= 23; i++) {
 225                for (x = 0; x <= 1; x++) {
 226                        switch (svbi->service_lines[1-x][i]) {
 227                        case V4L2_SLICED_TELETEXT_B:
 228                                lcr[i] |= 1 << (4 * x);
 229                                break;
 230                        case V4L2_SLICED_WSS_625:
 231                                lcr[i] |= 4 << (4 * x);
 232                                break;
 233                        case V4L2_SLICED_CAPTION_525:
 234                                lcr[i] |= 6 << (4 * x);
 235                                break;
 236                        case V4L2_SLICED_VPS:
 237                                lcr[i] |= 9 << (4 * x);
 238                                break;
 239                        }
 240                }
 241        }
 242
 243        if (is_pal) {
 244                for (x = 1, i = 0x424; i <= 0x434; i++, x++)
 245                        cx18_av_write(cx, i, lcr[6 + x]);
 246        } else {
 247                for (x = 1, i = 0x424; i <= 0x430; i++, x++)
 248                        cx18_av_write(cx, i, lcr[9 + x]);
 249                for (i = 0x431; i <= 0x434; i++)
 250                        cx18_av_write(cx, i, 0);
 251        }
 252
 253        cx18_av_write(cx, 0x43c, 0x16);
 254        /* Should match vblank set in cx18_av_std_setup() */
 255        cx18_av_write(cx, 0x474, is_pal ? 38 : 26);
 256        return 0;
 257}
 258
 259int cx18_av_decode_vbi_line(struct v4l2_subdev *sd,
 260                                   struct v4l2_decode_vbi_line *vbi)
 261{
 262        struct cx18 *cx = v4l2_get_subdevdata(sd);
 263        struct cx18_av_state *state = &cx->av_state;
 264        struct vbi_anc_data *anc = (struct vbi_anc_data *)vbi->p;
 265        u8 *p;
 266        int did, sdid, l, err = 0;
 267
 268        /*
 269         * Check for the ancillary data header for sliced VBI
 270         */
 271        if (anc->preamble[0] ||
 272                        anc->preamble[1] != 0xff || anc->preamble[2] != 0xff ||
 273                        (anc->did != sliced_vbi_did[0] &&
 274                         anc->did != sliced_vbi_did[1])) {
 275                vbi->line = vbi->type = 0;
 276                return 0;
 277        }
 278
 279        did = anc->did;
 280        sdid = anc->sdid & 0xf;
 281        l = anc->idid[0] & 0x3f;
 282        l += state->slicer_line_offset;
 283        p = anc->payload;
 284
 285        /* Decode the SDID set by the slicer */
 286        switch (sdid) {
 287        case 1:
 288                sdid = V4L2_SLICED_TELETEXT_B;
 289                break;
 290        case 4:
 291                sdid = V4L2_SLICED_WSS_625;
 292                break;
 293        case 6:
 294                sdid = V4L2_SLICED_CAPTION_525;
 295                err = !odd_parity(p[0]) || !odd_parity(p[1]);
 296                break;
 297        case 9:
 298                sdid = V4L2_SLICED_VPS;
 299                if (decode_vps(p, p) != 0)
 300                        err = 1;
 301                break;
 302        default:
 303                sdid = 0;
 304                err = 1;
 305                break;
 306        }
 307
 308        vbi->type = err ? 0 : sdid;
 309        vbi->line = err ? 0 : l;
 310        vbi->is_second_field = err ? 0 : (did == sliced_vbi_did[1]);
 311        vbi->p = p;
 312        return 0;
 313}
 314