diff options
Diffstat (limited to 'linux/drivers/media/video/cx88/cx88-blackbird.c')
-rw-r--r-- | linux/drivers/media/video/cx88/cx88-blackbird.c | 539 |
1 files changed, 317 insertions, 222 deletions
diff --git a/linux/drivers/media/video/cx88/cx88-blackbird.c b/linux/drivers/media/video/cx88/cx88-blackbird.c index 5d1b83107..51f4b1e9a 100644 --- a/linux/drivers/media/video/cx88/cx88-blackbird.c +++ b/linux/drivers/media/video/cx88/cx88-blackbird.c @@ -1,5 +1,5 @@ /* - * $Id: cx88-blackbird.c,v 1.4 2004/08/23 10:38:54 kraxel Exp $ + * $Id: cx88-blackbird.c,v 1.5 2004/08/25 14:47:53 kraxel Exp $ * * Support for a cx23416 mpeg encoder via cx2388x host port. * "blackbird" reference design. @@ -34,9 +34,23 @@ #include "cx88.h" MODULE_DESCRIPTION("driver for cx2388x/cx23416 based mpeg encoder cards"); -MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>"); +MODULE_AUTHOR("Jelle Foks <jelle@foks.8m.com>"); +MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]"); MODULE_LICENSE("GPL"); +static unsigned int mpegbufs = 8; +MODULE_PARM(mpegbufs,"i"); +MODULE_PARM_DESC(mpegbufs,"number of mpeg buffers, range 2-32"); + +static unsigned int debug = 0; +MODULE_PARM(debug,"i"); +MODULE_PARM_DESC(debug,"enable debug messages [blackbird]"); + +#define dprintk(level,fmt, arg...) if (debug >= level) \ + printk(KERN_DEBUG "%s/2-bb: " fmt, dev->core->name , ## arg) + +static struct list_head cx8802_devlist; + /* ------------------------------------------------------------------ */ #define BLACKBIRD_FIRM_ENC_FILENAME "blackbird-fw-enc.bin" @@ -222,364 +236,357 @@ static int register_read(struct cx88_core *core, u32 address, u32 *value) /* ------------------------------------------------------------------ */ -#if 0 - /* We don't need to call the API often, so using just one mailbox will probably suffice */ -int blackbird_cmd(struct cx8802_dev *dev, u32 command, u32 inputcnt, u32 outputcnt, ...) +static int blackbird_api_cmd(struct cx8802_dev *dev, u32 command, + u32 inputcnt, u32 outputcnt, ...) { va_list args; va_start(args, outputcnt); + unsigned long timeout; + u32 value, flag, retval; int i; - u32 value; - u32 flag; dprintk(1,"%s: 0x%X\n", __FUNCTION__, command); /* this may not be 100% safe if we can't read any memory location without side effects */ - memory_read(dev, dev->mpegport_mailbox - 4, &value); + memory_read(dev->core, dev->mailbox - 4, &value); if (value != 0x12345678) { dprintk(0, "Firmware and/or mailbox pointer not initialized or corrupted\n"); return -1; } - memory_read(dev, dev->mpegport_mailbox, &flag); + memory_read(dev->core, dev->mailbox, &flag); if (flag) { dprintk(0, "ERROR: Mailbox appears to be in use (%x)\n", flag); return -1; } flag |= 1; /* tell 'em we're working on it */ - memory_write(dev, dev->mpegport_mailbox, flag); + memory_write(dev->core, dev->mailbox, flag); - memory_write(dev, dev->mpegport_mailbox + 1, command); /* command code */ - memory_write(dev, dev->mpegport_mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ - - /* write input values */ + /* write command + args + fill remaining with zeros */ + memory_write(dev->core, dev->mailbox + 1, command); /* command code */ + memory_write(dev->core, dev->mailbox + 3, IVTV_API_STD_TIMEOUT); /* timeout */ for (i = 0; i < inputcnt ; i++) { - u32 value = va_arg(args, int); - memory_write(dev, dev->mpegport_mailbox + 4 + i, value); + value = va_arg(args, int); + memory_write(dev->core, dev->mailbox + 4 + i, value); dprintk(1, "API Input %d = %d\n", i, value); } - - /* fill with zeroes (ivtv does it, but is this necessary?) */ - for (; i < 16 ; i++) { - u32 value = 0; - memory_write(dev, dev->mpegport_mailbox + 4 + i, value); - } + for (; i < 16 ; i++) + memory_write(dev->core, dev->mailbox + 4 + i, 0); flag |= 3; /* tell 'em we're done writing */ - memory_write(dev, dev->mpegport_mailbox, flag); + memory_write(dev->core, dev->mailbox, flag); /* wait for firmware to handle the API command */ - int timeoutcnt = 500; /* trial and error plus a margin (longest command I've seen is capture start) */ - do { + timeout = jiffies + msecs_to_jiffies(10); + for (;;) { + memory_read(dev->core, dev->mailbox, &flag); + if (0 == (flag & 4)) + break; + if (time_after(jiffies,timeout)) { + dprintk(0, "ERROR: API Mailbox timeout\n"); + return -1; + } udelay(10); - timeoutcnt--; - memory_read(dev, dev->mpegport_mailbox, &flag); - } while (timeoutcnt && ((flag & 4)==0)); - - if (!timeoutcnt) { - dprintk(0, "ERROR: API Mailbox timeout\n"); - flag = 0; - memory_write(dev, dev->mpegport_mailbox, flag); - return -1; } - + /* read output values */ for (i = 0; i < outputcnt ; i++) { - u32 *value = va_arg(args, int *); - memory_read(dev, dev->mpegport_mailbox + 4 + i, value); - dprintk(1, "API Output %d = %d\n", i, *value); + int *vptr = va_arg(args, int *); + memory_read(dev->core, dev->mailbox + 4 + i, vptr); + dprintk(1, "API Output %d = %d\n", i, *vptr); } - va_end(args); - u32 retval; - memory_read(dev, dev->mpegport_mailbox + 2, &retval); - dprintk(1, "API result = %d (timeoutcnt=%d)\n",retval, timeoutcnt); + memory_read(dev->core, dev->mailbox + 2, &retval); + dprintk(1, "API result = %d\n",retval); + flag = 0; - memory_write(dev, dev->mpegport_mailbox, flag); + memory_write(dev->core, dev->mailbox, flag); return retval; } -int mpegport_find_mailbox(struct cx8800_dev *dev) +static int blackbird_find_mailbox(struct cx8802_dev *dev) { u32 signature[4]={0x12345678, 0x34567812, 0x56781234, 0x78123456}; int signaturecnt=0; + u32 value; int i; - for (i = 0; (i < BLACKBIRD_FIRM_IMAGE_SIZE) && (signaturecnt < 4) ; i++) - { - u32 value; - memory_read(dev, i, &value); + + for (i = 0; i < BLACKBIRD_FIRM_IMAGE_SIZE; i++) { + memory_read(dev->core, i, &value); if (value == signature[signaturecnt]) signaturecnt++; else signaturecnt = 0; + if (4 == signaturecnt) { + dprintk(1, "Mailbox signature found\n"); + return i; + } } - if (signaturecnt == 4) - { - dprintk(1, "Mailbox signature found\n"); - return i; - } - else - { - dprintk(0, "Mailbox signature values not found!\n"); - return -1; - } + dprintk(0, "Mailbox signature values not found!\n"); + return -1; } -int mpegport_load_firmware(struct cx8800_dev *dev) +static int blackbird_load_firmware(struct cx8802_dev *dev) { - dprintk(1,"Loading firmware\n"); + static const unsigned char magic[8] = { + 0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa + }; + const struct firmware *firmware; int i, retval = 0; u32 value = 0; - const struct firmware *blackbird_firmware; - - retval = register_write(dev, IVTV_REG_VPU, 0xFFFFFFED); - //retval = register_write(dev, IVTV_REG_VPU, 0xFFFFFFEF); - retval |= register_write(dev, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_write(dev, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); - retval |= register_write(dev, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); - udelay(500); - retval |= register_write(dev, IVTV_REG_APU, 0); - - if (retval < 0) dprintk(0, "Error with register_write\n"); + u32 checksum = 0; + u32 *dataptr; - /* without this, the encoder chip is just a dead chip */ + retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); + msleep(1); + retval |= register_write(dev->core, IVTV_REG_APU, 0); - /* for this to work, 'apt-get install hotplug' and copy the firmware binary to /usr/lib/hotplug/firmware */ - retval = request_firmware(&blackbird_firmware, BLACKBIRD_FIRM_ENC_FILENAME, &dev->pci->dev); + if (retval < 0) + dprintk(0, "Error with register_write\n"); + retval = request_firmware(&firmware, BLACKBIRD_FIRM_ENC_FILENAME, + &dev->pci->dev); if (retval != 0) { - dprintk(0, "ERROR: Hotplug firmware request failed! Fatal for mpegport support!\n"); - dprintk(0, "********** Perhaps hotplug utilities or the firmware file is not installed?\n"); - dprintk(0, "********** Or kernel hotplug support of Firmware loading support is not enabled?\n"); - dprintk(0, "********** - Kernel setup: Your kernel needs the following options:\n"); - dprintk(0, "********** 1) enable CONFIG_HOTPLUG from \"General Setup\"/\"Support for hot-pluggable devices\"\n"); - dprintk(0, "********** 2) enable CONFIG_FW_LOADER from \"Device Drivers\"/\"Generic Driver Options\"/\"Hotplug firmware loading support\"\n"); - dprintk(0, "********** - Hotplug support utilities:\n"); - dprintk(0, "********** 1) make sure sysfs is mounted on /sys\n"); - dprintk(0, "********** 2) copy the firmware binary to /usr/lib/hotplug/firmware/" BLACKBIRD_FIRM_ENC_FILENAME "\n"); - dprintk(0, "********** 3) Debian: 'apt-get install hotplug'\n"); - dprintk(0, "********** Others: Unknown (ask your vendor) or go here http://linux-hotplug.sourceforge.net/\n"); - dprintk(0, "********** You will also probably want to have a /etc/hotplug/firmware.agent\n"); + dprintk(0, "ERROR: Hotplug firmware request failed (%s).\n", + BLACKBIRD_FIRM_ENC_FILENAME); + dprintk(0, "Please fix your hotplug setup, the board will " + "not work without firmware loaded!\n"); return -1; } - if (blackbird_firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { - dprintk(0, "ERROR: Firmware is %d bytes long, which should be %d bytes.\n", blackbird_firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); + if (firmware->size != BLACKBIRD_FIRM_IMAGE_SIZE) { + dprintk(0, "ERROR: Firmware size mismatch (have %ld, expected %d)\n", + firmware->size, BLACKBIRD_FIRM_IMAGE_SIZE); return -1; } - if ((blackbird_firmware->data[0] != 0xA7) || - (blackbird_firmware->data[1] != 0x0D) || - (blackbird_firmware->data[2] != 0x00) || - (blackbird_firmware->data[3] != 0x00) || - (blackbird_firmware->data[4] != 0x66) || - (blackbird_firmware->data[5] != 0xBB) || - (blackbird_firmware->data[6] != 0x55) || - (blackbird_firmware->data[7] != 0xAA)) { - dprintk(0, "ERROR: Firmware is corrupt or not for an encoder chip\n"); + if (0 != memcmp(firmware->data, magic, 8)) { + dprintk(0, "ERROR: Firmware magic mismatch, wrong file?\n"); return -1; } /* transfer to the chip */ - u32 checksum = 0; - u32 *dataptr = (u32 *)blackbird_firmware->data; - for (i = 0; i < (blackbird_firmware->size >> 2); i++) { + dprintk(1,"Loading firmware ...\n"); + dataptr = (u32*)firmware->data; + for (i = 0; i < (firmware->size >> 2); i++) { value = *dataptr; checksum += ~value; - memory_write(dev, i, value); + memory_write(dev->core, i, value); dataptr++; } - release_firmware(blackbird_firmware); - - /* this takes a whole second, but it ensures the upload worked (maybe some hw needs other RAM timings, etc) */ /* read back to verify with the checksum */ for (i--; i >= 0; i--) { - memory_read(dev, i, &value); + memory_read(dev->core, i, &value); checksum -= ~value; } - if (checksum) { - dprintk(0, "ERROR: Firmware Upload Failed (memory checksums don't match).\n"); + dprintk(0, "ERROR: Firmware load failed (checksum mismatch).\n"); return -1; } - + release_firmware(firmware); dprintk(0, "Firmware upload successful.\n"); -#if 0 - for (i = 0; i < 1024; i+=4) { - //u32 value; - memory_read(dev, (i>>2), &value); - if (0 == (i % 16)) - printk(KERN_INFO "cx88 fw: %02x:",i); - printk(" %02x %02x %02x %02x",(value & 0xFF),((value>>8) & 0xFF),((value>>16) & 0xFF),((value>>24) & 0xFF)); - if (12 == (i % 16)) - printk("\n"); - } -#endif - - retval |= register_write(dev, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_read(dev, IVTV_REG_SPU, &value); - retval |= register_write(dev, IVTV_REG_SPU, value & 0xFFFFFFFE); - - udelay(1000); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_read(dev->core, IVTV_REG_SPU, &value); + retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); + msleep(1); - retval |= register_read(dev, IVTV_REG_VPU, &value); - retval |= register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8UL); - //retval |= register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFFB); + retval |= register_read(dev->core, IVTV_REG_VPU, &value); + retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); - if (retval < 0) dprintk(0, "Error with register_write\n"); + if (retval < 0) + dprintk(0, "Error with register_write\n"); return 0; } -void mpegport_codec_settings(struct cx8800_dev *dev) +static void blackbird_codec_settings(struct cx8802_dev *dev) { + int bitrate_mode = 1; + int bitrate = 7500000; + int bitrate_peak = 7500000; + /* assign stream type */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 0); /* program stream */ - //mpegport_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 2); /* MPEG1 stream */ - //mpegport_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 3); /* PES A/V */ - //mpegport_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 10); /* DVD stream */ + blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 0); /* program stream */ + //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 2); /* MPEG1 stream */ + //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 3); /* PES A/V */ + //blackbird_api_cmd(dev, IVTV_API_ASSIGN_STREAM_TYPE, 1, 0, 10); /* DVD stream */ /* assign output port */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_OUTPUT_PORT, 1, 0, 1); /* 1 = Host */ + blackbird_api_cmd(dev, IVTV_API_ASSIGN_OUTPUT_PORT, 1, 0, 1); /* 1 = Host */ /* assign framerate */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAMERATE, 1, 0, 0); /* assign frame size */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, 480, 720); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_SIZE, 2, 0, 480, 720); /* assign aspect ratio */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_ASPECT_RATIO, 1, 0, 2); - int bitrate_mode = 1; - int bitrate = 7500000; - int bitrate_peak = 7500000; /* assign bitrates */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_BITRATES, 5, 0, - bitrate_mode, /* mode */ - bitrate, /* bps */ - bitrate_peak / 400, /* peak/400 */ - 0, 0x70); /* encoding buffer, ckennedy */ + blackbird_api_cmd(dev, IVTV_API_ASSIGN_BITRATES, 5, 0, + bitrate_mode, /* mode */ + bitrate, /* bps */ + bitrate_peak / 400, /* peak/400 */ + 0, 0x70); /* encoding buffer, ckennedy */ /* assign gop properties */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 15, 3); - //mpegport_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 2, 1); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 15, 3); + //blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_PROPERTIES, 2, 0, 2, 1); /* assign 3 2 pulldown */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_3_2_PULLDOWN, 1, 0, 0); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_3_2_PULLDOWN, 1, 0, 0); /* note: it's not necessary to set the samplerate, the mpeg encoder seems to autodetect/adjust */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4)); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, (2<<2) | (8<<4)); /* assign gop closure */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_GOP_CLOSURE, 1, 0, 0); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_GOP_CLOSURE, 1, 0, 0); /* assign audio properties */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_AUDIO_PROPERTIES, 1, 0, 0 | (2 << 2) | (14 << 4)); /* assign dnr filter mode */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_MODE, 2, 0, 0, 0); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_MODE, 2, 0, 0, 0); /* assign dnr filter props*/ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_PROPS, 2, 0, 0, 0); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_DNR_FILTER_PROPS, 2, 0, 0, 0); /* assign coring levels (luma_h, luma_l, chroma_h, chroma_l) */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_CORING_LEVELS, 4, 0, 0, 255, 0, 255); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_CORING_LEVELS, 4, 0, 0, 255, 0, 255); /* assign spatial filter type: luma_t: 1 = horiz_only, chroma_t: 1 = horiz_only */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, 2, 0, 1, 1); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_SPATIAL_FILTER_TYPE, 2, 0, 1, 1); /* assign frame drop rate */ - mpegport_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_FRAME_DROP_RATE, 1, 0, 0); } -int mpegport_initialize_codec(struct cx8800_dev *dev) +static int blackbird_initialize_codec(struct cx8802_dev *dev) { + struct cx88_core *core = dev->core; + int version; int retval; + dprintk(1,"Initialize codec\n"); - - retval = mpegport_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ + retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { /* ping was not successful, reset and upload firmware */ - cx_write(MO_SRST_IO, 0); /* SYS_RSTO=0 */ - udelay(300); + msleep(1); cx_write(MO_SRST_IO, 1); /* SYS_RSTO=1 */ - udelay(100); - - retval = mpegport_load_firmware(dev); - if (retval < 0) { dprintk(0, "Error with firmware load!\n"); return retval; } - - dev->mpegport_mailbox = mpegport_find_mailbox(dev); - if (dev->mpegport_mailbox < 0) { dprintk(0, "Error with mailbox search!\n"); return dev->mpegport_mailbox; } + msleep(1); + retval = blackbird_load_firmware(dev); + if (retval < 0) + return retval; + + dev->mailbox = blackbird_find_mailbox(dev); + if (dev->mailbox < 0) + return -1; - retval = mpegport_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ + retval = blackbird_api_cmd(dev, IVTV_API_ENC_PING_FW, 0, 0); /* ping */ if (retval < 0) { dprintk(0, "ERROR: Firmware ping failed!\n"); return -1; } - int firmware_version; - retval = mpegport_api_cmd(dev, IVTV_API_ENC_GETVER, 0, 1, &firmware_version); + retval = blackbird_api_cmd(dev, IVTV_API_ENC_GETVER, 0, 1, &version); if (retval < 0) { dprintk(0, "ERROR: Firmware get encoder version failed!\n"); return -1; } - dprintk(0, "Encoder revision: 0x%08x\n", firmware_version); - - } - else - { - dprintk(1, "Firmware already present and responding to ping (not reloading)\n"); + dprintk(0, "Firmware version is 0x%08x\n", version); } - - udelay(500); + msleep(1); cx_write(MO_PINMUX_IO, 0x88); /* 656-8bit IO and enable MPEG parallel IO */ cx_clear(MO_INPUT_FORMAT, 0x100); /* chroma subcarrier lock to normal? */ cx_write(MO_VBOS_CONTROL, 0x84A00); /* no 656 mode, 8-bit pixels, disable VBI */ - cx_clear(MO_OUTPUT_FORMAT, 0x0008); /* Normal Y-limits to let the mpeg encoder sync */ - /* this seems to be necessary, because otherwise the picture isn't always correct, - even though I think the scaler in the cx23880 should not change the itu656 output. - maybe it's a pll or something? */ +#if 0 /* FIXME */ set_scale(dev, 720, 480, V4L2_FIELD_INTERLACED); +#endif + blackbird_codec_settings(dev); + msleep(1); - udelay(500); - - mpegport_codec_settings(dev); - - //mpegport_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); - mpegport_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); - //mpegport_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); - mpegport_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xef, 0xef); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0xf0, 0xf0); + //blackbird_api_cmd(dev, IVTV_API_ASSIGN_NUM_VSYNC_LINES, 4, 0, 0x180, 0x180); + blackbird_api_cmd(dev, IVTV_API_ASSIGN_PLACEHOLDER, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - mpegport_api_cmd(dev, IVTV_API_INITIALIZE_INPUT, 0, 0); /* initialize the video input */ + blackbird_api_cmd(dev, IVTV_API_INITIALIZE_INPUT, 0, 0); /* initialize the video input */ - udelay(500); + msleep(1); - mpegport_api_cmd(dev, IVTV_API_MUTE_VIDEO, 1, 0, 0); - udelay(500); - mpegport_api_cmd(dev, IVTV_API_MUTE_AUDIO, 1, 0, 0); - udelay(500); - - mpegport_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); /* start capturing to the host interface */ - //mpegport_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0); /* start capturing to the host interface */ + blackbird_api_cmd(dev, IVTV_API_MUTE_VIDEO, 1, 0, 0); + msleep(1); + blackbird_api_cmd(dev, IVTV_API_MUTE_AUDIO, 1, 0, 0); + msleep(1); - udelay(500); + blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0x13); /* start capturing to the host interface */ + //blackbird_api_cmd(dev, IVTV_API_BEGIN_CAPTURE, 2, 0, 0, 0); /* start capturing to the host interface */ + msleep(1); - mpegport_api_cmd(dev, IVTV_API_REFRESH_INPUT, 0,0); - return retval; + blackbird_api_cmd(dev, IVTV_API_REFRESH_INPUT, 0,0); + return 0; } -#endif +/* ------------------------------------------------------------------ */ + +static int bb_buf_setup(struct file *file, unsigned int *count, unsigned int *size) +{ + struct cx8802_fh *fh = file->private_data; + + fh->dev->ts_packet_size = 512; + fh->dev->ts_packet_count = 100; + + *size = fh->dev->ts_packet_size * fh->dev->ts_packet_count; + if (0 == *count) + *count = mpegbufs; + if (*count < 2) + *count = 2; + if (*count > 32) + *count = 32; + return 0; +} + +static int +bb_buf_prepare(struct file *file, struct videobuf_buffer *vb, + enum v4l2_field field) +{ + struct cx8802_fh *fh = file->private_data; + return cx8802_buf_prepare(fh->dev, (struct cx88_buffer*)vb); +} + +static void +bb_buf_queue(struct file *file, struct videobuf_buffer *vb) +{ + struct cx8802_fh *fh = file->private_data; + cx8802_buf_queue(fh->dev, (struct cx88_buffer*)vb); +} + +static void bb_buf_release(struct file *file, struct videobuf_buffer *vb) +{ + struct cx8802_fh *fh = file->private_data; + cx88_free_buffer(fh->dev->pci, (struct cx88_buffer*)vb); +} + +static struct videobuf_queue_ops blackbird_qops = { + .buf_setup = bb_buf_setup, + .buf_prepare = bb_buf_prepare, + .buf_queue = bb_buf_queue, + .buf_release = bb_buf_release, +}; /* ------------------------------------------------------------------ */ @@ -587,13 +594,10 @@ static int mpeg_do_ioctl(struct inode *inode, struct file *file, unsigned int cmd, void *arg) { struct cx8802_fh *fh = file->private_data; - -#if 0 struct cx8802_dev *dev = fh->dev; - if (mpeg_debug > 1) + if (debug > 1) cx88_print_ioctl(dev->core->name,cmd); -#endif switch (cmd) { @@ -670,16 +674,14 @@ static int mpeg_open(struct inode *inode, struct file *file) list_for_each(list,&cx8802_devlist) { h = list_entry(list, struct cx8802_dev, devlist); if (h->mpeg_dev->minor == minor) - dev = h; + dev = h; } if (NULL == dev) return -ENODEV; -#if 0 /* FIXME */ - if (mpegport_initialize_codec(dev) < 0) + if (blackbird_initialize_codec(dev) < 0) return -EINVAL; dprintk(1,"open minor=%d\n",minor); -#endif /* allocate + initialize per filehandle data */ fh = kmalloc(sizeof(*fh),GFP_KERNEL); @@ -689,7 +691,7 @@ static int mpeg_open(struct inode *inode, struct file *file) file->private_data = fh; fh->dev = dev; - videobuf_queue_init(&fh->mpegq, &cx8802_mpeg_qops, + videobuf_queue_init(&fh->mpegq, &blackbird_qops, dev->pci, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_TOP, @@ -703,9 +705,7 @@ static int mpeg_release(struct inode *inode, struct file *file) { struct cx8802_fh *fh = file->private_data; -#if 0 /* FIXME */ - mpegport_api_cmd(fh->dev, IVTV_API_END_CAPTURE, 3, 0, 1, 0, 0x13); -#endif + blackbird_api_cmd(fh->dev, IVTV_API_END_CAPTURE, 3, 0, 1, 0, 0x13); /* stop mpeg capture */ if (fh->mpegq.streaming) @@ -765,7 +765,7 @@ static struct video_device cx8802_mpeg_template = /* ------------------------------------------------------------------ */ -static void cx8802_unregister_video(struct cx8802_dev *dev) +static void blackbird_unregister_video(struct cx8802_dev *dev) { if (dev->mpeg_dev) { if (-1 != dev->mpeg_dev->minor) @@ -776,7 +776,7 @@ static void cx8802_unregister_video(struct cx8802_dev *dev) } } -static int cx8802_register_video(struct cx8802_dev *dev) +static int blackbird_register_video(struct cx8802_dev *dev) { int err; @@ -792,10 +792,105 @@ static int cx8802_register_video(struct cx8802_dev *dev) dev->core->name,dev->mpeg_dev->minor & 0x1f); } -#if 0 -module_init(cx8802_init); -module_exit(cx8802_fini); +/* ----------------------------------------------------------- */ + +static int __devinit blackbird_probe(struct pci_dev *pci_dev, + const struct pci_device_id *pci_id) +{ + struct cx8802_dev *dev; + struct cx88_core *core; + int err; + + /* general setup */ + core = cx88_core_get(pci_dev); + if (NULL == core) + return -EINVAL; + + err = -ENODEV; + if (!cx88_boards[core->board].blackbird) + goto fail_core; + + err = -ENOMEM; + dev = kmalloc(sizeof(*dev),GFP_KERNEL); + if (NULL == dev) + goto fail_core; + memset(dev,0,sizeof(*dev)); + dev->pci = pci_dev; + dev->core = core; + + err = cx8802_init_common(dev); + if (0 != err) + goto fail_free; + + /* blackbird stuff */ + printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n", + core->name); + host_setup(dev->core); + + list_add_tail(&dev->devlist,&cx8802_devlist); + blackbird_register_video(dev); + return 0; + + fail_free: + kfree(dev); + fail_core: + cx88_core_put(core,pci_dev); + return err; +} + +static void __devexit blackbird_remove(struct pci_dev *pci_dev) +{ + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + + /* blackbird */ + blackbird_unregister_video(dev); + list_del(&dev->devlist); + + /* common */ + cx8802_fini_common(dev); + cx88_core_put(dev->core,dev->pci); + kfree(dev); +} + +static struct pci_device_id cx8802_pci_tbl[] = { + { + .vendor = 0x14f1, + .device = 0x8802, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, + },{ + /* --- end of list --- */ + } +}; +MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); + +static struct pci_driver blackbird_pci_driver = { + .name = "cx8802", + .id_table = cx8802_pci_tbl, + .probe = blackbird_probe, + .remove = blackbird_remove, +}; + +static int blackbird_init(void) +{ + printk(KERN_INFO "cx2388x blackbird driver version %d.%d.%d loaded\n", + (CX88_VERSION_CODE >> 16) & 0xff, + (CX88_VERSION_CODE >> 8) & 0xff, + CX88_VERSION_CODE & 0xff); +#ifdef SNAPSHOT + printk(KERN_INFO "cx2388x: snapshot date %04d-%02d-%02d\n", + SNAPSHOT/10000, (SNAPSHOT/100)%100, SNAPSHOT%100); #endif + return pci_module_init(&blackbird_pci_driver); +} + +static void blackbird_fini(void) +{ + pci_unregister_driver(&blackbird_pci_driver); +} + +module_init(blackbird_init); +module_exit(blackbird_fini); /* ----------------------------------------------------------- */ /* |