linux/drivers/media/pci/cx88/cx88-blackbird.c
<<
>>
Prefs
   1/*
   2 *
   3 *  Support for a cx23416 mpeg encoder via cx2388x host port.
   4 *  "blackbird" reference design.
   5 *
   6 *    (c) 2004 Jelle Foks <jelle@foks.us>
   7 *    (c) 2004 Gerd Knorr <kraxel@bytesex.org>
   8 *
   9 *    (c) 2005-2006 Mauro Carvalho Chehab <mchehab@infradead.org>
  10 *        - video_ioctl2 conversion
  11 *
  12 *  Includes parts from the ivtv driver <http://sourceforge.net/projects/ivtv/>
  13 *
  14 *  This program is free software; you can redistribute it and/or modify
  15 *  it under the terms of the GNU General Public License as published by
  16 *  the Free Software Foundation; either version 2 of the License, or
  17 *  (at your option) any later version.
  18 *
  19 *  This program is distributed in the hope that it will be useful,
  20 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  21 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  22 *  GNU General Public License for more details.
  23 *
  24 *  You should have received a copy of the GNU General Public License
  25 *  along with this program; if not, write to the Free Software
  26 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  27 */
  28
  29#include <linux/module.h>
  30#include <linux/init.h>
  31#include <linux/slab.h>
  32#include <linux/fs.h>
  33#include <linux/delay.h>
  34#include <linux/device.h>
  35#include <linux/firmware.h>
  36#include <media/v4l2-common.h>
  37#include <media/v4l2-ioctl.h>
  38#include <media/v4l2-event.h>
  39#include <media/cx2341x.h>
  40
  41#include "cx88.h"
  42
  43MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards");
  44MODULE_AUTHOR("Jelle Foks <jelle@foks.us>, Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
  45MODULE_LICENSE("GPL");
  46MODULE_VERSION(CX88_VERSION);
  47
  48static unsigned int mpegbufs = 32;
  49module_param(mpegbufs,int,0644);
  50MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32");
  51
  52static unsigned int debug;
  53module_param(debug,int,0644);
  54MODULE_PARM_DESC(debug,"enable debug messages [blackbird]");
  55
  56#define dprintk(level, fmt, arg...) do {                                      \
  57        if (debug + 1 > level)                                                \
  58                printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg); \
  59} while(0)
  60
  61/* ------------------------------------------------------------------ */
  62
  63#define BLACKBIRD_FIRM_IMAGE_SIZE 376836
  64
  65/* defines below are from ivtv-driver.h */
  66
  67#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
  68
  69/* Firmware API commands */
  70#define IVTV_API_STD_TIMEOUT 500
  71
  72enum blackbird_capture_type {
  73        BLACKBIRD_MPEG_CAPTURE,
  74        BLACKBIRD_RAW_CAPTURE,
  75        BLACKBIRD_RAW_PASSTHRU_CAPTURE
  76};
  77enum blackbird_capture_bits {
  78        BLACKBIRD_RAW_BITS_NONE             = 0x00,
  79        BLACKBIRD_RAW_BITS_YUV_CAPTURE      = 0x01,
  80        BLACKBIRD_RAW_BITS_PCM_CAPTURE      = 0x02,
  81        BLACKBIRD_RAW_BITS_VBI_CAPTURE      = 0x04,
  82        BLACKBIRD_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
  83        BLACKBIRD_RAW_BITS_TO_HOST_CAPTURE  = 0x10
  84};
  85enum blackbird_capture_end {
  86        BLACKBIRD_END_AT_GOP, /* stop at the end of gop, generate irq */
  87        BLACKBIRD_END_NOW, /* stop immediately, no irq */
  88};
  89enum blackbird_framerate {
  90        BLACKBIRD_FRAMERATE_NTSC_30, /* NTSC: 30fps */
  91        BLACKBIRD_FRAMERATE_PAL_25   /* PAL: 25fps */
  92};
  93enum blackbird_stream_port {
  94        BLACKBIRD_OUTPUT_PORT_MEMORY,
  95        BLACKBIRD_OUTPUT_PORT_STREAMING,
  96        BLACKBIRD_OUTPUT_PORT_SERIAL
  97};
  98enum blackbird_data_xfer_status {
  99        BLACKBIRD_MORE_BUFFERS_FOLLOW,
 100        BLACKBIRD_LAST_BUFFER,
 101};
 102enum blackbird_picture_mask {
 103        BLACKBIRD_PICTURE_MASK_NONE,
 104        BLACKBIRD_PICTURE_MASK_I_FRAMES,
 105        BLACKBIRD_PICTURE_MASK_I_P_FRAMES = 0x3,
 106        BLACKBIRD_PICTURE_MASK_ALL_FRAMES = 0x7,
 107};
 108enum blackbird_vbi_mode_bits {
 109        BLACKBIRD_VBI_BITS_SLICED,
 110        BLACKBIRD_VBI_BITS_RAW,
 111};
 112enum blackbird_vbi_insertion_bits {
 113        BLACKBIRD_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
 114        BLACKBIRD_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
 115        BLACKBIRD_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
 116        BLACKBIRD_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
 117        BLACKBIRD_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
 118};
 119enum blackbird_dma_unit {
 120        BLACKBIRD_DMA_BYTES,
 121        BLACKBIRD_DMA_FRAMES,
 122};
 123enum blackbird_dma_transfer_status_bits {
 124        BLACKBIRD_DMA_TRANSFER_BITS_DONE = 0x01,
 125        BLACKBIRD_DMA_TRANSFER_BITS_ERROR = 0x04,
 126        BLACKBIRD_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
 127};
 128enum blackbird_pause {
 129        BLACKBIRD_PAUSE_ENCODING,
 130        BLACKBIRD_RESUME_ENCODING,
 131};
 132enum blackbird_copyright {
 133        BLACKBIRD_COPYRIGHT_OFF,
 134        BLACKBIRD_COPYRIGHT_ON,
 135};
 136enum blackbird_notification_type {
 137        BLACKBIRD_NOTIFICATION_REFRESH,
 138};
 139enum blackbird_notification_status {
 140        BLACKBIRD_NOTIFICATION_OFF,
 141        BLACKBIRD_NOTIFICATION_ON,
 142};
 143enum blackbird_notification_mailbox {
 144        BLACKBIRD_NOTIFICATION_NO_MAILBOX = -1,
 145};
 146enum blackbird_field1_lines {
 147        BLACKBIRD_FIELD1_SAA7114 = 0x00EF, /* 239 */
 148        BLACKBIRD_FIELD1_SAA7115 = 0x00F0, /* 240 */
 149        BLACKBIRD_FIELD1_MICRONAS = 0x0105, /* 261 */
 150};
 151enum blackbird_field2_lines {
 152        BLACKBIRD_FIELD2_SAA7114 = 0x00EF, /* 239 */
 153        BLACKBIRD_FIELD2_SAA7115 = 0x00F0, /* 240 */
 154        BLACKBIRD_FIELD2_MICRONAS = 0x0106, /* 262 */
 155};
 156enum blackbird_custom_data_type {
 157        BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
 158        BLACKBIRD_CUSTOM_PRIVATE_PACKET,
 159};
 160enum blackbird_mute {
 161        BLACKBIRD_UNMUTE,
 162        BLACKBIRD_MUTE,
 163};
 164enum blackbird_mute_video_mask {
 165        BLACKBIRD_MUTE_VIDEO_V_MASK = 0x0000FF00,
 166        BLACKBIRD_MUTE_VIDEO_U_MASK = 0x00FF0000,
 167        BLACKBIRD_MUTE_VIDEO_Y_MASK = 0xFF000000,
 168};
 169enum blackbird_mute_video_shift {
 170        BLACKBIRD_MUTE_VIDEO_V_SHIFT = 8,
 171        BLACKBIRD_MUTE_VIDEO_U_SHIFT = 16,
 172        BLACKBIRD_MUTE_VIDEO_Y_SHIFT = 24,
 173};
 174
 175/* Registers */
 176#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8 /*| IVTV_REG_OFFSET*/)
 177#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC /*| IVTV_REG_OFFSET*/)
 178#define IVTV_REG_SPU (0x9050 /*| IVTV_REG_OFFSET*/)
 179#define IVTV_REG_HW_BLOCKS (0x9054 /*| IVTV_REG_OFFSET*/)
 180#define IVTV_REG_VPU (0x9058 /*| IVTV_REG_OFFSET*/)
 181#define IVTV_REG_APU (0xA064 /*| IVTV_REG_OFFSET*/)
 182
 183/* ------------------------------------------------------------------ */
 184
 185static void host_setup(struct cx88_core *core)
 186{
 187        /* toggle reset of the host */
 188        cx_write(MO_GPHST_SOFT_RST, 1);
 189        udelay(100);
 190        cx_write(MO_GPHST_SOFT_RST, 0);
 191        udelay(100);
 192
 193        /* host port setup */
 194        cx_write(MO_GPHST_WSC, 0x44444444U);
 195        cx_write(MO_GPHST_XFR, 0);
 196        cx_write(MO_GPHST_WDTH, 15);
 197        cx_write(MO_GPHST_HDSHK, 0);
 198        cx_write(MO_GPHST_MUX16, 0x44448888U);
 199        cx_write(MO_GPHST_MODE, 0);
 200}
 201
 202/* ------------------------------------------------------------------ */
 203
 204#define P1_MDATA0 0x390000
 205#define P1_MDATA1 0x390001
 206#define P1_MDATA2 0x390002
 207#define P1_MDATA3 0x390003
 208#define P1_MADDR2 0x390004
 209#define P1_MADDR1 0x390005
 210#define P1_MADDR0 0x390006
 211#define P1_RDATA0 0x390008
 212#define P1_RDATA1 0x390009
 213#define P1_RDATA2 0x39000A
 214#define P1_RDATA3 0x39000B
 215#define P1_RADDR0 0x39000C
 216#define P1_RADDR1 0x39000D
 217#define P1_RRDWR  0x39000E
 218
 219static int wait_ready_gpio0_bit1(struct cx88_core *core, u32 state)
 220{
 221        unsigned long timeout = jiffies + msecs_to_jiffies(1);
 222        u32 gpio0,need;
 223
 224        need = state ? 2 : 0;
 225        for (;;) {
 226                gpio0 = cx_read(MO_GP0_IO) & 2;
 227                if (need == gpio0)
 228                        return 0;
 229                if (time_after(jiffies,timeout))
 230                        return -1;
 231                udelay(1);
 232        }
 233}
 234
 235static int memory_write(struct cx88_core *core, u32 address, u32 value)
 236{
 237        /* Warning: address is dword address (4 bytes) */
 238        cx_writeb(P1_MDATA0, (unsigned int)value);
 239        cx_writeb(P1_MDATA1, (unsigned int)(value >> 8));
 240        cx_writeb(P1_MDATA2, (unsigned int)(value >> 16));
 241        cx_writeb(P1_MDATA3, (unsigned int)(value >> 24));
 242        cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) | 0x40);
 243        cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
 244        cx_writeb(P1_MADDR0, (unsigned int)address);
 245        cx_read(P1_MDATA0);
 246        cx_read(P1_MADDR0);
 247
 248        return wait_ready_gpio0_bit1(core,1);
 249}
 250
 251static int memory_read(struct cx88_core *core, u32 address, u32 *value)
 252{
 253        int retval;
 254        u32 val;
 255
 256        /* Warning: address is dword address (4 bytes) */
 257        cx_writeb(P1_MADDR2, (unsigned int)(address >> 16) & ~0xC0);
 258        cx_writeb(P1_MADDR1, (unsigned int)(address >> 8));
 259        cx_writeb(P1_MADDR0, (unsigned int)address);
 260        cx_read(P1_MADDR0);
 261
 262        retval = wait_ready_gpio0_bit1(core,1);
 263
 264        cx_writeb(P1_MDATA3, 0);
 265        val     = (unsigned char)cx_read(P1_MDATA3) << 24;
 266        cx_writeb(P1_MDATA2, 0);
 267        val    |= (unsigned char)cx_read(P1_MDATA2) << 16;
 268        cx_writeb(P1_MDATA1, 0);
 269        val    |= (unsigned char)cx_read(P1_MDATA1) << 8;
 270        cx_writeb(P1_MDATA0, 0);
 271        val    |= (unsigned char)cx_read(P1_MDATA0);
 272
 273        *value  = val;
 274        return retval;
 275}
 276
 277static int register_write(struct cx88_core *core, u32 address, u32 value)
 278{
 279        cx_writeb(P1_RDATA0, (unsigned int)value);
 280        cx_writeb(P1_RDATA1, (unsigned int)(value >> 8));
 281        cx_writeb(P1_RDATA2, (unsigned int)(value >> 16));
 282        cx_writeb(P1_RDATA3, (unsigned int)(value >> 24));
 283        cx_writeb(P1_RADDR0, (unsigned int)address);
 284        cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
 285        cx_writeb(P1_RRDWR, 1);
 286        cx_read(P1_RDATA0);
 287        cx_read(P1_RADDR0);
 288
 289        return wait_ready_gpio0_bit1(core,1);
 290}
 291
 292
 293static int register_read(struct cx88_core *core, u32 address, u32 *value)
 294{
 295        int retval;
 296        u32 val;
 297
 298        cx_writeb(P1_RADDR0, (unsigned int)address);
 299        cx_writeb(P1_RADDR1, (unsigned int)(address >> 8));
 300        cx_writeb(P1_RRDWR, 0);
 301        cx_read(P1_RADDR0);
 302
 303        retval  = wait_ready_gpio0_bit1(core,1);
 304        val     = (unsigned char)cx_read(P1_RDATA0);
 305        val    |= (unsigned char)cx_read(P1_RDATA1) << 8;
 306        val    |= (unsigned char)cx_read(P1_RDATA2) << 16;
 307        val    |= (unsigned char)cx_read(P1_RDATA3) << 24;
 308
 309        *value  = val;
 310        return retval;
 311}
 312
 313/* ------------------------------------------------------------------ */
 314
 315static int blackbird_mbox_func(void *priv, u32 command, int in, int out, u32 data[CX2341X_MBOX_MAX_DATA])
 316{
 317        struct cx8802_dev *dev = priv;
 318        unsigned long timeout;
 319        u32 value, flag, retval;
 320        int i;
 321
 322        dprintk(1,"%s: 0x%X\n", __func__, command);
 323
 324        /* this may not be 100% safe if we can't read any memory location
 325           without side effects */
 326        memory_read(dev->core, dev->mailbox - 4, &value);
 327        if (value != 0x12345678) {
 328                dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n");
 329                return -1;
 330        }
 331
 332        memory_read(dev->core, dev->mailbox, &flag);
 333        if (flag) {
 334                dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag);
 335                return -1;
 336        }
 337
 338        flag |= 1; /* tell 'em we're working on it */
 339        memory_write(dev->core, dev->mailbox, flag);
 340
 341        /* write command + args + fill remaining with zeros */
 342        memory_write(dev->core, dev->mailbox + 1, command); /* command code */
 343        memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */
 344        for (i = 0; i < in; i++) {
 345                memory_write(dev->core, dev->mailbox + 4 + i, data[i]);
 346                dprintk(1, "API Input %d = %d\n", i, data[i]);
 347        }
 348        for (; i < CX2341X_MBOX_MAX_DATA; i++)
 349                memory_write(dev->core, dev->mailbox + 4 + i, 0);
 350
 351        flag |= 3; /* tell 'em we're done writing */
 352        memory_write(dev->core, dev->mailbox, flag);
 353
 354        /* wait for firmware to handle the API command */
 355        timeout = jiffies + msecs_to_jiffies(10);
 356        for (;;) {
 357                memory_read(dev->core, dev->mailbox, &flag);
 358                if (0 != (flag & 4))
 359                        break;
 360                if (time_after(jiffies,timeout)) {
 361                        dprintk(0, "ERROR: API Mailbox timeout\n");
 362                        return -1;
 363                }
 364                udelay(10);
 365        }
 366
 367        /* read output values */
 368        for (i = 0; i < out; i++) {
 369                memory_read(dev->core, dev->mailbox + 4 + i, data + i);
 370                dprintk(1, "API Output %d = %d\n", i, data[i]);
 371        }
 372
 373        memory_read(dev->core, dev->mailbox + 2, &retval);
 374        dprintk(1, "API result = %d\n",retval);
 375
 376        flag = 0;
 377        memory_write(dev->core, dev->mailbox, flag);
 378        return retval;
 379}
 380/* ------------------------------------------------------------------ */
 381
 382/* We don't need to call the API often, so using just one mailbox will probably suffice */
 383static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command,
 384                             u32 inputcnt, u32 outputcnt, ...)
 385{
 386        u32 data[CX2341X_MBOX_MAX_DATA];
 387        va_list vargs;
 388        int i, err;
 389
 390        va_start(vargs, outputcnt);
 391
 392        for (i = 0; i < inputcnt; i++) {
 393                data[i] = va_arg(vargs, int);
 394        }
 395        err = blackbird_mbox_func(dev, command, inputcnt, outputcnt, data);
 396        for (i = 0; i < outputcnt; i++) {
 397                int *vptr = va_arg(vargs, int *);
 398                *vptr = data[i];
 399        }
 400        va_end(vargs);
 401        return err;
 402}
 403
 404static int blackbird_find_mailbox(struct cx8802_dev *dev)
 405{
 406        u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456};
 407        int signaturecnt=0;
 408        u32 value;
 409        int i;
 410
 411        for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) {
 412                memory_read(dev->core, i, &value);
 413                if (value == signature[signaturecnt])
 414                        signaturecnt++;
 415                else
 416                        signaturecnt = 0;
 417                if (4 == signaturecnt) {
 418                        dprintk(1, "Mailbox signature found\n");
 419                        return i+1;
 420                }
 421        }
 422        dprintk(0, "Mailbox signature values not found!\n");
 423        return -1;
 424}
 425
 426static int blackbird_load_firmware(struct cx8802_dev *dev)
 427{
 428        static const unsigned char magic[8] = {
 429                0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
 430        };
 431        const struct firmware *firmware;
 432        int i, retval = 0;
 433        u32 value = 0;
 434        u32 checksum = 0;
 435        u32 *dataptr;
 436
 437        retval  = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED);
 438        retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
 439        retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640);
 440        retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
 441        msleep(1);
 442        retval |= register_write(dev->core, IVTV_REG_APU, 0);
 443
 444        if (retval < 0)
 445                dprintk(0, "Error with register_write\n");
 446
 447        retval = request_firmware(&firmware, CX2341X_FIRM_ENC_FILENAME,
 448                                  &dev->pci->dev);
 449
 450
 451        if (retval != 0) {
 452                dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n",
 453                        CX2341X_FIRM_ENC_FILENAME);
 454                dprintk(0, "Please fix your hotplug setup, the board will "
 455                        "not work without firmware loaded!\n");
 456                return -1;
 457        }
 458
 459        if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) {
 460                dprintk(0, "ERROR: Firmware size mismatch (have %zd, expected %d)\n",
 461                        firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE);
 462                release_firmware(firmware);
 463                return -1;
 464        }
 465
 466        if (0 != memcmp(firmware->data, magic, 8)) {
 467                dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n");
 468                release_firmware(firmware);
 469                return -1;
 470        }
 471
 472        /* transfer to the chip */
 473        dprintk(1,"Loading firmware ...\n");
 474        dataptr = (u32*)firmware->data;
 475        for (i = 0; i < (firmware->size >> 2); i++) {
 476                value = le32_to_cpu(*dataptr);
 477                checksum += ~value;
 478                memory_write(dev->core, i, value);
 479                dataptr++;
 480        }
 481
 482        /* read back to verify with the checksum */
 483        for (i--; i >= 0; i--) {
 484                memory_read(dev->core, i, &value);
 485                checksum -= ~value;
 486        }
 487        if (checksum) {
 488                dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n");
 489                release_firmware(firmware);
 490                return -1;
 491        }
 492        release_firmware(firmware);
 493        dprintk(0, "Firmware upload successful.\n");
 494
 495        retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
 496        retval |= register_read(dev->core, IVTV_REG_SPU, &value);
 497        retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE);
 498        msleep(1);
 499
 500        retval |= register_read(dev->core, IVTV_REG_VPU, &value);
 501        retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8);
 502
 503        if (retval < 0)
 504                dprintk(0, "Error with register_write\n");
 505        return 0;
 506}
 507
 508/**
 509 Settings used by the windows tv app for PVR2000:
 510=================================================================================================================
 511Profile | Codec | Resolution | CBR/VBR | Video Qlty   | V. Bitrate | Frmrate | Audio Codec | A. Bitrate | A. Mode
 512-----------------------------------------------------------------------------------------------------------------
 513MPEG-1  | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 2000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
 514MPEG-2  | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 4000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
 515VCD     | MPEG1 | 352x288PAL | (CBR)   | 1000:Optimal | 1150 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
 516DVD     | MPEG2 | 720x576PAL | VBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
 517DB* DVD | MPEG2 | 720x576PAL | CBR     | 600 :Good    | 6000 Kbps  | 25fps   | MPG1 Layer2 | 224kbps    | Stereo
 518=================================================================================================================
 519*DB: "DirectBurn"
 520*/
 521
 522static void blackbird_codec_settings(struct cx8802_dev *dev)
 523{
 524        /* assign frame size */
 525        blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
 526                                dev->height, dev->width);
 527
 528        dev->cxhdl.width = dev->width;
 529        dev->cxhdl.height = dev->height;
 530        cx2341x_handler_set_50hz(&dev->cxhdl, dev->core->tvnorm & V4L2_STD_625_50);
 531        cx2341x_handler_setup(&dev->cxhdl);
 532}
 533
 534static int blackbird_initialize_codec(struct cx8802_dev *dev)
 535{
 536        struct cx88_core *core = dev->core;
 537        int version;
 538        int retval;
 539
 540        dprintk(1,"Initialize codec\n");
 541        retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
 542        if (retval < 0) {
 543
 544                dev->mpeg_active = 0;
 545
 546                /* ping was not successful, reset and upload firmware */
 547                cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */
 548                cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */
 549                retval = blackbird_load_firmware(dev);
 550                if (retval < 0)
 551                        return retval;
 552
 553                retval = blackbird_find_mailbox(dev);
 554                if (retval < 0)
 555                        return -1;
 556
 557                dev->mailbox = retval;
 558
 559                retval = blackbird_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
 560                if (retval < 0) {
 561                        dprintk(0, "ERROR: Firmware ping failed!\n");
 562                        return -1;
 563                }
 564
 565                retval = blackbird_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1, &version);
 566                if (retval < 0) {
 567                        dprintk(0, "ERROR: Firmware get encoder version failed!\n");
 568                        return -1;
 569                }
 570                dprintk(0, "Firmware version is 0x%08x\n", version);
 571        }
 572
 573        cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */
 574        cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */
 575        cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */
 576        cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */
 577
 578        blackbird_codec_settings(dev);
 579
 580        blackbird_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
 581                        BLACKBIRD_FIELD1_SAA7115,
 582                        BLACKBIRD_FIELD2_SAA7115
 583                );
 584
 585        blackbird_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
 586                        BLACKBIRD_CUSTOM_EXTENSION_USR_DATA,
 587                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 588
 589        return 0;
 590}
 591
 592static int blackbird_start_codec(struct file *file, void *priv)
 593{
 594        struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
 595        struct cx88_core *core = dev->core;
 596        /* start capturing to the host interface */
 597        u32 reg;
 598
 599        int i;
 600        int lastchange = -1;
 601        int lastval = 0;
 602
 603        for (i = 0; (i < 10) && (i < (lastchange + 4)); i++) {
 604                reg = cx_read(AUD_STATUS);
 605
 606                dprintk(1, "AUD_STATUS:%dL: 0x%x\n", i, reg);
 607                if ((reg & 0x0F) != lastval) {
 608                        lastval = reg & 0x0F;
 609                        lastchange = i;
 610                }
 611                msleep(100);
 612        }
 613
 614        /* unmute audio source */
 615        cx_clear(AUD_VOL_CTL, (1 << 6));
 616
 617        blackbird_api_cmd(dev, CX2341X_ENC_REFRESH_INPUT, 0, 0);
 618
 619        /* initialize the video input */
 620        blackbird_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
 621
 622        cx2341x_handler_set_busy(&dev->cxhdl, 1);
 623
 624        /* start capturing to the host interface */
 625        blackbird_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
 626                        BLACKBIRD_MPEG_CAPTURE,
 627                        BLACKBIRD_RAW_BITS_NONE
 628                );
 629
 630        dev->mpeg_active = 1;
 631        return 0;
 632}
 633
 634static int blackbird_stop_codec(struct cx8802_dev *dev)
 635{
 636        blackbird_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
 637                        BLACKBIRD_END_NOW,
 638                        BLACKBIRD_MPEG_CAPTURE,
 639                        BLACKBIRD_RAW_BITS_NONE
 640                );
 641
 642        cx2341x_handler_set_busy(&dev->cxhdl, 0);
 643
 644        dev->mpeg_active = 0;
 645        return 0;
 646}
 647
 648/* ------------------------------------------------------------------ */
 649
 650static int bb_buf_setup(struct videobuf_queue *q,
 651                        unsigned int *count, unsigned int *size)
 652{
 653        struct cx8802_fh *fh = q->priv_data;
 654
 655        fh->dev->ts_packet_size  = 188 * 4; /* was: 512 */
 656        fh->dev->ts_packet_count = mpegbufs; /* was: 100 */
 657
 658        *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count;
 659        *count = fh->dev->ts_packet_count;
 660        return 0;
 661}
 662
 663static int
 664bb_buf_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb,
 665               enum v4l2_field field)
 666{
 667        struct cx8802_fh *fh = q->priv_data;
 668        return cx8802_buf_prepare(q, fh->dev, (struct cx88_buffer*)vb, field);
 669}
 670
 671static void
 672bb_buf_queue(struct videobuf_queue *q, struct videobuf_buffer *vb)
 673{
 674        struct cx8802_fh *fh = q->priv_data;
 675        cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb);
 676}
 677
 678static void
 679bb_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
 680{
 681        cx88_free_buffer(q, (struct cx88_buffer*)vb);
 682}
 683
 684static struct videobuf_queue_ops blackbird_qops = {
 685        .buf_setup    = bb_buf_setup,
 686        .buf_prepare  = bb_buf_prepare,
 687        .buf_queue    = bb_buf_queue,
 688        .buf_release  = bb_buf_release,
 689};
 690
 691/* ------------------------------------------------------------------ */
 692
 693static int vidioc_querycap(struct file *file, void  *priv,
 694                                        struct v4l2_capability *cap)
 695{
 696        struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
 697        struct cx88_core  *core = dev->core;
 698
 699        strcpy(cap->driver, "cx88_blackbird");
 700        sprintf(cap->bus_info, "PCI:%s", pci_name(dev->pci));
 701        cx88_querycap(file, core, cap);
 702        return 0;
 703}
 704
 705static int vidioc_enum_fmt_vid_cap (struct file *file, void  *priv,
 706                                        struct v4l2_fmtdesc *f)
 707{
 708        if (f->index != 0)
 709                return -EINVAL;
 710
 711        strlcpy(f->description, "MPEG", sizeof(f->description));
 712        f->pixelformat = V4L2_PIX_FMT_MPEG;
 713        f->flags = V4L2_FMT_FLAG_COMPRESSED;
 714        return 0;
 715}
 716
 717static int vidioc_g_fmt_vid_cap (struct file *file, void *priv,
 718                                        struct v4l2_format *f)
 719{
 720        struct cx8802_fh  *fh   = priv;
 721        struct cx8802_dev *dev  = fh->dev;
 722
 723        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 724        f->fmt.pix.bytesperline = 0;
 725        f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
 726        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
 727        f->fmt.pix.width        = dev->width;
 728        f->fmt.pix.height       = dev->height;
 729        f->fmt.pix.field        = fh->mpegq.field;
 730        dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
 731                dev->width, dev->height, fh->mpegq.field );
 732        return 0;
 733}
 734
 735static int vidioc_try_fmt_vid_cap (struct file *file, void *priv,
 736                        struct v4l2_format *f)
 737{
 738        struct cx8802_fh  *fh   = priv;
 739        struct cx8802_dev *dev  = fh->dev;
 740
 741        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 742        f->fmt.pix.bytesperline = 0;
 743        f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
 744        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
 745        dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
 746                dev->width, dev->height, fh->mpegq.field );
 747        return 0;
 748}
 749
 750static int vidioc_s_fmt_vid_cap (struct file *file, void *priv,
 751                                        struct v4l2_format *f)
 752{
 753        struct cx8802_fh  *fh   = priv;
 754        struct cx8802_dev *dev  = fh->dev;
 755        struct cx88_core  *core = dev->core;
 756
 757        f->fmt.pix.pixelformat  = V4L2_PIX_FMT_MPEG;
 758        f->fmt.pix.bytesperline = 0;
 759        f->fmt.pix.sizeimage    = 188 * 4 * mpegbufs; /* 188 * 4 * 1024; */
 760        f->fmt.pix.colorspace   = V4L2_COLORSPACE_SMPTE170M;
 761        dev->width              = f->fmt.pix.width;
 762        dev->height             = f->fmt.pix.height;
 763        fh->mpegq.field         = f->fmt.pix.field;
 764        cx88_set_scale(core, f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field);
 765        blackbird_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
 766                                f->fmt.pix.height, f->fmt.pix.width);
 767        dprintk(1, "VIDIOC_S_FMT: w: %d, h: %d, f: %d\n",
 768                f->fmt.pix.width, f->fmt.pix.height, f->fmt.pix.field );
 769        return 0;
 770}
 771
 772static int vidioc_reqbufs (struct file *file, void *priv, struct v4l2_requestbuffers *p)
 773{
 774        struct cx8802_fh  *fh   = priv;
 775        return (videobuf_reqbufs(&fh->mpegq, p));
 776}
 777
 778static int vidioc_querybuf (struct file *file, void *priv, struct v4l2_buffer *p)
 779{
 780        struct cx8802_fh  *fh   = priv;
 781        return (videobuf_querybuf(&fh->mpegq, p));
 782}
 783
 784static int vidioc_qbuf (struct file *file, void *priv, struct v4l2_buffer *p)
 785{
 786        struct cx8802_fh  *fh   = priv;
 787        return (videobuf_qbuf(&fh->mpegq, p));
 788}
 789
 790static int vidioc_dqbuf (struct file *file, void *priv, struct v4l2_buffer *p)
 791{
 792        struct cx8802_fh  *fh   = priv;
 793        return (videobuf_dqbuf(&fh->mpegq, p,
 794                                file->f_flags & O_NONBLOCK));
 795}
 796
 797static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 798{
 799        struct cx8802_fh  *fh   = priv;
 800        struct cx8802_dev *dev  = fh->dev;
 801
 802        if (!dev->mpeg_active)
 803                blackbird_start_codec(file, fh);
 804        return videobuf_streamon(&fh->mpegq);
 805}
 806
 807static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 808{
 809        struct cx8802_fh  *fh   = priv;
 810        struct cx8802_dev *dev  = fh->dev;
 811
 812        if (dev->mpeg_active)
 813                blackbird_stop_codec(dev);
 814        return videobuf_streamoff(&fh->mpegq);
 815}
 816
 817static int vidioc_s_frequency (struct file *file, void *priv,
 818                                const struct v4l2_frequency *f)
 819{
 820        struct cx8802_fh  *fh   = priv;
 821        struct cx8802_dev *dev  = fh->dev;
 822        struct cx88_core  *core = dev->core;
 823
 824        if (unlikely(UNSET == core->board.tuner_type))
 825                return -EINVAL;
 826        if (unlikely(f->tuner != 0))
 827                return -EINVAL;
 828        if (dev->mpeg_active)
 829                blackbird_stop_codec(dev);
 830
 831        cx88_set_freq (core,f);
 832        blackbird_initialize_codec(dev);
 833        cx88_set_scale(dev->core, dev->width, dev->height,
 834                        fh->mpegq.field);
 835        return 0;
 836}
 837
 838static int vidioc_log_status (struct file *file, void *priv)
 839{
 840        struct cx8802_dev *dev  = ((struct cx8802_fh *)priv)->dev;
 841        struct cx88_core  *core = dev->core;
 842        char name[32 + 2];
 843
 844        snprintf(name, sizeof(name), "%s/2", core->name);
 845        call_all(core, core, log_status);
 846        v4l2_ctrl_handler_log_status(&dev->cxhdl.hdl, name);
 847        return 0;
 848}
 849
 850static int vidioc_enum_input (struct file *file, void *priv,
 851                                struct v4l2_input *i)
 852{
 853        struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 854        return cx88_enum_input (core,i);
 855}
 856
 857static int vidioc_g_frequency (struct file *file, void *priv,
 858                                struct v4l2_frequency *f)
 859{
 860        struct cx8802_fh  *fh   = priv;
 861        struct cx88_core  *core = fh->dev->core;
 862
 863        if (unlikely(UNSET == core->board.tuner_type))
 864                return -EINVAL;
 865        if (unlikely(f->tuner != 0))
 866                return -EINVAL;
 867
 868        f->frequency = core->freq;
 869        call_all(core, tuner, g_frequency, f);
 870
 871        return 0;
 872}
 873
 874static int vidioc_g_input (struct file *file, void *priv, unsigned int *i)
 875{
 876        struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 877
 878        *i = core->input;
 879        return 0;
 880}
 881
 882static int vidioc_s_input (struct file *file, void *priv, unsigned int i)
 883{
 884        struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 885
 886        if (i >= 4)
 887                return -EINVAL;
 888        if (0 == INPUT(i).type)
 889                return -EINVAL;
 890
 891        mutex_lock(&core->lock);
 892        cx88_newstation(core);
 893        cx88_video_mux(core,i);
 894        mutex_unlock(&core->lock);
 895        return 0;
 896}
 897
 898static int vidioc_g_tuner (struct file *file, void *priv,
 899                                struct v4l2_tuner *t)
 900{
 901        struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 902        u32 reg;
 903
 904        if (unlikely(UNSET == core->board.tuner_type))
 905                return -EINVAL;
 906        if (0 != t->index)
 907                return -EINVAL;
 908
 909        strcpy(t->name, "Television");
 910        t->capability = V4L2_TUNER_CAP_NORM;
 911        t->rangehigh  = 0xffffffffUL;
 912        call_all(core, tuner, g_tuner, t);
 913
 914        cx88_get_stereo(core ,t);
 915        reg = cx_read(MO_DEVICE_STATUS);
 916        t->signal = (reg & (1<<5)) ? 0xffff : 0x0000;
 917        return 0;
 918}
 919
 920static int vidioc_s_tuner (struct file *file, void *priv,
 921                                const struct v4l2_tuner *t)
 922{
 923        struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 924
 925        if (UNSET == core->board.tuner_type)
 926                return -EINVAL;
 927        if (0 != t->index)
 928                return -EINVAL;
 929
 930        cx88_set_stereo(core, t->audmode, 1);
 931        return 0;
 932}
 933
 934static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
 935{
 936        struct cx88_core *core = ((struct cx8802_fh *)priv)->dev->core;
 937
 938        *tvnorm = core->tvnorm;
 939        return 0;
 940}
 941
 942static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id id)
 943{
 944        struct cx88_core  *core = ((struct cx8802_fh *)priv)->dev->core;
 945
 946        mutex_lock(&core->lock);
 947        cx88_set_tvnorm(core, id);
 948        mutex_unlock(&core->lock);
 949        return 0;
 950}
 951
 952/* FIXME: cx88_ioctl_hook not implemented */
 953
 954static int mpeg_open(struct file *file)
 955{
 956        struct video_device *vdev = video_devdata(file);
 957        struct cx8802_dev *dev = video_drvdata(file);
 958        struct cx8802_fh *fh;
 959        struct cx8802_driver *drv = NULL;
 960        int err;
 961
 962        dprintk( 1, "%s\n", __func__);
 963
 964        mutex_lock(&dev->core->lock);
 965
 966        /* Make sure we can acquire the hardware */
 967        drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
 968        if (!drv) {
 969                dprintk(1, "%s: blackbird driver is not loaded\n", __func__);
 970                mutex_unlock(&dev->core->lock);
 971                return -ENODEV;
 972        }
 973
 974        err = drv->request_acquire(drv);
 975        if (err != 0) {
 976                dprintk(1,"%s: Unable to acquire hardware, %d\n", __func__, err);
 977                mutex_unlock(&dev->core->lock);
 978                return err;
 979        }
 980
 981        if (!dev->core->mpeg_users && blackbird_initialize_codec(dev) < 0) {
 982                drv->request_release(drv);
 983                mutex_unlock(&dev->core->lock);
 984                return -EINVAL;
 985        }
 986        dprintk(1, "open dev=%s\n", video_device_node_name(vdev));
 987
 988        /* allocate + initialize per filehandle data */
 989        fh = kzalloc(sizeof(*fh),GFP_KERNEL);
 990        if (NULL == fh) {
 991                drv->request_release(drv);
 992                mutex_unlock(&dev->core->lock);
 993                return -ENOMEM;
 994        }
 995        v4l2_fh_init(&fh->fh, vdev);
 996        file->private_data = fh;
 997        fh->dev      = dev;
 998
 999        videobuf_queue_sg_init(&fh->mpegq, &blackbird_qops,
1000                            &dev->pci->dev, &dev->slock,
1001                            V4L2_BUF_TYPE_VIDEO_CAPTURE,
1002                            V4L2_FIELD_INTERLACED,
1003                            sizeof(struct cx88_buffer),
1004                            fh, NULL);
1005
1006        /* FIXME: locking against other video device */
1007        cx88_set_scale(dev->core, dev->width, dev->height,
1008                        fh->mpegq.field);
1009
1010        dev->core->mpeg_users++;
1011        mutex_unlock(&dev->core->lock);
1012        v4l2_fh_add(&fh->fh);
1013        return 0;
1014}
1015
1016static int mpeg_release(struct file *file)
1017{
1018        struct cx8802_fh  *fh  = file->private_data;
1019        struct cx8802_dev *dev = fh->dev;
1020        struct cx8802_driver *drv = NULL;
1021
1022        mutex_lock(&dev->core->lock);
1023
1024        if (dev->mpeg_active && dev->core->mpeg_users == 1)
1025                blackbird_stop_codec(dev);
1026
1027        cx8802_cancel_buffers(fh->dev);
1028        /* stop mpeg capture */
1029        videobuf_stop(&fh->mpegq);
1030
1031        videobuf_mmap_free(&fh->mpegq);
1032
1033        v4l2_fh_del(&fh->fh);
1034        v4l2_fh_exit(&fh->fh);
1035        file->private_data = NULL;
1036        kfree(fh);
1037
1038        /* Make sure we release the hardware */
1039        drv = cx8802_get_driver(dev, CX88_MPEG_BLACKBIRD);
1040        WARN_ON(!drv);
1041        if (drv)
1042                drv->request_release(drv);
1043
1044        dev->core->mpeg_users--;
1045
1046        mutex_unlock(&dev->core->lock);
1047
1048        return 0;
1049}
1050
1051static ssize_t
1052mpeg_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
1053{
1054        struct cx8802_fh *fh = file->private_data;
1055        struct cx8802_dev *dev = fh->dev;
1056
1057        if (!dev->mpeg_active)
1058                blackbird_start_codec(file, fh);
1059
1060        return videobuf_read_stream(&fh->mpegq, data, count, ppos, 0,
1061                                    file->f_flags & O_NONBLOCK);
1062}
1063
1064static unsigned int
1065mpeg_poll(struct file *file, struct poll_table_struct *wait)
1066{
1067        unsigned long req_events = poll_requested_events(wait);
1068        struct cx8802_fh *fh = file->private_data;
1069        struct cx8802_dev *dev = fh->dev;
1070
1071        if (!dev->mpeg_active && (req_events & (POLLIN | POLLRDNORM)))
1072                blackbird_start_codec(file, fh);
1073
1074        return v4l2_ctrl_poll(file, wait) | videobuf_poll_stream(file, &fh->mpegq, wait);
1075}
1076
1077static int
1078mpeg_mmap(struct file *file, struct vm_area_struct * vma)
1079{
1080        struct cx8802_fh *fh = file->private_data;
1081
1082        return videobuf_mmap_mapper(&fh->mpegq, vma);
1083}
1084
1085static const struct v4l2_file_operations mpeg_fops =
1086{
1087        .owner         = THIS_MODULE,
1088        .open          = mpeg_open,
1089        .release       = mpeg_release,
1090        .read          = mpeg_read,
1091        .poll          = mpeg_poll,
1092        .mmap          = mpeg_mmap,
1093        .unlocked_ioctl = video_ioctl2,
1094};
1095
1096static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
1097        .vidioc_querycap      = vidioc_querycap,
1098        .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
1099        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
1100        .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
1101        .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
1102        .vidioc_reqbufs       = vidioc_reqbufs,
1103        .vidioc_querybuf      = vidioc_querybuf,
1104        .vidioc_qbuf          = vidioc_qbuf,
1105        .vidioc_dqbuf         = vidioc_dqbuf,
1106        .vidioc_streamon      = vidioc_streamon,
1107        .vidioc_streamoff     = vidioc_streamoff,
1108        .vidioc_s_frequency   = vidioc_s_frequency,
1109        .vidioc_log_status    = vidioc_log_status,
1110        .vidioc_enum_input    = vidioc_enum_input,
1111        .vidioc_g_frequency   = vidioc_g_frequency,
1112        .vidioc_g_input       = vidioc_g_input,
1113        .vidioc_s_input       = vidioc_s_input,
1114        .vidioc_g_tuner       = vidioc_g_tuner,
1115        .vidioc_s_tuner       = vidioc_s_tuner,
1116        .vidioc_g_std         = vidioc_g_std,
1117        .vidioc_s_std         = vidioc_s_std,
1118        .vidioc_subscribe_event      = v4l2_ctrl_subscribe_event,
1119        .vidioc_unsubscribe_event    = v4l2_event_unsubscribe,
1120};
1121
1122static struct video_device cx8802_mpeg_template = {
1123        .name                 = "cx8802",
1124        .fops                 = &mpeg_fops,
1125        .ioctl_ops            = &mpeg_ioctl_ops,
1126        .tvnorms              = CX88_NORMS,
1127};
1128
1129/* ------------------------------------------------------------------ */
1130
1131/* The CX8802 MPEG API will call this when we can use the hardware */
1132static int cx8802_blackbird_advise_acquire(struct cx8802_driver *drv)
1133{
1134        struct cx88_core *core = drv->core;
1135        int err = 0;
1136
1137        switch (core->boardnr) {
1138        case CX88_BOARD_HAUPPAUGE_HVR1300:
1139                /* By default, core setup will leave the cx22702 out of reset, on the bus.
1140                 * We left the hardware on power up with the cx22702 active.
1141                 * We're being given access to re-arrange the GPIOs.
1142                 * Take the bus off the cx22702 and put the cx23416 on it.
1143                 */
1144                /* Toggle reset on cx22702 leaving i2c active */
1145                cx_set(MO_GP0_IO, 0x00000080);
1146                udelay(1000);
1147                cx_clear(MO_GP0_IO, 0x00000080);
1148                udelay(50);
1149                cx_set(MO_GP0_IO, 0x00000080);
1150                udelay(1000);
1151                /* tri-state the cx22702 pins */
1152                cx_set(MO_GP0_IO, 0x00000004);
1153                udelay(1000);
1154                break;
1155        default:
1156                err = -ENODEV;
1157        }
1158        return err;
1159}
1160
1161/* The CX8802 MPEG API will call this when we need to release the hardware */
1162static int cx8802_blackbird_advise_release(struct cx8802_driver *drv)
1163{
1164        struct cx88_core *core = drv->core;
1165        int err = 0;
1166
1167        switch (core->boardnr) {
1168        case CX88_BOARD_HAUPPAUGE_HVR1300:
1169                /* Exit leaving the cx23416 on the bus */
1170                break;
1171        default:
1172                err = -ENODEV;
1173        }
1174        return err;
1175}
1176
1177static void blackbird_unregister_video(struct cx8802_dev *dev)
1178{
1179        if (dev->mpeg_dev) {
1180                if (video_is_registered(dev->mpeg_dev))
1181                        video_unregister_device(dev->mpeg_dev);
1182                else
1183                        video_device_release(dev->mpeg_dev);
1184                dev->mpeg_dev = NULL;
1185        }
1186}
1187
1188static int blackbird_register_video(struct cx8802_dev *dev)
1189{
1190        int err;
1191
1192        dev->mpeg_dev = cx88_vdev_init(dev->core,dev->pci,
1193                                       &cx8802_mpeg_template,"mpeg");
1194        dev->mpeg_dev->ctrl_handler = &dev->cxhdl.hdl;
1195        video_set_drvdata(dev->mpeg_dev, dev);
1196        err = video_register_device(dev->mpeg_dev,VFL_TYPE_GRABBER, -1);
1197        if (err < 0) {
1198                printk(KERN_INFO "%s/2: can't register mpeg device\n",
1199                       dev->core->name);
1200                return err;
1201        }
1202        printk(KERN_INFO "%s/2: registered device %s [mpeg]\n",
1203               dev->core->name, video_device_node_name(dev->mpeg_dev));
1204        return 0;
1205}
1206
1207/* ----------------------------------------------------------- */
1208
1209static int cx8802_blackbird_probe(struct cx8802_driver *drv)
1210{
1211        struct cx88_core *core = drv->core;
1212        struct cx8802_dev *dev = core->dvbdev;
1213        int err;
1214
1215        dprintk( 1, "%s\n", __func__);
1216        dprintk( 1, " ->being probed by Card=%d Name=%s, PCI %02x:%02x\n",
1217                core->boardnr,
1218                core->name,
1219                core->pci_bus,
1220                core->pci_slot);
1221
1222        err = -ENODEV;
1223        if (!(core->board.mpeg & CX88_MPEG_BLACKBIRD))
1224                goto fail_core;
1225
1226        dev->width = 720;
1227        if (core->tvnorm & V4L2_STD_525_60) {
1228                dev->height = 480;
1229        } else {
1230                dev->height = 576;
1231        }
1232        dev->cxhdl.port = CX2341X_PORT_STREAMING;
1233        dev->cxhdl.width = dev->width;
1234        dev->cxhdl.height = dev->height;
1235        dev->cxhdl.func = blackbird_mbox_func;
1236        dev->cxhdl.priv = dev;
1237        err = cx2341x_handler_init(&dev->cxhdl, 36);
1238        if (err)
1239                goto fail_core;
1240        v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL);
1241
1242        /* blackbird stuff */
1243        printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
1244               core->name);
1245        host_setup(dev->core);
1246
1247        blackbird_initialize_codec(dev);
1248
1249        /* initial device configuration: needed ? */
1250//      init_controls(core);
1251        cx88_set_tvnorm(core,core->tvnorm);
1252        cx88_video_mux(core,0);
1253        cx2341x_handler_set_50hz(&dev->cxhdl, dev->height == 576);
1254        cx2341x_handler_setup(&dev->cxhdl);
1255        blackbird_register_video(dev);
1256
1257        return 0;
1258
1259 fail_core:
1260        return err;
1261}
1262
1263static int cx8802_blackbird_remove(struct cx8802_driver *drv)
1264{
1265        struct cx88_core *core = drv->core;
1266        struct cx8802_dev *dev = core->dvbdev;
1267
1268        /* blackbird */
1269        blackbird_unregister_video(drv->core->dvbdev);
1270        v4l2_ctrl_handler_free(&dev->cxhdl.hdl);
1271
1272        return 0;
1273}
1274
1275static struct cx8802_driver cx8802_blackbird_driver = {
1276        .type_id        = CX88_MPEG_BLACKBIRD,
1277        .hw_access      = CX8802_DRVCTL_SHARED,
1278        .probe          = cx8802_blackbird_probe,
1279        .remove         = cx8802_blackbird_remove,
1280        .advise_acquire = cx8802_blackbird_advise_acquire,
1281        .advise_release = cx8802_blackbird_advise_release,
1282};
1283
1284static int __init blackbird_init(void)
1285{
1286        printk(KERN_INFO "cx2388x blackbird driver version %s loaded\n",
1287               CX88_VERSION);
1288        return cx8802_register_driver(&cx8802_blackbird_driver);
1289}
1290
1291static void __exit blackbird_fini(void)
1292{
1293        cx8802_unregister_driver(&cx8802_blackbird_driver);
1294}
1295
1296module_init(blackbird_init);
1297module_exit(blackbird_fini);
1298
1299module_param_named(video_debug,cx8802_mpeg_template.debug, int, 0644);
1300MODULE_PARM_DESC(debug,"enable debug messages [video]");
1301