linux/drivers/staging/go7007/go7007-driver.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2005-2006 Micronas USA Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify
   5 * it under the terms of the GNU General Public License (Version 2) as
   6 * published by the Free Software Foundation.
   7 *
   8 * This program is distributed in the hope that it will be useful,
   9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11 * GNU General Public License for more details.
  12 *
  13 * You should have received a copy of the GNU General Public License
  14 * along with this program; if not, write to the Free Software Foundation,
  15 * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
  16 */
  17
  18#include <linux/module.h>
  19#include <linux/init.h>
  20#include <linux/delay.h>
  21#include <linux/sched.h>
  22#include <linux/spinlock.h>
  23#include <linux/unistd.h>
  24#include <linux/time.h>
  25#include <linux/mm.h>
  26#include <linux/vmalloc.h>
  27#include <linux/device.h>
  28#include <linux/i2c.h>
  29#include <linux/firmware.h>
  30#include <linux/mutex.h>
  31#include <linux/uaccess.h>
  32#include <linux/slab.h>
  33#include <asm/system.h>
  34#include <linux/videodev2.h>
  35#include <media/tuner.h>
  36#include <media/v4l2-common.h>
  37
  38#include "go7007-priv.h"
  39#include "wis-i2c.h"
  40
  41/*
  42 * Wait for an interrupt to be delivered from the GO7007SB and return
  43 * the associated value and data.
  44 *
  45 * Must be called with the hw_lock held.
  46 */
  47int go7007_read_interrupt(struct go7007 *go, u16 *value, u16 *data)
  48{
  49        go->interrupt_available = 0;
  50        go->hpi_ops->read_interrupt(go);
  51        if (wait_event_timeout(go->interrupt_waitq,
  52                                go->interrupt_available, 5*HZ) < 0) {
  53                v4l2_err(&go->v4l2_dev, "timeout waiting for read interrupt\n");
  54                return -1;
  55        }
  56        if (!go->interrupt_available)
  57                return -1;
  58        go->interrupt_available = 0;
  59        *value = go->interrupt_value & 0xfffe;
  60        *data = go->interrupt_data;
  61        return 0;
  62}
  63EXPORT_SYMBOL(go7007_read_interrupt);
  64
  65/*
  66 * Read a register/address on the GO7007SB.
  67 *
  68 * Must be called with the hw_lock held.
  69 */
  70int go7007_read_addr(struct go7007 *go, u16 addr, u16 *data)
  71{
  72        int count = 100;
  73        u16 value;
  74
  75        if (go7007_write_interrupt(go, 0x0010, addr) < 0)
  76                return -EIO;
  77        while (count-- > 0) {
  78                if (go7007_read_interrupt(go, &value, data) == 0 &&
  79                                value == 0xa000)
  80                        return 0;
  81        }
  82        return -EIO;
  83}
  84EXPORT_SYMBOL(go7007_read_addr);
  85
  86/*
  87 * Send the boot firmware to the encoder, which just wakes it up and lets
  88 * us talk to the GPIO pins and on-board I2C adapter.
  89 *
  90 * Must be called with the hw_lock held.
  91 */
  92static int go7007_load_encoder(struct go7007 *go)
  93{
  94        const struct firmware *fw_entry;
  95        char fw_name[] = "go7007fw.bin";
  96        void *bounce;
  97        int fw_len, rv = 0;
  98        u16 intr_val, intr_data;
  99
 100        if (request_firmware(&fw_entry, fw_name, go->dev)) {
 101                v4l2_err(go, "unable to load firmware from file "
 102                        "\"%s\"\n", fw_name);
 103                return -1;
 104        }
 105        if (fw_entry->size < 16 || memcmp(fw_entry->data, "WISGO7007FW", 11)) {
 106                v4l2_err(go, "file \"%s\" does not appear to be "
 107                                "go7007 firmware\n", fw_name);
 108                release_firmware(fw_entry);
 109                return -1;
 110        }
 111        fw_len = fw_entry->size - 16;
 112        bounce = kmalloc(fw_len, GFP_KERNEL);
 113        if (bounce == NULL) {
 114                v4l2_err(go, "unable to allocate %d bytes for "
 115                                "firmware transfer\n", fw_len);
 116                release_firmware(fw_entry);
 117                return -1;
 118        }
 119        memcpy(bounce, fw_entry->data + 16, fw_len);
 120        release_firmware(fw_entry);
 121        if (go7007_interface_reset(go) < 0 ||
 122                        go7007_send_firmware(go, bounce, fw_len) < 0 ||
 123                        go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
 124                        (intr_val & ~0x1) != 0x5a5a) {
 125                v4l2_err(go, "error transferring firmware\n");
 126                rv = -1;
 127        }
 128        kfree(bounce);
 129        return rv;
 130}
 131
 132MODULE_FIRMWARE("go7007fw.bin");
 133
 134/*
 135 * Boot the encoder and register the I2C adapter if requested.  Do the
 136 * minimum initialization necessary, since the board-specific code may
 137 * still need to probe the board ID.
 138 *
 139 * Must NOT be called with the hw_lock held.
 140 */
 141int go7007_boot_encoder(struct go7007 *go, int init_i2c)
 142{
 143        int ret;
 144
 145        mutex_lock(&go->hw_lock);
 146        ret = go7007_load_encoder(go);
 147        mutex_unlock(&go->hw_lock);
 148        if (ret < 0)
 149                return -1;
 150        if (!init_i2c)
 151                return 0;
 152        if (go7007_i2c_init(go) < 0)
 153                return -1;
 154        go->i2c_adapter_online = 1;
 155        return 0;
 156}
 157EXPORT_SYMBOL(go7007_boot_encoder);
 158
 159/*
 160 * Configure any hardware-related registers in the GO7007, such as GPIO
 161 * pins and bus parameters, which are board-specific.  This assumes
 162 * the boot firmware has already been downloaded.
 163 *
 164 * Must be called with the hw_lock held.
 165 */
 166static int go7007_init_encoder(struct go7007 *go)
 167{
 168        if (go->board_info->audio_flags & GO7007_AUDIO_I2S_MASTER) {
 169                go7007_write_addr(go, 0x1000, 0x0811);
 170                go7007_write_addr(go, 0x1000, 0x0c11);
 171        }
 172        if (go->board_id == GO7007_BOARDID_MATRIX_REV) {
 173                /* Set GPIO pin 0 to be an output (audio clock control) */
 174                go7007_write_addr(go, 0x3c82, 0x0001);
 175                go7007_write_addr(go, 0x3c80, 0x00fe);
 176        }
 177        return 0;
 178}
 179
 180/*
 181 * Send the boot firmware to the GO7007 and configure the registers.  This
 182 * is the only way to stop the encoder once it has started streaming video.
 183 *
 184 * Must be called with the hw_lock held.
 185 */
 186int go7007_reset_encoder(struct go7007 *go)
 187{
 188        if (go7007_load_encoder(go) < 0)
 189                return -1;
 190        return go7007_init_encoder(go);
 191}
 192
 193/*
 194 * Attempt to instantiate an I2C client by ID, probably loading a module.
 195 */
 196static int init_i2c_module(struct i2c_adapter *adapter, const char *type,
 197                           int addr)
 198{
 199        struct go7007 *go = i2c_get_adapdata(adapter);
 200        struct v4l2_device *v4l2_dev = &go->v4l2_dev;
 201
 202        if (v4l2_i2c_new_subdev(v4l2_dev, adapter, type, addr, NULL))
 203                return 0;
 204
 205        printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", type);
 206        return -1;
 207}
 208
 209/*
 210 * Finalize the GO7007 hardware setup, register the on-board I2C adapter
 211 * (if used on this board), load the I2C client driver for the sensor
 212 * (SAA7115 or whatever) and other devices, and register the ALSA and V4L2
 213 * interfaces.
 214 *
 215 * Must NOT be called with the hw_lock held.
 216 */
 217int go7007_register_encoder(struct go7007 *go)
 218{
 219        int i, ret;
 220
 221        printk(KERN_INFO "go7007: registering new %s\n", go->name);
 222
 223        mutex_lock(&go->hw_lock);
 224        ret = go7007_init_encoder(go);
 225        mutex_unlock(&go->hw_lock);
 226        if (ret < 0)
 227                return -1;
 228
 229        /* v4l2 init must happen before i2c subdevs */
 230        ret = go7007_v4l2_init(go);
 231        if (ret < 0)
 232                return ret;
 233
 234        if (!go->i2c_adapter_online &&
 235                        go->board_info->flags & GO7007_BOARD_USE_ONBOARD_I2C) {
 236                if (go7007_i2c_init(go) < 0)
 237                        return -1;
 238                go->i2c_adapter_online = 1;
 239        }
 240        if (go->i2c_adapter_online) {
 241                for (i = 0; i < go->board_info->num_i2c_devs; ++i)
 242                        init_i2c_module(&go->i2c_adapter,
 243                                        go->board_info->i2c_devs[i].type,
 244                                        go->board_info->i2c_devs[i].addr);
 245                if (go->board_id == GO7007_BOARDID_ADLINK_MPG24)
 246                        i2c_clients_command(&go->i2c_adapter,
 247                                DECODER_SET_CHANNEL, &go->channel_number);
 248        }
 249        if (go->board_info->flags & GO7007_BOARD_HAS_AUDIO) {
 250                go->audio_enabled = 1;
 251                go7007_snd_init(go);
 252        }
 253        return 0;
 254}
 255EXPORT_SYMBOL(go7007_register_encoder);
 256
 257/*
 258 * Send the encode firmware to the encoder, which will cause it
 259 * to immediately start delivering the video and audio streams.
 260 *
 261 * Must be called with the hw_lock held.
 262 */
 263int go7007_start_encoder(struct go7007 *go)
 264{
 265        u8 *fw;
 266        int fw_len, rv = 0, i;
 267        u16 intr_val, intr_data;
 268
 269        go->modet_enable = 0;
 270        if (!go->dvd_mode)
 271                for (i = 0; i < 4; ++i) {
 272                        if (go->modet[i].enable) {
 273                                go->modet_enable = 1;
 274                                continue;
 275                        }
 276                        go->modet[i].pixel_threshold = 32767;
 277                        go->modet[i].motion_threshold = 32767;
 278                        go->modet[i].mb_threshold = 32767;
 279                }
 280
 281        if (go7007_construct_fw_image(go, &fw, &fw_len) < 0)
 282                return -1;
 283
 284        if (go7007_send_firmware(go, fw, fw_len) < 0 ||
 285                        go7007_read_interrupt(go, &intr_val, &intr_data) < 0) {
 286                v4l2_err(&go->v4l2_dev, "error transferring firmware\n");
 287                rv = -1;
 288                goto start_error;
 289        }
 290
 291        go->state = STATE_DATA;
 292        go->parse_length = 0;
 293        go->seen_frame = 0;
 294        if (go7007_stream_start(go) < 0) {
 295                v4l2_err(&go->v4l2_dev, "error starting stream transfer\n");
 296                rv = -1;
 297                goto start_error;
 298        }
 299
 300start_error:
 301        kfree(fw);
 302        return rv;
 303}
 304
 305/*
 306 * Store a byte in the current video buffer, if there is one.
 307 */
 308static inline void store_byte(struct go7007_buffer *gobuf, u8 byte)
 309{
 310        if (gobuf != NULL && gobuf->bytesused < GO7007_BUF_SIZE) {
 311                unsigned int pgidx = gobuf->offset >> PAGE_SHIFT;
 312                unsigned int pgoff = gobuf->offset & ~PAGE_MASK;
 313
 314                *((u8 *)page_address(gobuf->pages[pgidx]) + pgoff) = byte;
 315                ++gobuf->offset;
 316                ++gobuf->bytesused;
 317        }
 318}
 319
 320/*
 321 * Deliver the last video buffer and get a new one to start writing to.
 322 */
 323static void frame_boundary(struct go7007 *go)
 324{
 325        struct go7007_buffer *gobuf;
 326        int i;
 327
 328        if (go->active_buf) {
 329                if (go->active_buf->modet_active) {
 330                        if (go->active_buf->bytesused + 216 < GO7007_BUF_SIZE) {
 331                                for (i = 0; i < 216; ++i)
 332                                        store_byte(go->active_buf,
 333                                                        go->active_map[i]);
 334                                go->active_buf->bytesused -= 216;
 335                        } else
 336                                go->active_buf->modet_active = 0;
 337                }
 338                go->active_buf->state = BUF_STATE_DONE;
 339                wake_up_interruptible(&go->frame_waitq);
 340                go->active_buf = NULL;
 341        }
 342        list_for_each_entry(gobuf, &go->stream, stream)
 343                if (gobuf->state == BUF_STATE_QUEUED) {
 344                        gobuf->seq = go->next_seq;
 345                        do_gettimeofday(&gobuf->timestamp);
 346                        go->active_buf = gobuf;
 347                        break;
 348                }
 349        ++go->next_seq;
 350}
 351
 352static void write_bitmap_word(struct go7007 *go)
 353{
 354        int x, y, i, stride = ((go->width >> 4) + 7) >> 3;
 355
 356        for (i = 0; i < 16; ++i) {
 357                y = (((go->parse_length - 1) << 3) + i) / (go->width >> 4);
 358                x = (((go->parse_length - 1) << 3) + i) % (go->width >> 4);
 359                if (stride * y + (x >> 3) < sizeof(go->active_map))
 360                        go->active_map[stride * y + (x >> 3)] |=
 361                                        (go->modet_word & 1) << (x & 0x7);
 362                go->modet_word >>= 1;
 363        }
 364}
 365
 366/*
 367 * Parse a chunk of the video stream into frames.  The frames are not
 368 * delimited by the hardware, so we have to parse the frame boundaries
 369 * based on the type of video stream we're receiving.
 370 */
 371void go7007_parse_video_stream(struct go7007 *go, u8 *buf, int length)
 372{
 373        int i, seq_start_code = -1, frame_start_code = -1;
 374
 375        spin_lock(&go->spinlock);
 376
 377        switch (go->format) {
 378        case GO7007_FORMAT_MPEG4:
 379                seq_start_code = 0xB0;
 380                frame_start_code = 0xB6;
 381                break;
 382        case GO7007_FORMAT_MPEG1:
 383        case GO7007_FORMAT_MPEG2:
 384                seq_start_code = 0xB3;
 385                frame_start_code = 0x00;
 386                break;
 387        }
 388
 389        for (i = 0; i < length; ++i) {
 390                if (go->active_buf != NULL &&
 391                            go->active_buf->bytesused >= GO7007_BUF_SIZE - 3) {
 392                        v4l2_info(&go->v4l2_dev, "dropping oversized frame\n");
 393                        go->active_buf->offset -= go->active_buf->bytesused;
 394                        go->active_buf->bytesused = 0;
 395                        go->active_buf->modet_active = 0;
 396                        go->active_buf = NULL;
 397                }
 398
 399                switch (go->state) {
 400                case STATE_DATA:
 401                        switch (buf[i]) {
 402                        case 0x00:
 403                                go->state = STATE_00;
 404                                break;
 405                        case 0xFF:
 406                                go->state = STATE_FF;
 407                                break;
 408                        default:
 409                                store_byte(go->active_buf, buf[i]);
 410                                break;
 411                        }
 412                        break;
 413                case STATE_00:
 414                        switch (buf[i]) {
 415                        case 0x00:
 416                                go->state = STATE_00_00;
 417                                break;
 418                        case 0xFF:
 419                                store_byte(go->active_buf, 0x00);
 420                                go->state = STATE_FF;
 421                                break;
 422                        default:
 423                                store_byte(go->active_buf, 0x00);
 424                                store_byte(go->active_buf, buf[i]);
 425                                go->state = STATE_DATA;
 426                                break;
 427                        }
 428                        break;
 429                case STATE_00_00:
 430                        switch (buf[i]) {
 431                        case 0x00:
 432                                store_byte(go->active_buf, 0x00);
 433                                /* go->state remains STATE_00_00 */
 434                                break;
 435                        case 0x01:
 436                                go->state = STATE_00_00_01;
 437                                break;
 438                        case 0xFF:
 439                                store_byte(go->active_buf, 0x00);
 440                                store_byte(go->active_buf, 0x00);
 441                                go->state = STATE_FF;
 442                                break;
 443                        default:
 444                                store_byte(go->active_buf, 0x00);
 445                                store_byte(go->active_buf, 0x00);
 446                                store_byte(go->active_buf, buf[i]);
 447                                go->state = STATE_DATA;
 448                                break;
 449                        }
 450                        break;
 451                case STATE_00_00_01:
 452                        if (buf[i] == 0xF8 && go->modet_enable == 0) {
 453                                /* MODET start code, but MODET not enabled */
 454                                store_byte(go->active_buf, 0x00);
 455                                store_byte(go->active_buf, 0x00);
 456                                store_byte(go->active_buf, 0x01);
 457                                store_byte(go->active_buf, 0xF8);
 458                                go->state = STATE_DATA;
 459                                break;
 460                        }
 461                        /* If this is the start of a new MPEG frame,
 462                         * get a new buffer */
 463                        if ((go->format == GO7007_FORMAT_MPEG1 ||
 464                                        go->format == GO7007_FORMAT_MPEG2 ||
 465                                        go->format == GO7007_FORMAT_MPEG4) &&
 466                                        (buf[i] == seq_start_code ||
 467                                                buf[i] == 0xB8 || /* GOP code */
 468                                                buf[i] == frame_start_code)) {
 469                                if (go->active_buf == NULL || go->seen_frame)
 470                                        frame_boundary(go);
 471                                if (buf[i] == frame_start_code) {
 472                                        if (go->active_buf != NULL)
 473                                                go->active_buf->frame_offset =
 474                                                        go->active_buf->offset;
 475                                        go->seen_frame = 1;
 476                                } else {
 477                                        go->seen_frame = 0;
 478                                }
 479                        }
 480                        /* Handle any special chunk types, or just write the
 481                         * start code to the (potentially new) buffer */
 482                        switch (buf[i]) {
 483                        case 0xF5: /* timestamp */
 484                                go->parse_length = 12;
 485                                go->state = STATE_UNPARSED;
 486                                break;
 487                        case 0xF6: /* vbi */
 488                                go->state = STATE_VBI_LEN_A;
 489                                break;
 490                        case 0xF8: /* MD map */
 491                                go->parse_length = 0;
 492                                memset(go->active_map, 0,
 493                                                sizeof(go->active_map));
 494                                go->state = STATE_MODET_MAP;
 495                                break;
 496                        case 0xFF: /* Potential JPEG start code */
 497                                store_byte(go->active_buf, 0x00);
 498                                store_byte(go->active_buf, 0x00);
 499                                store_byte(go->active_buf, 0x01);
 500                                go->state = STATE_FF;
 501                                break;
 502                        default:
 503                                store_byte(go->active_buf, 0x00);
 504                                store_byte(go->active_buf, 0x00);
 505                                store_byte(go->active_buf, 0x01);
 506                                store_byte(go->active_buf, buf[i]);
 507                                go->state = STATE_DATA;
 508                                break;
 509                        }
 510                        break;
 511                case STATE_FF:
 512                        switch (buf[i]) {
 513                        case 0x00:
 514                                store_byte(go->active_buf, 0xFF);
 515                                go->state = STATE_00;
 516                                break;
 517                        case 0xFF:
 518                                store_byte(go->active_buf, 0xFF);
 519                                /* go->state remains STATE_FF */
 520                                break;
 521                        case 0xD8:
 522                                if (go->format == GO7007_FORMAT_MJPEG)
 523                                        frame_boundary(go);
 524                                /* fall through */
 525                        default:
 526                                store_byte(go->active_buf, 0xFF);
 527                                store_byte(go->active_buf, buf[i]);
 528                                go->state = STATE_DATA;
 529                                break;
 530                        }
 531                        break;
 532                case STATE_VBI_LEN_A:
 533                        go->parse_length = buf[i] << 8;
 534                        go->state = STATE_VBI_LEN_B;
 535                        break;
 536                case STATE_VBI_LEN_B:
 537                        go->parse_length |= buf[i];
 538                        if (go->parse_length > 0)
 539                                go->state = STATE_UNPARSED;
 540                        else
 541                                go->state = STATE_DATA;
 542                        break;
 543                case STATE_MODET_MAP:
 544                        if (go->parse_length < 204) {
 545                                if (go->parse_length & 1) {
 546                                        go->modet_word |= buf[i];
 547                                        write_bitmap_word(go);
 548                                } else
 549                                        go->modet_word = buf[i] << 8;
 550                        } else if (go->parse_length == 207 && go->active_buf) {
 551                                go->active_buf->modet_active = buf[i];
 552                        }
 553                        if (++go->parse_length == 208)
 554                                go->state = STATE_DATA;
 555                        break;
 556                case STATE_UNPARSED:
 557                        if (--go->parse_length == 0)
 558                                go->state = STATE_DATA;
 559                        break;
 560                }
 561        }
 562
 563        spin_unlock(&go->spinlock);
 564}
 565EXPORT_SYMBOL(go7007_parse_video_stream);
 566
 567/*
 568 * Allocate a new go7007 struct.  Used by the hardware-specific probe.
 569 */
 570struct go7007 *go7007_alloc(struct go7007_board_info *board, struct device *dev)
 571{
 572        struct go7007 *go;
 573        int i;
 574
 575        go = kmalloc(sizeof(struct go7007), GFP_KERNEL);
 576        if (go == NULL)
 577                return NULL;
 578        go->dev = dev;
 579        go->board_info = board;
 580        go->board_id = 0;
 581        go->tuner_type = -1;
 582        go->channel_number = 0;
 583        go->name[0] = 0;
 584        mutex_init(&go->hw_lock);
 585        init_waitqueue_head(&go->frame_waitq);
 586        spin_lock_init(&go->spinlock);
 587        go->video_dev = NULL;
 588        go->ref_count = 0;
 589        go->status = STATUS_INIT;
 590        memset(&go->i2c_adapter, 0, sizeof(go->i2c_adapter));
 591        go->i2c_adapter_online = 0;
 592        go->interrupt_available = 0;
 593        init_waitqueue_head(&go->interrupt_waitq);
 594        go->in_use = 0;
 595        go->input = 0;
 596        if (board->sensor_flags & GO7007_SENSOR_TV) {
 597                go->standard = GO7007_STD_NTSC;
 598                go->width = 720;
 599                go->height = 480;
 600                go->sensor_framerate = 30000;
 601        } else {
 602                go->standard = GO7007_STD_OTHER;
 603                go->width = board->sensor_width;
 604                go->height = board->sensor_height;
 605                go->sensor_framerate = board->sensor_framerate;
 606        }
 607        go->encoder_v_offset = board->sensor_v_offset;
 608        go->encoder_h_offset = board->sensor_h_offset;
 609        go->encoder_h_halve = 0;
 610        go->encoder_v_halve = 0;
 611        go->encoder_subsample = 0;
 612        go->streaming = 0;
 613        go->format = GO7007_FORMAT_MJPEG;
 614        go->bitrate = 1500000;
 615        go->fps_scale = 1;
 616        go->pali = 0;
 617        go->aspect_ratio = GO7007_RATIO_1_1;
 618        go->gop_size = 0;
 619        go->ipb = 0;
 620        go->closed_gop = 0;
 621        go->repeat_seqhead = 0;
 622        go->seq_header_enable = 0;
 623        go->gop_header_enable = 0;
 624        go->dvd_mode = 0;
 625        go->interlace_coding = 0;
 626        for (i = 0; i < 4; ++i)
 627                go->modet[i].enable = 0;
 628        for (i = 0; i < 1624; ++i)
 629                go->modet_map[i] = 0;
 630        go->audio_deliver = NULL;
 631        go->audio_enabled = 0;
 632        INIT_LIST_HEAD(&go->stream);
 633
 634        return go;
 635}
 636EXPORT_SYMBOL(go7007_alloc);
 637
 638/*
 639 * Detach and unregister the encoder.  The go7007 struct won't be freed
 640 * until v4l2 finishes releasing its resources and all associated fds are
 641 * closed by applications.
 642 */
 643void go7007_remove(struct go7007 *go)
 644{
 645        if (go->i2c_adapter_online) {
 646                if (i2c_del_adapter(&go->i2c_adapter) == 0)
 647                        go->i2c_adapter_online = 0;
 648                else
 649                        v4l2_err(&go->v4l2_dev,
 650                                "error removing I2C adapter!\n");
 651        }
 652
 653        if (go->audio_enabled)
 654                go7007_snd_remove(go);
 655        go7007_v4l2_remove(go);
 656}
 657EXPORT_SYMBOL(go7007_remove);
 658
 659MODULE_LICENSE("GPL v2");
 660