Path: blob/master/drivers/media/video/cx231xx/cx231xx-417.c
17994 views
/*1*2* Support for a cx23417 mpeg encoder via cx231xx host port.3*4* (c) 2004 Jelle Foks <[email protected]>5* (c) 2004 Gerd Knorr <[email protected]>6* (c) 2008 Steven Toth <[email protected]>7* - CX23885/7/8 support8*9* Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),10*11* This program is free software; you can redistribute it and/or modify12* it under the terms of the GNU General Public License as published by13* the Free Software Foundation; either version 2 of the License, or14* (at your option) any later version.15*16* This program is distributed in the hope that it will be useful,17* but WITHOUT ANY WARRANTY; without even the implied warranty of18* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the19* GNU General Public License for more details.20*21* You should have received a copy of the GNU General Public License22* along with this program; if not, write to the Free Software23* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.24*/2526#include <linux/module.h>27#include <linux/moduleparam.h>28#include <linux/init.h>29#include <linux/fs.h>30#include <linux/delay.h>31#include <linux/device.h>32#include <linux/firmware.h>33#include <linux/vmalloc.h>34#include <media/v4l2-common.h>35#include <media/v4l2-ioctl.h>36#include <media/cx2341x.h>37#include <linux/usb.h>3839#include "cx231xx.h"40/*#include "cx23885-ioctl.h"*/4142#define CX231xx_FIRM_IMAGE_SIZE 37683643#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"4445/* for polaris ITVC */46#define ITVC_WRITE_DIR 0x03FDFC0047#define ITVC_READ_DIR 0x0001FC004849#define MCI_MEMORY_DATA_BYTE0 0x0050#define MCI_MEMORY_DATA_BYTE1 0x0851#define MCI_MEMORY_DATA_BYTE2 0x1052#define MCI_MEMORY_DATA_BYTE3 0x185354#define MCI_MEMORY_ADDRESS_BYTE2 0x2055#define MCI_MEMORY_ADDRESS_BYTE1 0x2856#define MCI_MEMORY_ADDRESS_BYTE0 0x305758#define MCI_REGISTER_DATA_BYTE0 0x4059#define MCI_REGISTER_DATA_BYTE1 0x4860#define MCI_REGISTER_DATA_BYTE2 0x5061#define MCI_REGISTER_DATA_BYTE3 0x586263#define MCI_REGISTER_ADDRESS_BYTE0 0x6064#define MCI_REGISTER_ADDRESS_BYTE1 0x686566#define MCI_REGISTER_MODE 0x706768/* Read and write modes for polaris ITVC */69#define MCI_MODE_REGISTER_READ 0x00070#define MCI_MODE_REGISTER_WRITE 0x10071#define MCI_MODE_MEMORY_READ 0x00072#define MCI_MODE_MEMORY_WRITE 0x40007374static unsigned int mpegbufs = 8;75module_param(mpegbufs, int, 0644);76MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");77static unsigned int mpeglines = 128;78module_param(mpeglines, int, 0644);79MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");80static unsigned int mpeglinesize = 512;81module_param(mpeglinesize, int, 0644);82MODULE_PARM_DESC(mpeglinesize,83"number of bytes in each line of an MPEG buffer, range 512-1024");8485static unsigned int v4l_debug = 1;86module_param(v4l_debug, int, 0644);87MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");88struct cx231xx_dmaqueue *dma_qq;89#define dprintk(level, fmt, arg...)\90do { if (v4l_debug >= level) \91printk(KERN_INFO "%s: " fmt, \92(dev) ? dev->name : "cx231xx[?]", ## arg); \93} while (0)9495static struct cx231xx_tvnorm cx231xx_tvnorms[] = {96{97.name = "NTSC-M",98.id = V4L2_STD_NTSC_M,99}, {100.name = "NTSC-JP",101.id = V4L2_STD_NTSC_M_JP,102}, {103.name = "PAL-BG",104.id = V4L2_STD_PAL_BG,105}, {106.name = "PAL-DK",107.id = V4L2_STD_PAL_DK,108}, {109.name = "PAL-I",110.id = V4L2_STD_PAL_I,111}, {112.name = "PAL-M",113.id = V4L2_STD_PAL_M,114}, {115.name = "PAL-N",116.id = V4L2_STD_PAL_N,117}, {118.name = "PAL-Nc",119.id = V4L2_STD_PAL_Nc,120}, {121.name = "PAL-60",122.id = V4L2_STD_PAL_60,123}, {124.name = "SECAM-L",125.id = V4L2_STD_SECAM_L,126}, {127.name = "SECAM-DK",128.id = V4L2_STD_SECAM_DK,129}130};131132/* ------------------------------------------------------------------ */133enum cx231xx_capture_type {134CX231xx_MPEG_CAPTURE,135CX231xx_RAW_CAPTURE,136CX231xx_RAW_PASSTHRU_CAPTURE137};138enum cx231xx_capture_bits {139CX231xx_RAW_BITS_NONE = 0x00,140CX231xx_RAW_BITS_YUV_CAPTURE = 0x01,141CX231xx_RAW_BITS_PCM_CAPTURE = 0x02,142CX231xx_RAW_BITS_VBI_CAPTURE = 0x04,143CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08,144CX231xx_RAW_BITS_TO_HOST_CAPTURE = 0x10145};146enum cx231xx_capture_end {147CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */148CX231xx_END_NOW, /* stop immediately, no irq */149};150enum cx231xx_framerate {151CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */152CX231xx_FRAMERATE_PAL_25 /* PAL: 25fps */153};154enum cx231xx_stream_port {155CX231xx_OUTPUT_PORT_MEMORY,156CX231xx_OUTPUT_PORT_STREAMING,157CX231xx_OUTPUT_PORT_SERIAL158};159enum cx231xx_data_xfer_status {160CX231xx_MORE_BUFFERS_FOLLOW,161CX231xx_LAST_BUFFER,162};163enum cx231xx_picture_mask {164CX231xx_PICTURE_MASK_NONE,165CX231xx_PICTURE_MASK_I_FRAMES,166CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3,167CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7,168};169enum cx231xx_vbi_mode_bits {170CX231xx_VBI_BITS_SLICED,171CX231xx_VBI_BITS_RAW,172};173enum cx231xx_vbi_insertion_bits {174CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,175CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,176CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,177CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,178CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,179};180enum cx231xx_dma_unit {181CX231xx_DMA_BYTES,182CX231xx_DMA_FRAMES,183};184enum cx231xx_dma_transfer_status_bits {185CX231xx_DMA_TRANSFER_BITS_DONE = 0x01,186CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04,187CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10,188};189enum cx231xx_pause {190CX231xx_PAUSE_ENCODING,191CX231xx_RESUME_ENCODING,192};193enum cx231xx_copyright {194CX231xx_COPYRIGHT_OFF,195CX231xx_COPYRIGHT_ON,196};197enum cx231xx_notification_type {198CX231xx_NOTIFICATION_REFRESH,199};200enum cx231xx_notification_status {201CX231xx_NOTIFICATION_OFF,202CX231xx_NOTIFICATION_ON,203};204enum cx231xx_notification_mailbox {205CX231xx_NOTIFICATION_NO_MAILBOX = -1,206};207enum cx231xx_field1_lines {208CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */209CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */210CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */211};212enum cx231xx_field2_lines {213CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */214CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */215CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */216};217enum cx231xx_custom_data_type {218CX231xx_CUSTOM_EXTENSION_USR_DATA,219CX231xx_CUSTOM_PRIVATE_PACKET,220};221enum cx231xx_mute {222CX231xx_UNMUTE,223CX231xx_MUTE,224};225enum cx231xx_mute_video_mask {226CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00,227CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000,228CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000,229};230enum cx231xx_mute_video_shift {231CX231xx_MUTE_VIDEO_V_SHIFT = 8,232CX231xx_MUTE_VIDEO_U_SHIFT = 16,233CX231xx_MUTE_VIDEO_Y_SHIFT = 24,234};235236/* defines below are from ivtv-driver.h */237#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF238239/* Firmware API commands */240#define IVTV_API_STD_TIMEOUT 500241242/* Registers */243/* IVTV_REG_OFFSET */244#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)245#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)246#define IVTV_REG_SPU (0x9050)247#define IVTV_REG_HW_BLOCKS (0x9054)248#define IVTV_REG_VPU (0x9058)249#define IVTV_REG_APU (0xA064)250251/*252* Bit definitions for MC417_RWD and MC417_OEN registers253*254* bits 31-16255*+-----------+256*| Reserved |257*|+-----------+258*| bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8259*|+-------+-------+-------+-------+-------+-------+-------+-------+260*|| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|261*|+-------+-------+-------+-------+-------+-------+-------+-------+262*| bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0263*|+-------+-------+-------+-------+-------+-------+-------+-------+264*||MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|265*|+-------+-------+-------+-------+-------+-------+-------+-------+266*/267#define MC417_MIWR 0x8000268#define MC417_MIRD 0x4000269#define MC417_MICS 0x2000270#define MC417_MIRDY 0x1000271#define MC417_MIADDR 0x0F00272#define MC417_MIDATA 0x00FF273274275/* Bit definitions for MC417_CTL register ****276*bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0277*+--------+-------------+--------+--------------+------------+278*|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|279*+--------+-------------+--------+--------------+------------+280*/281#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030)282#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006)283#define MC417_UART_GPIO_EN 0x00000001284285/* Values for speed control */286#define MC417_SPD_CTL_SLOW 0x1287#define MC417_SPD_CTL_MEDIUM 0x0288#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */289290/* Values for GPIO select */291#define MC417_GPIO_SEL_GPIO3 0x3292#define MC417_GPIO_SEL_GPIO2 0x2293#define MC417_GPIO_SEL_GPIO1 0x1294#define MC417_GPIO_SEL_GPIO0 0x0295296297#define CX23417_GPIO_MASK 0xFC0003FF298static int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value)299{300int status = 0;301u32 _gpio_direction = 0;302303_gpio_direction = _gpio_direction & CX23417_GPIO_MASK;304_gpio_direction = _gpio_direction|gpio_direction;305status = cx231xx_send_gpio_cmd(dev, _gpio_direction,306(u8 *)&value, 4, 0, 0);307return status;308}309static int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue)310{311int status = 0;312u32 _gpio_direction = 0;313314_gpio_direction = _gpio_direction & CX23417_GPIO_MASK;315_gpio_direction = _gpio_direction|gpio_direction;316317status = cx231xx_send_gpio_cmd(dev, _gpio_direction,318(u8 *)pValue, 4, 0, 1);319return status;320}321322static int waitForMciComplete(struct cx231xx *dev)323{324u32 gpio;325u32 gpio_driection = 0;326u8 count = 0;327getITVCReg(dev, gpio_driection, &gpio);328329while (!(gpio&0x020000)) {330msleep(10);331332getITVCReg(dev, gpio_driection, &gpio);333334if (count++ > 100) {335dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio);336return -1;337}338}339return 0;340}341342static int mc417_register_write(struct cx231xx *dev, u16 address, u32 value)343{344u32 temp;345int status = 0;346347temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8);348temp = temp<<10;349status = setITVCReg(dev, ITVC_WRITE_DIR, temp);350if (status < 0)351return status;352temp = temp|((0x05)<<10);353setITVCReg(dev, ITVC_WRITE_DIR, temp);354355/*write data byte 1;*/356temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00);357temp = temp<<10;358setITVCReg(dev, ITVC_WRITE_DIR, temp);359temp = temp|((0x05)<<10);360setITVCReg(dev, ITVC_WRITE_DIR, temp);361362/*write data byte 2;*/363temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8);364temp = temp<<10;365setITVCReg(dev, ITVC_WRITE_DIR, temp);366temp = temp|((0x05)<<10);367setITVCReg(dev, ITVC_WRITE_DIR, temp);368369/*write data byte 3;*/370temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16);371temp = temp<<10;372setITVCReg(dev, ITVC_WRITE_DIR, temp);373temp = temp|((0x05)<<10);374setITVCReg(dev, ITVC_WRITE_DIR, temp);375376/*write address byte 0;*/377temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8);378temp = temp<<10;379setITVCReg(dev, ITVC_WRITE_DIR, temp);380temp = temp|((0x05)<<10);381setITVCReg(dev, ITVC_WRITE_DIR, temp);382383/*write address byte 1;*/384temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00);385temp = temp<<10;386setITVCReg(dev, ITVC_WRITE_DIR, temp);387temp = temp|((0x05)<<10);388setITVCReg(dev, ITVC_WRITE_DIR, temp);389390/*Write that the mode is write.*/391temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE;392temp = temp<<10;393setITVCReg(dev, ITVC_WRITE_DIR, temp);394temp = temp|((0x05)<<10);395setITVCReg(dev, ITVC_WRITE_DIR, temp);396397return waitForMciComplete(dev);398}399400static int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value)401{402/*write address byte 0;*/403u32 temp;404u32 return_value = 0;405int ret = 0;406407temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE0 | ((address & 0x00FF) << 8);408temp = temp << 10;409setITVCReg(dev, ITVC_WRITE_DIR, temp);410temp = temp | ((0x05) << 10);411setITVCReg(dev, ITVC_WRITE_DIR, temp);412413/*write address byte 1;*/414temp = 0x82 | MCI_REGISTER_ADDRESS_BYTE1 | (address & 0xFF00);415temp = temp << 10;416setITVCReg(dev, ITVC_WRITE_DIR, temp);417temp = temp | ((0x05) << 10);418setITVCReg(dev, ITVC_WRITE_DIR, temp);419420/*write that the mode is read;*/421temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ;422temp = temp << 10;423setITVCReg(dev, ITVC_WRITE_DIR, temp);424temp = temp | ((0x05) << 10);425setITVCReg(dev, ITVC_WRITE_DIR, temp);426427/*wait for the MIRDY line to be asserted ,428signalling that the read is done;*/429ret = waitForMciComplete(dev);430431/*switch the DATA- GPIO to input mode;*/432433/*Read data byte 0;*/434temp = (0x82 | MCI_REGISTER_DATA_BYTE0) << 10;435setITVCReg(dev, ITVC_READ_DIR, temp);436temp = ((0x81 | MCI_REGISTER_DATA_BYTE0) << 10);437setITVCReg(dev, ITVC_READ_DIR, temp);438getITVCReg(dev, ITVC_READ_DIR, &temp);439return_value |= ((temp & 0x03FC0000) >> 18);440setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));441442/* Read data byte 1;*/443temp = (0x82 | MCI_REGISTER_DATA_BYTE1) << 10;444setITVCReg(dev, ITVC_READ_DIR, temp);445temp = ((0x81 | MCI_REGISTER_DATA_BYTE1) << 10);446setITVCReg(dev, ITVC_READ_DIR, temp);447getITVCReg(dev, ITVC_READ_DIR, &temp);448449return_value |= ((temp & 0x03FC0000) >> 10);450setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));451452/*Read data byte 2;*/453temp = (0x82 | MCI_REGISTER_DATA_BYTE2) << 10;454setITVCReg(dev, ITVC_READ_DIR, temp);455temp = ((0x81 | MCI_REGISTER_DATA_BYTE2) << 10);456setITVCReg(dev, ITVC_READ_DIR, temp);457getITVCReg(dev, ITVC_READ_DIR, &temp);458return_value |= ((temp & 0x03FC0000) >> 2);459setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));460461/*Read data byte 3;*/462temp = (0x82 | MCI_REGISTER_DATA_BYTE3) << 10;463setITVCReg(dev, ITVC_READ_DIR, temp);464temp = ((0x81 | MCI_REGISTER_DATA_BYTE3) << 10);465setITVCReg(dev, ITVC_READ_DIR, temp);466getITVCReg(dev, ITVC_READ_DIR, &temp);467return_value |= ((temp & 0x03FC0000) << 6);468setITVCReg(dev, ITVC_READ_DIR, (0x87 << 10));469470*value = return_value;471472473return ret;474}475476static int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value)477{478/*write data byte 0;*/479480u32 temp;481int ret = 0;482483temp = 0x82 | MCI_MEMORY_DATA_BYTE0|((value & 0x000000FF) << 8);484temp = temp << 10;485ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);486if (ret < 0)487return ret;488temp = temp | ((0x05) << 10);489setITVCReg(dev, ITVC_WRITE_DIR, temp);490491/*write data byte 1;*/492temp = 0x82 | MCI_MEMORY_DATA_BYTE1 | (value & 0x0000FF00);493temp = temp << 10;494setITVCReg(dev, ITVC_WRITE_DIR, temp);495temp = temp | ((0x05) << 10);496setITVCReg(dev, ITVC_WRITE_DIR, temp);497498/*write data byte 2;*/499temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);500temp = temp<<10;501setITVCReg(dev, ITVC_WRITE_DIR, temp);502temp = temp|((0x05)<<10);503setITVCReg(dev, ITVC_WRITE_DIR, temp);504505/*write data byte 3;*/506temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);507temp = temp<<10;508setITVCReg(dev, ITVC_WRITE_DIR, temp);509temp = temp|((0x05)<<10);510setITVCReg(dev, ITVC_WRITE_DIR, temp);511512/* write address byte 2;*/513temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |514((address & 0x003F0000)>>8);515temp = temp<<10;516setITVCReg(dev, ITVC_WRITE_DIR, temp);517temp = temp|((0x05)<<10);518setITVCReg(dev, ITVC_WRITE_DIR, temp);519520/* write address byte 1;*/521temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);522temp = temp<<10;523setITVCReg(dev, ITVC_WRITE_DIR, temp);524temp = temp|((0x05)<<10);525setITVCReg(dev, ITVC_WRITE_DIR, temp);526527/* write address byte 0;*/528temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);529temp = temp<<10;530setITVCReg(dev, ITVC_WRITE_DIR, temp);531temp = temp|((0x05)<<10);532setITVCReg(dev, ITVC_WRITE_DIR, temp);533534/*wait for MIRDY line;*/535waitForMciComplete(dev);536537return 0;538}539540static int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value)541{542u32 temp = 0;543u32 return_value = 0;544int ret = 0;545546/*write address byte 2;*/547temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ |548((address & 0x003F0000)>>8);549temp = temp<<10;550ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);551if (ret < 0)552return ret;553temp = temp|((0x05)<<10);554setITVCReg(dev, ITVC_WRITE_DIR, temp);555556/*write address byte 1*/557temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);558temp = temp<<10;559setITVCReg(dev, ITVC_WRITE_DIR, temp);560temp = temp|((0x05)<<10);561setITVCReg(dev, ITVC_WRITE_DIR, temp);562563/*write address byte 0*/564temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8);565temp = temp<<10;566setITVCReg(dev, ITVC_WRITE_DIR, temp);567temp = temp|((0x05)<<10);568setITVCReg(dev, ITVC_WRITE_DIR, temp);569570/*Wait for MIRDY line*/571ret = waitForMciComplete(dev);572573574/*Read data byte 3;*/575temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10;576setITVCReg(dev, ITVC_READ_DIR, temp);577temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10);578setITVCReg(dev, ITVC_READ_DIR, temp);579getITVCReg(dev, ITVC_READ_DIR, &temp);580return_value |= ((temp&0x03FC0000)<<6);581setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));582583/*Read data byte 2;*/584temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10;585setITVCReg(dev, ITVC_READ_DIR, temp);586temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10);587setITVCReg(dev, ITVC_READ_DIR, temp);588getITVCReg(dev, ITVC_READ_DIR, &temp);589return_value |= ((temp&0x03FC0000)>>2);590setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));591592/* Read data byte 1;*/593temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10;594setITVCReg(dev, ITVC_READ_DIR, temp);595temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10);596setITVCReg(dev, ITVC_READ_DIR, temp);597getITVCReg(dev, ITVC_READ_DIR, &temp);598return_value |= ((temp&0x03FC0000)>>10);599setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));600601/*Read data byte 0;*/602temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10;603setITVCReg(dev, ITVC_READ_DIR, temp);604temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10);605setITVCReg(dev, ITVC_READ_DIR, temp);606getITVCReg(dev, ITVC_READ_DIR, &temp);607return_value |= ((temp&0x03FC0000)>>18);608setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));609610*value = return_value;611return ret;612}613614/* ------------------------------------------------------------------ */615616/* MPEG encoder API */617static char *cmd_to_str(int cmd)618{619switch (cmd) {620case CX2341X_ENC_PING_FW:621return "PING_FW";622case CX2341X_ENC_START_CAPTURE:623return "START_CAPTURE";624case CX2341X_ENC_STOP_CAPTURE:625return "STOP_CAPTURE";626case CX2341X_ENC_SET_AUDIO_ID:627return "SET_AUDIO_ID";628case CX2341X_ENC_SET_VIDEO_ID:629return "SET_VIDEO_ID";630case CX2341X_ENC_SET_PCR_ID:631return "SET_PCR_PID";632case CX2341X_ENC_SET_FRAME_RATE:633return "SET_FRAME_RATE";634case CX2341X_ENC_SET_FRAME_SIZE:635return "SET_FRAME_SIZE";636case CX2341X_ENC_SET_BIT_RATE:637return "SET_BIT_RATE";638case CX2341X_ENC_SET_GOP_PROPERTIES:639return "SET_GOP_PROPERTIES";640case CX2341X_ENC_SET_ASPECT_RATIO:641return "SET_ASPECT_RATIO";642case CX2341X_ENC_SET_DNR_FILTER_MODE:643return "SET_DNR_FILTER_PROPS";644case CX2341X_ENC_SET_DNR_FILTER_PROPS:645return "SET_DNR_FILTER_PROPS";646case CX2341X_ENC_SET_CORING_LEVELS:647return "SET_CORING_LEVELS";648case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:649return "SET_SPATIAL_FILTER_TYPE";650case CX2341X_ENC_SET_VBI_LINE:651return "SET_VBI_LINE";652case CX2341X_ENC_SET_STREAM_TYPE:653return "SET_STREAM_TYPE";654case CX2341X_ENC_SET_OUTPUT_PORT:655return "SET_OUTPUT_PORT";656case CX2341X_ENC_SET_AUDIO_PROPERTIES:657return "SET_AUDIO_PROPERTIES";658case CX2341X_ENC_HALT_FW:659return "HALT_FW";660case CX2341X_ENC_GET_VERSION:661return "GET_VERSION";662case CX2341X_ENC_SET_GOP_CLOSURE:663return "SET_GOP_CLOSURE";664case CX2341X_ENC_GET_SEQ_END:665return "GET_SEQ_END";666case CX2341X_ENC_SET_PGM_INDEX_INFO:667return "SET_PGM_INDEX_INFO";668case CX2341X_ENC_SET_VBI_CONFIG:669return "SET_VBI_CONFIG";670case CX2341X_ENC_SET_DMA_BLOCK_SIZE:671return "SET_DMA_BLOCK_SIZE";672case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:673return "GET_PREV_DMA_INFO_MB_10";674case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:675return "GET_PREV_DMA_INFO_MB_9";676case CX2341X_ENC_SCHED_DMA_TO_HOST:677return "SCHED_DMA_TO_HOST";678case CX2341X_ENC_INITIALIZE_INPUT:679return "INITIALIZE_INPUT";680case CX2341X_ENC_SET_FRAME_DROP_RATE:681return "SET_FRAME_DROP_RATE";682case CX2341X_ENC_PAUSE_ENCODER:683return "PAUSE_ENCODER";684case CX2341X_ENC_REFRESH_INPUT:685return "REFRESH_INPUT";686case CX2341X_ENC_SET_COPYRIGHT:687return "SET_COPYRIGHT";688case CX2341X_ENC_SET_EVENT_NOTIFICATION:689return "SET_EVENT_NOTIFICATION";690case CX2341X_ENC_SET_NUM_VSYNC_LINES:691return "SET_NUM_VSYNC_LINES";692case CX2341X_ENC_SET_PLACEHOLDER:693return "SET_PLACEHOLDER";694case CX2341X_ENC_MUTE_VIDEO:695return "MUTE_VIDEO";696case CX2341X_ENC_MUTE_AUDIO:697return "MUTE_AUDIO";698case CX2341X_ENC_MISC:699return "MISC";700default:701return "UNKNOWN";702}703}704705static int cx231xx_mbox_func(void *priv,706u32 command,707int in,708int out,709u32 data[CX2341X_MBOX_MAX_DATA])710{711struct cx231xx *dev = priv;712unsigned long timeout;713u32 value, flag, retval = 0;714int i;715716dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,717cmd_to_str(command));718719/* this may not be 100% safe if we can't read any memory location720without side effects */721mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);722if (value != 0x12345678) {723dprintk(3,724"Firmware and/or mailbox pointer not initialized "725"or corrupted, signature = 0x%x, cmd = %s\n", value,726cmd_to_str(command));727return -1;728}729730/* This read looks at 32 bits, but flag is only 8 bits.731* Seems we also bail if CMD or TIMEOUT bytes are set???732*/733mc417_memory_read(dev, dev->cx23417_mailbox, &flag);734if (flag) {735dprintk(3, "ERROR: Mailbox appears to be in use "736"(%x), cmd = %s\n", flag, cmd_to_str(command));737return -1;738}739740flag |= 1; /* tell 'em we're working on it */741mc417_memory_write(dev, dev->cx23417_mailbox, flag);742743/* write command + args + fill remaining with zeros */744/* command code */745mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);746mc417_memory_write(dev, dev->cx23417_mailbox + 3,747IVTV_API_STD_TIMEOUT); /* timeout */748for (i = 0; i < in; i++) {749mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);750dprintk(3, "API Input %d = %d\n", i, data[i]);751}752for (; i < CX2341X_MBOX_MAX_DATA; i++)753mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);754755flag |= 3; /* tell 'em we're done writing */756mc417_memory_write(dev, dev->cx23417_mailbox, flag);757758/* wait for firmware to handle the API command */759timeout = jiffies + msecs_to_jiffies(10);760for (;;) {761mc417_memory_read(dev, dev->cx23417_mailbox, &flag);762if (0 != (flag & 4))763break;764if (time_after(jiffies, timeout)) {765dprintk(3, "ERROR: API Mailbox timeout\n");766return -1;767}768udelay(10);769}770771/* read output values */772for (i = 0; i < out; i++) {773mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);774dprintk(3, "API Output %d = %d\n", i, data[i]);775}776777mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);778dprintk(3, "API result = %d\n", retval);779780flag = 0;781mc417_memory_write(dev, dev->cx23417_mailbox, flag);782783return retval;784}785786/* We don't need to call the API often, so using just one787* mailbox will probably suffice788*/789static int cx231xx_api_cmd(struct cx231xx *dev,790u32 command,791u32 inputcnt,792u32 outputcnt,793...)794{795u32 data[CX2341X_MBOX_MAX_DATA];796va_list vargs;797int i, err;798799dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);800801va_start(vargs, outputcnt);802for (i = 0; i < inputcnt; i++)803data[i] = va_arg(vargs, int);804805err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data);806for (i = 0; i < outputcnt; i++) {807int *vptr = va_arg(vargs, int *);808*vptr = data[i];809}810va_end(vargs);811812return err;813}814815static int cx231xx_find_mailbox(struct cx231xx *dev)816{817u32 signature[4] = {8180x12345678, 0x34567812, 0x56781234, 0x78123456819};820int signaturecnt = 0;821u32 value;822int i;823int ret = 0;824825dprintk(2, "%s()\n", __func__);826827for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/828ret = mc417_memory_read(dev, i, &value);829if (ret < 0)830return ret;831if (value == signature[signaturecnt])832signaturecnt++;833else834signaturecnt = 0;835if (4 == signaturecnt) {836dprintk(1, "Mailbox signature found at 0x%x\n", i+1);837return i+1;838}839}840dprintk(3, "Mailbox signature values not found!\n");841return -1;842}843844static void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value,845u32 *p_fw_image)846{847848u32 temp = 0;849int i = 0;850851temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8);852temp = temp<<10;853*p_fw_image = temp;854p_fw_image++;855temp = temp|((0x05)<<10);856*p_fw_image = temp;857p_fw_image++;858859/*write data byte 1;*/860temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00);861temp = temp<<10;862*p_fw_image = temp;863p_fw_image++;864temp = temp|((0x05)<<10);865*p_fw_image = temp;866p_fw_image++;867868/*write data byte 2;*/869temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);870temp = temp<<10;871*p_fw_image = temp;872p_fw_image++;873temp = temp|((0x05)<<10);874*p_fw_image = temp;875p_fw_image++;876877/*write data byte 3;*/878temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);879temp = temp<<10;880*p_fw_image = temp;881p_fw_image++;882temp = temp|((0x05)<<10);883*p_fw_image = temp;884p_fw_image++;885886/* write address byte 2;*/887temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |888((address & 0x003F0000)>>8);889temp = temp<<10;890*p_fw_image = temp;891p_fw_image++;892temp = temp|((0x05)<<10);893*p_fw_image = temp;894p_fw_image++;895896/* write address byte 1;*/897temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);898temp = temp<<10;899*p_fw_image = temp;900p_fw_image++;901temp = temp|((0x05)<<10);902*p_fw_image = temp;903p_fw_image++;904905/* write address byte 0;*/906temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);907temp = temp<<10;908*p_fw_image = temp;909p_fw_image++;910temp = temp|((0x05)<<10);911*p_fw_image = temp;912p_fw_image++;913914for (i = 0; i < 6; i++) {915*p_fw_image = 0xFFFFFFFF;916p_fw_image++;917}918}919920921static int cx231xx_load_firmware(struct cx231xx *dev)922{923static const unsigned char magic[8] = {9240xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa925};926const struct firmware *firmware;927int i, retval = 0;928u32 value = 0;929u32 gpio_output = 0;930/*u32 checksum = 0;*/931/*u32 *dataptr;*/932u32 transfer_size = 0;933u32 fw_data = 0;934u32 address = 0;935/*u32 current_fw[800];*/936u32 *p_current_fw, *p_fw;937u32 *p_fw_data;938int frame = 0;939u16 _buffer_size = 4096;940u8 *p_buffer;941942p_current_fw = vmalloc(1884180 * 4);943p_fw = p_current_fw;944if (p_current_fw == NULL) {945dprintk(2, "FAIL!!!\n");946return -1;947}948949p_buffer = vmalloc(4096);950if (p_buffer == NULL) {951dprintk(2, "FAIL!!!\n");952return -1;953}954955dprintk(2, "%s()\n", __func__);956957/* Save GPIO settings before reset of APU */958retval |= mc417_memory_read(dev, 0x9020, &gpio_output);959retval |= mc417_memory_read(dev, 0x900C, &value);960961retval = mc417_register_write(dev,962IVTV_REG_VPU, 0xFFFFFFED);963retval |= mc417_register_write(dev,964IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);965retval |= mc417_register_write(dev,966IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);967retval |= mc417_register_write(dev,968IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);969retval |= mc417_register_write(dev,970IVTV_REG_APU, 0);971972if (retval != 0) {973printk(KERN_ERR "%s: Error with mc417_register_write\n",974__func__);975return -1;976}977978retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,979&dev->udev->dev);980981if (retval != 0) {982printk(KERN_ERR983"ERROR: Hotplug firmware request failed (%s).\n",984CX231xx_FIRM_IMAGE_NAME);985printk(KERN_ERR "Please fix your hotplug setup, the board will "986"not work without firmware loaded!\n");987return -1;988}989990if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {991printk(KERN_ERR "ERROR: Firmware size mismatch "992"(have %zd, expected %d)\n",993firmware->size, CX231xx_FIRM_IMAGE_SIZE);994release_firmware(firmware);995return -1;996}997998if (0 != memcmp(firmware->data, magic, 8)) {999printk(KERN_ERR1000"ERROR: Firmware magic mismatch, wrong file?\n");1001release_firmware(firmware);1002return -1;1003}10041005initGPIO(dev);10061007/* transfer to the chip */1008dprintk(2, "Loading firmware to GPIO...\n");1009p_fw_data = (u32 *)firmware->data;1010dprintk(2, "firmware->size=%zd\n", firmware->size);1011for (transfer_size = 0; transfer_size < firmware->size;1012transfer_size += 4) {1013fw_data = *p_fw_data;10141015mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw);1016address = address + 1;1017p_current_fw += 20;1018p_fw_data += 1;1019}10201021/*download the firmware by ep5-out*/10221023for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size);1024frame++) {1025for (i = 0; i < _buffer_size; i++) {1026*(p_buffer + i) = (u8)(*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x000000FF);1027i++;1028*(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x0000FF00) >> 8);1029i++;1030*(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0x00FF0000) >> 16);1031i++;1032*(p_buffer + i) = (u8)((*(p_fw + (frame * 128 * 8 + (i / 4))) & 0xFF000000) >> 24);1033}1034cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size);1035}10361037p_current_fw = p_fw;1038vfree(p_current_fw);1039p_current_fw = NULL;1040uninitGPIO(dev);1041release_firmware(firmware);1042dprintk(1, "Firmware upload successful.\n");10431044retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,1045IVTV_CMD_HW_BLOCKS_RST);1046if (retval < 0) {1047printk(KERN_ERR "%s: Error with mc417_register_write\n",1048__func__);1049return retval;1050}1051/* F/W power up disturbs the GPIOs, restore state */1052retval |= mc417_register_write(dev, 0x9020, gpio_output);1053retval |= mc417_register_write(dev, 0x900C, value);10541055retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);1056retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);10571058if (retval < 0) {1059printk(KERN_ERR "%s: Error with mc417_register_write\n",1060__func__);1061return retval;1062}1063return 0;1064}10651066static void cx231xx_417_check_encoder(struct cx231xx *dev)1067{1068u32 status, seq;10691070status = 0;1071seq = 0;1072cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);1073dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);1074}10751076static void cx231xx_codec_settings(struct cx231xx *dev)1077{1078dprintk(1, "%s()\n", __func__);10791080/* assign frame size */1081cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,1082dev->ts1.height, dev->ts1.width);10831084dev->mpeg_params.width = dev->ts1.width;1085dev->mpeg_params.height = dev->ts1.height;10861087cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params);10881089cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);1090cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);1091}10921093static int cx231xx_initialize_codec(struct cx231xx *dev)1094{1095int version;1096int retval;1097u32 i, data[7];1098u32 val = 0;10991100dprintk(1, "%s()\n", __func__);1101cx231xx_disable656(dev);1102retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */1103if (retval < 0) {1104dprintk(2, "%s() PING OK\n", __func__);1105retval = cx231xx_load_firmware(dev);1106if (retval < 0) {1107printk(KERN_ERR "%s() f/w load failed\n", __func__);1108return retval;1109}1110retval = cx231xx_find_mailbox(dev);1111if (retval < 0) {1112printk(KERN_ERR "%s() mailbox < 0, error\n",1113__func__);1114return -1;1115}1116dev->cx23417_mailbox = retval;1117retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);1118if (retval < 0) {1119printk(KERN_ERR1120"ERROR: cx23417 firmware ping failed!\n");1121return -1;1122}1123retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,1124&version);1125if (retval < 0) {1126printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"1127"version failed!\n");1128return -1;1129}1130dprintk(1, "cx23417 firmware version is 0x%08x\n", version);1131msleep(200);1132}11331134for (i = 0; i < 1; i++) {1135retval = mc417_register_read(dev, 0x20f8, &val);1136dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n",1137val);1138if (retval < 0)1139return retval;1140}11411142cx231xx_enable656(dev);1143/* stop mpeg capture */1144cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE,11453, 0, 1, 3, 4);11461147cx231xx_codec_settings(dev);1148msleep(60);11491150/* cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,1151CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115);1152cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,1153CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,11540, 0);1155*/1156/* Setup to capture VBI */1157data[0] = 0x0001BD00;1158data[1] = 1; /* frames per interrupt */1159data[2] = 4; /* total bufs */1160data[3] = 0x91559155; /* start codes */1161data[4] = 0x206080C0; /* stop codes */1162data[5] = 6; /* lines */1163data[6] = 64; /* BPL */1164/*1165cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],1166data[2], data[3], data[4], data[5], data[6]);11671168for (i = 2; i <= 24; i++) {1169int valid;11701171valid = ((i >= 19) && (i <= 21));1172cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,1173valid, 0 , 0, 0);1174cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,1175i | 0x80000000, valid, 0, 0, 0);1176}1177*/1178/* cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE);1179msleep(60);1180*/1181/* initialize the video input */1182retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);1183if (retval < 0)1184return retval;1185msleep(60);11861187/* Enable VIP style pixel invalidation so we work with scaled mode */1188mc417_memory_write(dev, 2120, 0x00000080);11891190/* start capturing to the host interface */1191retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,1192CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE);1193if (retval < 0)1194return retval;1195msleep(10);11961197for (i = 0; i < 1; i++) {1198mc417_register_read(dev, 0x20f8, &val);1199dprintk(3, "***VIM Capture Lines =%d ***\n", val);1200}12011202return 0;1203}12041205/* ------------------------------------------------------------------ */12061207static int bb_buf_setup(struct videobuf_queue *q,1208unsigned int *count, unsigned int *size)1209{1210struct cx231xx_fh *fh = q->priv_data;12111212fh->dev->ts1.ts_packet_size = mpeglinesize;1213fh->dev->ts1.ts_packet_count = mpeglines;12141215*size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;1216*count = mpegbufs;12171218return 0;1219}1220static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)1221{1222struct cx231xx_fh *fh = vq->priv_data;1223struct cx231xx *dev = fh->dev;1224unsigned long flags = 0;12251226if (in_interrupt())1227BUG();12281229spin_lock_irqsave(&dev->video_mode.slock, flags);1230if (dev->USE_ISO) {1231if (dev->video_mode.isoc_ctl.buf == buf)1232dev->video_mode.isoc_ctl.buf = NULL;1233} else {1234if (dev->video_mode.bulk_ctl.buf == buf)1235dev->video_mode.bulk_ctl.buf = NULL;1236}1237spin_unlock_irqrestore(&dev->video_mode.slock, flags);1238videobuf_waiton(vq, &buf->vb, 0, 0);1239videobuf_vmalloc_free(&buf->vb);1240buf->vb.state = VIDEOBUF_NEEDS_INIT;1241}12421243static void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb,1244struct cx231xx_dmaqueue *dma_q)1245{1246void *vbuf;1247struct cx231xx_buffer *buf;1248u32 tail_data = 0;1249char *p_data;12501251if (dma_q->mpeg_buffer_done == 0) {1252if (list_empty(&dma_q->active))1253return;12541255buf = list_entry(dma_q->active.next,1256struct cx231xx_buffer, vb.queue);1257dev->video_mode.isoc_ctl.buf = buf;1258dma_q->mpeg_buffer_done = 1;1259}1260/* Fill buffer */1261buf = dev->video_mode.isoc_ctl.buf;1262vbuf = videobuf_to_vmalloc(&buf->vb);12631264if ((dma_q->mpeg_buffer_completed+len) <1265mpeglines*mpeglinesize) {1266if (dma_q->add_ps_package_head ==1267CX231XX_NEED_ADD_PS_PACKAGE_HEAD) {1268memcpy(vbuf+dma_q->mpeg_buffer_completed,1269dma_q->ps_head, 3);1270dma_q->mpeg_buffer_completed =1271dma_q->mpeg_buffer_completed + 3;1272dma_q->add_ps_package_head =1273CX231XX_NONEED_PS_PACKAGE_HEAD;1274}1275memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len);1276dma_q->mpeg_buffer_completed =1277dma_q->mpeg_buffer_completed + len;1278} else {1279dma_q->mpeg_buffer_done = 0;12801281tail_data =1282mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed;1283memcpy(vbuf+dma_q->mpeg_buffer_completed,1284data, tail_data);12851286buf->vb.state = VIDEOBUF_DONE;1287buf->vb.field_count++;1288do_gettimeofday(&buf->vb.ts);1289list_del(&buf->vb.queue);1290wake_up(&buf->vb.done);1291dma_q->mpeg_buffer_completed = 0;12921293if (len - tail_data > 0) {1294p_data = data + tail_data;1295dma_q->left_data_count = len - tail_data;1296memcpy(dma_q->p_left_data,1297p_data, len - tail_data);1298}12991300}13011302return;1303}13041305static void buffer_filled(char *data, int len, struct urb *urb,1306struct cx231xx_dmaqueue *dma_q)1307{1308void *vbuf;1309struct cx231xx_buffer *buf;13101311if (list_empty(&dma_q->active))1312return;131313141315buf = list_entry(dma_q->active.next,1316struct cx231xx_buffer, vb.queue);131713181319/* Fill buffer */1320vbuf = videobuf_to_vmalloc(&buf->vb);1321memcpy(vbuf, data, len);1322buf->vb.state = VIDEOBUF_DONE;1323buf->vb.field_count++;1324do_gettimeofday(&buf->vb.ts);1325list_del(&buf->vb.queue);1326wake_up(&buf->vb.done);13271328return;1329}1330static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)1331{1332struct cx231xx_dmaqueue *dma_q = urb->context;1333unsigned char *p_buffer;1334u32 buffer_size = 0;1335u32 i = 0;13361337for (i = 0; i < urb->number_of_packets; i++) {1338if (dma_q->left_data_count > 0) {1339buffer_copy(dev, dma_q->p_left_data,1340dma_q->left_data_count, urb, dma_q);1341dma_q->mpeg_buffer_completed = dma_q->left_data_count;1342dma_q->left_data_count = 0;1343}13441345p_buffer = urb->transfer_buffer +1346urb->iso_frame_desc[i].offset;1347buffer_size = urb->iso_frame_desc[i].actual_length;13481349if (buffer_size > 0)1350buffer_copy(dev, p_buffer, buffer_size, urb, dma_q);1351}13521353return 0;1354}1355static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)1356{13571358/*char *outp;*/1359/*struct cx231xx_buffer *buf;*/1360struct cx231xx_dmaqueue *dma_q = urb->context;1361unsigned char *p_buffer, *buffer;1362u32 buffer_size = 0;13631364p_buffer = urb->transfer_buffer;1365buffer_size = urb->actual_length;13661367buffer = kmalloc(buffer_size, GFP_ATOMIC);13681369memcpy(buffer, dma_q->ps_head, 3);1370memcpy(buffer+3, p_buffer, buffer_size-3);1371memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3);13721373p_buffer = buffer;1374buffer_filled(p_buffer, buffer_size, urb, dma_q);13751376kfree(buffer);1377return 0;1378}13791380static int bb_buf_prepare(struct videobuf_queue *q,1381struct videobuf_buffer *vb, enum v4l2_field field)1382{1383struct cx231xx_fh *fh = q->priv_data;1384struct cx231xx_buffer *buf =1385container_of(vb, struct cx231xx_buffer, vb);1386struct cx231xx *dev = fh->dev;1387int rc = 0, urb_init = 0;1388int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;13891390dma_qq = &dev->video_mode.vidq;13911392if (0 != buf->vb.baddr && buf->vb.bsize < size)1393return -EINVAL;1394buf->vb.width = fh->dev->ts1.ts_packet_size;1395buf->vb.height = fh->dev->ts1.ts_packet_count;1396buf->vb.size = size;1397buf->vb.field = field;13981399if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {1400rc = videobuf_iolock(q, &buf->vb, NULL);1401if (rc < 0)1402goto fail;1403}14041405if (dev->USE_ISO) {1406if (!dev->video_mode.isoc_ctl.num_bufs)1407urb_init = 1;1408} else {1409if (!dev->video_mode.bulk_ctl.num_bufs)1410urb_init = 1;1411}1412/*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",1413urb_init, dev->video_mode.max_pkt_size);*/1414dev->mode_tv = 1;14151416if (urb_init) {1417rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);1418rc = cx231xx_unmute_audio(dev);1419if (dev->USE_ISO) {1420cx231xx_set_alt_setting(dev, INDEX_TS1, 4);1421rc = cx231xx_init_isoc(dev, mpeglines,1422mpegbufs,1423dev->ts1_mode.max_pkt_size,1424cx231xx_isoc_copy);1425} else {1426cx231xx_set_alt_setting(dev, INDEX_TS1, 0);1427rc = cx231xx_init_bulk(dev, mpeglines,1428mpegbufs,1429dev->ts1_mode.max_pkt_size,1430cx231xx_bulk_copy);1431}1432if (rc < 0)1433goto fail;1434}14351436buf->vb.state = VIDEOBUF_PREPARED;1437return 0;14381439fail:1440free_buffer(q, buf);1441return rc;1442}14431444static void bb_buf_queue(struct videobuf_queue *q,1445struct videobuf_buffer *vb)1446{1447struct cx231xx_fh *fh = q->priv_data;14481449struct cx231xx_buffer *buf =1450container_of(vb, struct cx231xx_buffer, vb);1451struct cx231xx *dev = fh->dev;1452struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;14531454buf->vb.state = VIDEOBUF_QUEUED;1455list_add_tail(&buf->vb.queue, &vidq->active);14561457}14581459static void bb_buf_release(struct videobuf_queue *q,1460struct videobuf_buffer *vb)1461{1462struct cx231xx_buffer *buf =1463container_of(vb, struct cx231xx_buffer, vb);1464/*struct cx231xx_fh *fh = q->priv_data;*/1465/*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/14661467free_buffer(q, buf);1468}14691470static struct videobuf_queue_ops cx231xx_qops = {1471.buf_setup = bb_buf_setup,1472.buf_prepare = bb_buf_prepare,1473.buf_queue = bb_buf_queue,1474.buf_release = bb_buf_release,1475};14761477/* ------------------------------------------------------------------ */14781479static const u32 *ctrl_classes[] = {1480cx2341x_mpeg_ctrls,1481NULL1482};14831484static int cx231xx_queryctrl(struct cx231xx *dev,1485struct v4l2_queryctrl *qctrl)1486{1487qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);1488if (qctrl->id == 0)1489return -EINVAL;14901491/* MPEG V4L2 controls */1492if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))1493qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;14941495return 0;1496}14971498static int cx231xx_querymenu(struct cx231xx *dev,1499struct v4l2_querymenu *qmenu)1500{1501struct v4l2_queryctrl qctrl;15021503qctrl.id = qmenu->id;1504cx231xx_queryctrl(dev, &qctrl);1505return v4l2_ctrl_query_menu(qmenu, &qctrl,1506cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));1507}15081509static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)1510{1511struct cx231xx_fh *fh = file->private_data;1512struct cx231xx *dev = fh->dev;15131514*norm = dev->encodernorm.id;1515return 0;1516}1517static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)1518{1519struct cx231xx_fh *fh = file->private_data;1520struct cx231xx *dev = fh->dev;1521unsigned int i;15221523for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++)1524if (*id & cx231xx_tvnorms[i].id)1525break;1526if (i == ARRAY_SIZE(cx231xx_tvnorms))1527return -EINVAL;1528dev->encodernorm = cx231xx_tvnorms[i];15291530if (dev->encodernorm.id & 0xb000) {1531dprintk(3, "encodernorm set to NTSC\n");1532dev->norm = V4L2_STD_NTSC;1533dev->ts1.height = 480;1534dev->mpeg_params.is_50hz = 0;1535} else {1536dprintk(3, "encodernorm set to PAL\n");1537dev->norm = V4L2_STD_PAL_B;1538dev->ts1.height = 576;1539dev->mpeg_params.is_50hz = 1;1540}1541call_all(dev, core, s_std, dev->norm);1542/* do mode control overrides */1543cx231xx_do_mode_ctrl_overrides(dev);15441545dprintk(3, "exit vidioc_s_std() i=0x%x\n", i);1546return 0;1547}1548static int vidioc_g_audio(struct file *file, void *fh,1549struct v4l2_audio *a)1550{1551struct v4l2_audio *vin = a;15521553int ret = -EINVAL;1554if (vin->index > 0)1555return ret;1556strncpy(vin->name, "VideoGrabber Audio", 14);1557vin->capability = V4L2_AUDCAP_STEREO;1558return 0;1559}1560static int vidioc_enumaudio(struct file *file, void *fh,1561struct v4l2_audio *a)1562{1563struct v4l2_audio *vin = a;15641565int ret = -EINVAL;15661567if (vin->index > 0)1568return ret;1569strncpy(vin->name, "VideoGrabber Audio", 14);1570vin->capability = V4L2_AUDCAP_STEREO;157115721573return 0;1574}1575static const char *iname[] = {1576[CX231XX_VMUX_COMPOSITE1] = "Composite1",1577[CX231XX_VMUX_SVIDEO] = "S-Video",1578[CX231XX_VMUX_TELEVISION] = "Television",1579[CX231XX_VMUX_CABLE] = "Cable TV",1580[CX231XX_VMUX_DVB] = "DVB",1581[CX231XX_VMUX_DEBUG] = "for debug only",1582};1583static int vidioc_enum_input(struct file *file, void *priv,1584struct v4l2_input *i)1585{1586struct cx231xx_fh *fh = file->private_data;1587struct cx231xx *dev = fh->dev;1588struct cx231xx_input *input;1589int n;1590dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index);15911592if (i->index >= 4)1593return -EINVAL;159415951596input = &cx231xx_boards[dev->model].input[i->index];15971598if (input->type == 0)1599return -EINVAL;16001601/* FIXME1602* strcpy(i->name, input->name); */16031604n = i->index;1605strcpy(i->name, iname[INPUT(n)->type]);16061607if (input->type == CX231XX_VMUX_TELEVISION ||1608input->type == CX231XX_VMUX_CABLE)1609i->type = V4L2_INPUT_TYPE_TUNER;1610else1611i->type = V4L2_INPUT_TYPE_CAMERA;161216131614return 0;1615}16161617static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)1618{1619*i = 0;1620return 0;1621}16221623static int vidioc_s_input(struct file *file, void *priv, unsigned int i)1624{1625struct cx231xx_fh *fh = file->private_data;1626struct cx231xx *dev = fh->dev;16271628dprintk(3, "enter vidioc_s_input() i=%d\n", i);16291630mutex_lock(&dev->lock);16311632video_mux(dev, i);16331634mutex_unlock(&dev->lock);16351636if (i >= 4)1637return -EINVAL;1638dev->input = i;1639dprintk(3, "exit vidioc_s_input()\n");1640return 0;1641}16421643static int vidioc_g_tuner(struct file *file, void *priv,1644struct v4l2_tuner *t)1645{1646return 0;1647}16481649static int vidioc_s_tuner(struct file *file, void *priv,1650struct v4l2_tuner *t)1651{1652return 0;1653}16541655static int vidioc_g_frequency(struct file *file, void *priv,1656struct v4l2_frequency *f)1657{1658return 0;1659}16601661static int vidioc_s_frequency(struct file *file, void *priv,1662struct v4l2_frequency *f)1663{166416651666return 0;1667}16681669static int vidioc_s_ctrl(struct file *file, void *priv,1670struct v4l2_control *ctl)1671{1672struct cx231xx_fh *fh = file->private_data;1673struct cx231xx *dev = fh->dev;1674dprintk(3, "enter vidioc_s_ctrl()\n");1675/* Update the A/V core */1676call_all(dev, core, s_ctrl, ctl);1677dprintk(3, "exit vidioc_s_ctrl()\n");1678return 0;1679}1680static struct v4l2_capability pvr_capability = {1681.driver = "cx231xx",1682.card = "VideoGrabber",1683.bus_info = "usb",1684.version = 1,1685.capabilities = (V4L2_CAP_VIDEO_CAPTURE |1686V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |1687V4L2_CAP_STREAMING | V4L2_CAP_READWRITE),1688.reserved = {0, 0, 0, 0}1689};1690static int vidioc_querycap(struct file *file, void *priv,1691struct v4l2_capability *cap)1692{1693169416951696memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));1697return 0;1698}16991700static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,1701struct v4l2_fmtdesc *f)1702{17031704if (f->index != 0)1705return -EINVAL;17061707strlcpy(f->description, "MPEG", sizeof(f->description));1708f->pixelformat = V4L2_PIX_FMT_MPEG;17091710return 0;1711}17121713static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,1714struct v4l2_format *f)1715{1716struct cx231xx_fh *fh = file->private_data;1717struct cx231xx *dev = fh->dev;1718dprintk(3, "enter vidioc_g_fmt_vid_cap()\n");1719f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;1720f->fmt.pix.bytesperline = 0;1721f->fmt.pix.sizeimage =1722dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;1723f->fmt.pix.colorspace = 0;1724f->fmt.pix.width = dev->ts1.width;1725f->fmt.pix.height = dev->ts1.height;1726f->fmt.pix.field = fh->vidq.field;1727dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",1728dev->ts1.width, dev->ts1.height, fh->vidq.field);1729dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");1730return 0;1731}17321733static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,1734struct v4l2_format *f)1735{1736struct cx231xx_fh *fh = file->private_data;1737struct cx231xx *dev = fh->dev;1738dprintk(3, "enter vidioc_try_fmt_vid_cap()\n");1739f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;1740f->fmt.pix.bytesperline = 0;1741f->fmt.pix.sizeimage =1742dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;1743f->fmt.pix.colorspace = 0;1744dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",1745dev->ts1.width, dev->ts1.height, fh->vidq.field);1746dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");1747return 0;1748}17491750static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,1751struct v4l2_format *f)1752{17531754return 0;1755}17561757static int vidioc_reqbufs(struct file *file, void *priv,1758struct v4l2_requestbuffers *p)1759{1760struct cx231xx_fh *fh = file->private_data;17611762return videobuf_reqbufs(&fh->vidq, p);1763}17641765static int vidioc_querybuf(struct file *file, void *priv,1766struct v4l2_buffer *p)1767{1768struct cx231xx_fh *fh = file->private_data;17691770return videobuf_querybuf(&fh->vidq, p);1771}17721773static int vidioc_qbuf(struct file *file, void *priv,1774struct v4l2_buffer *p)1775{1776struct cx231xx_fh *fh = file->private_data;17771778return videobuf_qbuf(&fh->vidq, p);1779}17801781static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)1782{1783struct cx231xx_fh *fh = priv;17841785return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK);1786}178717881789static int vidioc_streamon(struct file *file, void *priv,1790enum v4l2_buf_type i)1791{1792struct cx231xx_fh *fh = file->private_data;17931794struct cx231xx *dev = fh->dev;1795int rc = 0;1796dprintk(3, "enter vidioc_streamon()\n");1797cx231xx_set_alt_setting(dev, INDEX_TS1, 0);1798rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);1799if (dev->USE_ISO)1800rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,1801CX231XX_NUM_BUFS,1802dev->video_mode.max_pkt_size,1803cx231xx_isoc_copy);1804else {1805rc = cx231xx_init_bulk(dev, 320,18065,1807dev->ts1_mode.max_pkt_size,1808cx231xx_bulk_copy);1809}1810dprintk(3, "exit vidioc_streamon()\n");1811return videobuf_streamon(&fh->vidq);1812}18131814static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)1815{1816struct cx231xx_fh *fh = file->private_data;18171818return videobuf_streamoff(&fh->vidq);1819}18201821static int vidioc_g_ext_ctrls(struct file *file, void *priv,1822struct v4l2_ext_controls *f)1823{1824struct cx231xx_fh *fh = priv;1825struct cx231xx *dev = fh->dev;1826dprintk(3, "enter vidioc_g_ext_ctrls()\n");1827if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)1828return -EINVAL;1829dprintk(3, "exit vidioc_g_ext_ctrls()\n");1830return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);1831}18321833static int vidioc_s_ext_ctrls(struct file *file, void *priv,1834struct v4l2_ext_controls *f)1835{1836struct cx231xx_fh *fh = priv;1837struct cx231xx *dev = fh->dev;1838struct cx2341x_mpeg_params p;1839int err;1840dprintk(3, "enter vidioc_s_ext_ctrls()\n");1841if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)1842return -EINVAL;18431844p = dev->mpeg_params;1845err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);1846if (err == 0) {1847err = cx2341x_update(dev, cx231xx_mbox_func,1848&dev->mpeg_params, &p);1849dev->mpeg_params = p;1850}18511852return err;185318541855return 0;1856}18571858static int vidioc_try_ext_ctrls(struct file *file, void *priv,1859struct v4l2_ext_controls *f)1860{1861struct cx231xx_fh *fh = priv;1862struct cx231xx *dev = fh->dev;1863struct cx2341x_mpeg_params p;1864int err;1865dprintk(3, "enter vidioc_try_ext_ctrls()\n");1866if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)1867return -EINVAL;18681869p = dev->mpeg_params;1870err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);1871dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err);1872return err;1873}18741875static int vidioc_log_status(struct file *file, void *priv)1876{1877struct cx231xx_fh *fh = priv;1878struct cx231xx *dev = fh->dev;1879char name[32 + 2];18801881snprintf(name, sizeof(name), "%s/2", dev->name);1882dprintk(3,1883"%s/2: ============ START LOG STATUS ============\n",1884dev->name);1885call_all(dev, core, log_status);1886cx2341x_log_status(&dev->mpeg_params, name);1887dprintk(3,1888"%s/2: ============= END LOG STATUS =============\n",1889dev->name);1890return 0;1891}18921893static int vidioc_querymenu(struct file *file, void *priv,1894struct v4l2_querymenu *a)1895{1896struct cx231xx_fh *fh = priv;1897struct cx231xx *dev = fh->dev;1898dprintk(3, "enter vidioc_querymenu()\n");1899dprintk(3, "exit vidioc_querymenu()\n");1900return cx231xx_querymenu(dev, a);1901}19021903static int vidioc_queryctrl(struct file *file, void *priv,1904struct v4l2_queryctrl *c)1905{1906struct cx231xx_fh *fh = priv;1907struct cx231xx *dev = fh->dev;1908dprintk(3, "enter vidioc_queryctrl()\n");1909dprintk(3, "exit vidioc_queryctrl()\n");1910return cx231xx_queryctrl(dev, c);1911}19121913static int mpeg_open(struct file *file)1914{1915int minor = video_devdata(file)->minor;1916struct cx231xx *h, *dev = NULL;1917/*struct list_head *list;*/1918struct cx231xx_fh *fh;1919/*u32 value = 0;*/19201921dprintk(2, "%s()\n", __func__);19221923list_for_each_entry(h, &cx231xx_devlist, devlist) {1924if (h->v4l_device->minor == minor)1925dev = h;1926}19271928if (dev == NULL)1929return -ENODEV;19301931mutex_lock(&dev->lock);19321933/* allocate + initialize per filehandle data */1934fh = kzalloc(sizeof(*fh), GFP_KERNEL);1935if (NULL == fh) {1936mutex_unlock(&dev->lock);1937return -ENOMEM;1938}19391940file->private_data = fh;1941fh->dev = dev;194219431944videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops,1945NULL, &dev->video_mode.slock,1946V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,1947sizeof(struct cx231xx_buffer), fh, NULL);1948/*1949videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,1950&dev->udev->dev, &dev->ts1.slock,1951V4L2_BUF_TYPE_VIDEO_CAPTURE,1952V4L2_FIELD_INTERLACED,1953sizeof(struct cx231xx_buffer),1954fh, NULL);1955*/195619571958cx231xx_set_alt_setting(dev, INDEX_VANC, 1);1959cx231xx_set_gpio_value(dev, 2, 0);19601961cx231xx_initialize_codec(dev);19621963mutex_unlock(&dev->lock);1964cx231xx_start_TS1(dev);19651966return 0;1967}19681969static int mpeg_release(struct file *file)1970{1971struct cx231xx_fh *fh = file->private_data;1972struct cx231xx *dev = fh->dev;19731974dprintk(3, "mpeg_release()! dev=0x%p\n", dev);19751976if (!dev) {1977dprintk(3, "abort!!!\n");1978return 0;1979}19801981mutex_lock(&dev->lock);19821983cx231xx_stop_TS1(dev);19841985/* do this before setting alternate! */1986if (dev->USE_ISO)1987cx231xx_uninit_isoc(dev);1988else1989cx231xx_uninit_bulk(dev);1990cx231xx_set_mode(dev, CX231XX_SUSPEND);19911992cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,1993CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,1994CX231xx_RAW_BITS_NONE);19951996/* FIXME: Review this crap */1997/* Shut device down on last close */1998if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {1999if (atomic_dec_return(&dev->v4l_reader_count) == 0) {2000/* stop mpeg capture */20012002msleep(500);2003cx231xx_417_check_encoder(dev);20042005}2006}20072008if (fh->vidq.streaming)2009videobuf_streamoff(&fh->vidq);2010if (fh->vidq.reading)2011videobuf_read_stop(&fh->vidq);20122013videobuf_mmap_free(&fh->vidq);2014file->private_data = NULL;2015kfree(fh);2016mutex_unlock(&dev->lock);2017return 0;2018}20192020static ssize_t mpeg_read(struct file *file, char __user *data,2021size_t count, loff_t *ppos)2022{2023struct cx231xx_fh *fh = file->private_data;2024struct cx231xx *dev = fh->dev;202520262027/* Deal w/ A/V decoder * and mpeg encoder sync issues. */2028/* Start mpeg encoder on first read. */2029if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {2030if (atomic_inc_return(&dev->v4l_reader_count) == 1) {2031if (cx231xx_initialize_codec(dev) < 0)2032return -EINVAL;2033}2034}20352036return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,2037file->f_flags & O_NONBLOCK);2038}20392040static unsigned int mpeg_poll(struct file *file,2041struct poll_table_struct *wait)2042{2043struct cx231xx_fh *fh = file->private_data;2044/*struct cx231xx *dev = fh->dev;*/20452046/*dprintk(2, "%s\n", __func__);*/20472048return videobuf_poll_stream(file, &fh->vidq, wait);2049}20502051static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)2052{2053struct cx231xx_fh *fh = file->private_data;2054struct cx231xx *dev = fh->dev;20552056dprintk(2, "%s()\n", __func__);20572058return videobuf_mmap_mapper(&fh->vidq, vma);2059}20602061static struct v4l2_file_operations mpeg_fops = {2062.owner = THIS_MODULE,2063.open = mpeg_open,2064.release = mpeg_release,2065.read = mpeg_read,2066.poll = mpeg_poll,2067.mmap = mpeg_mmap,2068.ioctl = video_ioctl2,2069};20702071static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {2072.vidioc_s_std = vidioc_s_std,2073.vidioc_g_std = vidioc_g_std,2074.vidioc_enum_input = vidioc_enum_input,2075.vidioc_enumaudio = vidioc_enumaudio,2076.vidioc_g_audio = vidioc_g_audio,2077.vidioc_g_input = vidioc_g_input,2078.vidioc_s_input = vidioc_s_input,2079.vidioc_g_tuner = vidioc_g_tuner,2080.vidioc_s_tuner = vidioc_s_tuner,2081.vidioc_g_frequency = vidioc_g_frequency,2082.vidioc_s_frequency = vidioc_s_frequency,2083.vidioc_s_ctrl = vidioc_s_ctrl,2084.vidioc_querycap = vidioc_querycap,2085.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,2086.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,2087.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,2088.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,2089.vidioc_reqbufs = vidioc_reqbufs,2090.vidioc_querybuf = vidioc_querybuf,2091.vidioc_qbuf = vidioc_qbuf,2092.vidioc_dqbuf = vidioc_dqbuf,2093.vidioc_streamon = vidioc_streamon,2094.vidioc_streamoff = vidioc_streamoff,2095.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,2096.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,2097.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,2098.vidioc_log_status = vidioc_log_status,2099.vidioc_querymenu = vidioc_querymenu,2100.vidioc_queryctrl = vidioc_queryctrl,2101/* .vidioc_g_chip_ident = cx231xx_g_chip_ident,*/2102#ifdef CONFIG_VIDEO_ADV_DEBUG2103/* .vidioc_g_register = cx231xx_g_register,*/2104/* .vidioc_s_register = cx231xx_s_register,*/2105#endif2106};21072108static struct video_device cx231xx_mpeg_template = {2109.name = "cx231xx",2110.fops = &mpeg_fops,2111.ioctl_ops = &mpeg_ioctl_ops,2112.minor = -1,2113.tvnorms = CX231xx_NORMS,2114.current_norm = V4L2_STD_NTSC_M,2115};21162117void cx231xx_417_unregister(struct cx231xx *dev)2118{2119dprintk(1, "%s()\n", __func__);2120dprintk(3, "%s()\n", __func__);21212122if (dev->v4l_device) {2123if (-1 != dev->v4l_device->minor)2124video_unregister_device(dev->v4l_device);2125else2126video_device_release(dev->v4l_device);2127dev->v4l_device = NULL;2128}2129}21302131static struct video_device *cx231xx_video_dev_alloc(2132struct cx231xx *dev,2133struct usb_device *usbdev,2134struct video_device *template,2135char *type)2136{2137struct video_device *vfd;21382139dprintk(1, "%s()\n", __func__);2140vfd = video_device_alloc();2141if (NULL == vfd)2142return NULL;2143*vfd = *template;2144vfd->minor = -1;2145snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,2146type, cx231xx_boards[dev->model].name);21472148vfd->v4l2_dev = &dev->v4l2_dev;2149vfd->release = video_device_release;21502151return vfd;21522153}21542155int cx231xx_417_register(struct cx231xx *dev)2156{2157/* FIXME: Port1 hardcoded here */2158int err = -ENODEV;2159struct cx231xx_tsport *tsport = &dev->ts1;21602161dprintk(1, "%s()\n", __func__);21622163/* Set default TV standard */2164dev->encodernorm = cx231xx_tvnorms[0];21652166if (dev->encodernorm.id & V4L2_STD_525_60)2167tsport->height = 480;2168else2169tsport->height = 576;21702171tsport->width = 720;2172cx2341x_fill_defaults(&dev->mpeg_params);2173dev->norm = V4L2_STD_NTSC;21742175dev->mpeg_params.port = CX2341X_PORT_SERIAL;21762177/* Allocate and initialize V4L video device */2178dev->v4l_device = cx231xx_video_dev_alloc(dev,2179dev->udev, &cx231xx_mpeg_template, "mpeg");2180err = video_register_device(dev->v4l_device,2181VFL_TYPE_GRABBER, -1);2182if (err < 0) {2183dprintk(3, "%s: can't register mpeg device\n", dev->name);2184return err;2185}21862187dprintk(3, "%s: registered device video%d [mpeg]\n",2188dev->name, dev->v4l_device->num);21892190return 0;2191}219221932194