staticint alt = CX231XX_PINOUT;
module_param(alt, int, 0644);
MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
#define cx231xx_isocdbg(fmt, arg...) do {\ if (core_debug) \
printk(KERN_INFO "%s %s :"fmt, \
dev->name, __func__ , ##arg); } while (0)
/***************************************************************** * Device control list functions *
******************************************************************/
/* * cx231xx_realease_resources() * unregisters the v4l2,i2c and usb devices * called when the device gets disconnected or at module unload
*/ void cx231xx_remove_from_devlist(struct cx231xx *dev)
{ if (dev == NULL) return; if (dev->udev == NULL) return;
/**************************************************************** * U S B related functions *
*****************************************************************/ int cx231xx_send_usb_command(struct cx231xx_i2c *i2c_bus, struct cx231xx_i2c_xfer_data *req_data)
{ int status = 0; struct cx231xx *dev = i2c_bus->dev; struct VENDOR_REQUEST_IN ven_req;
/* set channel number */ if (req_data->direction & I2C_M_RD) { /* channel number, for read,spec required channel_num +4 */
ven_req.bRequest = i2c_bus->nr + 4;
} else
ven_req.bRequest = i2c_bus->nr; /* channel number, */
/* set index value */ switch (saddr_len) { case 0:
ven_req.wIndex = 0; /* need check */ break; case 1:
ven_req.wIndex = (req_data->saddr_dat & 0xff); break; case 2:
ven_req.wIndex = req_data->saddr_dat; break;
}
/* set wLength value */
ven_req.wLength = req_data->buf_size;
/* set bData value */
ven_req.bData = 0;
/* set the direction */ if (req_data->direction) {
ven_req.direction = USB_DIR_IN;
memset(req_data->p_buffer, 0x00, ven_req.wLength);
} else
ven_req.direction = USB_DIR_OUT;
/* set the buffer for read / write */
ven_req.pBuff = req_data->p_buffer;
/* call common vendor command request */
status = cx231xx_send_vendor_cmd(dev, &ven_req); if (status < 0 && !dev->i2c_scan_running) {
dev_err(dev->dev, "%s: failed with status -%d\n",
__func__, status);
}
/* * Sends/Receives URB control messages, assuring to use a kalloced buffer * for all operations (dev->urb_buf), to avoid using stacked buffers, as * they aren't safe for usage with USB, due to DMA restrictions. * Also implements the debug code for control URB's.
*/ staticint __usb_control_msg(struct cx231xx *dev, unsignedint pipe,
__u8 request, __u8 requesttype, __u16 value, __u16 index, void *data, __u16 size, int timeout)
{ int rc, i;
if (reg_debug) {
printk(KERN_DEBUG "%s: (pipe 0x%08x): %s: %02x %02x %02x %02x %02x %02x %02x %02x ",
dev->name,
pipe,
(requesttype & USB_DIR_IN) ? "IN" : "OUT",
requesttype,
request,
value & 0xff, value >> 8,
index & 0xff, index >> 8,
size & 0xff, size >> 8); if (!(requesttype & USB_DIR_IN)) {
printk(KERN_CONT ">>>"); for (i = 0; i < size; i++)
printk(KERN_CONT " %02x",
((unsignedchar *)data)[i]);
}
}
/* Do the real call to usb_control_msg */
mutex_lock(&dev->ctrl_urb_lock); if (!(requesttype & USB_DIR_IN) && size)
memcpy(dev->urb_buf, data, size);
rc = usb_control_msg(dev->udev, pipe, request, requesttype, value,
index, dev->urb_buf, size, timeout); if ((requesttype & USB_DIR_IN) && size)
memcpy(data, dev->urb_buf, size);
mutex_unlock(&dev->ctrl_urb_lock);
if (reg_debug) { if (unlikely(rc < 0)) {
printk(KERN_CONT "FAILED!\n"); return rc;
}
if ((requesttype & USB_DIR_IN)) {
printk(KERN_CONT "<<<"); for (i = 0; i < size; i++)
printk(KERN_CONT " %02x",
((unsignedchar *)data)[i]);
}
printk(KERN_CONT "\n");
}
return rc;
}
/* * cx231xx_read_ctrl_reg() * reads data from the usb device specifying bRequest and wValue
*/ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, int len)
{
u8 val = 0; int ret; int pipe = usb_rcvctrlpipe(dev->udev, 0);
if (dev->state & DEV_DISCONNECTED) return -ENODEV;
if (len > URB_MAX_CTRL_SIZE) return -EINVAL;
switch (len) { case 1:
val = ENABLE_ONE_BYTE; break; case 2:
val = ENABLE_TWE_BYTE; break; case 3:
val = ENABLE_THREE_BYTE; break; case 4:
val = ENABLE_FOUR_BYTE; break; default:
val = 0xFF; /* invalid option */
}
/* * If the cx23102 read more than 4 bytes with i2c bus, * need chop to 4 byte per request
*/ if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) ||
(ven_req->bRequest == 0x5) ||
(ven_req->bRequest == 0x6) ||
/* Internal Master 3 Bus can send * and receive only 4 bytes per time
*/
(ven_req->bRequest == 0x2))) {
unsend_size = 0;
pdata = ven_req->pBuff;
/* * cx231xx_write_ctrl_reg() * sends data to the usb device, specifying bRequest
*/ int cx231xx_write_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, char *buf, int len)
{
u8 val = 0; int ret; int pipe = usb_sndctrlpipe(dev->udev, 0);
if (dev->state & DEV_DISCONNECTED) return -ENODEV;
if ((len < 1) || (len > URB_MAX_CTRL_SIZE)) return -EINVAL;
switch (len) { case 1:
val = ENABLE_ONE_BYTE; break; case 2:
val = ENABLE_TWE_BYTE; break; case 3:
val = ENABLE_THREE_BYTE; break; case 4:
val = ENABLE_FOUR_BYTE; break; default:
val = 0xFF; /* invalid option */
}
/* When image size is bigger than a certain value, the frame size should be increased, otherwise, only green screen will be received.
*/ if (dev->width * 2 * dev->height > 720 * 240 * 2)
min_pkt_size *= 2;
int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
{ int errCode = 0;
if (dev->mode == set_mode) return 0;
if (set_mode == CX231XX_SUSPEND) { /* Set the chip in power saving mode */
dev->mode = set_mode;
}
/* Resource is locked */ if (dev->mode != CX231XX_SUSPEND) return -EINVAL;
dev->mode = set_mode;
if (dev->mode == CX231XX_DIGITAL_MODE)/* Set Digital power mode */ { /* set AGC mode to Digital */ switch (dev->model) { case CX231XX_BOARD_CNXT_CARRAERA: case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_SHELBY: case CX231XX_BOARD_CNXT_RDU_250:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); break; case CX231XX_BOARD_HAUPPAUGE_EXETER: case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx:
errCode = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_DIGITAL); break; default: break;
}
} else/* Set Analog Power mode */ { /* set AGC mode to Analog */ switch (dev->model) { case CX231XX_BOARD_CNXT_CARRAERA: case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_SHELBY: case CX231XX_BOARD_CNXT_RDU_250:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); break; case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_HAUPPAUGE_EXETER: case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; default: break;
}
}
if (errCode < 0) {
dev_err(dev->dev, "Failed to set devmode to %s: error: %i",
dev->mode == CX231XX_DIGITAL_MODE ? "digital" : "analog",
errCode); return errCode;
}
return 0;
}
EXPORT_SYMBOL_GPL(cx231xx_set_mode);
int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size)
{ int errCode = 0; int actlen = -1; int ret = -ENOMEM;
u32 *buffer;
cx231xx_isocdbg("cx231xx: called cx231xx_uninit_isoc\n");
dev->video_mode.isoc_ctl.nfields = -1; for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
urb = dev->video_mode.isoc_ctl.urb[i]; if (urb) { if (!irqs_disabled())
usb_kill_urb(urb); else
usb_unlink_urb(urb);
/* * Stop and Deallocate URBs
*/ void cx231xx_uninit_bulk(struct cx231xx *dev)
{ struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; struct urb *urb; int i; bool broken_pipe = false;
cx231xx_isocdbg("cx231xx: called cx231xx_uninit_bulk\n");
dev->video_mode.bulk_ctl.nfields = -1; for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
urb = dev->video_mode.bulk_ctl.urb[i]; if (urb) { if (!irqs_disabled())
usb_kill_urb(urb); else
usb_unlink_urb(urb);
/* * Allocate URBs and start IRQ
*/ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, int num_bufs, int max_pkt_size, int (*isoc_copy) (struct cx231xx *dev, struct urb *urb))
{ struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; int i; int sb_size, pipe; struct urb *urb; int j, k; int rc;
/* De-allocates all pending stuff */
cx231xx_uninit_isoc(dev);
dma_q->p_left_data = kzalloc(EP5_BUF_SIZE, GFP_KERNEL); if (dma_q->p_left_data == NULL) return -ENOMEM;
/* allocate urbs and transfer buffers */ for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
urb = usb_alloc_urb(max_packets, GFP_KERNEL); if (!urb) {
cx231xx_uninit_isoc(dev); return -ENOMEM;
}
dev->video_mode.isoc_ctl.urb[i] = urb;
dev->video_mode.isoc_ctl.transfer_buffer[i] =
usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma); if (!dev->video_mode.isoc_ctl.transfer_buffer[i]) {
dev_err(dev->dev, "unable to allocate %i bytes for transfer buffer %i\n",
sb_size, i);
cx231xx_uninit_isoc(dev); return -ENOMEM;
}
memset(dev->video_mode.isoc_ctl.transfer_buffer[i], 0, sb_size);
k = 0; for (j = 0; j < max_packets; j++) {
urb->iso_frame_desc[j].offset = k;
urb->iso_frame_desc[j].length =
dev->video_mode.isoc_ctl.max_pkt_size;
k += dev->video_mode.isoc_ctl.max_pkt_size;
}
}
init_waitqueue_head(&dma_q->wq);
/* submit urbs and enables IRQ */ for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
rc = usb_submit_urb(dev->video_mode.isoc_ctl.urb[i],
GFP_ATOMIC); if (rc) {
dev_err(dev->dev, "submit of urb %i failed (error=%i)\n", i,
rc);
cx231xx_uninit_isoc(dev); return rc;
}
}
/* * Allocate URBs and start IRQ
*/ int cx231xx_init_bulk(struct cx231xx *dev, int max_packets, int num_bufs, int max_pkt_size, int (*bulk_copy) (struct cx231xx *dev, struct urb *urb))
{ struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq; int i; int sb_size, pipe; struct urb *urb; int rc;
/* allocate urbs and transfer buffers */ for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) {
cx231xx_uninit_bulk(dev); return -ENOMEM;
}
dev->video_mode.bulk_ctl.urb[i] = urb;
urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
dev->video_mode.bulk_ctl.transfer_buffer[i] =
usb_alloc_coherent(dev->udev, sb_size, GFP_KERNEL,
&urb->transfer_dma); if (!dev->video_mode.bulk_ctl.transfer_buffer[i]) {
dev_err(dev->dev, "unable to allocate %i bytes for transfer buffer %i\n",
sb_size, i);
cx231xx_uninit_bulk(dev); return -ENOMEM;
}
memset(dev->video_mode.bulk_ctl.transfer_buffer[i], 0, sb_size);
/* clear halt */
rc = usb_clear_halt(dev->udev, dev->video_mode.bulk_ctl.urb[0]->pipe); if (rc < 0) {
dev_err(dev->dev, "failed to clear USB bulk endpoint stall/halt condition (error=%i)\n",
rc);
cx231xx_uninit_bulk(dev); return rc;
}
init_waitqueue_head(&dma_q->wq);
/* submit urbs and enables IRQ */ for (i = 0; i < dev->video_mode.bulk_ctl.num_bufs; i++) {
rc = usb_submit_urb(dev->video_mode.bulk_ctl.urb[i],
GFP_ATOMIC); if (rc) {
dev_err(dev->dev, "submit of urb %i failed (error=%i)\n", i, rc);
cx231xx_uninit_bulk(dev); return rc;
}
}
errCode = cx231xx_i2c_mux_create(dev); if (errCode < 0) {
dev_err(dev->dev, "%s: Failed to create I2C mux\n", __func__); return errCode;
}
errCode = cx231xx_i2c_mux_register(dev, 0); if (errCode < 0) return errCode;
errCode = cx231xx_i2c_mux_register(dev, 1); if (errCode < 0) return errCode;
/* scan the real bus segments in the order of physical port numbers */
cx231xx_do_i2c_scan(dev, I2C_0);
cx231xx_do_i2c_scan(dev, I2C_1_MUX_1);
cx231xx_do_i2c_scan(dev, I2C_2);
cx231xx_do_i2c_scan(dev, I2C_1_MUX_3);
/* init hardware */ /* Note : with out calling set power mode function,
afe can not be set up correctly */ if (dev->board.external_av) {
errCode = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ENXTERNAL_AV); if (errCode < 0) {
dev_err(dev->dev, "%s: Failed to set Power - errCode [%d]!\n",
__func__, errCode); return errCode;
}
} else {
errCode = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ANALOGT_TV); if (errCode < 0) {
dev_err(dev->dev, "%s: Failed to set Power - errCode [%d]!\n",
__func__, errCode); return errCode;
}
}
/* reset the Tuner, if it is a Xceive tuner */ if ((dev->board.tuner_type == TUNER_XC5000) ||
(dev->board.tuner_type == TUNER_XC2028))
cx231xx_gpio_set(dev, dev->board.tuner_gpio);
/* Set DIF in By pass mode */
errCode = cx231xx_dif_set_standard(dev, DIF_USE_BASEBAND); if (errCode < 0) {
dev_err(dev->dev, "%s: cx231xx_dif set to By pass mode - errCode [%d]!\n",
__func__, errCode); return errCode;
}
/* set AGC mode to Analog */ switch (dev->model) { case CX231XX_BOARD_CNXT_CARRAERA: case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_SHELBY: case CX231XX_BOARD_CNXT_RDU_250:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1); break; case CX231XX_BOARD_CNXT_RDE_253S: case CX231XX_BOARD_CNXT_RDU_253S: case CX231XX_BOARD_HAUPPAUGE_EXETER: case CX231XX_BOARD_HAUPPAUGE_930C_HD_1113xx: case CX231XX_BOARD_PV_PLAYTV_USB_HYBRID: case CX231XX_BOARD_HAUPPAUGE_USB2_FM_PAL: case CX231XX_BOARD_HAUPPAUGE_USB2_FM_NTSC:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0); break; default: break;
} if (errCode < 0) {
dev_err(dev->dev, "%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
__func__, errCode); return errCode;
}
/* set all alternate settings to zero initially */
cx231xx_set_alt_setting(dev, INDEX_VIDEO, 0);
cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
cx231xx_set_alt_setting(dev, INDEX_HANC, 0); if (dev->board.has_dvb)
cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
void cx231xx_dev_uninit(struct cx231xx *dev)
{ /* Un Initialize I2C bus */
cx231xx_i2c_mux_unregister(dev);
cx231xx_i2c_unregister(&dev->i2c_bus[2]);
cx231xx_i2c_unregister(&dev->i2c_bus[1]);
cx231xx_i2c_unregister(&dev->i2c_bus[0]);
}
EXPORT_SYMBOL_GPL(cx231xx_dev_uninit);
/***************************************************************** * G P I O related functions *
******************************************************************/ int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
u8 len, u8 request, u8 direction)
{ int status = 0; struct VENDOR_REQUEST_IN ven_req;
/* set index value */
ven_req.wIndex = (u16) (gpio_bit & 0xffff);
/* set wLength value */
ven_req.wLength = len;
/* set bData value */
ven_req.bData = 0;
/* set the buffer for read / write */
ven_req.pBuff = gpio_val;
/* set the direction */ if (direction) {
ven_req.direction = USB_DIR_IN;
memset(ven_req.pBuff, 0x00, ven_req.wLength);
} else
ven_req.direction = USB_DIR_OUT;
/* call common vendor command request */
status = cx231xx_send_vendor_cmd(dev, &ven_req); if (status < 0) {
dev_err(dev->dev, "%s: failed with status -%d\n",
__func__, status);
}
/***************************************************************** * C O N T R O L - Register R E A D / W R I T E functions *
*****************************************************************/ int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode)
{
u8 value[4] = { 0x0, 0x0, 0x0, 0x0 };
u32 tmp = 0; int status = 0;
status =
cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, address, value, 4); if (status < 0) return status;
status =
cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER, address, value, 4);
return status;
}
/***************************************************************** * I 2 C Internal C O N T R O L functions *
*****************************************************************/ int cx231xx_read_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
u8 saddr_len, u32 *data, u8 data_len, int master)
{ int status = 0; struct cx231xx_i2c_xfer_data req_data;
u8 value[64] = "0";
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.