linux/drivers/media/video/saa5249.c
<<
>>
Prefs
   1/*
   2 * Modified in order to keep it compatible both with new and old videotext IOCTLs by
   3 * Michael Geng <linux@MichaelGeng.de>
   4 *
   5 *      Cleaned up to use existing videodev interface and allow the idea
   6 *      of multiple teletext decoders on the video4linux iface. Changed i2c
   7 *      to cover addressing clashes on device busses. It's also rebuilt so
   8 *      you can add arbitary multiple teletext devices to Linux video4linux
   9 *      now (well 32 anyway).
  10 *
  11 *      Alan Cox <alan@lxorguk.ukuu.org.uk>
  12 *
  13 *      The original driver was heavily modified to match the i2c interface
  14 *      It was truncated to use the WinTV boards, too.
  15 *
  16 *      Copyright (c) 1998 Richard Guenther <richard.guenther@student.uni-tuebingen.de>
  17 *
  18 *      Derived From
  19 *
  20 * vtx.c:
  21 * This is a loadable character-device-driver for videotext-interfaces
  22 * (aka teletext). Please check the Makefile/README for a list of supported
  23 * interfaces.
  24 *
  25 * Copyright (c) 1994-97 Martin Buck  <martin-2.buck@student.uni-ulm.de>
  26 *
  27 *
  28 * This program is free software; you can redistribute it and/or modify
  29 * it under the terms of the GNU General Public License as published by
  30 * the Free Software Foundation; either version 2 of the License, or
  31 * (at your option) any later version.
  32 *
  33 * This program is distributed in the hope that it will be useful,
  34 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  35 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  36 * GNU General Public License for more details.
  37 *
  38 * You should have received a copy of the GNU General Public License
  39 * along with this program; if not, write to the Free Software
  40 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  41 * USA.
  42 */
  43
  44#include <linux/module.h>
  45#include <linux/kernel.h>
  46#include <linux/mm.h>
  47#include <linux/init.h>
  48#include <linux/i2c.h>
  49#include <linux/mutex.h>
  50#include <linux/delay.h>
  51#include <linux/videotext.h>
  52#include <linux/videodev2.h>
  53#include <media/v4l2-device.h>
  54#include <media/v4l2-chip-ident.h>
  55#include <media/v4l2-ioctl.h>
  56#include <media/v4l2-i2c-drv.h>
  57
  58MODULE_AUTHOR("Michael Geng <linux@MichaelGeng.de>");
  59MODULE_DESCRIPTION("Philips SAA5249 Teletext decoder driver");
  60MODULE_LICENSE("GPL");
  61
  62
  63#define VTX_VER_MAJ 1
  64#define VTX_VER_MIN 8
  65
  66
  67#define NUM_DAUS 4
  68#define NUM_BUFS 8
  69
  70static const int disp_modes[8][3] =
  71{
  72        { 0x46, 0x03, 0x03 },   /* DISPOFF */
  73        { 0x46, 0xcc, 0xcc },   /* DISPNORM */
  74        { 0x44, 0x0f, 0x0f },   /* DISPTRANS */
  75        { 0x46, 0xcc, 0x46 },   /* DISPINS */
  76        { 0x44, 0x03, 0x03 },   /* DISPOFF, interlaced */
  77        { 0x44, 0xcc, 0xcc },   /* DISPNORM, interlaced */
  78        { 0x44, 0x0f, 0x0f },   /* DISPTRANS, interlaced */
  79        { 0x44, 0xcc, 0x46 }    /* DISPINS, interlaced */
  80};
  81
  82
  83
  84#define PAGE_WAIT    msecs_to_jiffies(300)      /* Time between requesting page and */
  85                                                /* checking status bits */
  86#define PGBUF_EXPIRE msecs_to_jiffies(15000)    /* Time to wait before retransmitting */
  87                                                /* page regardless of infobits */
  88typedef struct {
  89        u8 pgbuf[VTX_VIRTUALSIZE];              /* Page-buffer */
  90        u8 laststat[10];                        /* Last value of infobits for DAU */
  91        u8 sregs[7];                            /* Page-request registers */
  92        unsigned long expire;                   /* Time when page will be expired */
  93        unsigned clrfound : 1;                  /* VTXIOCCLRFOUND has been called */
  94        unsigned stopped : 1;                   /* VTXIOCSTOPDAU has been called */
  95} vdau_t;
  96
  97struct saa5249_device
  98{
  99        struct v4l2_subdev sd;
 100        struct video_device *vdev;
 101        vdau_t vdau[NUM_DAUS];                  /* Data for virtual DAUs (the 5249 only has one */
 102                                                /* real DAU, so we have to simulate some more) */
 103        int vtx_use_count;
 104        int is_searching[NUM_DAUS];
 105        int disp_mode;
 106        int virtual_mode;
 107        unsigned long in_use;
 108        struct mutex lock;
 109};
 110
 111static inline struct saa5249_device *to_dev(struct v4l2_subdev *sd)
 112{
 113        return container_of(sd, struct saa5249_device, sd);
 114}
 115
 116
 117#define CCTWR 34                /* I²C write/read-address of vtx-chip */
 118#define CCTRD 35
 119#define NOACK_REPEAT 10         /* Retry access this many times on failure */
 120#define CLEAR_DELAY   msecs_to_jiffies(50)      /* Time required to clear a page */
 121#define READY_TIMEOUT msecs_to_jiffies(30)      /* Time to wait for ready signal of I2C-bus interface */
 122#define INIT_DELAY 500          /* Time in usec to wait at initialization of CEA interface */
 123#define START_DELAY 10          /* Time in usec to wait before starting write-cycle (CEA) */
 124
 125#define VTX_DEV_MINOR 0
 126
 127static struct video_device saa_template;        /* Declared near bottom */
 128
 129/*
 130 *      Wait the given number of jiffies (10ms). This calls the scheduler, so the actual
 131 *      delay may be longer.
 132 */
 133
 134static void jdelay(unsigned long delay)
 135{
 136        sigset_t oldblocked = current->blocked;
 137
 138        spin_lock_irq(&current->sighand->siglock);
 139        sigfillset(&current->blocked);
 140        recalc_sigpending();
 141        spin_unlock_irq(&current->sighand->siglock);
 142        msleep_interruptible(jiffies_to_msecs(delay));
 143
 144        spin_lock_irq(&current->sighand->siglock);
 145        current->blocked = oldblocked;
 146        recalc_sigpending();
 147        spin_unlock_irq(&current->sighand->siglock);
 148}
 149
 150
 151/*
 152 *      I2C interfaces
 153 */
 154
 155static int i2c_sendbuf(struct saa5249_device *t, int reg, int count, u8 *data)
 156{
 157        struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
 158        char buf[64];
 159
 160        buf[0] = reg;
 161        memcpy(buf+1, data, count);
 162
 163        if (i2c_master_send(client, buf, count + 1) == count + 1)
 164                return 0;
 165        return -1;
 166}
 167
 168static int i2c_senddata(struct saa5249_device *t, ...)
 169{
 170        unsigned char buf[64];
 171        int v;
 172        int ct = 0;
 173        va_list argp;
 174        va_start(argp,t);
 175
 176        while ((v = va_arg(argp, int)) != -1)
 177                buf[ct++] = v;
 178
 179        va_end(argp);
 180        return i2c_sendbuf(t, buf[0], ct-1, buf+1);
 181}
 182
 183/* Get count number of bytes from I²C-device at address adr, store them in buf. Start & stop
 184 * handshaking is done by this routine, ack will be sent after the last byte to inhibit further
 185 * sending of data. If uaccess is 'true', data is written to user-space with put_user.
 186 * Returns -1 if I²C-device didn't send acknowledge, 0 otherwise
 187 */
 188
 189static int i2c_getdata(struct saa5249_device *t, int count, u8 *buf)
 190{
 191        struct i2c_client *client = v4l2_get_subdevdata(&t->sd);
 192
 193        if (i2c_master_recv(client, buf, count) != count)
 194                return -1;
 195        return 0;
 196}
 197
 198
 199/*
 200 *      Standard character-device-driver functions
 201 */
 202
 203static long do_saa5249_ioctl(struct file *file, unsigned int cmd, void *arg)
 204{
 205        static int virtual_mode = false;
 206        struct saa5249_device *t = video_drvdata(file);
 207
 208        switch (cmd) {
 209        case VTXIOCGETINFO:
 210        {
 211                vtx_info_t *info = arg;
 212                info->version_major = VTX_VER_MAJ;
 213                info->version_minor = VTX_VER_MIN;
 214                info->numpages = NUM_DAUS;
 215                /*info->cct_type = CCT_TYPE;*/
 216                return 0;
 217        }
 218
 219        case VTXIOCCLRPAGE:
 220        {
 221                vtx_pagereq_t *req = arg;
 222
 223                if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 224                        return -EINVAL;
 225                memset(t->vdau[req->pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
 226                t->vdau[req->pgbuf].clrfound = true;
 227                return 0;
 228        }
 229
 230        case VTXIOCCLRFOUND:
 231        {
 232                vtx_pagereq_t *req = arg;
 233
 234                if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 235                        return -EINVAL;
 236                t->vdau[req->pgbuf].clrfound = true;
 237                return 0;
 238        }
 239
 240        case VTXIOCPAGEREQ:
 241        {
 242                vtx_pagereq_t *req = arg;
 243                if (!(req->pagemask & PGMASK_PAGE))
 244                        req->page = 0;
 245                if (!(req->pagemask & PGMASK_HOUR))
 246                        req->hour = 0;
 247                if (!(req->pagemask & PGMASK_MINUTE))
 248                        req->minute = 0;
 249                if (req->page < 0 || req->page > 0x8ff) /* 7FF ?? */
 250                        return -EINVAL;
 251                req->page &= 0x7ff;
 252                if (req->hour < 0 || req->hour > 0x3f || req->minute < 0 || req->minute > 0x7f ||
 253                        req->pagemask < 0 || req->pagemask >= PGMASK_MAX || req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 254                        return -EINVAL;
 255                t->vdau[req->pgbuf].sregs[0] = (req->pagemask & PG_HUND ? 0x10 : 0) | (req->page / 0x100);
 256                t->vdau[req->pgbuf].sregs[1] = (req->pagemask & PG_TEN ? 0x10 : 0) | ((req->page / 0x10) & 0xf);
 257                t->vdau[req->pgbuf].sregs[2] = (req->pagemask & PG_UNIT ? 0x10 : 0) | (req->page & 0xf);
 258                t->vdau[req->pgbuf].sregs[3] = (req->pagemask & HR_TEN ? 0x10 : 0) | (req->hour / 0x10);
 259                t->vdau[req->pgbuf].sregs[4] = (req->pagemask & HR_UNIT ? 0x10 : 0) | (req->hour & 0xf);
 260                t->vdau[req->pgbuf].sregs[5] = (req->pagemask & MIN_TEN ? 0x10 : 0) | (req->minute / 0x10);
 261                t->vdau[req->pgbuf].sregs[6] = (req->pagemask & MIN_UNIT ? 0x10 : 0) | (req->minute & 0xf);
 262                t->vdau[req->pgbuf].stopped = false;
 263                t->vdau[req->pgbuf].clrfound = true;
 264                t->is_searching[req->pgbuf] = true;
 265                return 0;
 266        }
 267
 268        case VTXIOCGETSTAT:
 269        {
 270                vtx_pagereq_t *req = arg;
 271                u8 infobits[10];
 272                vtx_pageinfo_t info;
 273                int a;
 274
 275                if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 276                        return -EINVAL;
 277                if (!t->vdau[req->pgbuf].stopped) {
 278                        if (i2c_senddata(t, 2, 0, -1) ||
 279                                i2c_sendbuf(t, 3, sizeof(t->vdau[0].sregs), t->vdau[req->pgbuf].sregs) ||
 280                                i2c_senddata(t, 8, 0, 25, 0, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', -1) ||
 281                                i2c_senddata(t, 2, 0, t->vdau[req->pgbuf].sregs[0] | 8, -1) ||
 282                                i2c_senddata(t, 8, 0, 25, 0, -1))
 283                                return -EIO;
 284                        jdelay(PAGE_WAIT);
 285                        if (i2c_getdata(t, 10, infobits))
 286                                return -EIO;
 287
 288                        if (!(infobits[8] & 0x10) && !(infobits[7] & 0xf0) &&   /* check FOUND-bit */
 289                                (memcmp(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits)) ||
 290                                time_after_eq(jiffies, t->vdau[req->pgbuf].expire)))
 291                        {               /* check if new page arrived */
 292                                if (i2c_senddata(t, 8, 0, 0, 0, -1) ||
 293                                        i2c_getdata(t, VTX_PAGESIZE, t->vdau[req->pgbuf].pgbuf))
 294                                        return -EIO;
 295                                t->vdau[req->pgbuf].expire = jiffies + PGBUF_EXPIRE;
 296                                memset(t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE, ' ', VTX_VIRTUALSIZE - VTX_PAGESIZE);
 297                                if (t->virtual_mode) {
 298                                        /* Packet X/24 */
 299                                        if (i2c_senddata(t, 8, 0, 0x20, 0, -1) ||
 300                                                i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 20 * 40))
 301                                                return -EIO;
 302                                        /* Packet X/27/0 */
 303                                        if (i2c_senddata(t, 8, 0, 0x21, 0, -1) ||
 304                                                i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 16 * 40))
 305                                                return -EIO;
 306                                        /* Packet 8/30/0...8/30/15
 307                                         * FIXME: AFAIK, the 5249 does hamming-decoding for some bytes in packet 8/30,
 308                                         *        so we should undo this here.
 309                                         */
 310                                        if (i2c_senddata(t, 8, 0, 0x22, 0, -1) ||
 311                                                i2c_getdata(t, 40, t->vdau[req->pgbuf].pgbuf + VTX_PAGESIZE + 23 * 40))
 312                                                return -EIO;
 313                                }
 314                                t->vdau[req->pgbuf].clrfound = false;
 315                                memcpy(t->vdau[req->pgbuf].laststat, infobits, sizeof(infobits));
 316                        } else {
 317                                memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
 318                        }
 319                } else {
 320                        memcpy(infobits, t->vdau[req->pgbuf].laststat, sizeof(infobits));
 321                }
 322
 323                info.pagenum = ((infobits[8] << 8) & 0x700) | ((infobits[1] << 4) & 0xf0) | (infobits[0] & 0x0f);
 324                if (info.pagenum < 0x100)
 325                        info.pagenum += 0x800;
 326                info.hour = ((infobits[5] << 4) & 0x30) | (infobits[4] & 0x0f);
 327                info.minute = ((infobits[3] << 4) & 0x70) | (infobits[2] & 0x0f);
 328                info.charset = ((infobits[7] >> 1) & 7);
 329                info.delete = !!(infobits[3] & 8);
 330                info.headline = !!(infobits[5] & 4);
 331                info.subtitle = !!(infobits[5] & 8);
 332                info.supp_header = !!(infobits[6] & 1);
 333                info.update = !!(infobits[6] & 2);
 334                info.inter_seq = !!(infobits[6] & 4);
 335                info.dis_disp = !!(infobits[6] & 8);
 336                info.serial = !!(infobits[7] & 1);
 337                info.notfound = !!(infobits[8] & 0x10);
 338                info.pblf = !!(infobits[9] & 0x20);
 339                info.hamming = 0;
 340                for (a = 0; a <= 7; a++) {
 341                        if (infobits[a] & 0xf0) {
 342                                info.hamming = 1;
 343                                break;
 344                        }
 345                }
 346                if (t->vdau[req->pgbuf].clrfound)
 347                        info.notfound = 1;
 348                if (copy_to_user(req->buffer, &info, sizeof(vtx_pageinfo_t)))
 349                        return -EFAULT;
 350                if (!info.hamming && !info.notfound)
 351                        t->is_searching[req->pgbuf] = false;
 352                return 0;
 353        }
 354
 355        case VTXIOCGETPAGE:
 356        {
 357                vtx_pagereq_t *req = arg;
 358                int start, end;
 359
 360                if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS || req->start < 0 ||
 361                        req->start > req->end || req->end >= (virtual_mode ? VTX_VIRTUALSIZE : VTX_PAGESIZE))
 362                        return -EINVAL;
 363                if (copy_to_user(req->buffer, &t->vdau[req->pgbuf].pgbuf[req->start], req->end - req->start + 1))
 364                        return -EFAULT;
 365
 366                 /*
 367                  *     Always read the time directly from SAA5249
 368                  */
 369
 370                if (req->start <= 39 && req->end >= 32) {
 371                        int len;
 372                        char buf[16];
 373                        start = max(req->start, 32);
 374                        end = min(req->end, 39);
 375                        len = end - start + 1;
 376                        if (i2c_senddata(t, 8, 0, 0, start, -1) ||
 377                                i2c_getdata(t, len, buf))
 378                                return -EIO;
 379                        if (copy_to_user(req->buffer + start - req->start, buf, len))
 380                                return -EFAULT;
 381                }
 382                /* Insert the current header if DAU is still searching for a page */
 383                if (req->start <= 31 && req->end >= 7 && t->is_searching[req->pgbuf]) {
 384                        char buf[32];
 385                        int len;
 386
 387                        start = max(req->start, 7);
 388                        end = min(req->end, 31);
 389                        len = end - start + 1;
 390                        if (i2c_senddata(t, 8, 0, 0, start, -1) ||
 391                                i2c_getdata(t, len, buf))
 392                                return -EIO;
 393                        if (copy_to_user(req->buffer + start - req->start, buf, len))
 394                                return -EFAULT;
 395                }
 396                return 0;
 397        }
 398
 399        case VTXIOCSTOPDAU:
 400        {
 401                vtx_pagereq_t *req = arg;
 402
 403                if (req->pgbuf < 0 || req->pgbuf >= NUM_DAUS)
 404                        return -EINVAL;
 405                t->vdau[req->pgbuf].stopped = true;
 406                t->is_searching[req->pgbuf] = false;
 407                return 0;
 408        }
 409
 410        case VTXIOCPUTPAGE:
 411        case VTXIOCSETDISP:
 412        case VTXIOCPUTSTAT:
 413                return 0;
 414
 415        case VTXIOCCLRCACHE:
 416        {
 417                if (i2c_senddata(t, 0, NUM_DAUS, 0, 8, -1) || i2c_senddata(t, 11,
 418                        ' ', ' ', ' ', ' ', ' ', ' ',
 419                        ' ', ' ', ' ', ' ', ' ', ' ',
 420                        ' ', ' ', ' ', ' ', ' ', ' ',
 421                        ' ', ' ', ' ', ' ', ' ', ' ',
 422                        -1))
 423                        return -EIO;
 424                if (i2c_senddata(t, 3, 0x20, -1))
 425                        return -EIO;
 426                jdelay(10 * CLEAR_DELAY);                       /* I have no idea how long we have to wait here */
 427                return 0;
 428        }
 429
 430        case VTXIOCSETVIRT:
 431        {
 432                /* The SAA5249 has virtual-row reception turned on always */
 433                t->virtual_mode = (int)(long)arg;
 434                return 0;
 435        }
 436        }
 437        return -EINVAL;
 438}
 439
 440/*
 441 * Translates old vtx IOCTLs to new ones
 442 *
 443 * This keeps new kernel versions compatible with old userspace programs.
 444 */
 445static inline unsigned int vtx_fix_command(unsigned int cmd)
 446{
 447        switch (cmd) {
 448        case VTXIOCGETINFO_OLD:
 449                cmd = VTXIOCGETINFO;
 450                break;
 451        case VTXIOCCLRPAGE_OLD:
 452                cmd = VTXIOCCLRPAGE;
 453                break;
 454        case VTXIOCCLRFOUND_OLD:
 455                cmd = VTXIOCCLRFOUND;
 456                break;
 457        case VTXIOCPAGEREQ_OLD:
 458                cmd = VTXIOCPAGEREQ;
 459                break;
 460        case VTXIOCGETSTAT_OLD:
 461                cmd = VTXIOCGETSTAT;
 462                break;
 463        case VTXIOCGETPAGE_OLD:
 464                cmd = VTXIOCGETPAGE;
 465                break;
 466        case VTXIOCSTOPDAU_OLD:
 467                cmd = VTXIOCSTOPDAU;
 468                break;
 469        case VTXIOCPUTPAGE_OLD:
 470                cmd = VTXIOCPUTPAGE;
 471                break;
 472        case VTXIOCSETDISP_OLD:
 473                cmd = VTXIOCSETDISP;
 474                break;
 475        case VTXIOCPUTSTAT_OLD:
 476                cmd = VTXIOCPUTSTAT;
 477                break;
 478        case VTXIOCCLRCACHE_OLD:
 479                cmd = VTXIOCCLRCACHE;
 480                break;
 481        case VTXIOCSETVIRT_OLD:
 482                cmd = VTXIOCSETVIRT;
 483                break;
 484        }
 485        return cmd;
 486}
 487
 488/*
 489 *      Handle the locking
 490 */
 491
 492static long saa5249_ioctl(struct file *file,
 493                         unsigned int cmd, unsigned long arg)
 494{
 495        struct saa5249_device *t = video_drvdata(file);
 496        long err;
 497
 498        cmd = vtx_fix_command(cmd);
 499        mutex_lock(&t->lock);
 500        err = video_usercopy(file, cmd, arg, do_saa5249_ioctl);
 501        mutex_unlock(&t->lock);
 502        return err;
 503}
 504
 505static int saa5249_open(struct file *file)
 506{
 507        struct saa5249_device *t = video_drvdata(file);
 508        int pgbuf;
 509
 510        if (test_and_set_bit(0, &t->in_use))
 511                return -EBUSY;
 512
 513        if (i2c_senddata(t, 0, 0, -1) || /* Select R11 */
 514                /* Turn off parity checks (we do this ourselves) */
 515                i2c_senddata(t, 1, disp_modes[t->disp_mode][0], 0, -1) ||
 516                /* Display TV-picture, no virtual rows */
 517                i2c_senddata(t, 4, NUM_DAUS, disp_modes[t->disp_mode][1], disp_modes[t->disp_mode][2], 7, -1))
 518                /* Set display to page 4 */
 519        {
 520                clear_bit(0, &t->in_use);
 521                return -EIO;
 522        }
 523
 524        for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
 525                memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
 526                memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
 527                memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
 528                t->vdau[pgbuf].expire = 0;
 529                t->vdau[pgbuf].clrfound = true;
 530                t->vdau[pgbuf].stopped = true;
 531                t->is_searching[pgbuf] = false;
 532        }
 533        t->virtual_mode = false;
 534        return 0;
 535}
 536
 537
 538
 539static int saa5249_release(struct file *file)
 540{
 541        struct saa5249_device *t = video_drvdata(file);
 542
 543        i2c_senddata(t, 1, 0x20, -1);           /* Turn off CCT */
 544        i2c_senddata(t, 5, 3, 3, -1);           /* Turn off TV-display */
 545        clear_bit(0, &t->in_use);
 546        return 0;
 547}
 548
 549static const struct v4l2_file_operations saa_fops = {
 550        .owner          = THIS_MODULE,
 551        .open           = saa5249_open,
 552        .release        = saa5249_release,
 553        .ioctl          = saa5249_ioctl,
 554};
 555
 556static struct video_device saa_template =
 557{
 558        .name           = "saa5249",
 559        .fops           = &saa_fops,
 560        .release        = video_device_release,
 561};
 562
 563static int saa5249_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 564{
 565        struct i2c_client *client = v4l2_get_subdevdata(sd);
 566
 567        return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_SAA5249, 0);
 568}
 569
 570static const struct v4l2_subdev_core_ops saa5249_core_ops = {
 571        .g_chip_ident = saa5249_g_chip_ident,
 572};
 573
 574static const struct v4l2_subdev_ops saa5249_ops = {
 575        .core = &saa5249_core_ops,
 576};
 577
 578static int saa5249_probe(struct i2c_client *client,
 579                        const struct i2c_device_id *id)
 580{
 581        int pgbuf;
 582        int err;
 583        struct saa5249_device *t;
 584        struct v4l2_subdev *sd;
 585
 586        v4l_info(client, "chip found @ 0x%x (%s)\n",
 587                        client->addr << 1, client->adapter->name);
 588        v4l_info(client, "VideoText version %d.%d\n",
 589                        VTX_VER_MAJ, VTX_VER_MIN);
 590        t = kzalloc(sizeof(*t), GFP_KERNEL);
 591        if (t == NULL)
 592                return -ENOMEM;
 593        sd = &t->sd;
 594        v4l2_i2c_subdev_init(sd, client, &saa5249_ops);
 595        mutex_init(&t->lock);
 596
 597        /* Now create a video4linux device */
 598        t->vdev = video_device_alloc();
 599        if (t->vdev == NULL) {
 600                kfree(t);
 601                kfree(client);
 602                return -ENOMEM;
 603        }
 604        memcpy(t->vdev, &saa_template, sizeof(*t->vdev));
 605
 606        for (pgbuf = 0; pgbuf < NUM_DAUS; pgbuf++) {
 607                memset(t->vdau[pgbuf].pgbuf, ' ', sizeof(t->vdau[0].pgbuf));
 608                memset(t->vdau[pgbuf].sregs, 0, sizeof(t->vdau[0].sregs));
 609                memset(t->vdau[pgbuf].laststat, 0, sizeof(t->vdau[0].laststat));
 610                t->vdau[pgbuf].expire = 0;
 611                t->vdau[pgbuf].clrfound = true;
 612                t->vdau[pgbuf].stopped = true;
 613                t->is_searching[pgbuf] = false;
 614        }
 615        video_set_drvdata(t->vdev, t);
 616
 617        /* Register it */
 618        err = video_register_device(t->vdev, VFL_TYPE_VTX, -1);
 619        if (err < 0) {
 620                video_device_release(t->vdev);
 621                kfree(t);
 622                return err;
 623        }
 624        return 0;
 625}
 626
 627static int saa5249_remove(struct i2c_client *client)
 628{
 629        struct v4l2_subdev *sd = i2c_get_clientdata(client);
 630        struct saa5249_device *t = to_dev(sd);
 631
 632        video_unregister_device(t->vdev);
 633        v4l2_device_unregister_subdev(sd);
 634        kfree(t);
 635        return 0;
 636}
 637
 638static const struct i2c_device_id saa5249_id[] = {
 639        { "saa5249", 0 },
 640        { }
 641};
 642MODULE_DEVICE_TABLE(i2c, saa5249_id);
 643
 644static struct v4l2_i2c_driver_data v4l2_i2c_data = {
 645        .name = "saa5249",
 646        .probe = saa5249_probe,
 647        .remove = saa5249_remove,
 648        .id_table = saa5249_id,
 649};
 650