Path: blob/master/drivers/media/video/cx231xx/cx231xx-core.c
17884 views
/*1cx231xx-core.c - driver for Conexant Cx23100/101/1022USB video capture devices34Copyright (C) 2008 <srinivasa.deevi at conexant dot com>5Based on em28xx driver67This program is free software; you can redistribute it and/or modify8it under the terms of the GNU General Public License as published by9the Free Software Foundation; either version 2 of the License, or10(at your option) any later version.1112This program is distributed in the hope that it will be useful,13but WITHOUT ANY WARRANTY; without even the implied warranty of14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15GNU General Public License for more details.1617You should have received a copy of the GNU General Public License18along with this program; if not, write to the Free Software19Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.20*/2122#include <linux/init.h>23#include <linux/list.h>24#include <linux/module.h>25#include <linux/slab.h>26#include <linux/usb.h>27#include <linux/vmalloc.h>28#include <media/v4l2-common.h>29#include <media/tuner.h>3031#include "cx231xx.h"32#include "cx231xx-reg.h"3334/* #define ENABLE_DEBUG_ISOC_FRAMES */3536static unsigned int core_debug;37module_param(core_debug, int, 0644);38MODULE_PARM_DESC(core_debug, "enable debug messages [core]");3940#define cx231xx_coredbg(fmt, arg...) do {\41if (core_debug) \42printk(KERN_INFO "%s %s :"fmt, \43dev->name, __func__ , ##arg); } while (0)4445static unsigned int reg_debug;46module_param(reg_debug, int, 0644);47MODULE_PARM_DESC(reg_debug, "enable debug messages [URB reg]");4849static int alt = CX231XX_PINOUT;50module_param(alt, int, 0644);51MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");5253#define cx231xx_isocdbg(fmt, arg...) do {\54if (core_debug) \55printk(KERN_INFO "%s %s :"fmt, \56dev->name, __func__ , ##arg); } while (0)5758/*****************************************************************59* Device control list functions *60******************************************************************/6162LIST_HEAD(cx231xx_devlist);63static DEFINE_MUTEX(cx231xx_devlist_mutex);6465/*66* cx231xx_realease_resources()67* unregisters the v4l2,i2c and usb devices68* called when the device gets disconected or at module unload69*/70void cx231xx_remove_from_devlist(struct cx231xx *dev)71{72if (dev == NULL)73return;74if (dev->udev == NULL)75return;7677if (atomic_read(&dev->devlist_count) > 0) {78mutex_lock(&cx231xx_devlist_mutex);79list_del(&dev->devlist);80atomic_dec(&dev->devlist_count);81mutex_unlock(&cx231xx_devlist_mutex);82}83};8485void cx231xx_add_into_devlist(struct cx231xx *dev)86{87mutex_lock(&cx231xx_devlist_mutex);88list_add_tail(&dev->devlist, &cx231xx_devlist);89atomic_inc(&dev->devlist_count);90mutex_unlock(&cx231xx_devlist_mutex);91};9293static LIST_HEAD(cx231xx_extension_devlist);9495int cx231xx_register_extension(struct cx231xx_ops *ops)96{97struct cx231xx *dev = NULL;9899mutex_lock(&cx231xx_devlist_mutex);100list_add_tail(&ops->next, &cx231xx_extension_devlist);101list_for_each_entry(dev, &cx231xx_devlist, devlist)102ops->init(dev);103104printk(KERN_INFO DRIVER_NAME ": %s initialized\n", ops->name);105mutex_unlock(&cx231xx_devlist_mutex);106return 0;107}108EXPORT_SYMBOL(cx231xx_register_extension);109110void cx231xx_unregister_extension(struct cx231xx_ops *ops)111{112struct cx231xx *dev = NULL;113114mutex_lock(&cx231xx_devlist_mutex);115list_for_each_entry(dev, &cx231xx_devlist, devlist)116ops->fini(dev);117118119printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name);120list_del(&ops->next);121mutex_unlock(&cx231xx_devlist_mutex);122}123EXPORT_SYMBOL(cx231xx_unregister_extension);124125void cx231xx_init_extension(struct cx231xx *dev)126{127struct cx231xx_ops *ops = NULL;128129mutex_lock(&cx231xx_devlist_mutex);130if (!list_empty(&cx231xx_extension_devlist)) {131list_for_each_entry(ops, &cx231xx_extension_devlist, next) {132if (ops->init)133ops->init(dev);134}135}136mutex_unlock(&cx231xx_devlist_mutex);137}138139void cx231xx_close_extension(struct cx231xx *dev)140{141struct cx231xx_ops *ops = NULL;142143mutex_lock(&cx231xx_devlist_mutex);144if (!list_empty(&cx231xx_extension_devlist)) {145list_for_each_entry(ops, &cx231xx_extension_devlist, next) {146if (ops->fini)147ops->fini(dev);148}149}150mutex_unlock(&cx231xx_devlist_mutex);151}152153/****************************************************************154* U S B related functions *155*****************************************************************/156int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus,157struct cx231xx_i2c_xfer_data *req_data)158{159int status = 0;160struct cx231xx *dev = i2c_bus->dev;161struct VENDOR_REQUEST_IN ven_req;162163u8 saddr_len = 0;164u8 _i2c_period = 0;165u8 _i2c_nostop = 0;166u8 _i2c_reserve = 0;167168/* Get the I2C period, nostop and reserve parameters */169_i2c_period = i2c_bus->i2c_period;170_i2c_nostop = i2c_bus->i2c_nostop;171_i2c_reserve = i2c_bus->i2c_reserve;172173saddr_len = req_data->saddr_len;174175/* Set wValue */176if (saddr_len == 1) /* need check saddr_len == 0 */177ven_req.wValue =178req_data->179dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |180_i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;181else182ven_req.wValue =183req_data->184dev_addr << 9 | _i2c_period << 4 | saddr_len << 2 |185_i2c_nostop << 1 | I2C_SYNC | _i2c_reserve << 6;186187/* set channel number */188if (req_data->direction & I2C_M_RD) {189/* channel number, for read,spec required channel_num +4 */190ven_req.bRequest = i2c_bus->nr + 4;191} else192ven_req.bRequest = i2c_bus->nr; /* channel number, */193194/* set index value */195switch (saddr_len) {196case 0:197ven_req.wIndex = 0; /* need check */198break;199case 1:200ven_req.wIndex = (req_data->saddr_dat & 0xff);201break;202case 2:203ven_req.wIndex = req_data->saddr_dat;204break;205}206207/* set wLength value */208ven_req.wLength = req_data->buf_size;209210/* set bData value */211ven_req.bData = 0;212213/* set the direction */214if (req_data->direction) {215ven_req.direction = USB_DIR_IN;216memset(req_data->p_buffer, 0x00, ven_req.wLength);217} else218ven_req.direction = USB_DIR_OUT;219220/* set the buffer for read / write */221ven_req.pBuff = req_data->p_buffer;222223224/* call common vendor command request */225status = cx231xx_send_vendor_cmd(dev, &ven_req);226if (status < 0) {227cx231xx_info228("UsbInterface::sendCommand, failed with status -%d\n",229status);230}231232return status;233}234EXPORT_SYMBOL_GPL(cx231xx_send_usb_command);235236/*237* Sends/Receives URB control messages, assuring to use a kalloced buffer238* for all operations (dev->urb_buf), to avoid using stacked buffers, as239* they aren't safe for usage with USB, due to DMA restrictions.240* Also implements the debug code for control URB's.241*/242static int __usb_control_msg(struct cx231xx *dev, unsigned int pipe,243__u8 request, __u8 requesttype, __u16 value, __u16 index,244void *data, __u16 size, int timeout)245{246int rc, i;247248if (reg_debug) {249printk(KERN_DEBUG "%s: (pipe 0x%08x): "250"%s: %02x %02x %02x %02x %02x %02x %02x %02x ",251dev->name,252pipe,253(requesttype & USB_DIR_IN) ? "IN" : "OUT",254requesttype,255request,256value & 0xff, value >> 8,257index & 0xff, index >> 8,258size & 0xff, size >> 8);259if (!(requesttype & USB_DIR_IN)) {260printk(KERN_CONT ">>>");261for (i = 0; i < size; i++)262printk(KERN_CONT " %02x",263((unsigned char *)data)[i]);264}265}266267/* Do the real call to usb_control_msg */268mutex_lock(&dev->ctrl_urb_lock);269if (!(requesttype & USB_DIR_IN) && size)270memcpy(dev->urb_buf, data, size);271rc = usb_control_msg(dev->udev, pipe, request, requesttype, value,272index, dev->urb_buf, size, timeout);273if ((requesttype & USB_DIR_IN) && size)274memcpy(data, dev->urb_buf, size);275mutex_unlock(&dev->ctrl_urb_lock);276277if (reg_debug) {278if (unlikely(rc < 0)) {279printk(KERN_CONT "FAILED!\n");280return rc;281}282283if ((requesttype & USB_DIR_IN)) {284printk(KERN_CONT "<<<");285for (i = 0; i < size; i++)286printk(KERN_CONT " %02x",287((unsigned char *)data)[i]);288}289printk(KERN_CONT "\n");290}291292return rc;293}294295296/*297* cx231xx_read_ctrl_reg()298* reads data from the usb device specifying bRequest and wValue299*/300int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,301char *buf, int len)302{303u8 val = 0;304int ret;305int pipe = usb_rcvctrlpipe(dev->udev, 0);306307if (dev->state & DEV_DISCONNECTED)308return -ENODEV;309310if (len > URB_MAX_CTRL_SIZE)311return -EINVAL;312313switch (len) {314case 1:315val = ENABLE_ONE_BYTE;316break;317case 2:318val = ENABLE_TWE_BYTE;319break;320case 3:321val = ENABLE_THREE_BYTE;322break;323case 4:324val = ENABLE_FOUR_BYTE;325break;326default:327val = 0xFF; /* invalid option */328}329330if (val == 0xFF)331return -EINVAL;332333ret = __usb_control_msg(dev, pipe, req,334USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,335val, reg, buf, len, HZ);336return ret;337}338339int cx231xx_send_vendor_cmd(struct cx231xx *dev,340struct VENDOR_REQUEST_IN *ven_req)341{342int ret;343int pipe = 0;344int unsend_size = 0;345u8 *pdata;346347if (dev->state & DEV_DISCONNECTED)348return -ENODEV;349350if ((ven_req->wLength > URB_MAX_CTRL_SIZE))351return -EINVAL;352353if (ven_req->direction)354pipe = usb_rcvctrlpipe(dev->udev, 0);355else356pipe = usb_sndctrlpipe(dev->udev, 0);357358/*359* If the cx23102 read more than 4 bytes with i2c bus,360* need chop to 4 byte per request361*/362if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) ||363(ven_req->bRequest == 0x5) ||364(ven_req->bRequest == 0x6))) {365unsend_size = 0;366pdata = ven_req->pBuff;367368369unsend_size = ven_req->wLength;370371/* the first package */372ven_req->wValue = ven_req->wValue & 0xFFFB;373ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x2;374ret = __usb_control_msg(dev, pipe, ven_req->bRequest,375ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,376ven_req->wValue, ven_req->wIndex, pdata,3770x0004, HZ);378unsend_size = unsend_size - 4;379380/* the middle package */381ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x42;382while (unsend_size - 4 > 0) {383pdata = pdata + 4;384ret = __usb_control_msg(dev, pipe,385ven_req->bRequest,386ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,387ven_req->wValue, ven_req->wIndex, pdata,3880x0004, HZ);389unsend_size = unsend_size - 4;390}391392/* the last package */393ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x40;394pdata = pdata + 4;395ret = __usb_control_msg(dev, pipe, ven_req->bRequest,396ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,397ven_req->wValue, ven_req->wIndex, pdata,398unsend_size, HZ);399} else {400ret = __usb_control_msg(dev, pipe, ven_req->bRequest,401ven_req->direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,402ven_req->wValue, ven_req->wIndex,403ven_req->pBuff, ven_req->wLength, HZ);404}405406return ret;407}408409/*410* cx231xx_write_ctrl_reg()411* sends data to the usb device, specifying bRequest412*/413int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf,414int len)415{416u8 val = 0;417int ret;418int pipe = usb_sndctrlpipe(dev->udev, 0);419420if (dev->state & DEV_DISCONNECTED)421return -ENODEV;422423if ((len < 1) || (len > URB_MAX_CTRL_SIZE))424return -EINVAL;425426switch (len) {427case 1:428val = ENABLE_ONE_BYTE;429break;430case 2:431val = ENABLE_TWE_BYTE;432break;433case 3:434val = ENABLE_THREE_BYTE;435break;436case 4:437val = ENABLE_FOUR_BYTE;438break;439default:440val = 0xFF; /* invalid option */441}442443if (val == 0xFF)444return -EINVAL;445446if (reg_debug) {447int byte;448449cx231xx_isocdbg("(pipe 0x%08x): "450"OUT: %02x %02x %02x %02x %02x %02x %02x %02x >>>",451pipe,452USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,453req, 0, val, reg & 0xff,454reg >> 8, len & 0xff, len >> 8);455456for (byte = 0; byte < len; byte++)457cx231xx_isocdbg(" %02x", (unsigned char)buf[byte]);458cx231xx_isocdbg("\n");459}460461ret = __usb_control_msg(dev, pipe, req,462USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,463val, reg, buf, len, HZ);464465return ret;466}467468/****************************************************************469* USB Alternate Setting functions *470*****************************************************************/471472int cx231xx_set_video_alternate(struct cx231xx *dev)473{474int errCode, prev_alt = dev->video_mode.alt;475unsigned int min_pkt_size = dev->width * 2 + 4;476u32 usb_interface_index = 0;477478/* When image size is bigger than a certain value,479the frame size should be increased, otherwise, only480green screen will be received.481*/482if (dev->width * 2 * dev->height > 720 * 240 * 2)483min_pkt_size *= 2;484485if (dev->width > 360) {486/* resolutions: 720,704,640 */487dev->video_mode.alt = 3;488} else if (dev->width > 180) {489/* resolutions: 360,352,320,240 */490dev->video_mode.alt = 2;491} else if (dev->width > 0) {492/* resolutions: 180,176,160,128,88 */493dev->video_mode.alt = 1;494} else {495/* Change to alt0 BULK to release USB bandwidth */496dev->video_mode.alt = 0;497}498499if (dev->USE_ISO == 0)500dev->video_mode.alt = 0;501502cx231xx_coredbg("dev->video_mode.alt= %d\n", dev->video_mode.alt);503504/* Get the correct video interface Index */505usb_interface_index =506dev->current_pcb_config.hs_config_info[0].interface_info.507video_index + 1;508509if (dev->video_mode.alt != prev_alt) {510cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",511min_pkt_size, dev->video_mode.alt);512513if (dev->video_mode.alt_max_pkt_size != NULL)514dev->video_mode.max_pkt_size =515dev->video_mode.alt_max_pkt_size[dev->video_mode.alt];516cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",517dev->video_mode.alt,518dev->video_mode.max_pkt_size);519errCode =520usb_set_interface(dev->udev, usb_interface_index,521dev->video_mode.alt);522if (errCode < 0) {523cx231xx_errdev524("cannot change alt number to %d (error=%i)\n",525dev->video_mode.alt, errCode);526return errCode;527}528}529return 0;530}531532int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt)533{534int status = 0;535u32 usb_interface_index = 0;536u32 max_pkt_size = 0;537538switch (index) {539case INDEX_TS1:540usb_interface_index =541dev->current_pcb_config.hs_config_info[0].interface_info.542ts1_index + 1;543dev->ts1_mode.alt = alt;544if (dev->ts1_mode.alt_max_pkt_size != NULL)545max_pkt_size = dev->ts1_mode.max_pkt_size =546dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt];547break;548case INDEX_TS2:549usb_interface_index =550dev->current_pcb_config.hs_config_info[0].interface_info.551ts2_index + 1;552break;553case INDEX_AUDIO:554usb_interface_index =555dev->current_pcb_config.hs_config_info[0].interface_info.556audio_index + 1;557dev->adev.alt = alt;558if (dev->adev.alt_max_pkt_size != NULL)559max_pkt_size = dev->adev.max_pkt_size =560dev->adev.alt_max_pkt_size[dev->adev.alt];561break;562case INDEX_VIDEO:563usb_interface_index =564dev->current_pcb_config.hs_config_info[0].interface_info.565video_index + 1;566dev->video_mode.alt = alt;567if (dev->video_mode.alt_max_pkt_size != NULL)568max_pkt_size = dev->video_mode.max_pkt_size =569dev->video_mode.alt_max_pkt_size[dev->video_mode.570alt];571break;572case INDEX_VANC:573if (dev->board.no_alt_vanc)574return 0;575usb_interface_index =576dev->current_pcb_config.hs_config_info[0].interface_info.577vanc_index + 1;578dev->vbi_mode.alt = alt;579if (dev->vbi_mode.alt_max_pkt_size != NULL)580max_pkt_size = dev->vbi_mode.max_pkt_size =581dev->vbi_mode.alt_max_pkt_size[dev->vbi_mode.alt];582break;583case INDEX_HANC:584usb_interface_index =585dev->current_pcb_config.hs_config_info[0].interface_info.586hanc_index + 1;587dev->sliced_cc_mode.alt = alt;588if (dev->sliced_cc_mode.alt_max_pkt_size != NULL)589max_pkt_size = dev->sliced_cc_mode.max_pkt_size =590dev->sliced_cc_mode.alt_max_pkt_size[dev->591sliced_cc_mode.592alt];593break;594default:595break;596}597598if (alt > 0 && max_pkt_size == 0) {599cx231xx_errdev600("can't change interface %d alt no. to %d: Max. Pkt size = 0\n",601usb_interface_index, alt);602/*To workaround error number=-71 on EP0 for videograbber,603need add following codes.*/604if (dev->board.no_alt_vanc)605return -1;606}607608cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u,"609"Interface = %d\n", alt, max_pkt_size,610usb_interface_index);611612if (usb_interface_index > 0) {613status = usb_set_interface(dev->udev, usb_interface_index, alt);614if (status < 0) {615cx231xx_errdev616("can't change interface %d alt no. to %d (err=%i)\n",617usb_interface_index, alt, status);618return status;619}620}621622return status;623}624EXPORT_SYMBOL_GPL(cx231xx_set_alt_setting);625626int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio)627{628int rc = 0;629630if (!gpio)631return rc;632633/* Send GPIO reset sequences specified at board entry */634while (gpio->sleep >= 0) {635rc = cx231xx_set_gpio_value(dev, gpio->bit, gpio->val);636if (rc < 0)637return rc;638639if (gpio->sleep > 0)640msleep(gpio->sleep);641642gpio++;643}644return rc;645}646647int cx231xx_demod_reset(struct cx231xx *dev)648{649650u8 status = 0;651u8 value[4] = { 0, 0, 0, 0 };652653status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,654value, 4);655656cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN,657value[0], value[1], value[2], value[3]);658659cx231xx_coredbg("Enter cx231xx_demod_reset()\n");660661value[1] = (u8) 0x3;662status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,663PWR_CTL_EN, value, 4);664msleep(10);665666value[1] = (u8) 0x0;667status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,668PWR_CTL_EN, value, 4);669msleep(10);670671value[1] = (u8) 0x3;672status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,673PWR_CTL_EN, value, 4);674msleep(10);675676677678status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,679value, 4);680681cx231xx_coredbg("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN,682value[0], value[1], value[2], value[3]);683684return status;685}686EXPORT_SYMBOL_GPL(cx231xx_demod_reset);687int is_fw_load(struct cx231xx *dev)688{689return cx231xx_check_fw(dev);690}691EXPORT_SYMBOL_GPL(is_fw_load);692693int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)694{695int errCode = 0;696697if (dev->mode == set_mode)698return 0;699700if (set_mode == CX231XX_SUSPEND) {701/* Set the chip in power saving mode */702dev->mode = set_mode;703}704705/* Resource is locked */706if (dev->mode != CX231XX_SUSPEND)707return -EINVAL;708709dev->mode = set_mode;710711if (dev->mode == CX231XX_DIGITAL_MODE)/* Set Digital power mode */ {712/* set AGC mode to Digital */713switch (dev->model) {714case CX231XX_BOARD_CNXT_CARRAERA:715case CX231XX_BOARD_CNXT_RDE_250:716case CX231XX_BOARD_CNXT_SHELBY:717case CX231XX_BOARD_CNXT_RDU_250:718errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);719break;720case CX231XX_BOARD_CNXT_RDE_253S:721case CX231XX_BOARD_CNXT_RDU_253S:722errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);723break;724case CX231XX_BOARD_HAUPPAUGE_EXETER:725errCode = cx231xx_set_power_mode(dev,726POLARIS_AVMODE_DIGITAL);727break;728default:729break;730}731} else/* Set Analog Power mode */ {732/* set AGC mode to Analog */733switch (dev->model) {734case CX231XX_BOARD_CNXT_CARRAERA:735case CX231XX_BOARD_CNXT_RDE_250:736case CX231XX_BOARD_CNXT_SHELBY:737case CX231XX_BOARD_CNXT_RDU_250:738errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);739break;740case CX231XX_BOARD_CNXT_RDE_253S:741case CX231XX_BOARD_CNXT_RDU_253S:742case CX231XX_BOARD_HAUPPAUGE_EXETER:743case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:744errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);745break;746default:747break;748}749}750751return 0;752}753EXPORT_SYMBOL_GPL(cx231xx_set_mode);754755int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size)756{757int errCode = 0;758int actlen, ret = -ENOMEM;759u32 *buffer;760761buffer = kzalloc(4096, GFP_KERNEL);762if (buffer == NULL) {763cx231xx_info("out of mem\n");764return -ENOMEM;765}766memcpy(&buffer[0], firmware, 4096);767768ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 5),769buffer, 4096, &actlen, 2000);770771if (ret)772cx231xx_info("bulk message failed: %d (%d/%d)", ret,773size, actlen);774else {775errCode = actlen != size ? -1 : 0;776}777kfree(buffer);778return 0;779}780781/*****************************************************************782* URB Streaming functions *783******************************************************************/784785/*786* IRQ callback, called by URB callback787*/788static void cx231xx_isoc_irq_callback(struct urb *urb)789{790struct cx231xx_dmaqueue *dma_q = urb->context;791struct cx231xx_video_mode *vmode =792container_of(dma_q, struct cx231xx_video_mode, vidq);793struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);794int rc, i;795796switch (urb->status) {797case 0: /* success */798case -ETIMEDOUT: /* NAK */799break;800case -ECONNRESET: /* kill */801case -ENOENT:802case -ESHUTDOWN:803return;804default: /* error */805cx231xx_isocdbg("urb completition error %d.\n", urb->status);806break;807}808809/* Copy data from URB */810spin_lock(&dev->video_mode.slock);811rc = dev->video_mode.isoc_ctl.isoc_copy(dev, urb);812spin_unlock(&dev->video_mode.slock);813814/* Reset urb buffers */815for (i = 0; i < urb->number_of_packets; i++) {816urb->iso_frame_desc[i].status = 0;817urb->iso_frame_desc[i].actual_length = 0;818}819urb->status = 0;820821urb->status = usb_submit_urb(urb, GFP_ATOMIC);822if (urb->status) {823cx231xx_isocdbg("urb resubmit failed (error=%i)\n",824urb->status);825}826}827/*****************************************************************828* URB Streaming functions *829******************************************************************/830831/*832* IRQ callback, called by URB callback833*/834static void cx231xx_bulk_irq_callback(struct urb *urb)835{836struct cx231xx_dmaqueue *dma_q = urb->context;837struct cx231xx_video_mode *vmode =838container_of(dma_q, struct cx231xx_video_mode, vidq);839struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);840int rc;841842switch (urb->status) {843case 0: /* success */844case -ETIMEDOUT: /* NAK */845break;846case -ECONNRESET: /* kill */847case -ENOENT:848case -ESHUTDOWN:849return;850default: /* error */851cx231xx_isocdbg("urb completition error %d.\n", urb->status);852break;853}854855/* Copy data from URB */856spin_lock(&dev->video_mode.slock);857rc = dev->video_mode.bulk_ctl.bulk_copy(dev, urb);858spin_unlock(&dev->video_mode.slock);859860/* Reset urb buffers */861urb->status = 0;862863urb->status = usb_submit_urb(urb, GFP_ATOMIC);864if (urb->status) {865cx231xx_isocdbg("urb resubmit failed (error=%i)\n",866urb->status);867}868}869/*870* Stop and Deallocate URBs871*/872void cx231xx_uninit_isoc(struct cx231xx *dev)873{874struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;875struct urb *urb;876int i;877878cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n");879880dev->video_mode.isoc_ctl.nfields = -1;881for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {882urb = dev->video_mode.isoc_ctl.urb[i];883if (urb) {884if (!irqs_disabled())885usb_kill_urb(urb);886else887usb_unlink_urb(urb);888889if (dev->video_mode.isoc_ctl.transfer_buffer[i]) {890usb_free_coherent(dev->udev,891urb->transfer_buffer_length,892dev->video_mode.isoc_ctl.893transfer_buffer[i],894urb->transfer_dma);895}896usb_free_urb(urb);897dev->video_mode.isoc_ctl.urb[i] = NULL;898}899dev->video_mode.isoc_ctl.transfer_buffer[i] = NULL;900}901902kfree(dev->video_mode.isoc_ctl.urb);903kfree(dev->video_mode.isoc_ctl.transfer_buffer);904kfree(dma_q->p_left_data);905906dev->video_mode.isoc_ctl.urb = NULL;907dev->video_mode.isoc_ctl.transfer_buffer = NULL;908dev->video_mode.isoc_ctl.num_bufs = 0;909dma_q->p_left_data = NULL;910911if (dev->mode_tv == 0)912cx231xx_capture_start(dev, 0, Raw_Video);913else914cx231xx_capture_start(dev, 0, TS1_serial_mode);915916917}918EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc);919920/*921* Stop and Deallocate URBs922*/923void cx231xx_uninit_bulk(struct cx231xx *dev)924{925struct urb *urb;926int i;927928cx231xx_isocdbg("cx231xx: called cx231xx_uninit_bulk\n");929930dev->video_mode.bulk_ctl.nfields = -1;931for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {932urb = dev->video_mode.bulk_ctl.urb[i];933if (urb) {934if (!irqs_disabled())935usb_kill_urb(urb);936else937usb_unlink_urb(urb);938939if (dev->video_mode.bulk_ctl.transfer_buffer[i]) {940usb_free_coherent(dev->udev,941urb->transfer_buffer_length,942dev->video_mode.isoc_ctl.943transfer_buffer[i],944urb->transfer_dma);945}946usb_free_urb(urb);947dev->video_mode.bulk_ctl.urb[i] = NULL;948}949dev->video_mode.bulk_ctl.transfer_buffer[i] = NULL;950}951952kfree(dev->video_mode.bulk_ctl.urb);953kfree(dev->video_mode.bulk_ctl.transfer_buffer);954955dev->video_mode.bulk_ctl.urb = NULL;956dev->video_mode.bulk_ctl.transfer_buffer = NULL;957dev->video_mode.bulk_ctl.num_bufs = 0;958959if (dev->mode_tv == 0)960cx231xx_capture_start(dev, 0, Raw_Video);961else962cx231xx_capture_start(dev, 0, TS1_serial_mode);963964965}966EXPORT_SYMBOL_GPL(cx231xx_uninit_bulk);967968/*969* Allocate URBs and start IRQ970*/971int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,972int num_bufs, int max_pkt_size,973int (*isoc_copy) (struct cx231xx *dev, struct urb *urb))974{975struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;976int i;977int sb_size, pipe;978struct urb *urb;979int j, k;980int rc;981982/* De-allocates all pending stuff */983cx231xx_uninit_isoc(dev);984985dma_q->p_left_data = kzalloc(4096, GFP_KERNEL);986if (dma_q->p_left_data == NULL) {987cx231xx_info("out of mem\n");988return -ENOMEM;989}990991992993dev->video_mode.isoc_ctl.isoc_copy = isoc_copy;994dev->video_mode.isoc_ctl.num_bufs = num_bufs;995dma_q->pos = 0;996dma_q->is_partial_line = 0;997dma_q->last_sav = 0;998dma_q->current_field = -1;999dma_q->field1_done = 0;1000dma_q->lines_per_field = dev->height / 2;1001dma_q->bytes_left_in_line = dev->width << 1;1002dma_q->lines_completed = 0;1003dma_q->mpeg_buffer_done = 0;1004dma_q->left_data_count = 0;1005dma_q->mpeg_buffer_completed = 0;1006dma_q->add_ps_package_head = CX231XX_NEED_ADD_PS_PACKAGE_HEAD;1007dma_q->ps_head[0] = 0x00;1008dma_q->ps_head[1] = 0x00;1009dma_q->ps_head[2] = 0x01;1010dma_q->ps_head[3] = 0xBA;1011for (i = 0; i < 8; i++)1012dma_q->partial_buf[i] = 0;10131014dev->video_mode.isoc_ctl.urb =1015kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);1016if (!dev->video_mode.isoc_ctl.urb) {1017cx231xx_errdev("cannot alloc memory for usb buffers\n");1018return -ENOMEM;1019}10201021dev->video_mode.isoc_ctl.transfer_buffer =1022kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);1023if (!dev->video_mode.isoc_ctl.transfer_buffer) {1024cx231xx_errdev("cannot allocate memory for usbtransfer\n");1025kfree(dev->video_mode.isoc_ctl.urb);1026return -ENOMEM;1027}10281029dev->video_mode.isoc_ctl.max_pkt_size = max_pkt_size;1030dev->video_mode.isoc_ctl.buf = NULL;10311032sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size;10331034if (dev->mode_tv == 1)1035dev->video_mode.end_point_addr = 0x81;1036else1037dev->video_mode.end_point_addr = 0x84;103810391040/* allocate urbs and transfer buffers */1041for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {1042urb = usb_alloc_urb(max_packets, GFP_KERNEL);1043if (!urb) {1044cx231xx_err("cannot alloc isoc_ctl.urb %i\n", i);1045cx231xx_uninit_isoc(dev);1046return -ENOMEM;1047}1048dev->video_mode.isoc_ctl.urb[i] = urb;10491050dev->video_mode.isoc_ctl.transfer_buffer[i] =1051usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,1052&urb->transfer_dma);1053if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {1054cx231xx_err("unable to allocate %i bytes for transfer"1055" buffer %i%s\n",1056sb_size, i,1057in_interrupt() ? " while in int" : "");1058cx231xx_uninit_isoc(dev);1059return -ENOMEM;1060}1061memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size);10621063pipe =1064usb_rcvisocpipe(dev->udev, dev->video_mode.end_point_addr);10651066usb_fill_int_urb(urb, dev->udev, pipe,1067dev->video_mode.isoc_ctl.transfer_buffer[i],1068sb_size, cx231xx_isoc_irq_callback, dma_q, 1);10691070urb->number_of_packets = max_packets;1071urb->transfer_flags = URB_ISO_ASAP;10721073k = 0;1074for (j = 0; j < max_packets; j++) {1075urb->iso_frame_desc[j].offset = k;1076urb->iso_frame_desc[j].length =1077dev->video_mode.isoc_ctl.max_pkt_size;1078k += dev->video_mode.isoc_ctl.max_pkt_size;1079}1080}10811082init_waitqueue_head(&dma_q->wq);10831084/* submit urbs and enables IRQ */1085for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {1086rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i],1087GFP_ATOMIC);1088if (rc) {1089cx231xx_err("submit of urb %i failed (error=%i)\n", i,1090rc);1091cx231xx_uninit_isoc(dev);1092return rc;1093}1094}10951096if (dev->mode_tv == 0)1097cx231xx_capture_start(dev, 1, Raw_Video);1098else1099cx231xx_capture_start(dev, 1, TS1_serial_mode);11001101return 0;1102}1103EXPORT_SYMBOL_GPL(cx231xx_init_isoc);11041105/*1106* Allocate URBs and start IRQ1107*/1108int cx231xx_init_bulk(struct cx231xx *dev, int max_packets,1109int num_bufs, int max_pkt_size,1110int (*bulk_copy) (struct cx231xx *dev, struct urb *urb))1111{1112struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;1113int i;1114int sb_size, pipe;1115struct urb *urb;1116int rc;11171118dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;11191120cx231xx_coredbg("Setting Video mux to %d\n", dev->video_input);11211122video_mux(dev, dev->video_input);11231124/* De-allocates all pending stuff */1125cx231xx_uninit_bulk(dev);11261127dev->video_mode.bulk_ctl.bulk_copy = bulk_copy;1128dev->video_mode.bulk_ctl.num_bufs = num_bufs;1129dma_q->pos = 0;1130dma_q->is_partial_line = 0;1131dma_q->last_sav = 0;1132dma_q->current_field = -1;1133dma_q->field1_done = 0;1134dma_q->lines_per_field = dev->height / 2;1135dma_q->bytes_left_in_line = dev->width << 1;1136dma_q->lines_completed = 0;1137dma_q->mpeg_buffer_done = 0;1138dma_q->left_data_count = 0;1139dma_q->mpeg_buffer_completed = 0;1140dma_q->ps_head[0] = 0x00;1141dma_q->ps_head[1] = 0x00;1142dma_q->ps_head[2] = 0x01;1143dma_q->ps_head[3] = 0xBA;1144for (i = 0; i < 8; i++)1145dma_q->partial_buf[i] = 0;11461147dev->video_mode.bulk_ctl.urb =1148kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);1149if (!dev->video_mode.bulk_ctl.urb) {1150cx231xx_errdev("cannot alloc memory for usb buffers\n");1151return -ENOMEM;1152}11531154dev->video_mode.bulk_ctl.transfer_buffer =1155kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);1156if (!dev->video_mode.bulk_ctl.transfer_buffer) {1157cx231xx_errdev("cannot allocate memory for usbtransfer\n");1158kfree(dev->video_mode.bulk_ctl.urb);1159return -ENOMEM;1160}11611162dev->video_mode.bulk_ctl.max_pkt_size = max_pkt_size;1163dev->video_mode.bulk_ctl.buf = NULL;11641165sb_size = max_packets * dev->video_mode.bulk_ctl.max_pkt_size;11661167if (dev->mode_tv == 1)1168dev->video_mode.end_point_addr = 0x81;1169else1170dev->video_mode.end_point_addr = 0x84;117111721173/* allocate urbs and transfer buffers */1174for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {1175urb = usb_alloc_urb(0, GFP_KERNEL);1176if (!urb) {1177cx231xx_err("cannot alloc bulk_ctl.urb %i\n", i);1178cx231xx_uninit_bulk(dev);1179return -ENOMEM;1180}1181dev->video_mode.bulk_ctl.urb[i] = urb;1182urb->transfer_flags = 0;11831184dev->video_mode.bulk_ctl.transfer_buffer[i] =1185usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,1186&urb->transfer_dma);1187if (!dev->video_mode.bulk_ctl.transfer_buffer[i]) {1188cx231xx_err("unable to allocate %i bytes for transfer"1189" buffer %i%s\n",1190sb_size, i,1191in_interrupt() ? " while in int" : "");1192cx231xx_uninit_bulk(dev);1193return -ENOMEM;1194}1195memset(dev->video_mode.bulk_ctl.transfer_buffer[i], 0, sb_size);11961197pipe = usb_rcvbulkpipe(dev->udev,1198dev->video_mode.end_point_addr);1199usb_fill_bulk_urb(urb, dev->udev, pipe,1200dev->video_mode.bulk_ctl.transfer_buffer[i],1201sb_size, cx231xx_bulk_irq_callback, dma_q);1202}12031204init_waitqueue_head(&dma_q->wq);12051206/* submit urbs and enables IRQ */1207for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {1208rc = usb_submit_urb(dev->video_mode.bulk_ctl.urb[i],1209GFP_ATOMIC);1210if (rc) {1211cx231xx_err("submit of urb %i failed (error=%i)\n", i,1212rc);1213cx231xx_uninit_bulk(dev);1214return rc;1215}1216}12171218if (dev->mode_tv == 0)1219cx231xx_capture_start(dev, 1, Raw_Video);1220else1221cx231xx_capture_start(dev, 1, TS1_serial_mode);12221223return 0;1224}1225EXPORT_SYMBOL_GPL(cx231xx_init_bulk);1226void cx231xx_stop_TS1(struct cx231xx *dev)1227{1228int status = 0;1229u8 val[4] = { 0, 0, 0, 0 };12301231val[0] = 0x00;1232val[1] = 0x03;1233val[2] = 0x00;1234val[3] = 0x00;1235status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,1236TS_MODE_REG, val, 4);12371238val[0] = 0x00;1239val[1] = 0x70;1240val[2] = 0x04;1241val[3] = 0x00;1242status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,1243TS1_CFG_REG, val, 4);1244}1245/* EXPORT_SYMBOL_GPL(cx231xx_stop_TS1); */1246void cx231xx_start_TS1(struct cx231xx *dev)1247{1248int status = 0;1249u8 val[4] = { 0, 0, 0, 0 };12501251val[0] = 0x03;1252val[1] = 0x03;1253val[2] = 0x00;1254val[3] = 0x00;1255status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,1256TS_MODE_REG, val, 4);12571258val[0] = 0x04;1259val[1] = 0xA3;1260val[2] = 0x3B;1261val[3] = 0x00;1262status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,1263TS1_CFG_REG, val, 4);1264}1265/* EXPORT_SYMBOL_GPL(cx231xx_start_TS1); */1266/*****************************************************************1267* Device Init/UnInit functions *1268******************************************************************/1269int cx231xx_dev_init(struct cx231xx *dev)1270{1271int errCode = 0;12721273/* Initialize I2C bus */12741275/* External Master 1 Bus */1276dev->i2c_bus[0].nr = 0;1277dev->i2c_bus[0].dev = dev;1278dev->i2c_bus[0].i2c_period = I2C_SPEED_100K; /* 100 KHz */1279dev->i2c_bus[0].i2c_nostop = 0;1280dev->i2c_bus[0].i2c_reserve = 0;12811282/* External Master 2 Bus */1283dev->i2c_bus[1].nr = 1;1284dev->i2c_bus[1].dev = dev;1285dev->i2c_bus[1].i2c_period = I2C_SPEED_100K; /* 100 KHz */1286dev->i2c_bus[1].i2c_nostop = 0;1287dev->i2c_bus[1].i2c_reserve = 0;12881289/* Internal Master 3 Bus */1290dev->i2c_bus[2].nr = 2;1291dev->i2c_bus[2].dev = dev;1292dev->i2c_bus[2].i2c_period = I2C_SPEED_100K; /* 100kHz */1293dev->i2c_bus[2].i2c_nostop = 0;1294dev->i2c_bus[2].i2c_reserve = 0;12951296/* register I2C buses */1297cx231xx_i2c_register(&dev->i2c_bus[0]);1298cx231xx_i2c_register(&dev->i2c_bus[1]);1299cx231xx_i2c_register(&dev->i2c_bus[2]);13001301/* init hardware */1302/* Note : with out calling set power mode function,1303afe can not be set up correctly */1304if (dev->board.external_av) {1305errCode = cx231xx_set_power_mode(dev,1306POLARIS_AVMODE_ENXTERNAL_AV);1307if (errCode < 0) {1308cx231xx_errdev1309("%s: Failed to set Power - errCode [%d]!\n",1310__func__, errCode);1311return errCode;1312}1313} else {1314errCode = cx231xx_set_power_mode(dev,1315POLARIS_AVMODE_ANALOGT_TV);1316if (errCode < 0) {1317cx231xx_errdev1318("%s: Failed to set Power - errCode [%d]!\n",1319__func__, errCode);1320return errCode;1321}1322}13231324/* reset the Tuner, if it is a Xceive tuner */1325if ((dev->board.tuner_type == TUNER_XC5000) ||1326(dev->board.tuner_type == TUNER_XC2028))1327cx231xx_gpio_set(dev, dev->board.tuner_gpio);13281329/* initialize Colibri block */1330errCode = cx231xx_afe_init_super_block(dev, 0x23c);1331if (errCode < 0) {1332cx231xx_errdev1333("%s: cx231xx_afe init super block - errCode [%d]!\n",1334__func__, errCode);1335return errCode;1336}1337errCode = cx231xx_afe_init_channels(dev);1338if (errCode < 0) {1339cx231xx_errdev1340("%s: cx231xx_afe init channels - errCode [%d]!\n",1341__func__, errCode);1342return errCode;1343}13441345/* Set DIF in By pass mode */1346errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND);1347if (errCode < 0) {1348cx231xx_errdev1349("%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",1350__func__, errCode);1351return errCode;1352}13531354/* I2S block related functions */1355errCode = cx231xx_i2s_blk_initialize(dev);1356if (errCode < 0) {1357cx231xx_errdev1358("%s: cx231xx_i2s block initialize - errCode [%d]!\n",1359__func__, errCode);1360return errCode;1361}13621363/* init control pins */1364errCode = cx231xx_init_ctrl_pin_status(dev);1365if (errCode < 0) {1366cx231xx_errdev("%s: cx231xx_init ctrl pins - errCode [%d]!\n",1367__func__, errCode);1368return errCode;1369}13701371/* set AGC mode to Analog */1372switch (dev->model) {1373case CX231XX_BOARD_CNXT_CARRAERA:1374case CX231XX_BOARD_CNXT_RDE_250:1375case CX231XX_BOARD_CNXT_SHELBY:1376case CX231XX_BOARD_CNXT_RDU_250:1377errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);1378break;1379case CX231XX_BOARD_CNXT_RDE_253S:1380case CX231XX_BOARD_CNXT_RDU_253S:1381case CX231XX_BOARD_HAUPPAUGE_EXETER:1382case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:1383errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);1384break;1385default:1386break;1387}1388if (errCode < 0) {1389cx231xx_errdev1390("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",1391__func__, errCode);1392return errCode;1393}13941395/* set all alternate settings to zero initially */1396cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);1397cx231xx_set_alt_setting(dev, INDEX_VANC, 0);1398cx231xx_set_alt_setting(dev, INDEX_HANC, 0);1399if (dev->board.has_dvb)1400cx231xx_set_alt_setting(dev, INDEX_TS1, 0);14011402/* set the I2C master port to 3 on channel 1 */1403errCode = cx231xx_enable_i2c_port_3(dev, true);14041405return errCode;1406}1407EXPORT_SYMBOL_GPL(cx231xx_dev_init);14081409void cx231xx_dev_uninit(struct cx231xx *dev)1410{1411/* Un Initialize I2C bus */1412cx231xx_i2c_unregister(&dev->i2c_bus[2]);1413cx231xx_i2c_unregister(&dev->i2c_bus[1]);1414cx231xx_i2c_unregister(&dev->i2c_bus[0]);1415}1416EXPORT_SYMBOL_GPL(cx231xx_dev_uninit);14171418/*****************************************************************1419* G P I O related functions *1420******************************************************************/1421int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,1422u8 len, u8 request, u8 direction)1423{1424int status = 0;1425struct VENDOR_REQUEST_IN ven_req;14261427/* Set wValue */1428ven_req.wValue = (u16) (gpio_bit >> 16 & 0xffff);14291430/* set request */1431if (!request) {1432if (direction)1433ven_req.bRequest = VRT_GET_GPIO; /* 0x8 gpio */1434else1435ven_req.bRequest = VRT_SET_GPIO; /* 0x9 gpio */1436} else {1437if (direction)1438ven_req.bRequest = VRT_GET_GPIE; /* 0xa gpie */1439else1440ven_req.bRequest = VRT_SET_GPIE; /* 0xb gpie */1441}14421443/* set index value */1444ven_req.wIndex = (u16) (gpio_bit & 0xffff);14451446/* set wLength value */1447ven_req.wLength = len;14481449/* set bData value */1450ven_req.bData = 0;14511452/* set the buffer for read / write */1453ven_req.pBuff = gpio_val;14541455/* set the direction */1456if (direction) {1457ven_req.direction = USB_DIR_IN;1458memset(ven_req.pBuff, 0x00, ven_req.wLength);1459} else1460ven_req.direction = USB_DIR_OUT;146114621463/* call common vendor command request */1464status = cx231xx_send_vendor_cmd(dev, &ven_req);1465if (status < 0) {1466cx231xx_info1467("UsbInterface::sendCommand, failed with status -%d\n",1468status);1469}14701471return status;1472}1473EXPORT_SYMBOL_GPL(cx231xx_send_gpio_cmd);14741475/*****************************************************************1476* C O N T R O L - Register R E A D / W R I T E functions *1477*****************************************************************/1478int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode)1479{1480u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };1481u32 tmp = 0;1482int status = 0;14831484status =1485cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, address, value, 4);1486if (status < 0)1487return status;14881489tmp = *((u32 *) value);1490tmp |= mode;14911492value[0] = (u8) tmp;1493value[1] = (u8) (tmp >> 8);1494value[2] = (u8) (tmp >> 16);1495value[3] = (u8) (tmp >> 24);14961497status =1498cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, address, value, 4);14991500return status;1501}15021503/*****************************************************************1504* I 2 C Internal C O N T R O L functions *1505*****************************************************************/1506int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,1507u8 saddr_len, u32 *data, u8 data_len, int master)1508{1509int status = 0;1510struct cx231xx_i2c_xfer_data req_data;1511u8 value[64] = "0";15121513if (saddr_len == 0)1514saddr = 0;1515else if (saddr_len == 1)1516saddr &= 0xff;15171518/* prepare xfer_data struct */1519req_data.dev_addr = dev_addr >> 1;1520req_data.direction = I2C_M_RD;1521req_data.saddr_len = saddr_len;1522req_data.saddr_dat = saddr;1523req_data.buf_size = data_len;1524req_data.p_buffer = (u8 *) value;15251526/* usb send command */1527if (master == 0)1528status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],1529&req_data);1530else if (master == 1)1531status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],1532&req_data);1533else if (master == 2)1534status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],1535&req_data);15361537if (status >= 0) {1538/* Copy the data read back to main buffer */1539if (data_len == 1)1540*data = value[0];1541else if (data_len == 4)1542*data =1543value[0] | value[1] << 8 | value[2] << 16 | value[3]1544<< 24;1545else if (data_len > 4)1546*data = value[saddr];1547}15481549return status;1550}15511552int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,1553u8 saddr_len, u32 data, u8 data_len, int master)1554{1555int status = 0;1556u8 value[4] = { 0, 0, 0, 0 };1557struct cx231xx_i2c_xfer_data req_data;15581559value[0] = (u8) data;1560value[1] = (u8) (data >> 8);1561value[2] = (u8) (data >> 16);1562value[3] = (u8) (data >> 24);15631564if (saddr_len == 0)1565saddr = 0;1566else if (saddr_len == 1)1567saddr &= 0xff;15681569/* prepare xfer_data struct */1570req_data.dev_addr = dev_addr >> 1;1571req_data.direction = 0;1572req_data.saddr_len = saddr_len;1573req_data.saddr_dat = saddr;1574req_data.buf_size = data_len;1575req_data.p_buffer = value;15761577/* usb send command */1578if (master == 0)1579status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],1580&req_data);1581else if (master == 1)1582status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],1583&req_data);1584else if (master == 2)1585status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],1586&req_data);15871588return status;1589}15901591int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,1592u8 saddr_len, u32 *data, u8 data_len)1593{1594int status = 0;1595struct cx231xx_i2c_xfer_data req_data;1596u8 value[4] = { 0, 0, 0, 0 };15971598if (saddr_len == 0)1599saddr = 0;1600else if (saddr_len == 1)1601saddr &= 0xff;16021603/* prepare xfer_data struct */1604req_data.dev_addr = dev_addr >> 1;1605req_data.direction = I2C_M_RD;1606req_data.saddr_len = saddr_len;1607req_data.saddr_dat = saddr;1608req_data.buf_size = data_len;1609req_data.p_buffer = (u8 *) value;16101611/* usb send command */1612status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);16131614if (status >= 0) {1615/* Copy the data read back to main buffer */1616if (data_len == 1)1617*data = value[0];1618else1619*data =1620value[0] | value[1] << 8 | value[2] << 16 | value[3]1621<< 24;1622}16231624return status;1625}16261627int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,1628u8 saddr_len, u32 data, u8 data_len)1629{1630int status = 0;1631u8 value[4] = { 0, 0, 0, 0 };1632struct cx231xx_i2c_xfer_data req_data;16331634value[0] = (u8) data;1635value[1] = (u8) (data >> 8);1636value[2] = (u8) (data >> 16);1637value[3] = (u8) (data >> 24);16381639if (saddr_len == 0)1640saddr = 0;1641else if (saddr_len == 1)1642saddr &= 0xff;16431644/* prepare xfer_data struct */1645req_data.dev_addr = dev_addr >> 1;1646req_data.direction = 0;1647req_data.saddr_len = saddr_len;1648req_data.saddr_dat = saddr;1649req_data.buf_size = data_len;1650req_data.p_buffer = value;16511652/* usb send command */1653status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0], &req_data);16541655return status;1656}16571658int cx231xx_reg_mask_write(struct cx231xx *dev, u8 dev_addr, u8 size,1659u16 register_address, u8 bit_start, u8 bit_end,1660u32 value)1661{1662int status = 0;1663u32 tmp;1664u32 mask = 0;1665int i;16661667if (bit_start > (size - 1) || bit_end > (size - 1))1668return -1;16691670if (size == 8) {1671status =1672cx231xx_read_i2c_data(dev, dev_addr, register_address, 2,1673&tmp, 1);1674} else {1675status =1676cx231xx_read_i2c_data(dev, dev_addr, register_address, 2,1677&tmp, 4);1678}16791680if (status < 0)1681return status;16821683mask = 1 << bit_end;1684for (i = bit_end; i > bit_start && i > 0; i--)1685mask = mask + (1 << (i - 1));16861687value <<= bit_start;16881689if (size == 8) {1690tmp &= ~mask;1691tmp |= value;1692tmp &= 0xff;1693status =1694cx231xx_write_i2c_data(dev, dev_addr, register_address, 2,1695tmp, 1);1696} else {1697tmp &= ~mask;1698tmp |= value;1699status =1700cx231xx_write_i2c_data(dev, dev_addr, register_address, 2,1701tmp, 4);1702}17031704return status;1705}17061707int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,1708u16 saddr, u32 mask, u32 value)1709{1710u32 temp;1711int status = 0;17121713status = cx231xx_read_i2c_data(dev, dev_addr, saddr, 2, &temp, 4);17141715if (status < 0)1716return status;17171718temp &= ~mask;1719temp |= value;17201721status = cx231xx_write_i2c_data(dev, dev_addr, saddr, 2, temp, 4);17221723return status;1724}17251726u32 cx231xx_set_field(u32 field_mask, u32 data)1727{1728u32 temp;17291730for (temp = field_mask; (temp & 1) == 0; temp >>= 1)1731data <<= 1;17321733return data;1734}173517361737