Commit 64fbf444 authored by Palash Bandyopadhyay's avatar Palash Bandyopadhyay Committed by Mauro Carvalho Chehab

[media] cx231xx: Added support for Carraera, Shelby, RDx_253S and VIDEO_GRABBER

Added support for new cx231xx boards - Carraera, Shelby, RDx_253S and
VIDEO_GRABBER.

[mchehab@redhat.com: Fix a merge conflict with BKL removal patches]
Signed-off-by: default avatarPalash Bandyopadhyay <palash.bandyopadhyay@conexant.com>
Signed-off-by: default avatarDevin Heitmueller <dheitmueller@hauppauge.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 47b75ec1
cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \ cx231xx-objs := cx231xx-video.o cx231xx-i2c.o cx231xx-cards.o cx231xx-core.o \
cx231xx-avcore.o cx231xx-pcb-cfg.o cx231xx-vbi.o cx231xx-avcore.o cx231xx-417.o cx231xx-pcb-cfg.o cx231xx-vbi.o
cx231xx-alsa-objs := cx231xx-audio.o cx231xx-alsa-objs := cx231xx-audio.o
......
/*
*
* Support for a cx23417 mpeg encoder via cx231xx host port.
*
* (c) 2004 Jelle Foks <jelle@foks.us>
* (c) 2004 Gerd Knorr <kraxel@bytesex.org>
* (c) 2008 Steven Toth <stoth@linuxtv.org>
* - CX23885/7/8 support
*
* Includes parts from the ivtv driver( http://ivtv.sourceforge.net/),
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/smp_lock.h>
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/cx2341x.h>
#include <linux/usb.h>
#include "cx231xx.h"
/*#include "cx23885-ioctl.h"*/
#define CX231xx_FIRM_IMAGE_SIZE 376836
#define CX231xx_FIRM_IMAGE_NAME "v4l-cx23885-enc.fw"
/* for polaris ITVC*/
#define ITVC_WRITE_DIR 0x03FDFC00
#define ITVC_READ_DIR 0x0001FC00
#define MCI_MEMORY_DATA_BYTE0 0x00
#define MCI_MEMORY_DATA_BYTE1 0x08
#define MCI_MEMORY_DATA_BYTE2 0x10
#define MCI_MEMORY_DATA_BYTE3 0x18
#define MCI_MEMORY_ADDRESS_BYTE2 0x20
#define MCI_MEMORY_ADDRESS_BYTE1 0x28
#define MCI_MEMORY_ADDRESS_BYTE0 0x30
#define MCI_REGISTER_DATA_BYTE0 0x40
#define MCI_REGISTER_DATA_BYTE1 0x48
#define MCI_REGISTER_DATA_BYTE2 0x50
#define MCI_REGISTER_DATA_BYTE3 0x58
#define MCI_REGISTER_ADDRESS_BYTE0 0x60
#define MCI_REGISTER_ADDRESS_BYTE1 0x68
#define MCI_REGISTER_MODE 0x70
/*Read and write modes
for polaris ITVC*/
#define MCI_MODE_REGISTER_READ 0x000
#define MCI_MODE_REGISTER_WRITE 0x100
#define MCI_MODE_MEMORY_READ 0x000
#define MCI_MODE_MEMORY_WRITE 0x4000
static unsigned int mpegbufs = 8;
module_param(mpegbufs, int, 0644);
MODULE_PARM_DESC(mpegbufs, "number of mpeg buffers, range 2-32");
static unsigned int mpeglines = 128;
module_param(mpeglines, int, 0644);
MODULE_PARM_DESC(mpeglines, "number of lines in an MPEG buffer, range 2-32");
static unsigned int mpeglinesize = 512;
module_param(mpeglinesize, int, 0644);
MODULE_PARM_DESC(mpeglinesize,
"number of bytes in each line of an MPEG buffer, range 512-1024");
static unsigned int v4l_debug = 1;
module_param(v4l_debug, int, 0644);
MODULE_PARM_DESC(v4l_debug, "enable V4L debug messages");
struct cx231xx_dmaqueue *dma_qq;
#define dprintk(level, fmt, arg...)\
do { if (v4l_debug >= level) \
printk(KERN_INFO "%s: " fmt, \
(dev) ? dev->name : "cx231xx[?]", ## arg); \
} while (0)
static struct cx231xx_tvnorm cx231xx_tvnorms[] = {
{
.name = "NTSC-M",
.id = V4L2_STD_NTSC_M,
}, {
.name = "NTSC-JP",
.id = V4L2_STD_NTSC_M_JP,
}, {
.name = "PAL-BG",
.id = V4L2_STD_PAL_BG,
}, {
.name = "PAL-DK",
.id = V4L2_STD_PAL_DK,
}, {
.name = "PAL-I",
.id = V4L2_STD_PAL_I,
}, {
.name = "PAL-M",
.id = V4L2_STD_PAL_M,
}, {
.name = "PAL-N",
.id = V4L2_STD_PAL_N,
}, {
.name = "PAL-Nc",
.id = V4L2_STD_PAL_Nc,
}, {
.name = "PAL-60",
.id = V4L2_STD_PAL_60,
}, {
.name = "SECAM-L",
.id = V4L2_STD_SECAM_L,
}, {
.name = "SECAM-DK",
.id = V4L2_STD_SECAM_DK,
}
};
/* ------------------------------------------------------------------ */
enum cx231xx_capture_type {
CX231xx_MPEG_CAPTURE,
CX231xx_RAW_CAPTURE,
CX231xx_RAW_PASSTHRU_CAPTURE
};
enum cx231xx_capture_bits {
CX231xx_RAW_BITS_NONE = 0x00,
CX231xx_RAW_BITS_YUV_CAPTURE = 0x01,
CX231xx_RAW_BITS_PCM_CAPTURE = 0x02,
CX231xx_RAW_BITS_VBI_CAPTURE = 0x04,
CX231xx_RAW_BITS_PASSTHRU_CAPTURE = 0x08,
CX231xx_RAW_BITS_TO_HOST_CAPTURE = 0x10
};
enum cx231xx_capture_end {
CX231xx_END_AT_GOP, /* stop at the end of gop, generate irq */
CX231xx_END_NOW, /* stop immediately, no irq */
};
enum cx231xx_framerate {
CX231xx_FRAMERATE_NTSC_30, /* NTSC: 30fps */
CX231xx_FRAMERATE_PAL_25 /* PAL: 25fps */
};
enum cx231xx_stream_port {
CX231xx_OUTPUT_PORT_MEMORY,
CX231xx_OUTPUT_PORT_STREAMING,
CX231xx_OUTPUT_PORT_SERIAL
};
enum cx231xx_data_xfer_status {
CX231xx_MORE_BUFFERS_FOLLOW,
CX231xx_LAST_BUFFER,
};
enum cx231xx_picture_mask {
CX231xx_PICTURE_MASK_NONE,
CX231xx_PICTURE_MASK_I_FRAMES,
CX231xx_PICTURE_MASK_I_P_FRAMES = 0x3,
CX231xx_PICTURE_MASK_ALL_FRAMES = 0x7,
};
enum cx231xx_vbi_mode_bits {
CX231xx_VBI_BITS_SLICED,
CX231xx_VBI_BITS_RAW,
};
enum cx231xx_vbi_insertion_bits {
CX231xx_VBI_BITS_INSERT_IN_XTENSION_USR_DATA,
CX231xx_VBI_BITS_INSERT_IN_PRIVATE_PACKETS = 0x1 << 1,
CX231xx_VBI_BITS_SEPARATE_STREAM = 0x2 << 1,
CX231xx_VBI_BITS_SEPARATE_STREAM_USR_DATA = 0x4 << 1,
CX231xx_VBI_BITS_SEPARATE_STREAM_PRV_DATA = 0x5 << 1,
};
enum cx231xx_dma_unit {
CX231xx_DMA_BYTES,
CX231xx_DMA_FRAMES,
};
enum cx231xx_dma_transfer_status_bits {
CX231xx_DMA_TRANSFER_BITS_DONE = 0x01,
CX231xx_DMA_TRANSFER_BITS_ERROR = 0x04,
CX231xx_DMA_TRANSFER_BITS_LL_ERROR = 0x10,
};
enum cx231xx_pause {
CX231xx_PAUSE_ENCODING,
CX231xx_RESUME_ENCODING,
};
enum cx231xx_copyright {
CX231xx_COPYRIGHT_OFF,
CX231xx_COPYRIGHT_ON,
};
enum cx231xx_notification_type {
CX231xx_NOTIFICATION_REFRESH,
};
enum cx231xx_notification_status {
CX231xx_NOTIFICATION_OFF,
CX231xx_NOTIFICATION_ON,
};
enum cx231xx_notification_mailbox {
CX231xx_NOTIFICATION_NO_MAILBOX = -1,
};
enum cx231xx_field1_lines {
CX231xx_FIELD1_SAA7114 = 0x00EF, /* 239 */
CX231xx_FIELD1_SAA7115 = 0x00F0, /* 240 */
CX231xx_FIELD1_MICRONAS = 0x0105, /* 261 */
};
enum cx231xx_field2_lines {
CX231xx_FIELD2_SAA7114 = 0x00EF, /* 239 */
CX231xx_FIELD2_SAA7115 = 0x00F0, /* 240 */
CX231xx_FIELD2_MICRONAS = 0x0106, /* 262 */
};
enum cx231xx_custom_data_type {
CX231xx_CUSTOM_EXTENSION_USR_DATA,
CX231xx_CUSTOM_PRIVATE_PACKET,
};
enum cx231xx_mute {
CX231xx_UNMUTE,
CX231xx_MUTE,
};
enum cx231xx_mute_video_mask {
CX231xx_MUTE_VIDEO_V_MASK = 0x0000FF00,
CX231xx_MUTE_VIDEO_U_MASK = 0x00FF0000,
CX231xx_MUTE_VIDEO_Y_MASK = 0xFF000000,
};
enum cx231xx_mute_video_shift {
CX231xx_MUTE_VIDEO_V_SHIFT = 8,
CX231xx_MUTE_VIDEO_U_SHIFT = 16,
CX231xx_MUTE_VIDEO_Y_SHIFT = 24,
};
/* defines below are from ivtv-driver.h */
#define IVTV_CMD_HW_BLOCKS_RST 0xFFFFFFFF
/* Firmware API commands */
#define IVTV_API_STD_TIMEOUT 500
/* Registers */
/* IVTV_REG_OFFSET */
#define IVTV_REG_ENC_SDRAM_REFRESH (0x07F8)
#define IVTV_REG_ENC_SDRAM_PRECHARGE (0x07FC)
#define IVTV_REG_SPU (0x9050)
#define IVTV_REG_HW_BLOCKS (0x9054)
#define IVTV_REG_VPU (0x9058)
#define IVTV_REG_APU (0xA064)
/**** Bit definitions for MC417_RWD and MC417_OEN registers ***
bits 31-16
+-----------+
| Reserved |
+-----------+
bit 15 bit 14 bit 13 bit 12 bit 11 bit 10 bit 9 bit 8
+-------+-------+-------+-------+-------+-------+-------+-------+
| MIWR# | MIRD# | MICS# |MIRDY# |MIADDR3|MIADDR2|MIADDR1|MIADDR0|
+-------+-------+-------+-------+-------+-------+-------+-------+
bit 7 bit 6 bit 5 bit 4 bit 3 bit 2 bit 1 bit 0
+-------+-------+-------+-------+-------+-------+-------+-------+
|MIDATA7|MIDATA6|MIDATA5|MIDATA4|MIDATA3|MIDATA2|MIDATA1|MIDATA0|
+-------+-------+-------+-------+-------+-------+-------+-------+
***/
#define MC417_MIWR 0x8000
#define MC417_MIRD 0x4000
#define MC417_MICS 0x2000
#define MC417_MIRDY 0x1000
#define MC417_MIADDR 0x0F00
#define MC417_MIDATA 0x00FF
/*** Bit definitions for MC417_CTL register ****
bits 31-6 bits 5-4 bit 3 bits 2-1 Bit 0
+--------+-------------+--------+--------------+------------+
|Reserved|MC417_SPD_CTL|Reserved|MC417_GPIO_SEL|UART_GPIO_EN|
+--------+-------------+--------+--------------+------------+
***/
#define MC417_SPD_CTL(x) (((x) << 4) & 0x00000030)
#define MC417_GPIO_SEL(x) (((x) << 1) & 0x00000006)
#define MC417_UART_GPIO_EN 0x00000001
/* Values for speed control */
#define MC417_SPD_CTL_SLOW 0x1
#define MC417_SPD_CTL_MEDIUM 0x0
#define MC417_SPD_CTL_FAST 0x3 /* b'1x, but we use b'11 */
/* Values for GPIO select */
#define MC417_GPIO_SEL_GPIO3 0x3
#define MC417_GPIO_SEL_GPIO2 0x2
#define MC417_GPIO_SEL_GPIO1 0x1
#define MC417_GPIO_SEL_GPIO0 0x0
#define CX23417_GPIO_MASK 0xFC0003FF
int setITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 value)
{
int status = 0;
u32 _gpio_direction = 0;
_gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
_gpio_direction = _gpio_direction|gpio_direction;
status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
(u8 *)&value, 4, 0, 0);
return status;
}
int getITVCReg(struct cx231xx *dev, u32 gpio_direction, u32 *pValue)
{
int status = 0;
u32 _gpio_direction = 0;
_gpio_direction = _gpio_direction & CX23417_GPIO_MASK;
_gpio_direction = _gpio_direction|gpio_direction;
status = cx231xx_send_gpio_cmd(dev, _gpio_direction,
(u8 *)pValue, 4, 0, 1);
return status;
}
int waitForMciComplete(struct cx231xx *dev)
{
u32 gpio;
u32 gpio_driection = 0;
u8 count = 0;
getITVCReg(dev, gpio_driection, &gpio);
while (!(gpio&0x020000)) {
msleep(10);
getITVCReg(dev, gpio_driection, &gpio);
if (count++ > 100) {
dprintk(3, "ERROR: Timeout - gpio=%x\n", gpio);
return -1;
}
}
return 0;
}
int mc417_register_write(struct cx231xx *dev, u16 address, u32 value)
{
u32 temp;
int status = 0;
temp = 0x82|MCI_REGISTER_DATA_BYTE0|((value&0x000000FF)<<8);
temp = temp<<10;
status = setITVCReg(dev, ITVC_WRITE_DIR, temp);
if (status < 0)
return status;
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write data byte 1;*/
temp = 0x82|MCI_REGISTER_DATA_BYTE1|(value&0x0000FF00);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write data byte 2;*/
temp = 0x82|MCI_REGISTER_DATA_BYTE2|((value&0x00FF0000)>>8);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write data byte 3;*/
temp = 0x82|MCI_REGISTER_DATA_BYTE3|((value&0xFF000000)>>16);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write address byte 0;*/
temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x000000FF)<<8);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write address byte 1;*/
temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0x0000FF00);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*Write that the mode is write.*/
temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_WRITE;
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
return waitForMciComplete(dev);
}
int mc417_register_read(struct cx231xx *dev, u16 address, u32 *value)
{
/*write address byte 0;*/
u32 temp;
u32 return_value = 0;
int ret = 0;
temp = 0x82|MCI_REGISTER_ADDRESS_BYTE0|((address&0x00FF)<<8);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write address byte 1;*/
temp = 0x82|MCI_REGISTER_ADDRESS_BYTE1|(address&0xFF00);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write that the mode is read;*/
temp = 0x82 | MCI_REGISTER_MODE | MCI_MODE_REGISTER_READ;
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*wait for the MIRDY line to be asserted ,
signalling that the read is done;*/
ret = waitForMciComplete(dev);
/*switch the DATA- GPIO to input mode;*/
/*Read data byte 0;*/
temp = (0x82|MCI_REGISTER_DATA_BYTE0)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_REGISTER_DATA_BYTE0)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)>>18);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
/* Read data byte 1;*/
temp = (0x82|MCI_REGISTER_DATA_BYTE1)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_REGISTER_DATA_BYTE1)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)>>10);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
/*Read data byte 2;*/
temp = (0x82|MCI_REGISTER_DATA_BYTE2)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_REGISTER_DATA_BYTE2)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)>>2);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
/*Read data byte 3;*/
temp = (0x82|MCI_REGISTER_DATA_BYTE3)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_REGISTER_DATA_BYTE3)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)<<6);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
*value = return_value;
return ret;
}
int mc417_memory_write(struct cx231xx *dev, u32 address, u32 value)
{
/*write data byte 0;*/
u32 temp;
int ret = 0;
temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8);
temp = temp<<10;
ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
if (ret < 0)
return ret;
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write data byte 1;*/
temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write data byte 2;*/
temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write data byte 3;*/
temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/* write address byte 2;*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
((address & 0x003F0000)>>8);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/* write address byte 1;*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/* write address byte 0;*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*wait for MIRDY line;*/
waitForMciComplete(dev);
return 0;
}
int mc417_memory_read(struct cx231xx *dev, u32 address, u32 *value)
{
u32 temp = 0;
u32 return_value = 0;
int ret = 0;
/*write address byte 2;*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_READ |
((address & 0x003F0000)>>8);
temp = temp<<10;
ret = setITVCReg(dev, ITVC_WRITE_DIR, temp);
if (ret < 0)
return ret;
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write address byte 1*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*write address byte 0*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0 | ((address & 0x00FF)<<8);
temp = temp<<10;
setITVCReg(dev, ITVC_WRITE_DIR, temp);
temp = temp|((0x05)<<10);
setITVCReg(dev, ITVC_WRITE_DIR, temp);
/*Wait for MIRDY line*/
ret = waitForMciComplete(dev);
/*Read data byte 3;*/
temp = (0x82|MCI_MEMORY_DATA_BYTE3)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_MEMORY_DATA_BYTE3)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)<<6);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
/*Read data byte 2;*/
temp = (0x82|MCI_MEMORY_DATA_BYTE2)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_MEMORY_DATA_BYTE2)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)>>2);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
/* Read data byte 1;*/
temp = (0x82|MCI_MEMORY_DATA_BYTE1)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_MEMORY_DATA_BYTE1)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)>>10);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
/*Read data byte 0;*/
temp = (0x82|MCI_MEMORY_DATA_BYTE0)<<10;
setITVCReg(dev, ITVC_READ_DIR, temp);
temp = ((0x81|MCI_MEMORY_DATA_BYTE0)<<10);
setITVCReg(dev, ITVC_READ_DIR, temp);
getITVCReg(dev, ITVC_READ_DIR, &temp);
return_value |= ((temp&0x03FC0000)>>18);
setITVCReg(dev, ITVC_READ_DIR, (0x87<<10));
*value = return_value;
return ret;
}
void mc417_gpio_set(struct cx231xx *dev, u32 mask)
{
u32 val;
/* Set the gpio value */
mc417_register_read(dev, 0x900C, &val);
val |= (mask & 0x000ffff);
mc417_register_write(dev, 0x900C, val);
}
void mc417_gpio_clear(struct cx231xx *dev, u32 mask)
{
u32 val;
/* Clear the gpio value */
mc417_register_read(dev, 0x900C, &val);
val &= ~(mask & 0x0000ffff);
mc417_register_write(dev, 0x900C, val);
}
void mc417_gpio_enable(struct cx231xx *dev, u32 mask, int asoutput)
{
u32 val;
/* Enable GPIO direction bits */
mc417_register_read(dev, 0x9020, &val);
if (asoutput)
val |= (mask & 0x0000ffff);
else
val &= ~(mask & 0x0000ffff);
mc417_register_write(dev, 0x9020, val);
}
/* ------------------------------------------------------------------ */
/* MPEG encoder API */
static char *cmd_to_str(int cmd)
{
switch (cmd) {
case CX2341X_ENC_PING_FW:
return "PING_FW";
case CX2341X_ENC_START_CAPTURE:
return "START_CAPTURE";
case CX2341X_ENC_STOP_CAPTURE:
return "STOP_CAPTURE";
case CX2341X_ENC_SET_AUDIO_ID:
return "SET_AUDIO_ID";
case CX2341X_ENC_SET_VIDEO_ID:
return "SET_VIDEO_ID";
case CX2341X_ENC_SET_PCR_ID:
return "SET_PCR_PID";
case CX2341X_ENC_SET_FRAME_RATE:
return "SET_FRAME_RATE";
case CX2341X_ENC_SET_FRAME_SIZE:
return "SET_FRAME_SIZE";
case CX2341X_ENC_SET_BIT_RATE:
return "SET_BIT_RATE";
case CX2341X_ENC_SET_GOP_PROPERTIES:
return "SET_GOP_PROPERTIES";
case CX2341X_ENC_SET_ASPECT_RATIO:
return "SET_ASPECT_RATIO";
case CX2341X_ENC_SET_DNR_FILTER_MODE:
return "SET_DNR_FILTER_PROPS";
case CX2341X_ENC_SET_DNR_FILTER_PROPS:
return "SET_DNR_FILTER_PROPS";
case CX2341X_ENC_SET_CORING_LEVELS:
return "SET_CORING_LEVELS";
case CX2341X_ENC_SET_SPATIAL_FILTER_TYPE:
return "SET_SPATIAL_FILTER_TYPE";
case CX2341X_ENC_SET_VBI_LINE:
return "SET_VBI_LINE";
case CX2341X_ENC_SET_STREAM_TYPE:
return "SET_STREAM_TYPE";
case CX2341X_ENC_SET_OUTPUT_PORT:
return "SET_OUTPUT_PORT";
case CX2341X_ENC_SET_AUDIO_PROPERTIES:
return "SET_AUDIO_PROPERTIES";
case CX2341X_ENC_HALT_FW:
return "HALT_FW";
case CX2341X_ENC_GET_VERSION:
return "GET_VERSION";
case CX2341X_ENC_SET_GOP_CLOSURE:
return "SET_GOP_CLOSURE";
case CX2341X_ENC_GET_SEQ_END:
return "GET_SEQ_END";
case CX2341X_ENC_SET_PGM_INDEX_INFO:
return "SET_PGM_INDEX_INFO";
case CX2341X_ENC_SET_VBI_CONFIG:
return "SET_VBI_CONFIG";
case CX2341X_ENC_SET_DMA_BLOCK_SIZE:
return "SET_DMA_BLOCK_SIZE";
case CX2341X_ENC_GET_PREV_DMA_INFO_MB_10:
return "GET_PREV_DMA_INFO_MB_10";
case CX2341X_ENC_GET_PREV_DMA_INFO_MB_9:
return "GET_PREV_DMA_INFO_MB_9";
case CX2341X_ENC_SCHED_DMA_TO_HOST:
return "SCHED_DMA_TO_HOST";
case CX2341X_ENC_INITIALIZE_INPUT:
return "INITIALIZE_INPUT";
case CX2341X_ENC_SET_FRAME_DROP_RATE:
return "SET_FRAME_DROP_RATE";
case CX2341X_ENC_PAUSE_ENCODER:
return "PAUSE_ENCODER";
case CX2341X_ENC_REFRESH_INPUT:
return "REFRESH_INPUT";
case CX2341X_ENC_SET_COPYRIGHT:
return "SET_COPYRIGHT";
case CX2341X_ENC_SET_EVENT_NOTIFICATION:
return "SET_EVENT_NOTIFICATION";
case CX2341X_ENC_SET_NUM_VSYNC_LINES:
return "SET_NUM_VSYNC_LINES";
case CX2341X_ENC_SET_PLACEHOLDER:
return "SET_PLACEHOLDER";
case CX2341X_ENC_MUTE_VIDEO:
return "MUTE_VIDEO";
case CX2341X_ENC_MUTE_AUDIO:
return "MUTE_AUDIO";
case CX2341X_ENC_MISC:
return "MISC";
default:
return "UNKNOWN";
}
}
static int cx231xx_mbox_func(void *priv,
u32 command,
int in,
int out,
u32 data[CX2341X_MBOX_MAX_DATA])
{
struct cx231xx *dev = priv;
unsigned long timeout;
u32 value, flag, retval = 0;
int i;
dprintk(3, "%s: command(0x%X) = %s\n", __func__, command,
cmd_to_str(command));
/* this may not be 100% safe if we can't read any memory location
without side effects */
mc417_memory_read(dev, dev->cx23417_mailbox - 4, &value);
if (value != 0x12345678) {
dprintk(3,
"Firmware and/or mailbox pointer not initialized "
"or corrupted, signature = 0x%x, cmd = %s\n", value,
cmd_to_str(command));
return -1;
}
/* This read looks at 32 bits, but flag is only 8 bits.
* Seems we also bail if CMD or TIMEOUT bytes are set???
*/
mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
if (flag) {
dprintk(3, "ERROR: Mailbox appears to be in use "
"(%x), cmd = %s\n", flag, cmd_to_str(command));
return -1;
}
flag |= 1; /* tell 'em we're working on it */
mc417_memory_write(dev, dev->cx23417_mailbox, flag);
/* write command + args + fill remaining with zeros */
/* command code */
mc417_memory_write(dev, dev->cx23417_mailbox + 1, command);
mc417_memory_write(dev, dev->cx23417_mailbox + 3,
IVTV_API_STD_TIMEOUT); /* timeout */
for (i = 0; i < in; i++) {
mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, data[i]);
dprintk(3, "API Input %d = %d\n", i, data[i]);
}
for (; i < CX2341X_MBOX_MAX_DATA; i++)
mc417_memory_write(dev, dev->cx23417_mailbox + 4 + i, 0);
flag |= 3; /* tell 'em we're done writing */
mc417_memory_write(dev, dev->cx23417_mailbox, flag);
/* wait for firmware to handle the API command */
timeout = jiffies + msecs_to_jiffies(10);
for (;;) {
mc417_memory_read(dev, dev->cx23417_mailbox, &flag);
if (0 != (flag & 4))
break;
if (time_after(jiffies, timeout)) {
dprintk(3, "ERROR: API Mailbox timeout\n");
return -1;
}
udelay(10);
}
/* read output values */
for (i = 0; i < out; i++) {
mc417_memory_read(dev, dev->cx23417_mailbox + 4 + i, data + i);
dprintk(3, "API Output %d = %d\n", i, data[i]);
}
mc417_memory_read(dev, dev->cx23417_mailbox + 2, &retval);
dprintk(3, "API result = %d\n", retval);
flag = 0;
mc417_memory_write(dev, dev->cx23417_mailbox, flag);
return retval;
}
/* We don't need to call the API often, so using just one
* mailbox will probably suffice
*/
static int cx231xx_api_cmd(struct cx231xx *dev,
u32 command,
u32 inputcnt,
u32 outputcnt,
...)
{
u32 data[CX2341X_MBOX_MAX_DATA];
va_list vargs;
int i, err;
dprintk(3, "%s() cmds = 0x%08x\n", __func__, command);
va_start(vargs, outputcnt);
for (i = 0; i < inputcnt; i++)
data[i] = va_arg(vargs, int);
err = cx231xx_mbox_func(dev, command, inputcnt, outputcnt, data);
for (i = 0; i < outputcnt; i++) {
int *vptr = va_arg(vargs, int *);
*vptr = data[i];
}
va_end(vargs);
return err;
}
static int cx231xx_find_mailbox(struct cx231xx *dev)
{
u32 signature[4] = {
0x12345678, 0x34567812, 0x56781234, 0x78123456
};
int signaturecnt = 0;
u32 value;
int i;
int ret = 0;
dprintk(2, "%s()\n", __func__);
for (i = 0; i < 0x100; i++) {/*CX231xx_FIRM_IMAGE_SIZE*/
ret = mc417_memory_read(dev, i, &value);
if (ret < 0)
return ret;
if (value == signature[signaturecnt])
signaturecnt++;
else
signaturecnt = 0;
if (4 == signaturecnt) {
dprintk(1, "Mailbox signature found at 0x%x\n", i+1);
return i+1;
}
}
dprintk(3, "Mailbox signature values not found!\n");
return -1;
}
void mciWriteMemoryToGPIO(struct cx231xx *dev, u32 address, u32 value,
u32 *p_fw_image)
{
u32 temp = 0;
int i = 0;
temp = 0x82|MCI_MEMORY_DATA_BYTE0|((value&0x000000FF)<<8);
temp = temp<<10;
*p_fw_image = temp;
p_fw_image++;
temp = temp|((0x05)<<10);
*p_fw_image = temp;
p_fw_image++;
/*write data byte 1;*/
temp = 0x82|MCI_MEMORY_DATA_BYTE1|(value&0x0000FF00);
temp = temp<<10;
*p_fw_image = temp;
p_fw_image++;
temp = temp|((0x05)<<10);
*p_fw_image = temp;
p_fw_image++;
/*write data byte 2;*/
temp = 0x82|MCI_MEMORY_DATA_BYTE2|((value&0x00FF0000)>>8);
temp = temp<<10;
*p_fw_image = temp;
p_fw_image++;
temp = temp|((0x05)<<10);
*p_fw_image = temp;
p_fw_image++;
/*write data byte 3;*/
temp = 0x82|MCI_MEMORY_DATA_BYTE3|((value&0xFF000000)>>16);
temp = temp<<10;
*p_fw_image = temp;
p_fw_image++;
temp = temp|((0x05)<<10);
*p_fw_image = temp;
p_fw_image++;
/* write address byte 2;*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE2 | MCI_MODE_MEMORY_WRITE |
((address & 0x003F0000)>>8);
temp = temp<<10;
*p_fw_image = temp;
p_fw_image++;
temp = temp|((0x05)<<10);
*p_fw_image = temp;
p_fw_image++;
/* write address byte 1;*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE1 | (address & 0xFF00);
temp = temp<<10;
*p_fw_image = temp;
p_fw_image++;
temp = temp|((0x05)<<10);
*p_fw_image = temp;
p_fw_image++;
/* write address byte 0;*/
temp = 0x82|MCI_MEMORY_ADDRESS_BYTE0|((address & 0x00FF)<<8);
temp = temp<<10;
*p_fw_image = temp;
p_fw_image++;
temp = temp|((0x05)<<10);
*p_fw_image = temp;
p_fw_image++;
for (i = 0; i < 6; i++) {
*p_fw_image = 0xFFFFFFFF;
p_fw_image++;
}
}
static int cx231xx_load_firmware(struct cx231xx *dev)
{
static const unsigned char magic[8] = {
0xa7, 0x0d, 0x00, 0x00, 0x66, 0xbb, 0x55, 0xaa
};
const struct firmware *firmware;
int i, retval = 0;
u32 value = 0;
u32 gpio_output = 0;
/*u32 checksum = 0;*/
/*u32 *dataptr;*/
u32 transfer_size = 0;
u32 fw_data = 0;
u32 address = 0;
/*u32 current_fw[800];*/
u32 *p_current_fw, *p_fw;
u32 *p_fw_data;
int frame = 0;
u16 _buffer_size = 4096;
u8 *p_buffer;
p_current_fw = (u32 *)vmalloc(1884180*4);
p_fw = p_current_fw;
if (p_current_fw == 0) {
dprintk(2, "FAIL!!!\n");
return -1;
}
p_buffer = (u8 *)vmalloc(4096);
if (p_buffer == 0) {
dprintk(2, "FAIL!!!\n");
return -1;
}
dprintk(2, "%s()\n", __func__);
/* Save GPIO settings before reset of APU */
retval |= mc417_memory_read(dev, 0x9020, &gpio_output);
retval |= mc417_memory_read(dev, 0x900C, &value);
retval = mc417_register_write(dev,
IVTV_REG_VPU, 0xFFFFFFED);
retval |= mc417_register_write(dev,
IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST);
retval |= mc417_register_write(dev,
IVTV_REG_ENC_SDRAM_REFRESH, 0x80000800);
retval |= mc417_register_write(dev,
IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A);
retval |= mc417_register_write(dev,
IVTV_REG_APU, 0);
if (retval != 0) {
printk(KERN_ERR "%s: Error with mc417_register_write\n",
__func__);
return -1;
}
retval = request_firmware(&firmware, CX231xx_FIRM_IMAGE_NAME,
&dev->udev->dev);
if (retval != 0) {
printk(KERN_ERR
"ERROR: Hotplug firmware request failed (%s).\n",
CX231xx_FIRM_IMAGE_NAME);
printk(KERN_ERR "Please fix your hotplug setup, the board will "
"not work without firmware loaded!\n");
return -1;
}
if (firmware->size != CX231xx_FIRM_IMAGE_SIZE) {
printk(KERN_ERR "ERROR: Firmware size mismatch "
"(have %zd, expected %d)\n",
firmware->size, CX231xx_FIRM_IMAGE_SIZE);
release_firmware(firmware);
return -1;
}
if (0 != memcmp(firmware->data, magic, 8)) {
printk(KERN_ERR
"ERROR: Firmware magic mismatch, wrong file?\n");
release_firmware(firmware);
return -1;
}
initGPIO(dev);
/* transfer to the chip */
dprintk(2, "Loading firmware to GPIO...\n");
p_fw_data = (u32 *)firmware->data;
dprintk(2, "firmware->size=%d\n", firmware->size);
for (transfer_size = 0; transfer_size < firmware->size;
transfer_size += 4) {
fw_data = *p_fw_data;
mciWriteMemoryToGPIO(dev, address, fw_data, p_current_fw);
address = address + 1;
p_current_fw += 20;
p_fw_data += 1;
}
/*download the firmware by ep5-out*/
for (frame = 0; frame < (int)(CX231xx_FIRM_IMAGE_SIZE*20/_buffer_size);
frame++) {
for (i = 0; i < _buffer_size; i++) {
*(p_buffer+i) =
(u8)(*(p_fw+(frame*128*8+(i++/4))) & 0x000000FF);
*(p_buffer+i) =
(u8)((*(p_fw+(frame*128*8+(i++/4))) & 0x0000FF00)>>8);
*(p_buffer+i) =
(u8)((*(p_fw+(frame*128*8+(i++/4))) & 0x00FF0000)>>16);
*(p_buffer+i) =
(u8)((*(p_fw+(frame*128*8+(i/4))) & 0xFF000000)>>24);
}
cx231xx_ep5_bulkout(dev, p_buffer, _buffer_size);
}
p_current_fw = p_fw;
vfree(p_current_fw);
p_current_fw = NULL;
uninitGPIO(dev);
release_firmware(firmware);
dprintk(1, "Firmware upload successful.\n");
retval |= mc417_register_write(dev, IVTV_REG_HW_BLOCKS,
IVTV_CMD_HW_BLOCKS_RST);
if (retval < 0) {
printk(KERN_ERR "%s: Error with mc417_register_write\n",
__func__);
return retval;
}
/* F/W power up disturbs the GPIOs, restore state */
retval |= mc417_register_write(dev, 0x9020, gpio_output);
retval |= mc417_register_write(dev, 0x900C, value);
retval |= mc417_register_read(dev, IVTV_REG_VPU, &value);
retval |= mc417_register_write(dev, IVTV_REG_VPU, value & 0xFFFFFFE8);
if (retval < 0) {
printk(KERN_ERR "%s: Error with mc417_register_write\n",
__func__);
return retval;
}
return 0;
}
void cx231xx_417_check_encoder(struct cx231xx *dev)
{
u32 status, seq;
status = 0;
seq = 0;
cx231xx_api_cmd(dev, CX2341X_ENC_GET_SEQ_END, 0, 2, &status, &seq);
dprintk(1, "%s() status = %d, seq = %d\n", __func__, status, seq);
}
static void cx231xx_codec_settings(struct cx231xx *dev)
{
dprintk(1, "%s()\n", __func__);
/* assign frame size */
cx231xx_api_cmd(dev, CX2341X_ENC_SET_FRAME_SIZE, 2, 0,
dev->ts1.height, dev->ts1.width);
dev->mpeg_params.width = dev->ts1.width;
dev->mpeg_params.height = dev->ts1.height;
cx2341x_update(dev, cx231xx_mbox_func, NULL, &dev->mpeg_params);
cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 3, 1);
cx231xx_api_cmd(dev, CX2341X_ENC_MISC, 2, 0, 4, 1);
}
static int cx231xx_initialize_codec(struct cx231xx *dev)
{
int version;
int retval;
u32 i, data[7];
u32 val = 0;
dprintk(1, "%s()\n", __func__);
cx231xx_disable656(dev);
retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0); /* ping */
if (retval < 0) {
dprintk(2, "%s() PING OK\n", __func__);
retval = cx231xx_load_firmware(dev);
if (retval < 0) {
printk(KERN_ERR "%s() f/w load failed\n", __func__);
return retval;
}
retval = cx231xx_find_mailbox(dev);
if (retval < 0) {
printk(KERN_ERR "%s() mailbox < 0, error\n",
__func__);
return -1;
}
dev->cx23417_mailbox = retval;
retval = cx231xx_api_cmd(dev, CX2341X_ENC_PING_FW, 0, 0);
if (retval < 0) {
printk(KERN_ERR
"ERROR: cx23417 firmware ping failed!\n");
return -1;
}
retval = cx231xx_api_cmd(dev, CX2341X_ENC_GET_VERSION, 0, 1,
&version);
if (retval < 0) {
printk(KERN_ERR "ERROR: cx23417 firmware get encoder :"
"version failed!\n");
return -1;
}
dprintk(1, "cx23417 firmware version is 0x%08x\n", version);
msleep(200);
}
for (i = 0; i < 1; i++) {
retval = mc417_register_read(dev, 0x20f8, &val);
dprintk(3, "***before enable656() VIM Capture Lines =%d ***\n",
val);
if (retval < 0)
return retval;
}
cx231xx_enable656(dev);
/* stop mpeg capture */
cx231xx_api_cmd(dev, CX2341X_ENC_STOP_CAPTURE,
3, 0, 1, 3, 4);
cx231xx_codec_settings(dev);
msleep(60);
/* cx231xx_api_cmd(dev, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, 0,
CX231xx_FIELD1_SAA7115, CX231xx_FIELD2_SAA7115);
cx231xx_api_cmd(dev, CX2341X_ENC_SET_PLACEHOLDER, 12, 0,
CX231xx_CUSTOM_EXTENSION_USR_DATA, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0);
*/
/* Setup to capture VBI */
data[0] = 0x0001BD00;
data[1] = 1; /* frames per interrupt */
data[2] = 4; /* total bufs */
data[3] = 0x91559155; /* start codes */
data[4] = 0x206080C0; /* stop codes */
data[5] = 6; /* lines */
data[6] = 64; /* BPL */
/*
cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_CONFIG, 7, 0, data[0], data[1],
data[2], data[3], data[4], data[5], data[6]);
for (i = 2; i <= 24; i++) {
int valid;
valid = ((i >= 19) && (i <= 21));
cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0, i,
valid, 0 , 0, 0);
cx231xx_api_cmd(dev, CX2341X_ENC_SET_VBI_LINE, 5, 0,
i | 0x80000000, valid, 0, 0, 0);
}
*/
/* cx231xx_api_cmd(dev, CX2341X_ENC_MUTE_AUDIO, 1, 0, CX231xx_UNMUTE);
msleep(60);
*/
/* initialize the video input */
retval = cx231xx_api_cmd(dev, CX2341X_ENC_INITIALIZE_INPUT, 0, 0);
if (retval < 0)
return retval;
msleep(60);
/* Enable VIP style pixel invalidation so we work with scaled mode */
mc417_memory_write(dev, 2120, 0x00000080);
/* start capturing to the host interface */
retval = cx231xx_api_cmd(dev, CX2341X_ENC_START_CAPTURE, 2, 0,
CX231xx_MPEG_CAPTURE, CX231xx_RAW_BITS_NONE);
if (retval < 0)
return retval;
msleep(10);
for (i = 0; i < 1; i++) {
mc417_register_read(dev, 0x20f8, &val);
dprintk(3, "***VIM Capture Lines =%d ***\n", val);
}
return 0;
}
/* ------------------------------------------------------------------ */
static int bb_buf_setup(struct videobuf_queue *q,
unsigned int *count, unsigned int *size)
{
struct cx231xx_fh *fh = q->priv_data;
fh->dev->ts1.ts_packet_size = mpeglinesize;
fh->dev->ts1.ts_packet_count = mpeglines;
*size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
*count = mpegbufs;
return 0;
}
static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
{
struct cx231xx_fh *fh = vq->priv_data;
struct cx231xx *dev = fh->dev;
unsigned long flags = 0;
if (in_interrupt())
BUG();
spin_lock_irqsave(&dev->video_mode.slock, flags);
if (dev->USE_ISO) {
if (dev->video_mode.isoc_ctl.buf == buf)
dev->video_mode.isoc_ctl.buf = NULL;
} else {
if (dev->video_mode.bulk_ctl.buf == buf)
dev->video_mode.bulk_ctl.buf = NULL;
}
spin_unlock_irqrestore(&dev->video_mode.slock, flags);
videobuf_waiton(vq, &buf->vb, 0, 0);
videobuf_vmalloc_free(&buf->vb);
buf->vb.state = VIDEOBUF_NEEDS_INIT;
}
void buffer_copy(struct cx231xx *dev, char *data, int len, struct urb *urb,
struct cx231xx_dmaqueue *dma_q)
{
void *vbuf;
struct cx231xx_buffer *buf;
u32 tail_data = 0;
char *p_data;
if (dma_q->mpeg_buffer_done == 0) {
if (list_empty(&dma_q->active))
return;
buf = list_entry(dma_q->active.next,
struct cx231xx_buffer, vb.queue);
dev->video_mode.isoc_ctl.buf = buf;
dma_q->mpeg_buffer_done = 1;
}
/* Fill buffer */
buf = dev->video_mode.isoc_ctl.buf;
vbuf = videobuf_to_vmalloc(&buf->vb);
if ((dma_q->mpeg_buffer_completed+len) <
mpeglines*mpeglinesize) {
if (dma_q->add_ps_package_head ==
CX231XX_NEED_ADD_PS_PACKAGE_HEAD) {
memcpy(vbuf+dma_q->mpeg_buffer_completed,
dma_q->ps_head, 3);
dma_q->mpeg_buffer_completed =
dma_q->mpeg_buffer_completed + 3;
dma_q->add_ps_package_head =
CX231XX_NONEED_PS_PACKAGE_HEAD;
}
memcpy(vbuf+dma_q->mpeg_buffer_completed, data, len);
dma_q->mpeg_buffer_completed =
dma_q->mpeg_buffer_completed + len;
} else {
dma_q->mpeg_buffer_done = 0;
tail_data =
mpeglines*mpeglinesize - dma_q->mpeg_buffer_completed;
memcpy(vbuf+dma_q->mpeg_buffer_completed,
data, tail_data);
buf->vb.state = VIDEOBUF_DONE;
buf->vb.field_count++;
do_gettimeofday(&buf->vb.ts);
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
dma_q->mpeg_buffer_completed = 0;
if (len - tail_data > 0) {
p_data = data + tail_data;
dma_q->left_data_count = len - tail_data;
memcpy(dma_q->p_left_data,
p_data, len - tail_data);
}
}
return;
}
void buffer_filled(char *data, int len, struct urb *urb,
struct cx231xx_dmaqueue *dma_q)
{
void *vbuf;
struct cx231xx_buffer *buf;
if (list_empty(&dma_q->active))
return;
buf = list_entry(dma_q->active.next,
struct cx231xx_buffer, vb.queue);
/* Fill buffer */
vbuf = videobuf_to_vmalloc(&buf->vb);
memcpy(vbuf, data, len);
buf->vb.state = VIDEOBUF_DONE;
buf->vb.field_count++;
do_gettimeofday(&buf->vb.ts);
list_del(&buf->vb.queue);
wake_up(&buf->vb.done);
return;
}
static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
{
struct cx231xx_dmaqueue *dma_q = urb->context;
unsigned char *p_buffer;
u32 buffer_size = 0;
u32 i = 0;
for (i = 0; i < urb->number_of_packets; i++) {
if (dma_q->left_data_count > 0) {
buffer_copy(dev, dma_q->p_left_data,
dma_q->left_data_count, urb, dma_q);
dma_q->mpeg_buffer_completed = dma_q->left_data_count;
dma_q->left_data_count = 0;
}
p_buffer = urb->transfer_buffer +
urb->iso_frame_desc[i].offset;
buffer_size = urb->iso_frame_desc[i].actual_length;
if (buffer_size > 0)
buffer_copy(dev, p_buffer, buffer_size, urb, dma_q);
}
return 0;
}
static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
{
/*char *outp;*/
/*struct cx231xx_buffer *buf;*/
struct cx231xx_dmaqueue *dma_q = urb->context;
unsigned char *p_buffer, *buffer;
u32 buffer_size = 0;
p_buffer = urb->transfer_buffer;
buffer_size = urb->actual_length;
buffer = kmalloc(buffer_size, GFP_ATOMIC);
memcpy(buffer, dma_q->ps_head, 3);
memcpy(buffer+3, p_buffer, buffer_size-3);
memcpy(dma_q->ps_head, p_buffer+buffer_size-3, 3);
p_buffer = buffer;
buffer_filled(p_buffer, buffer_size, urb, dma_q);
kfree(buffer);
return 0;
}
static int bb_buf_prepare(struct videobuf_queue *q,
struct videobuf_buffer *vb, enum v4l2_field field)
{
struct cx231xx_fh *fh = q->priv_data;
struct cx231xx_buffer *buf =
container_of(vb, struct cx231xx_buffer, vb);
struct cx231xx *dev = fh->dev;
int rc = 0, urb_init = 0;
int size = fh->dev->ts1.ts_packet_size * fh->dev->ts1.ts_packet_count;
dma_qq = &dev->video_mode.vidq;
if (0 != buf->vb.baddr && buf->vb.bsize < size)
return -EINVAL;
buf->vb.width = fh->dev->ts1.ts_packet_size;
buf->vb.height = fh->dev->ts1.ts_packet_count;
buf->vb.size = size;
buf->vb.field = field;
if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
rc = videobuf_iolock(q, &buf->vb, NULL);
if (rc < 0)
goto fail;
}
if (dev->USE_ISO) {
if (!dev->video_mode.isoc_ctl.num_bufs)
urb_init = 1;
} else {
if (!dev->video_mode.bulk_ctl.num_bufs)
urb_init = 1;
}
/*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
urb_init, dev->video_mode.max_pkt_size);*/
dev->mode_tv = 1;
if (urb_init) {
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
rc = cx231xx_unmute_audio(dev);
if (dev->USE_ISO) {
cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
rc = cx231xx_init_isoc(dev, mpeglines,
mpegbufs,
dev->ts1_mode.max_pkt_size,
cx231xx_isoc_copy);
} else {
cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
rc = cx231xx_init_bulk(dev, mpeglines,
mpegbufs,
dev->ts1_mode.max_pkt_size,
cx231xx_bulk_copy);
}
if (rc < 0)
goto fail;
}
buf->vb.state = VIDEOBUF_PREPARED;
return 0;
fail:
free_buffer(q, buf);
return rc;
}
static void bb_buf_queue(struct videobuf_queue *q,
struct videobuf_buffer *vb)
{
struct cx231xx_fh *fh = q->priv_data;
struct cx231xx_buffer *buf =
container_of(vb, struct cx231xx_buffer, vb);
struct cx231xx *dev = fh->dev;
struct cx231xx_dmaqueue *vidq = &dev->video_mode.vidq;
buf->vb.state = VIDEOBUF_QUEUED;
list_add_tail(&buf->vb.queue, &vidq->active);
}
static void bb_buf_release(struct videobuf_queue *q,
struct videobuf_buffer *vb)
{
struct cx231xx_buffer *buf =
container_of(vb, struct cx231xx_buffer, vb);
/*struct cx231xx_fh *fh = q->priv_data;*/
/*struct cx231xx *dev = (struct cx231xx *)fh->dev;*/
free_buffer(q, buf);
}
static struct videobuf_queue_ops cx231xx_qops = {
.buf_setup = bb_buf_setup,
.buf_prepare = bb_buf_prepare,
.buf_queue = bb_buf_queue,
.buf_release = bb_buf_release,
};
/* ------------------------------------------------------------------ */
static const u32 *ctrl_classes[] = {
cx2341x_mpeg_ctrls,
NULL
};
static int cx231xx_queryctrl(struct cx231xx *dev,
struct v4l2_queryctrl *qctrl)
{
qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
if (qctrl->id == 0)
return -EINVAL;
/* MPEG V4L2 controls */
if (cx2341x_ctrl_query(&dev->mpeg_params, qctrl))
qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
return 0;
}
static int cx231xx_querymenu(struct cx231xx *dev,
struct v4l2_querymenu *qmenu)
{
struct v4l2_queryctrl qctrl;
qctrl.id = qmenu->id;
cx231xx_queryctrl(dev, &qctrl);
return v4l2_ctrl_query_menu(qmenu, &qctrl,
cx2341x_ctrl_get_menu(&dev->mpeg_params, qmenu->id));
}
static int vidioc_g_std(struct file *file, void *fh0, v4l2_std_id *norm)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
*norm = dev->encodernorm.id;
return 0;
}
static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *id)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
unsigned int i;
for (i = 0; i < ARRAY_SIZE(cx231xx_tvnorms); i++)
if (*id & cx231xx_tvnorms[i].id)
break;
if (i == ARRAY_SIZE(cx231xx_tvnorms))
return -EINVAL;
dev->encodernorm = cx231xx_tvnorms[i];
if (dev->encodernorm.id & 0xb000) {
dprintk(3, "encodernorm set to NTSC\n");
dev->norm = V4L2_STD_NTSC;
dev->ts1.height = 480;
dev->mpeg_params.is_50hz = 0;
} else {
dprintk(3, "encodernorm set to PAL\n");
dev->norm = V4L2_STD_PAL_B;
dev->ts1.height = 576;
dev->mpeg_params.is_50hz = 1;
}
call_all(dev, core, s_std, dev->norm);
/* do mode control overrides */
cx231xx_do_mode_ctrl_overrides(dev);
dprintk(3, "exit vidioc_s_std() i=0x%x\n", i);
return 0;
}
static int vidioc_g_audio(struct file *file, void *fh,
struct v4l2_audio *a)
{
struct v4l2_audio *vin = a;
int ret = -EINVAL;
if (vin->index > 0)
return ret;
strncpy(vin->name, "VideoGrabber Audio", 14);
vin->capability = V4L2_AUDCAP_STEREO;
return 0;
}
static int vidioc_enumaudio(struct file *file, void *fh,
struct v4l2_audio *a)
{
struct v4l2_audio *vin = a;
int ret = -EINVAL;
if (vin->index > 0)
return ret;
strncpy(vin->name, "VideoGrabber Audio", 14);
vin->capability = V4L2_AUDCAP_STEREO;
return 0;
}
static const char *iname[] = {
[CX231XX_VMUX_COMPOSITE1] = "Composite1",
[CX231XX_VMUX_SVIDEO] = "S-Video",
[CX231XX_VMUX_TELEVISION] = "Television",
[CX231XX_VMUX_CABLE] = "Cable TV",
[CX231XX_VMUX_DVB] = "DVB",
[CX231XX_VMUX_DEBUG] = "for debug only",
};
static int vidioc_enum_input(struct file *file, void *priv,
struct v4l2_input *i)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
struct cx231xx_input *input;
int n;
dprintk(3, "enter vidioc_enum_input()i->index=%d\n", i->index);
if (i->index >= 4)
return -EINVAL;
input = &cx231xx_boards[dev->model].input[i->index];
if (input->type == 0)
return -EINVAL;
/* FIXME
* strcpy(i->name, input->name); */
n = i->index;
strcpy(i->name, iname[INPUT(n)->type]);
if (input->type == CX231XX_VMUX_TELEVISION ||
input->type == CX231XX_VMUX_CABLE)
i->type = V4L2_INPUT_TYPE_TUNER;
else
i->type = V4L2_INPUT_TYPE_CAMERA;
return 0;
}
static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
{
*i = 0;
return 0;
}
static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
dprintk(3, "enter vidioc_s_input() i=%d\n", i);
mutex_lock(&dev->lock);
video_mux(dev, i);
mutex_unlock(&dev->lock);
if (i >= 4)
return -EINVAL;
dev->input = i;
dprintk(3, "exit vidioc_s_input()\n");
return 0;
}
static int vidioc_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
return 0;
}
static int vidioc_s_tuner(struct file *file, void *priv,
struct v4l2_tuner *t)
{
return 0;
}
static int vidioc_g_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
return 0;
}
static int vidioc_s_frequency(struct file *file, void *priv,
struct v4l2_frequency *f)
{
return 0;
}
static int vidioc_s_ctrl(struct file *file, void *priv,
struct v4l2_control *ctl)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
dprintk(3, "enter vidioc_s_ctrl()\n");
/* Update the A/V core */
call_all(dev, core, s_ctrl, ctl);
dprintk(3, "exit vidioc_s_ctrl()\n");
return 0;
}
static struct v4l2_capability pvr_capability = {
.driver = "cx231xx",
.card = "VideoGrabber",
.bus_info = "usb",
.version = 1,
.capabilities = (V4L2_CAP_VIDEO_CAPTURE |
V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_RADIO |
V4L2_CAP_STREAMING | V4L2_CAP_READWRITE),
.reserved = {0, 0, 0, 0}
};
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
memcpy(cap, &pvr_capability, sizeof(struct v4l2_capability));
return 0;
}
static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
if (f->index != 0)
return -EINVAL;
strlcpy(f->description, "MPEG", sizeof(f->description));
f->pixelformat = V4L2_PIX_FMT_MPEG;
return 0;
}
static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
dprintk(3, "enter vidioc_g_fmt_vid_cap()\n");
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage =
dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
f->fmt.pix.colorspace = 0;
f->fmt.pix.width = dev->ts1.width;
f->fmt.pix.height = dev->ts1.height;
f->fmt.pix.field = fh->vidq.field;
dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d, f: %d\n",
dev->ts1.width, dev->ts1.height, fh->vidq.field);
dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
return 0;
}
static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
dprintk(3, "enter vidioc_try_fmt_vid_cap()\n");
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.bytesperline = 0;
f->fmt.pix.sizeimage =
dev->ts1.ts_packet_size * dev->ts1.ts_packet_count;
f->fmt.pix.colorspace = 0;
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d, f: %d\n",
dev->ts1.width, dev->ts1.height, fh->vidq.field);
dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
return 0;
}
static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
return 0;
}
static int vidioc_reqbufs(struct file *file, void *priv,
struct v4l2_requestbuffers *p)
{
struct cx231xx_fh *fh = file->private_data;
return videobuf_reqbufs(&fh->vidq, p);
}
static int vidioc_querybuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx231xx_fh *fh = file->private_data;
return videobuf_querybuf(&fh->vidq, p);
}
static int vidioc_qbuf(struct file *file, void *priv,
struct v4l2_buffer *p)
{
struct cx231xx_fh *fh = file->private_data;
return videobuf_qbuf(&fh->vidq, p);
}
static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *b)
{
struct cx231xx_fh *fh = priv;
return videobuf_dqbuf(&fh->vidq, b, file->f_flags & O_NONBLOCK);
}
static int vidioc_streamon(struct file *file, void *priv,
enum v4l2_buf_type i)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
int rc = 0;
dprintk(3, "enter vidioc_streamon()\n");
cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
if (dev->USE_ISO)
rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
CX231XX_NUM_BUFS,
dev->video_mode.max_pkt_size,
cx231xx_isoc_copy);
else {
rc = cx231xx_init_bulk(dev, 320,
5,
dev->ts1_mode.max_pkt_size,
cx231xx_bulk_copy);
}
dprintk(3, "exit vidioc_streamon()\n");
return videobuf_streamon(&fh->vidq);
}
static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
{
struct cx231xx_fh *fh = file->private_data;
return videobuf_streamoff(&fh->vidq);
}
static int vidioc_g_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
dprintk(3, "enter vidioc_g_ext_ctrls()\n");
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
dprintk(3, "exit vidioc_g_ext_ctrls()\n");
return cx2341x_ext_ctrls(&dev->mpeg_params, 0, f, VIDIOC_G_EXT_CTRLS);
}
static int vidioc_s_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
struct cx2341x_mpeg_params p;
int err;
dprintk(3, "enter vidioc_s_ext_ctrls()\n");
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->mpeg_params;
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
if (err == 0) {
err = cx2341x_update(dev, cx231xx_mbox_func,
&dev->mpeg_params, &p);
dev->mpeg_params = p;
}
return err;
return 0;
}
static int vidioc_try_ext_ctrls(struct file *file, void *priv,
struct v4l2_ext_controls *f)
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
struct cx2341x_mpeg_params p;
int err;
dprintk(3, "enter vidioc_try_ext_ctrls()\n");
if (f->ctrl_class != V4L2_CTRL_CLASS_MPEG)
return -EINVAL;
p = dev->mpeg_params;
err = cx2341x_ext_ctrls(&p, 0, f, VIDIOC_TRY_EXT_CTRLS);
dprintk(3, "exit vidioc_try_ext_ctrls() err=%d\n", err);
return err;
}
static int vidioc_log_status(struct file *file, void *priv)
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
char name[32 + 2];
snprintf(name, sizeof(name), "%s/2", dev->name);
dprintk(3,
"%s/2: ============ START LOG STATUS ============\n",
dev->name);
call_all(dev, core, log_status);
cx2341x_log_status(&dev->mpeg_params, name);
dprintk(3,
"%s/2: ============= END LOG STATUS =============\n",
dev->name);
return 0;
}
static int vidioc_querymenu(struct file *file, void *priv,
struct v4l2_querymenu *a)
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
dprintk(3, "enter vidioc_querymenu()\n");
dprintk(3, "exit vidioc_querymenu()\n");
return cx231xx_querymenu(dev, a);
}
static int vidioc_queryctrl(struct file *file, void *priv,
struct v4l2_queryctrl *c)
{
struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev;
dprintk(3, "enter vidioc_queryctrl()\n");
dprintk(3, "exit vidioc_queryctrl()\n");
return cx231xx_queryctrl(dev, c);
}
static int mpeg_open(struct file *file)
{
int minor = video_devdata(file)->minor;
struct cx231xx *h, *dev = NULL;
/*struct list_head *list;*/
struct cx231xx_fh *fh;
/*u32 value = 0;*/
dprintk(2, "%s()\n", __func__);
list_for_each_entry(h, &cx231xx_devlist, devlist) {
if (h->v4l_device->minor == minor)
dev = h;
}
if (dev == NULL) {
unlock_kernel();
return -ENODEV;
}
mutex_lock(&dev->lock);
/* allocate + initialize per filehandle data */
fh = kzalloc(sizeof(*fh), GFP_KERNEL);
if (NULL == fh) {
mutex_unlock(&dev->lock);
return -ENOMEM;
}
file->private_data = fh;
fh->dev = dev;
videobuf_queue_vmalloc_init(&fh->vidq, &cx231xx_qops,
NULL, &dev->video_mode.slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_INTERLACED,
sizeof(struct cx231xx_buffer), fh, NULL);
/*
videobuf_queue_sg_init(&fh->vidq, &cx231xx_qops,
&dev->udev->dev, &dev->ts1.slock,
V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,
sizeof(struct cx231xx_buffer),
fh, NULL);
*/
cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
cx231xx_set_gpio_value(dev, 2, 0);
cx231xx_initialize_codec(dev);
mutex_unlock(&dev->lock);
cx231xx_start_TS1(dev);
return 0;
}
static int mpeg_release(struct file *file)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
dprintk(3, "mpeg_release()! dev=0x%x\n", dev);
if (!dev) {
dprintk(3, "abort!!!\n");
return 0;
}
mutex_lock(&dev->lock);
cx231xx_stop_TS1(dev);
/* do this before setting alternate! */
if (dev->USE_ISO)
cx231xx_uninit_isoc(dev);
else
cx231xx_uninit_bulk(dev);
cx231xx_set_mode(dev, CX231XX_SUSPEND);
cx231xx_api_cmd(fh->dev, CX2341X_ENC_STOP_CAPTURE, 3, 0,
CX231xx_END_NOW, CX231xx_MPEG_CAPTURE,
CX231xx_RAW_BITS_NONE);
/* FIXME: Review this crap */
/* Shut device down on last close */
if (atomic_cmpxchg(&fh->v4l_reading, 1, 0) == 1) {
if (atomic_dec_return(&dev->v4l_reader_count) == 0) {
/* stop mpeg capture */
msleep(500);
cx231xx_417_check_encoder(dev);
}
}
if (fh->vidq.streaming)
videobuf_streamoff(&fh->vidq);
if (fh->vidq.reading)
videobuf_read_stop(&fh->vidq);
videobuf_mmap_free(&fh->vidq);
file->private_data = NULL;
kfree(fh);
mutex_unlock(&dev->lock);
return 0;
}
static ssize_t mpeg_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
/* Deal w/ A/V decoder * and mpeg encoder sync issues. */
/* Start mpeg encoder on first read. */
if (atomic_cmpxchg(&fh->v4l_reading, 0, 1) == 0) {
if (atomic_inc_return(&dev->v4l_reader_count) == 1) {
if (cx231xx_initialize_codec(dev) < 0)
return -EINVAL;
}
}
return videobuf_read_stream(&fh->vidq, data, count, ppos, 0,
file->f_flags & O_NONBLOCK);
}
static unsigned int mpeg_poll(struct file *file,
struct poll_table_struct *wait)
{
struct cx231xx_fh *fh = file->private_data;
/*struct cx231xx *dev = fh->dev;*/
/*dprintk(2, "%s\n", __func__);*/
return videobuf_poll_stream(file, &fh->vidq, wait);
}
static int mpeg_mmap(struct file *file, struct vm_area_struct *vma)
{
struct cx231xx_fh *fh = file->private_data;
struct cx231xx *dev = fh->dev;
dprintk(2, "%s()\n", __func__);
return videobuf_mmap_mapper(&fh->vidq, vma);
}
static struct v4l2_file_operations mpeg_fops = {
.owner = THIS_MODULE,
.open = mpeg_open,
.release = mpeg_release,
.read = mpeg_read,
.poll = mpeg_poll,
.mmap = mpeg_mmap,
.ioctl = video_ioctl2,
};
static const struct v4l2_ioctl_ops mpeg_ioctl_ops = {
.vidioc_s_std = vidioc_s_std,
.vidioc_g_std = vidioc_g_std,
.vidioc_enum_input = vidioc_enum_input,
.vidioc_enumaudio = vidioc_enumaudio,
.vidioc_g_audio = vidioc_g_audio,
.vidioc_g_input = vidioc_g_input,
.vidioc_s_input = vidioc_s_input,
.vidioc_g_tuner = vidioc_g_tuner,
.vidioc_s_tuner = vidioc_s_tuner,
.vidioc_g_frequency = vidioc_g_frequency,
.vidioc_s_frequency = vidioc_s_frequency,
.vidioc_s_ctrl = vidioc_s_ctrl,
.vidioc_querycap = vidioc_querycap,
.vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
.vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
.vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
.vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
.vidioc_reqbufs = vidioc_reqbufs,
.vidioc_querybuf = vidioc_querybuf,
.vidioc_qbuf = vidioc_qbuf,
.vidioc_dqbuf = vidioc_dqbuf,
.vidioc_streamon = vidioc_streamon,
.vidioc_streamoff = vidioc_streamoff,
.vidioc_g_ext_ctrls = vidioc_g_ext_ctrls,
.vidioc_s_ext_ctrls = vidioc_s_ext_ctrls,
.vidioc_try_ext_ctrls = vidioc_try_ext_ctrls,
.vidioc_log_status = vidioc_log_status,
.vidioc_querymenu = vidioc_querymenu,
.vidioc_queryctrl = vidioc_queryctrl,
/* .vidioc_g_chip_ident = cx231xx_g_chip_ident,*/
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* .vidioc_g_register = cx231xx_g_register,*/
/* .vidioc_s_register = cx231xx_s_register,*/
#endif
};
static struct video_device cx231xx_mpeg_template = {
.name = "cx231xx",
.fops = &mpeg_fops,
.ioctl_ops = &mpeg_ioctl_ops,
.minor = -1,
.tvnorms = CX231xx_NORMS,
.current_norm = V4L2_STD_NTSC_M,
};
void cx231xx_417_unregister(struct cx231xx *dev)
{
dprintk(1, "%s()\n", __func__);
dprintk(3, "%s()\n", __func__);
if (dev->v4l_device) {
if (-1 != dev->v4l_device->minor)
video_unregister_device(dev->v4l_device);
else
video_device_release(dev->v4l_device);
dev->v4l_device = NULL;
}
}
static struct video_device *cx231xx_video_dev_alloc(
struct cx231xx *dev,
struct usb_device *usbdev,
struct video_device *template,
char *type)
{
struct video_device *vfd;
dprintk(1, "%s()\n", __func__);
vfd = video_device_alloc();
if (NULL == vfd)
return NULL;
*vfd = *template;
vfd->minor = -1;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)", dev->name,
type, cx231xx_boards[dev->model].name);
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->release = video_device_release;
return vfd;
}
int cx231xx_417_register(struct cx231xx *dev)
{
/* FIXME: Port1 hardcoded here */
int err = -ENODEV;
struct cx231xx_tsport *tsport = &dev->ts1;
dprintk(1, "%s()\n", __func__);
/* Set default TV standard */
dev->encodernorm = cx231xx_tvnorms[0];
if (dev->encodernorm.id & V4L2_STD_525_60)
tsport->height = 480;
else
tsport->height = 576;
tsport->width = 720;
cx2341x_fill_defaults(&dev->mpeg_params);
dev->norm = V4L2_STD_NTSC;
dev->mpeg_params.port = CX2341X_PORT_SERIAL;
/* Allocate and initialize V4L video device */
dev->v4l_device = cx231xx_video_dev_alloc(dev,
dev->udev, &cx231xx_mpeg_template, "mpeg");
err = video_register_device(dev->v4l_device,
VFL_TYPE_GRABBER, -1);
if (err < 0) {
dprintk(3, "%s: can't register mpeg device\n", dev->name);
return err;
}
dprintk(3, "%s: registered device video%d [mpeg]\n",
dev->name, dev->v4l_device->num);
return 0;
}
...@@ -75,6 +75,30 @@ static int cx231xx_isoc_audio_deinit(struct cx231xx *dev) ...@@ -75,6 +75,30 @@ static int cx231xx_isoc_audio_deinit(struct cx231xx *dev)
return 0; return 0;
} }
static int cx231xx_bulk_audio_deinit(struct cx231xx *dev)
{
int i;
dprintk("Stopping bulk\n");
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
if (dev->adev.urb[i]) {
if (!irqs_disabled())
usb_kill_urb(dev->adev.urb[i]);
else
usb_unlink_urb(dev->adev.urb[i]);
usb_free_urb(dev->adev.urb[i]);
dev->adev.urb[i] = NULL;
kfree(dev->adev.transfer_buffer[i]);
dev->adev.transfer_buffer[i] = NULL;
}
}
return 0;
}
static void cx231xx_audio_isocirq(struct urb *urb) static void cx231xx_audio_isocirq(struct urb *urb)
{ {
struct cx231xx *dev = urb->context; struct cx231xx *dev = urb->context;
...@@ -158,14 +182,92 @@ static void cx231xx_audio_isocirq(struct urb *urb) ...@@ -158,14 +182,92 @@ static void cx231xx_audio_isocirq(struct urb *urb)
return; return;
} }
static void cx231xx_audio_bulkirq(struct urb *urb)
{
struct cx231xx *dev = urb->context;
unsigned int oldptr;
int period_elapsed = 0;
int status;
unsigned char *cp;
unsigned int stride;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
switch (urb->status) {
case 0: /* success */
case -ETIMEDOUT: /* NAK */
break;
case -ECONNRESET: /* kill */
case -ENOENT:
case -ESHUTDOWN:
return;
default: /* error */
dprintk("urb completition error %d.\n", urb->status);
break;
}
if (dev->adev.capture_pcm_substream) {
substream = dev->adev.capture_pcm_substream;
runtime = substream->runtime;
stride = runtime->frame_bits >> 3;
if (1) {
int length = urb->actual_length /
stride;
cp = (unsigned char *)urb->transfer_buffer;
oldptr = dev->adev.hwptr_done_capture;
if (oldptr + length >= runtime->buffer_size) {
unsigned int cnt;
cnt = runtime->buffer_size - oldptr;
memcpy(runtime->dma_area + oldptr * stride, cp,
cnt * stride);
memcpy(runtime->dma_area, cp + cnt * stride,
length * stride - cnt * stride);
} else {
memcpy(runtime->dma_area + oldptr * stride, cp,
length * stride);
}
snd_pcm_stream_lock(substream);
dev->adev.hwptr_done_capture += length;
if (dev->adev.hwptr_done_capture >=
runtime->buffer_size)
dev->adev.hwptr_done_capture -=
runtime->buffer_size;
dev->adev.capture_transfer_done += length;
if (dev->adev.capture_transfer_done >=
runtime->period_size) {
dev->adev.capture_transfer_done -=
runtime->period_size;
period_elapsed = 1;
}
snd_pcm_stream_unlock(substream);
}
if (period_elapsed)
snd_pcm_period_elapsed(substream);
}
urb->status = 0;
status = usb_submit_urb(urb, GFP_ATOMIC);
if (status < 0) {
cx231xx_errdev("resubmit of audio urb failed (error=%i)\n",
status);
}
return;
}
static int cx231xx_init_audio_isoc(struct cx231xx *dev) static int cx231xx_init_audio_isoc(struct cx231xx *dev)
{ {
int i, errCode; int i, errCode;
int sb_size; int sb_size;
cx231xx_info("%s: Starting AUDIO transfers\n", __func__); cx231xx_info("%s: Starting ISO AUDIO transfers\n", __func__);
sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size; sb_size = CX231XX_ISO_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) { for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
struct urb *urb; struct urb *urb;
...@@ -176,7 +278,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) ...@@ -176,7 +278,7 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
return -ENOMEM; return -ENOMEM;
memset(dev->adev.transfer_buffer[i], 0x80, sb_size); memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC); urb = usb_alloc_urb(CX231XX_ISO_NUM_AUDIO_PACKETS, GFP_ATOMIC);
if (!urb) { if (!urb) {
cx231xx_errdev("usb_alloc_urb failed!\n"); cx231xx_errdev("usb_alloc_urb failed!\n");
for (j = 0; j < i; j++) { for (j = 0; j < i; j++) {
...@@ -194,10 +296,10 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) ...@@ -194,10 +296,10 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
urb->transfer_buffer = dev->adev.transfer_buffer[i]; urb->transfer_buffer = dev->adev.transfer_buffer[i];
urb->interval = 1; urb->interval = 1;
urb->complete = cx231xx_audio_isocirq; urb->complete = cx231xx_audio_isocirq;
urb->number_of_packets = CX231XX_NUM_AUDIO_PACKETS; urb->number_of_packets = CX231XX_ISO_NUM_AUDIO_PACKETS;
urb->transfer_buffer_length = sb_size; urb->transfer_buffer_length = sb_size;
for (j = k = 0; j < CX231XX_NUM_AUDIO_PACKETS; for (j = k = 0; j < CX231XX_ISO_NUM_AUDIO_PACKETS;
j++, k += dev->adev.max_pkt_size) { j++, k += dev->adev.max_pkt_size) {
urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].offset = k;
urb->iso_frame_desc[j].length = dev->adev.max_pkt_size; urb->iso_frame_desc[j].length = dev->adev.max_pkt_size;
...@@ -216,6 +318,59 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev) ...@@ -216,6 +318,59 @@ static int cx231xx_init_audio_isoc(struct cx231xx *dev)
return errCode; return errCode;
} }
static int cx231xx_init_audio_bulk(struct cx231xx *dev)
{
int i, errCode;
int sb_size;
cx231xx_info("%s: Starting BULK AUDIO transfers\n", __func__);
sb_size = CX231XX_NUM_AUDIO_PACKETS * dev->adev.max_pkt_size;
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
struct urb *urb;
int j;
dev->adev.transfer_buffer[i] = kmalloc(sb_size, GFP_ATOMIC);
if (!dev->adev.transfer_buffer[i])
return -ENOMEM;
memset(dev->adev.transfer_buffer[i], 0x80, sb_size);
urb = usb_alloc_urb(CX231XX_NUM_AUDIO_PACKETS, GFP_ATOMIC);
if (!urb) {
cx231xx_errdev("usb_alloc_urb failed!\n");
for (j = 0; j < i; j++) {
usb_free_urb(dev->adev.urb[j]);
kfree(dev->adev.transfer_buffer[j]);
}
return -ENOMEM;
}
urb->dev = dev->udev;
urb->context = dev;
urb->pipe = usb_rcvbulkpipe(dev->udev,
dev->adev.end_point_addr);
urb->transfer_flags = 0;
urb->transfer_buffer = dev->adev.transfer_buffer[i];
urb->complete = cx231xx_audio_bulkirq;
urb->transfer_buffer_length = sb_size;
dev->adev.urb[i] = urb;
}
for (i = 0; i < CX231XX_AUDIO_BUFS; i++) {
errCode = usb_submit_urb(dev->adev.urb[i], GFP_ATOMIC);
if (errCode < 0) {
cx231xx_bulk_audio_deinit(dev);
return errCode;
}
}
return errCode;
}
static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg)
{ {
dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ? dprintk("%s transfer\n", (dev->adev.capture_stream == STREAM_ON) ?
...@@ -225,7 +380,12 @@ static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg) ...@@ -225,7 +380,12 @@ static int cx231xx_cmd(struct cx231xx *dev, int cmd, int arg)
case CX231XX_CAPTURE_STREAM_EN: case CX231XX_CAPTURE_STREAM_EN:
if (dev->adev.capture_stream == STREAM_OFF && arg == 1) { if (dev->adev.capture_stream == STREAM_OFF && arg == 1) {
dev->adev.capture_stream = STREAM_ON; dev->adev.capture_stream = STREAM_ON;
cx231xx_init_audio_isoc(dev); if (is_fw_load(dev) == 0)
cx25840_call(dev, core, load_fw);
if (dev->USE_ISO)
cx231xx_init_audio_isoc(dev);
else
cx231xx_init_audio_bulk(dev);
} else if (dev->adev.capture_stream == STREAM_ON && arg == 0) { } else if (dev->adev.capture_stream == STREAM_ON && arg == 0) {
dev->adev.capture_stream = STREAM_OFF; dev->adev.capture_stream = STREAM_OFF;
cx231xx_isoc_audio_deinit(dev); cx231xx_isoc_audio_deinit(dev);
...@@ -300,7 +460,10 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream) ...@@ -300,7 +460,10 @@ static int snd_cx231xx_capture_open(struct snd_pcm_substream *substream)
/* set alternate setting for audio interface */ /* set alternate setting for audio interface */
/* 1 - 48000 samples per sec */ /* 1 - 48000 samples per sec */
ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); if (dev->USE_ISO)
ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1);
else
ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
if (ret < 0) { if (ret < 0) {
cx231xx_errdev("failed to set alternate setting !\n"); cx231xx_errdev("failed to set alternate setting !\n");
...@@ -330,6 +493,9 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) ...@@ -330,6 +493,9 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
dprintk("closing device\n"); dprintk("closing device\n");
/* inform hardware to start streaming */
ret = cx231xx_capture_start(dev, 0, Audio);
/* set alternate setting for audio interface */ /* set alternate setting for audio interface */
/* 1 - 48000 samples per sec */ /* 1 - 48000 samples per sec */
ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0); ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 0);
...@@ -339,9 +505,6 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream) ...@@ -339,9 +505,6 @@ static int snd_cx231xx_pcm_close(struct snd_pcm_substream *substream)
return ret; return ret;
} }
/* inform hardware to start streaming */
ret = cx231xx_capture_start(dev, 0, Audio);
dev->mute = 1; dev->mute = 1;
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
dev->adev.users--; dev->adev.users--;
...@@ -391,6 +554,11 @@ static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream) ...@@ -391,6 +554,11 @@ static int snd_cx231xx_hw_capture_free(struct snd_pcm_substream *substream)
static int snd_cx231xx_prepare(struct snd_pcm_substream *substream) static int snd_cx231xx_prepare(struct snd_pcm_substream *substream)
{ {
struct cx231xx *dev = snd_pcm_substream_chip(substream);
dev->adev.hwptr_done_capture = 0;
dev->adev.capture_transfer_done = 0;
return 0; return 0;
} }
...@@ -495,6 +663,7 @@ static int cx231xx_audio_init(struct cx231xx *dev) ...@@ -495,6 +663,7 @@ static int cx231xx_audio_init(struct cx231xx *dev)
pcm->info_flags = 0; pcm->info_flags = 0;
pcm->private_data = dev; pcm->private_data = dev;
strcpy(pcm->name, "Conexant cx231xx Capture"); strcpy(pcm->name, "Conexant cx231xx Capture");
snd_card_set_dev(card, &dev->udev->dev);
strcpy(card->driver, "Cx231xx-Audio"); strcpy(card->driver, "Cx231xx-Audio");
strcpy(card->shortname, "Cx231xx Audio"); strcpy(card->shortname, "Cx231xx Audio");
strcpy(card->longname, "Conexant cx231xx Audio"); strcpy(card->longname, "Conexant cx231xx Audio");
......
...@@ -31,13 +31,16 @@ ...@@ -31,13 +31,16 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <media/tuner.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h> #include <media/v4l2-ioctl.h>
#include <media/v4l2-chip-ident.h> #include <media/v4l2-chip-ident.h>
#include "cx231xx.h" #include "cx231xx.h"
#include "cx231xx-dif.h"
#define TUNER_MODE_FM_RADIO 0
/****************************************************************************** /******************************************************************************
-: BLOCK ARRANGEMENT :- -: BLOCK ARRANGEMENT :-
I2S block ----------------------| I2S block ----------------------|
...@@ -50,6 +53,57 @@ ...@@ -50,6 +53,57 @@
[Video] [Video]
*******************************************************************************/ *******************************************************************************/
/******************************************************************************
* VERVE REGISTER *
* *
******************************************************************************/
static int verve_write_byte(struct cx231xx *dev, u8 saddr, u8 data)
{
return cx231xx_write_i2c_data(dev, VERVE_I2C_ADDRESS,
saddr, 1, data, 1);
}
static int verve_read_byte(struct cx231xx *dev, u8 saddr, u8 *data)
{
int status;
u32 temp = 0;
status = cx231xx_read_i2c_data(dev, VERVE_I2C_ADDRESS,
saddr, 1, &temp, 1);
*data = (u8) temp;
return status;
}
void initGPIO(struct cx231xx *dev)
{
u32 _gpio_direction = 0;
u32 value = 0;
u8 val = 0;
_gpio_direction = _gpio_direction & 0xFC0003FF;
_gpio_direction = _gpio_direction | 0x03FDFC00;
cx231xx_send_gpio_cmd(dev, _gpio_direction, (u8 *)&value, 4, 0, 0);
verve_read_byte(dev, 0x07, &val);
cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
verve_write_byte(dev, 0x07, 0xF4);
verve_read_byte(dev, 0x07, &val);
cx231xx_info(" verve_read_byte address0x07=0x%x\n", val);
cx231xx_capture_start(dev, 1, 2);
cx231xx_mode_register(dev, EP_MODE_SET, 0x0500FE00);
cx231xx_mode_register(dev, GBULK_BIT_EN, 0xFFFDFFFF);
}
void uninitGPIO(struct cx231xx *dev)
{
u8 value[4] = { 0, 0, 0, 0 };
cx231xx_capture_start(dev, 0, 2);
verve_write_byte(dev, 0x07, 0x14);
cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
0x68, value, 4);
}
/****************************************************************************** /******************************************************************************
* A F E - B L O C K C O N T R O L functions * * A F E - B L O C K C O N T R O L functions *
...@@ -258,7 +312,7 @@ int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode) ...@@ -258,7 +312,7 @@ int cx231xx_afe_set_mode(struct cx231xx *dev, enum AFE_MODE mode)
switch (mode) { switch (mode) {
case AFE_MODE_LOW_IF: case AFE_MODE_LOW_IF:
/* SetupAFEforLowIF(); */ cx231xx_Setup_AFE_for_LowIF(dev);
break; break;
case AFE_MODE_BASEBAND: case AFE_MODE_BASEBAND:
status = cx231xx_afe_setup_AFE_for_baseband(dev); status = cx231xx_afe_setup_AFE_for_baseband(dev);
...@@ -291,8 +345,13 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev, ...@@ -291,8 +345,13 @@ int cx231xx_afe_update_power_control(struct cx231xx *dev,
int status = 0; int status = 0;
switch (dev->model) { switch (dev->model) {
case CX231XX_BOARD_CNXT_CARRAERA:
case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDE_250:
case CX231XX_BOARD_CNXT_SHELBY:
case CX231XX_BOARD_CNXT_RDU_250: case CX231XX_BOARD_CNXT_RDU_250:
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
if (avmode == POLARIS_AVMODE_ANALOGT_TV) { if (avmode == POLARIS_AVMODE_ANALOGT_TV) {
while (afe_power_status != (FLD_PWRDN_TUNING_BIAS | while (afe_power_status != (FLD_PWRDN_TUNING_BIAS |
FLD_PWRDN_ENABLE_PLL)) { FLD_PWRDN_ENABLE_PLL)) {
...@@ -483,6 +542,17 @@ static int vid_blk_read_word(struct cx231xx *dev, u16 saddr, u32 *data) ...@@ -483,6 +542,17 @@ static int vid_blk_read_word(struct cx231xx *dev, u16 saddr, u32 *data)
return cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS, return cx231xx_read_i2c_data(dev, VID_BLK_I2C_ADDRESS,
saddr, 2, data, 4); saddr, 2, data, 4);
} }
int cx231xx_check_fw(struct cx231xx *dev)
{
u8 temp = 0;
int status = 0;
status = vid_blk_read_byte(dev, DL_CTL_ADDRESS_LOW, &temp);
if (status < 0)
return status;
else
return temp;
}
int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input)
{ {
...@@ -521,9 +591,15 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input) ...@@ -521,9 +591,15 @@ int cx231xx_set_video_input_mux(struct cx231xx *dev, u8 input)
return status; return status;
} }
} }
status = cx231xx_set_decoder_video_input(dev, if (dev->tuner_type == TUNER_NXP_TDA18271)
status = cx231xx_set_decoder_video_input(dev,
CX231XX_VMUX_TELEVISION,
INPUT(input)->vmux);
else
status = cx231xx_set_decoder_video_input(dev,
CX231XX_VMUX_COMPOSITE1, CX231XX_VMUX_COMPOSITE1,
INPUT(input)->vmux); INPUT(input)->vmux);
break; break;
default: default:
cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n", cx231xx_errdev("%s: set_power_mode : Unknown Input %d !\n",
...@@ -681,7 +757,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, ...@@ -681,7 +757,9 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev,
case CX231XX_VMUX_CABLE: case CX231XX_VMUX_CABLE:
default: default:
switch (dev->model) { switch (dev->model) {
case CX231XX_BOARD_CNXT_CARRAERA:
case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDE_250:
case CX231XX_BOARD_CNXT_SHELBY:
case CX231XX_BOARD_CNXT_RDU_250: case CX231XX_BOARD_CNXT_RDU_250:
/* Disable the use of DIF */ /* Disable the use of DIF */
...@@ -816,9 +894,21 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, ...@@ -816,9 +894,21 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev,
/* Set VGA_SEL (for audio control) (bit 7-8) */ /* Set VGA_SEL (for audio control) (bit 7-8) */
status = vid_blk_read_word(dev, AFE_CTRL, &value); status = vid_blk_read_word(dev, AFE_CTRL, &value);
/*Set Func mode:01-DIF 10-baseband 11-YUV*/
value &= (~(FLD_FUNC_MODE));
value |= 0x800000;
value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2; value |= FLD_VGA_SEL_CH3 | FLD_VGA_SEL_CH2;
status = vid_blk_write_word(dev, AFE_CTRL, value); status = vid_blk_write_word(dev, AFE_CTRL, value);
if (dev->tuner_type == TUNER_NXP_TDA18271) {
status = vid_blk_read_word(dev, PIN_CTRL,
&value);
status = vid_blk_write_word(dev, PIN_CTRL,
(value & 0xFFFFFFEF));
}
break; break;
} }
...@@ -840,6 +930,39 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev, ...@@ -840,6 +930,39 @@ int cx231xx_set_decoder_video_input(struct cx231xx *dev,
return status; return status;
} }
void cx231xx_enable656(struct cx231xx *dev)
{
u8 temp = 0;
int status;
/*enable TS1 data[0:7] as output to export 656*/
status = vid_blk_write_byte(dev, TS1_PIN_CTL0, 0xFF);
/*enable TS1 clock as output to export 656*/
status = vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp);
temp = temp|0x04;
status = vid_blk_write_byte(dev, TS1_PIN_CTL1, temp);
}
EXPORT_SYMBOL_GPL(cx231xx_enable656);
void cx231xx_disable656(struct cx231xx *dev)
{
u8 temp = 0;
int status;
status = vid_blk_write_byte(dev, TS1_PIN_CTL0, 0x00);
status = vid_blk_read_byte(dev, TS1_PIN_CTL1, &temp);
temp = temp&0xFB;
status = vid_blk_write_byte(dev, TS1_PIN_CTL1, temp);
}
EXPORT_SYMBOL_GPL(cx231xx_disable656);
/* /*
* Handle any video-mode specific overrides that are different * Handle any video-mode specific overrides that are different
* on a per video standards basis after touching the MODE_CTRL * on a per video standards basis after touching the MODE_CTRL
...@@ -873,7 +996,7 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) ...@@ -873,7 +996,7 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev)
VID_BLK_I2C_ADDRESS, VID_BLK_I2C_ADDRESS,
VERT_TIM_CTRL, VERT_TIM_CTRL,
FLD_V656BLANK_CNT, FLD_V656BLANK_CNT,
0x1E000000); 0x1C000000);
status = cx231xx_read_modify_write_i2c_dword(dev, status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS, VID_BLK_I2C_ADDRESS,
...@@ -881,12 +1004,20 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) ...@@ -881,12 +1004,20 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev)
FLD_HBLANK_CNT, FLD_HBLANK_CNT,
cx231xx_set_field cx231xx_set_field
(FLD_HBLANK_CNT, 0x79)); (FLD_HBLANK_CNT, 0x79));
} else if (dev->norm & V4L2_STD_SECAM) { } else if (dev->norm & V4L2_STD_SECAM) {
cx231xx_info("do_mode_ctrl_overrides SECAM\n"); cx231xx_info("do_mode_ctrl_overrides SECAM\n");
status = cx231xx_read_modify_write_i2c_dword(dev, status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS, VID_BLK_I2C_ADDRESS,
VERT_TIM_CTRL, VERT_TIM_CTRL,
FLD_VBLANK_CNT, 0x24); FLD_VBLANK_CNT, 0x24);
status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS,
VERT_TIM_CTRL,
FLD_V656BLANK_CNT,
cx231xx_set_field
(FLD_V656BLANK_CNT,
0x28));
/* Adjust the active video horizontal start point */ /* Adjust the active video horizontal start point */
status = cx231xx_read_modify_write_i2c_dword(dev, status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS, VID_BLK_I2C_ADDRESS,
...@@ -900,6 +1031,13 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) ...@@ -900,6 +1031,13 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev)
VID_BLK_I2C_ADDRESS, VID_BLK_I2C_ADDRESS,
VERT_TIM_CTRL, VERT_TIM_CTRL,
FLD_VBLANK_CNT, 0x24); FLD_VBLANK_CNT, 0x24);
status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS,
VERT_TIM_CTRL,
FLD_V656BLANK_CNT,
cx231xx_set_field
(FLD_V656BLANK_CNT,
0x28));
/* Adjust the active video horizontal start point */ /* Adjust the active video horizontal start point */
status = cx231xx_read_modify_write_i2c_dword(dev, status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS, VID_BLK_I2C_ADDRESS,
...@@ -907,11 +1045,28 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev) ...@@ -907,11 +1045,28 @@ int cx231xx_do_mode_ctrl_overrides(struct cx231xx *dev)
FLD_HBLANK_CNT, FLD_HBLANK_CNT,
cx231xx_set_field cx231xx_set_field
(FLD_HBLANK_CNT, 0x85)); (FLD_HBLANK_CNT, 0x85));
} }
return status; return status;
} }
int cx231xx_unmute_audio(struct cx231xx *dev)
{
return vid_blk_write_byte(dev, PATH1_VOL_CTL, 0x24);
}
EXPORT_SYMBOL_GPL(cx231xx_unmute_audio);
int stopAudioFirmware(struct cx231xx *dev)
{
return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x03);
}
int restartAudioFirmware(struct cx231xx *dev)
{
return vid_blk_write_byte(dev, DL_CTL_CONTROL, 0x13);
}
int cx231xx_set_audio_input(struct cx231xx *dev, u8 input) int cx231xx_set_audio_input(struct cx231xx *dev, u8 input)
{ {
int status = 0; int status = 0;
...@@ -970,6 +1125,7 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, ...@@ -970,6 +1125,7 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
/* unmute all, AC97 in, independence mode /* unmute all, AC97 in, independence mode
adr 08d0, data 0x00063073 */ adr 08d0, data 0x00063073 */
status = vid_blk_write_word(dev, DL_CTL, 0x3000001);
status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063073); status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063073);
/* set AVC maximum threshold, adr 08d4, dat ffff0024 */ /* set AVC maximum threshold, adr 08d4, dat ffff0024 */
...@@ -985,7 +1141,7 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, ...@@ -985,7 +1141,7 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
case AUDIO_INPUT_TUNER_TV: case AUDIO_INPUT_TUNER_TV:
default: default:
status = stopAudioFirmware(dev);
/* Setup SRC sources and clocks */ /* Setup SRC sources and clocks */
status = vid_blk_write_word(dev, BAND_OUT_SEL, status = vid_blk_write_word(dev, BAND_OUT_SEL,
cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00) | cx231xx_set_field(FLD_SRC6_IN_SEL, 0x00) |
...@@ -1013,17 +1169,30 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev, ...@@ -1013,17 +1169,30 @@ int cx231xx_set_audio_decoder_input(struct cx231xx *dev,
status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F063870); status = vid_blk_write_word(dev, PATH1_CTL1, 0x1F063870);
/* setAudioStandard(_audio_standard); */ /* setAudioStandard(_audio_standard); */
status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063870); status = vid_blk_write_word(dev, PATH1_CTL1, 0x00063870);
status = restartAudioFirmware(dev);
switch (dev->model) { switch (dev->model) {
case CX231XX_BOARD_CNXT_CARRAERA:
case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDE_250:
case CX231XX_BOARD_CNXT_SHELBY:
case CX231XX_BOARD_CNXT_RDU_250: case CX231XX_BOARD_CNXT_RDU_250:
case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
status = cx231xx_read_modify_write_i2c_dword(dev, status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS, VID_BLK_I2C_ADDRESS,
CHIP_CTRL, CHIP_CTRL,
FLD_SIF_EN, FLD_SIF_EN,
cx231xx_set_field(FLD_SIF_EN, 1)); cx231xx_set_field(FLD_SIF_EN, 1));
break; break;
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
status = cx231xx_read_modify_write_i2c_dword(dev,
VID_BLK_I2C_ADDRESS,
CHIP_CTRL,
FLD_SIF_EN,
cx231xx_set_field(FLD_SIF_EN, 0));
break;
default: default:
break; break;
} }
...@@ -1058,7 +1227,9 @@ int cx231xx_resolution_set(struct cx231xx *dev) ...@@ -1058,7 +1227,9 @@ int cx231xx_resolution_set(struct cx231xx *dev)
return status; return status;
/* set vertical scale */ /* set vertical scale */
return vid_blk_write_word(dev, VSCALE_CTRL, dev->vscale); status = vid_blk_write_word(dev, VSCALE_CTRL, dev->vscale);
return status;
} }
/****************************************************************************** /******************************************************************************
...@@ -1122,6 +1293,346 @@ int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex) ...@@ -1122,6 +1293,346 @@ int cx231xx_enable_i2c_for_tuner(struct cx231xx *dev, u8 I2CIndex)
return status; return status;
}
EXPORT_SYMBOL_GPL(cx231xx_enable_i2c_for_tuner);
void update_HH_register_after_set_DIF(struct cx231xx *dev)
{
/*
u8 status = 0;
u32 value = 0;
vid_blk_write_word(dev, PIN_CTRL, 0xA0FFF82F);
vid_blk_write_word(dev, DIF_MISC_CTRL, 0x0A203F11);
vid_blk_write_word(dev, DIF_SRC_PHASE_INC, 0x1BEFBF06);
status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
*/
}
void cx231xx_dump_HH_reg(struct cx231xx *dev)
{
u8 status = 0;
u32 value = 0;
u16 i = 0;
value = 0x45005390;
status = vid_blk_write_word(dev, 0x104, value);
for (i = 0x100; i < 0x140; i++) {
status = vid_blk_read_word(dev, i, &value);
cx231xx_info("reg0x%x=0x%x\n", i, value);
i = i+3;
}
for (i = 0x300; i < 0x400; i++) {
status = vid_blk_read_word(dev, i, &value);
cx231xx_info("reg0x%x=0x%x\n", i, value);
i = i+3;
}
for (i = 0x400; i < 0x440; i++) {
status = vid_blk_read_word(dev, i, &value);
cx231xx_info("reg0x%x=0x%x\n", i, value);
i = i+3;
}
status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
vid_blk_write_word(dev, AFE_CTRL_C2HH_SRC_CTRL, 0x4485D390);
status = vid_blk_read_word(dev, AFE_CTRL_C2HH_SRC_CTRL, &value);
cx231xx_info("AFE_CTRL_C2HH_SRC_CTRL=0x%x\n", value);
}
void cx231xx_dump_SC_reg(struct cx231xx *dev)
{
u8 value[4] = { 0, 0, 0, 0 };
int status = 0;
cx231xx_info("cx231xx_dump_SC_reg %s!\n", __TIME__);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, BOARD_CFG_STAT,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", BOARD_CFG_STAT, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS_MODE_REG,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS_MODE_REG, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_CFG_REG,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_CFG_REG, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS1_LENGTH_REG,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS1_LENGTH_REG, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_CFG_REG,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_CFG_REG, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, TS2_LENGTH_REG,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", TS2_LENGTH_REG, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, EP_MODE_SET,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", EP_MODE_SET, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN1,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN1, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN2,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN2, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_PTN3,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_PTN3, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK0,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK0, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK1,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK1, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_PWR_MASK2,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_PWR_MASK2, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_GAIN,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_GAIN, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_CAR_REG,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_CAR_REG, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG1,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG1, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, CIR_OT_CFG2,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", CIR_OT_CFG2, value[0],
value[1], value[2], value[3]);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
value[1], value[2], value[3]);
}
void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev)
{
u8 status = 0;
u8 value = 0;
status = afe_read_byte(dev, ADC_STATUS2_CH3, &value);
value = (value & 0xFE)|0x01;
status = afe_write_byte(dev, ADC_STATUS2_CH3, value);
status = afe_read_byte(dev, ADC_STATUS2_CH3, &value);
value = (value & 0xFE)|0x00;
status = afe_write_byte(dev, ADC_STATUS2_CH3, value);
/*
config colibri to lo-if mode
FIXME: ntf_mode = 2'b00 by default. But set 0x1 would reduce
the diff IF input by half,
for low-if agc defect
*/
status = afe_read_byte(dev, ADC_NTF_PRECLMP_EN_CH3, &value);
value = (value & 0xFC)|0x00;
status = afe_write_byte(dev, ADC_NTF_PRECLMP_EN_CH3, value);
status = afe_read_byte(dev, ADC_INPUT_CH3, &value);
value = (value & 0xF9)|0x02;
status = afe_write_byte(dev, ADC_INPUT_CH3, value);
status = afe_read_byte(dev, ADC_FB_FRCRST_CH3, &value);
value = (value & 0xFB)|0x04;
status = afe_write_byte(dev, ADC_FB_FRCRST_CH3, value);
status = afe_read_byte(dev, ADC_DCSERVO_DEM_CH3, &value);
value = (value & 0xFC)|0x03;
status = afe_write_byte(dev, ADC_DCSERVO_DEM_CH3, value);
status = afe_read_byte(dev, ADC_CTRL_DAC1_CH3, &value);
value = (value & 0xFB)|0x04;
status = afe_write_byte(dev, ADC_CTRL_DAC1_CH3, value);
status = afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value);
value = (value & 0xF8)|0x06;
status = afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value);
status = afe_read_byte(dev, ADC_CTRL_DAC23_CH3, &value);
value = (value & 0x8F)|0x40;
status = afe_write_byte(dev, ADC_CTRL_DAC23_CH3, value);
status = afe_read_byte(dev, ADC_PWRDN_CLAMP_CH3, &value);
value = (value & 0xDF)|0x20;
status = afe_write_byte(dev, ADC_PWRDN_CLAMP_CH3, value);
}
void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq,
u8 spectral_invert, u32 mode)
{
u32 colibri_carrier_offset = 0;
u8 status = 0;
u32 func_mode = 0;
u32 standard = 0;
u8 value[4] = { 0, 0, 0, 0 };
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:
case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
func_mode = 0x03;
break;
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
func_mode = 0x01;
break;
default:
func_mode = 0x01;
}
cx231xx_info("Enter cx231xx_set_Colibri_For_LowIF()\n");
value[0] = (u8) 0x6F;
value[1] = (u8) 0x6F;
value[2] = (u8) 0x6F;
value[3] = (u8) 0x6F;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
PWR_CTL_EN, value, 4);
if (1) {
/*Set colibri for low IF*/
status = cx231xx_afe_set_mode(dev, AFE_MODE_LOW_IF);
/* Set C2HH for low IF operation.*/
standard = dev->norm;
status = cx231xx_dif_configure_C2HH_for_low_IF(dev, dev->active_mode,
func_mode, standard);
/* Get colibri offsets.*/
colibri_carrier_offset = cx231xx_Get_Colibri_CarrierOffset(mode,
standard);
cx231xx_info("colibri_carrier_offset=%d, standard=0x%x\n",
colibri_carrier_offset, standard);
/* Set the band Pass filter for DIF*/
cx231xx_set_DIF_bandpass(dev, (if_freq+colibri_carrier_offset)
, spectral_invert, mode);
}
}
u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd)
{
u32 colibri_carrier_offset = 0;
if (mode == TUNER_MODE_FM_RADIO) {
colibri_carrier_offset = 1100000;
} else if (standerd & (V4L2_STD_NTSC | V4L2_STD_NTSC_M_JP)) {
colibri_carrier_offset = 4832000; /*4.83MHz */
} else if (standerd & (V4L2_STD_PAL_B | V4L2_STD_PAL_G)) {
colibri_carrier_offset = 2700000; /*2.70MHz */
} else if (standerd & (V4L2_STD_PAL_D | V4L2_STD_PAL_I
| V4L2_STD_SECAM)) {
colibri_carrier_offset = 2100000; /*2.10MHz */
}
return colibri_carrier_offset;
}
void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq,
u8 spectral_invert, u32 mode)
{
unsigned long pll_freq_word;
int status = 0;
u32 dif_misc_ctrl_value = 0;
u64 pll_freq_u64 = 0;
u32 i = 0;
cx231xx_info("if_freq=%d;spectral_invert=0x%x;mode=0x%x\n",
if_freq, spectral_invert, mode);
if (mode == TUNER_MODE_FM_RADIO) {
pll_freq_word = 0x905A1CAC;
status = vid_blk_write_word(dev, DIF_PLL_FREQ_WORD, pll_freq_word);
} else /*KSPROPERTY_TUNER_MODE_TV*/{
/* Calculate the PLL frequency word based on the adjusted if_freq*/
pll_freq_word = if_freq;
pll_freq_u64 = (u64)pll_freq_word << 28L;
do_div(pll_freq_u64, 50000000);
pll_freq_word = (u32)pll_freq_u64;
/*pll_freq_word = 0x3463497;*/
status = vid_blk_write_word(dev, DIF_PLL_FREQ_WORD, pll_freq_word);
if (spectral_invert) {
if_freq -= 400000;
/* Enable Spectral Invert*/
status = vid_blk_read_word(dev, DIF_MISC_CTRL,
&dif_misc_ctrl_value);
dif_misc_ctrl_value = dif_misc_ctrl_value | 0x00200000;
status = vid_blk_write_word(dev, DIF_MISC_CTRL,
dif_misc_ctrl_value);
} else {
if_freq += 400000;
/* Disable Spectral Invert*/
status = vid_blk_read_word(dev, DIF_MISC_CTRL,
&dif_misc_ctrl_value);
dif_misc_ctrl_value = dif_misc_ctrl_value & 0xFFDFFFFF;
status = vid_blk_write_word(dev, DIF_MISC_CTRL,
dif_misc_ctrl_value);
}
if_freq = (if_freq/100000)*100000;
if (if_freq < 3000000)
if_freq = 3000000;
if (if_freq > 16000000)
if_freq = 16000000;
}
cx231xx_info("Enter IF=%d\n",
sizeof(Dif_set_array)/sizeof(struct dif_settings));
for (i = 0; i < sizeof(Dif_set_array)/sizeof(struct dif_settings); i++) {
if (Dif_set_array[i].if_freq == if_freq) {
status = vid_blk_write_word(dev,
Dif_set_array[i].register_address, Dif_set_array[i].value);
}
}
} }
/****************************************************************************** /******************************************************************************
...@@ -1132,6 +1643,7 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, ...@@ -1132,6 +1643,7 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
{ {
int status = 0; int status = 0;
if (mode == V4L2_TUNER_RADIO) { if (mode == V4L2_TUNER_RADIO) {
/* C2HH */ /* C2HH */
/* lo if big signal */ /* lo if big signal */
...@@ -1174,6 +1686,7 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, ...@@ -1174,6 +1686,7 @@ int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
VID_BLK_I2C_ADDRESS, 32, VID_BLK_I2C_ADDRESS, 32,
AUD_IO_CTRL, 0, 31, 0x00000003); AUD_IO_CTRL, 0, 31, 0x00000003);
} else if ((standard == V4L2_STD_PAL_I) | } else if ((standard == V4L2_STD_PAL_I) |
(standard & V4L2_STD_PAL_D) |
(standard & V4L2_STD_SECAM)) { (standard & V4L2_STD_SECAM)) {
/* C2HH setup */ /* C2HH setup */
/* lo if big signal */ /* lo if big signal */
...@@ -1232,10 +1745,17 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard) ...@@ -1232,10 +1745,17 @@ int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard)
dev->norm = standard; dev->norm = standard;
switch (dev->model) { switch (dev->model) {
case CX231XX_BOARD_CNXT_CARRAERA:
case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDE_250:
case CX231XX_BOARD_CNXT_SHELBY:
case CX231XX_BOARD_CNXT_RDU_250: case CX231XX_BOARD_CNXT_RDU_250:
case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
func_mode = 0x03; func_mode = 0x03;
break; break;
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
func_mode = 0x01;
break;
default: default:
func_mode = 0x01; func_mode = 0x01;
} }
...@@ -1617,17 +2137,27 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev) ...@@ -1617,17 +2137,27 @@ int cx231xx_tuner_post_channel_change(struct cx231xx *dev)
{ {
int status = 0; int status = 0;
u32 dwval; u32 dwval;
cx231xx_info("cx231xx_tuner_post_channel_change dev->tuner_type =0%d\n",
dev->tuner_type);
/* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for /* Set the RF and IF k_agc values to 4 for PAL/NTSC and 8 for
* SECAM L/B/D standards */ * SECAM L/B/D standards */
status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval); status = vid_blk_read_word(dev, DIF_AGC_IF_REF, &dwval);
dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF); dwval &= ~(FLD_DIF_K_AGC_RF | FLD_DIF_K_AGC_IF);
if (dev->norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B | if (dev->norm & (V4L2_STD_SECAM_L | V4L2_STD_SECAM_B |
V4L2_STD_SECAM_D)) V4L2_STD_SECAM_D)) {
dwval |= 0x88000000; if (dev->tuner_type == TUNER_NXP_TDA18271) {
else dwval &= ~FLD_DIF_IF_REF;
dwval |= 0x44000000; dwval |= 0x88000300;
} else
dwval |= 0x88000000;
} else {
if (dev->tuner_type == TUNER_NXP_TDA18271) {
dwval &= ~FLD_DIF_IF_REF;
dwval |= 0xCC000300;
} else
dwval |= 0x44000000;
}
status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval); status = vid_blk_write_word(dev, DIF_AGC_IF_REF, dwval);
...@@ -1714,8 +2244,6 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) ...@@ -1714,8 +2244,6 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
return 0; return 0;
} }
cx231xx_info(" setPowerMode::mode = %d\n", mode);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value,
4); 4);
if (status < 0) if (status < 0)
...@@ -1761,7 +2289,7 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) ...@@ -1761,7 +2289,7 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
case POLARIS_AVMODE_ANALOGT_TV: case POLARIS_AVMODE_ANALOGT_TV:
tmp &= (~PWR_DEMOD_EN); tmp |= PWR_DEMOD_EN;
tmp |= (I2C_DEMOD_EN); tmp |= (I2C_DEMOD_EN);
value[0] = (u8) tmp; value[0] = (u8) tmp;
value[1] = (u8) (tmp >> 8); value[1] = (u8) (tmp >> 8);
...@@ -1814,14 +2342,27 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) ...@@ -1814,14 +2342,27 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
msleep(PWR_SLEEP_INTERVAL); msleep(PWR_SLEEP_INTERVAL);
} }
if ((dev->model == CX231XX_BOARD_CNXT_RDE_250) || if ((dev->model == CX231XX_BOARD_CNXT_CARRAERA) ||
(dev->model == CX231XX_BOARD_CNXT_RDE_250) ||
(dev->model == CX231XX_BOARD_CNXT_SHELBY) ||
(dev->model == CX231XX_BOARD_CNXT_RDU_250)) { (dev->model == CX231XX_BOARD_CNXT_RDU_250)) {
/* tuner path to channel 1 from port 3 */ /* tuner path to channel 1 from port 3 */
cx231xx_enable_i2c_for_tuner(dev, I2C_3); cx231xx_enable_i2c_for_tuner(dev, I2C_3);
/* reset the Tuner */
cx231xx_gpio_set(dev, dev->board.tuner_gpio);
if (dev->cx231xx_reset_analog_tuner)
dev->cx231xx_reset_analog_tuner(dev);
} else if ((dev->model == CX231XX_BOARD_CNXT_RDE_253S) ||
(dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) ||
(dev->model == CX231XX_BOARD_CNXT_RDU_253S)) {
/* tuner path to channel 1 from port 3 */
cx231xx_enable_i2c_for_tuner(dev, I2C_3);
if (dev->cx231xx_reset_analog_tuner) if (dev->cx231xx_reset_analog_tuner)
dev->cx231xx_reset_analog_tuner(dev); dev->cx231xx_reset_analog_tuner(dev);
} }
break; break;
case POLARIS_AVMODE_DIGITAL: case POLARIS_AVMODE_DIGITAL:
...@@ -1876,14 +2417,27 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) ...@@ -1876,14 +2417,27 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
msleep(PWR_SLEEP_INTERVAL); msleep(PWR_SLEEP_INTERVAL);
} }
if ((dev->model == CX231XX_BOARD_CNXT_RDE_250) || if ((dev->model == CX231XX_BOARD_CNXT_CARRAERA) ||
(dev->model == CX231XX_BOARD_CNXT_RDE_250) ||
(dev->model == CX231XX_BOARD_CNXT_SHELBY) ||
(dev->model == CX231XX_BOARD_CNXT_RDU_250)) { (dev->model == CX231XX_BOARD_CNXT_RDU_250)) {
/* tuner path to channel 1 from port 3 */ /* tuner path to channel 1 from port 3 */
cx231xx_enable_i2c_for_tuner(dev, I2C_3); cx231xx_enable_i2c_for_tuner(dev, I2C_3);
/* reset the Tuner */
cx231xx_gpio_set(dev, dev->board.tuner_gpio);
if (dev->cx231xx_reset_analog_tuner)
dev->cx231xx_reset_analog_tuner(dev);
} else if ((dev->model == CX231XX_BOARD_CNXT_RDE_253S) ||
(dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) ||
(dev->model == CX231XX_BOARD_CNXT_RDU_253S)) {
/* tuner path to channel 1 from port 3 */
cx231xx_enable_i2c_for_tuner(dev, I2C_3);
if (dev->cx231xx_reset_analog_tuner) if (dev->cx231xx_reset_analog_tuner)
dev->cx231xx_reset_analog_tuner(dev); dev->cx231xx_reset_analog_tuner(dev);
} }
break; break;
default: default:
...@@ -1913,9 +2467,6 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode) ...@@ -1913,9 +2467,6 @@ int cx231xx_set_power_mode(struct cx231xx *dev, enum AV_MODE mode)
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value, status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN, value,
4); 4);
cx231xx_info(" The data of PWR_CTL_EN register 0x74"
"=0x%0x,0x%0x,0x%0x,0x%0x\n",
value[0], value[1], value[2], value[3]);
return status; return status;
} }
...@@ -2000,6 +2551,8 @@ int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask) ...@@ -2000,6 +2551,8 @@ int cx231xx_stop_stream(struct cx231xx *dev, u32 ep_mask)
int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
{ {
int status = 0; int status = 0;
u32 value = 0;
u8 val[4] = { 0, 0, 0, 0 };
if (dev->udev->speed == USB_SPEED_HIGH) { if (dev->udev->speed == USB_SPEED_HIGH) {
switch (media_type) { switch (media_type) {
...@@ -2026,10 +2579,36 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type) ...@@ -2026,10 +2579,36 @@ int cx231xx_initialize_stream_xfer(struct cx231xx *dev, u32 media_type)
break; break;
case 4: /* ts1 */ case 4: /* ts1 */
cx231xx_info("%s: set ts1 registers\n", __func__); cx231xx_info("%s: set ts1 registers", __func__);
if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
cx231xx_info(" MPEG\n");
value &= 0xFFFFFFFC;
value |= 0x3;
status = cx231xx_mode_register(dev, TS_MODE_REG, value);
val[0] = 0x04;
val[1] = 0xA3;
val[2] = 0x3B;
val[3] = 0x00;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
TS1_CFG_REG, val, 4);
val[0] = 0x00;
val[1] = 0x08;
val[2] = 0x00;
val[3] = 0x08;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
TS1_LENGTH_REG, val, 4);
} else {
cx231xx_info(" BDA\n");
status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101); status = cx231xx_mode_register(dev, TS_MODE_REG, 0x101);
status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400); status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x010);
}
break; break;
case 6: /* ts1 parallel mode */ case 6: /* ts1 parallel mode */
cx231xx_info("%s: set ts1 parrallel mode registers\n", cx231xx_info("%s: set ts1 parrallel mode registers\n",
__func__); __func__);
...@@ -2128,7 +2707,7 @@ EXPORT_SYMBOL_GPL(cx231xx_capture_start); ...@@ -2128,7 +2707,7 @@ EXPORT_SYMBOL_GPL(cx231xx_capture_start);
/***************************************************************************** /*****************************************************************************
* G P I O B I T control functions * * G P I O B I T control functions *
******************************************************************************/ ******************************************************************************/
int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val) int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
{ {
int status = 0; int status = 0;
...@@ -2137,7 +2716,7 @@ int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val) ...@@ -2137,7 +2716,7 @@ int cx231xx_set_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val)
return status; return status;
} }
int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val) int cx231xx_get_gpio_bit(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val)
{ {
int status = 0; int status = 0;
...@@ -2344,7 +2923,7 @@ int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data) ...@@ -2344,7 +2923,7 @@ int cx231xx_gpio_i2c_write_byte(struct cx231xx *dev, u8 data)
return status; return status;
} }
int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 * buf) int cx231xx_gpio_i2c_read_byte(struct cx231xx *dev, u8 *buf)
{ {
u8 value = 0; u8 value = 0;
int status = 0; int status = 0;
...@@ -2494,7 +3073,7 @@ int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev) ...@@ -2494,7 +3073,7 @@ int cx231xx_gpio_i2c_write_nak(struct cx231xx *dev)
/* cx231xx_gpio_i2c_read /* cx231xx_gpio_i2c_read
* Function to read data from gpio based I2C interface * Function to read data from gpio based I2C interface
*/ */
int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len) int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len)
{ {
int status = 0; int status = 0;
int i = 0; int i = 0;
...@@ -2538,7 +3117,7 @@ int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len) ...@@ -2538,7 +3117,7 @@ int cx231xx_gpio_i2c_read(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len)
/* cx231xx_gpio_i2c_write /* cx231xx_gpio_i2c_write
* Function to write data to gpio based I2C interface * Function to write data to gpio based I2C interface
*/ */
int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 * buf, u8 len) int cx231xx_gpio_i2c_write(struct cx231xx *dev, u8 dev_addr, u8 *buf, u8 len)
{ {
int status = 0; int status = 0;
int i = 0; int i = 0;
......
...@@ -41,6 +41,10 @@ static int tuner = -1; ...@@ -41,6 +41,10 @@ static int tuner = -1;
module_param(tuner, int, 0444); module_param(tuner, int, 0444);
MODULE_PARM_DESC(tuner, "tuner type"); MODULE_PARM_DESC(tuner, "tuner type");
static int transfer_mode = 1;
module_param(transfer_mode, int, 0444);
MODULE_PARM_DESC(transfer_mode, "transfer mode (1-ISO or 0-BULK)");
static unsigned int disable_ir; static unsigned int disable_ir;
module_param(disable_ir, int, 0444); module_param(disable_ir, int, 0444);
MODULE_PARM_DESC(disable_ir, "disable infrared remote support"); MODULE_PARM_DESC(disable_ir, "disable infrared remote support");
...@@ -86,8 +90,8 @@ struct cx231xx_board cx231xx_boards[] = { ...@@ -86,8 +90,8 @@ struct cx231xx_board cx231xx_boards[] = {
} }
}, },
}, },
[CX231XX_BOARD_CNXT_RDE_250] = { [CX231XX_BOARD_CNXT_CARRAERA] = {
.name = "Conexant Hybrid TV - RDE250", .name = "Conexant Hybrid TV - CARRAERA",
.tuner_type = TUNER_XC5000, .tuner_type = TUNER_XC5000,
.tuner_addr = 0x61, .tuner_addr = 0x61,
.tuner_gpio = RDE250_XCV_TUNER, .tuner_gpio = RDE250_XCV_TUNER,
...@@ -125,9 +129,8 @@ struct cx231xx_board cx231xx_boards[] = { ...@@ -125,9 +129,8 @@ struct cx231xx_board cx231xx_boards[] = {
} }
}, },
}, },
[CX231XX_BOARD_CNXT_SHELBY] = {
[CX231XX_BOARD_CNXT_RDU_250] = { .name = "Conexant Hybrid TV - SHELBY",
.name = "Conexant Hybrid TV - RDU250",
.tuner_type = TUNER_XC5000, .tuner_type = TUNER_XC5000,
.tuner_addr = 0x61, .tuner_addr = 0x61,
.tuner_gpio = RDE250_XCV_TUNER, .tuner_gpio = RDE250_XCV_TUNER,
...@@ -165,6 +168,183 @@ struct cx231xx_board cx231xx_boards[] = { ...@@ -165,6 +168,183 @@ struct cx231xx_board cx231xx_boards[] = {
} }
}, },
}, },
[CX231XX_BOARD_CNXT_RDE_253S] = {
.name = "Conexant Hybrid TV - RDE253S",
.tuner_type = TUNER_NXP_TDA18271,
.tuner_addr = 0x60,
.tuner_gpio = RDE250_XCV_TUNER,
.tuner_sif_gpio = 0x05,
.tuner_scl_gpio = 0x1a,
.tuner_sda_gpio = 0x1b,
.decoder = CX231XX_AVDECODER,
.demod_xfer_mode = 0,
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x1c,
.gpio_pin_status_mask = 0x4001000,
.tuner_i2c_master = 1,
.demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
.input = {{
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_3_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_SVIDEO,
.vmux = CX231XX_VIN_1_1 |
(CX231XX_VIN_1_2 << 8) |
CX25840_SVIDEO_ON,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = NULL,
}
},
},
[CX231XX_BOARD_CNXT_RDU_253S] = {
.name = "Conexant Hybrid TV - RDU253S",
.tuner_type = TUNER_NXP_TDA18271,
.tuner_addr = 0x60,
.tuner_gpio = RDE250_XCV_TUNER,
.tuner_sif_gpio = 0x05,
.tuner_scl_gpio = 0x1a,
.tuner_sda_gpio = 0x1b,
.decoder = CX231XX_AVDECODER,
.demod_xfer_mode = 0,
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x1c,
.gpio_pin_status_mask = 0x4001000,
.tuner_i2c_master = 1,
.demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
.input = {{
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_3_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_SVIDEO,
.vmux = CX231XX_VIN_1_1 |
(CX231XX_VIN_1_2 << 8) |
CX25840_SVIDEO_ON,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = NULL,
}
},
},
[CX231XX_BOARD_CNXT_VIDEO_GRABBER] = {
.name = "Conexant VIDEO GRABBER",
.tuner_type = TUNER_NXP_TDA18271,
.tuner_addr = 0x60,
.tuner_gpio = RDE250_XCV_TUNER,
.tuner_sif_gpio = 0x05,
.tuner_scl_gpio = 0x1a,
.tuner_sda_gpio = 0x1b,
.decoder = CX231XX_AVDECODER,
.demod_xfer_mode = 0,
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x1c,
.gpio_pin_status_mask = 0x4001000,
.tuner_i2c_master = 1,
.demod_i2c_master = 2,
.has_dvb = 0,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
.input = {{
.type = CX231XX_VMUX_COMPOSITE1,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_SVIDEO,
.vmux = CX231XX_VIN_1_1 |
(CX231XX_VIN_1_2 << 8) |
CX25840_SVIDEO_ON,
.amux = CX231XX_AMUX_LINE_IN,
.gpio = NULL,
}, {
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_3_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = NULL,
}
},
},
[CX231XX_BOARD_CNXT_RDE_250] = {
.name = "Conexant Hybrid TV - rde 250",
.tuner_type = TUNER_XC5000,
.tuner_addr = 0x61,
.tuner_gpio = RDE250_XCV_TUNER,
.tuner_sif_gpio = 0x05,
.tuner_scl_gpio = 0x1a,
.tuner_sda_gpio = 0x1b,
.decoder = CX231XX_AVDECODER,
.demod_xfer_mode = 0,
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
.tuner_i2c_master = 1,
.demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x02,
.norm = V4L2_STD_PAL,
.input = {{
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = NULL,
}
},
},
[CX231XX_BOARD_CNXT_RDU_250] = {
.name = "Conexant Hybrid TV - RDU 250",
.tuner_type = TUNER_XC5000,
.tuner_addr = 0x61,
.tuner_gpio = RDE250_XCV_TUNER,
.tuner_sif_gpio = 0x05,
.tuner_scl_gpio = 0x1a,
.tuner_sda_gpio = 0x1b,
.decoder = CX231XX_AVDECODER,
.demod_xfer_mode = 0,
.ctl_pin_status_mask = 0xFFFFFFC4,
.agc_analog_digital_select_gpio = 0x0c,
.gpio_pin_status_mask = 0x4001000,
.tuner_i2c_master = 1,
.demod_i2c_master = 2,
.has_dvb = 1,
.demod_addr = 0x32,
.norm = V4L2_STD_NTSC,
.input = {{
.type = CX231XX_VMUX_TELEVISION,
.vmux = CX231XX_VIN_2_1,
.amux = CX231XX_AMUX_VIDEO,
.gpio = NULL,
}
},
},
}; };
const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards); const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
...@@ -173,8 +353,18 @@ struct usb_device_id cx231xx_id_table[] = { ...@@ -173,8 +353,18 @@ struct usb_device_id cx231xx_id_table[] = {
{USB_DEVICE(0x0572, 0x5A3C), {USB_DEVICE(0x0572, 0x5A3C),
.driver_info = CX231XX_BOARD_UNKNOWN}, .driver_info = CX231XX_BOARD_UNKNOWN},
{USB_DEVICE(0x0572, 0x58A2), {USB_DEVICE(0x0572, 0x58A2),
.driver_info = CX231XX_BOARD_CNXT_RDE_250}, .driver_info = CX231XX_BOARD_CNXT_CARRAERA},
{USB_DEVICE(0x0572, 0x58A1), {USB_DEVICE(0x0572, 0x58A1),
.driver_info = CX231XX_BOARD_CNXT_SHELBY},
{USB_DEVICE(0x0572, 0x58A4),
.driver_info = CX231XX_BOARD_CNXT_RDE_253S},
{USB_DEVICE(0x0572, 0x58A5),
.driver_info = CX231XX_BOARD_CNXT_RDU_253S},
{USB_DEVICE(0x0572, 0x58A6),
.driver_info = CX231XX_BOARD_CNXT_VIDEO_GRABBER},
{USB_DEVICE(0x0572, 0x589E),
.driver_info = CX231XX_BOARD_CNXT_RDE_250},
{USB_DEVICE(0x0572, 0x58A0),
.driver_info = CX231XX_BOARD_CNXT_RDU_250}, .driver_info = CX231XX_BOARD_CNXT_RDU_250},
{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff), {USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000,0x4fff),
.driver_info = CX231XX_BOARD_UNKNOWN}, .driver_info = CX231XX_BOARD_UNKNOWN},
...@@ -212,6 +402,23 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg) ...@@ -212,6 +402,23 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg)
} }
EXPORT_SYMBOL_GPL(cx231xx_tuner_callback); EXPORT_SYMBOL_GPL(cx231xx_tuner_callback);
void cx231xx_reset_out(struct cx231xx *dev)
{
cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
msleep(200);
cx231xx_set_gpio_value(dev, CX23417_RESET, 0);
msleep(200);
cx231xx_set_gpio_value(dev, CX23417_RESET, 1);
}
void cx231xx_enable_OSC(struct cx231xx *dev)
{
cx231xx_set_gpio_value(dev, CX23417_OSC_EN, 1);
}
void cx231xx_sleep_s5h1432(struct cx231xx *dev)
{
cx231xx_set_gpio_value(dev, SLEEP_S5H1432, 0);
}
static inline void cx231xx_set_model(struct cx231xx *dev) static inline void cx231xx_set_model(struct cx231xx *dev)
{ {
memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board)); memcpy(&dev->board, &cx231xx_boards[dev->model], sizeof(dev->board));
...@@ -235,9 +442,6 @@ void cx231xx_pre_card_setup(struct cx231xx *dev) ...@@ -235,9 +442,6 @@ void cx231xx_pre_card_setup(struct cx231xx *dev)
cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1); cx231xx_set_gpio_direction(dev, dev->board.tuner_sif_gpio, 1);
/* request some modules if any required */ /* request some modules if any required */
/* reset the Tuner */
cx231xx_gpio_set(dev, dev->board.tuner_gpio);
} }
/* set the mode to Analog mode initially */ /* set the mode to Analog mode initially */
...@@ -297,10 +501,20 @@ void cx231xx_register_i2c_ir(struct cx231xx *dev) ...@@ -297,10 +501,20 @@ void cx231xx_register_i2c_ir(struct cx231xx *dev)
/* detect & configure */ /* detect & configure */
switch (dev->model) { switch (dev->model) {
case CX231XX_BOARD_CNXT_CARRAERA:
break;
case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDE_250:
break; break;
case CX231XX_BOARD_CNXT_SHELBY:
break;
case CX231XX_BOARD_CNXT_RDU_250: case CX231XX_BOARD_CNXT_RDU_250:
break; break;
case CX231XX_BOARD_CNXT_RDE_253S:
break;
case CX231XX_BOARD_CNXT_RDU_253S:
break;
case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
break;
default: default:
break; break;
} }
...@@ -326,14 +540,38 @@ void cx231xx_card_setup(struct cx231xx *dev) ...@@ -326,14 +540,38 @@ void cx231xx_card_setup(struct cx231xx *dev)
} }
if (dev->board.tuner_type != TUNER_ABSENT) { switch (dev->model) {
dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, case CX231XX_BOARD_CNXT_CARRAERA:
&dev->i2c_bus[1].i2c_adap, case CX231XX_BOARD_CNXT_RDE_250:
"tuner", "tuner", 0xc2 >> 1, NULL); case CX231XX_BOARD_CNXT_SHELBY:
if (dev->sd_tuner == NULL) case CX231XX_BOARD_CNXT_RDU_250:
cx231xx_info("tuner subdev registration failure\n"); if (dev->board.tuner_type != TUNER_ABSENT) {
dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
cx231xx_config_tuner(dev); &dev->i2c_bus[1].i2c_adap,
"tuner", "tuner", 0xc2 >> 1, NULL);
if (dev->sd_tuner == NULL)
cx231xx_info(
"tuner subdev registration failure\n");
cx231xx_config_tuner(dev);
}
break;
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
case CX231XX_BOARD_CNXT_VIDEO_GRABBER:
if (dev->board.tuner_type != TUNER_ABSENT) {
dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
&dev->i2c_bus[1].i2c_adap,
"tuner", "tuner", 0xc0 >> 1, NULL);
if (dev->sd_tuner == NULL)
cx231xx_info(
"tuner subdev registration failure\n");
cx231xx_config_tuner(dev);
}
break;
default:
break;
} }
cx231xx_config_tuner(dev); cx231xx_config_tuner(dev);
...@@ -409,6 +647,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, ...@@ -409,6 +647,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev,
mutex_init(&dev->lock); mutex_init(&dev->lock);
mutex_init(&dev->ctrl_urb_lock); mutex_init(&dev->ctrl_urb_lock);
mutex_init(&dev->gpio_i2c_lock); mutex_init(&dev->gpio_i2c_lock);
mutex_init(&dev->i2c_lock);
spin_lock_init(&dev->video_mode.slock); spin_lock_init(&dev->video_mode.slock);
spin_lock_init(&dev->vbi_mode.slock); spin_lock_init(&dev->vbi_mode.slock);
...@@ -427,6 +666,12 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, ...@@ -427,6 +666,12 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev,
/* Query cx231xx to find what pcb config it is related to */ /* Query cx231xx to find what pcb config it is related to */
initialize_cx231xx(dev); initialize_cx231xx(dev);
/*To workaround error number=-71 on EP0 for VideoGrabber,
need set alt here.*/
if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
cx231xx_set_alt_setting(dev, INDEX_VANC, 1);
}
/* Cx231xx pre card setup */ /* Cx231xx pre card setup */
cx231xx_pre_card_setup(dev); cx231xx_pre_card_setup(dev);
...@@ -442,6 +687,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, ...@@ -442,6 +687,7 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev,
/* register i2c bus */ /* register i2c bus */
errCode = cx231xx_dev_init(dev); errCode = cx231xx_dev_init(dev);
if (errCode < 0) { if (errCode < 0) {
cx231xx_dev_uninit(dev);
cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n", cx231xx_errdev("%s: cx231xx_i2c_register - errCode [%d]!\n",
__func__, errCode); __func__, errCode);
return errCode; return errCode;
...@@ -480,9 +726,17 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev, ...@@ -480,9 +726,17 @@ static int cx231xx_init_dev(struct cx231xx **devhandle, struct usb_device *udev,
INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued); INIT_LIST_HEAD(&dev->vbi_mode.vidq.queued);
/* Reset other chips required if they are tied up with GPIO pins */ /* Reset other chips required if they are tied up with GPIO pins */
cx231xx_add_into_devlist(dev); cx231xx_add_into_devlist(dev);
printk(KERN_INFO "attach 417 %d\n", dev->model);
if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
if (cx231xx_417_register(dev) < 0) {
printk(KERN_ERR
"%s() Failed to register 417 on VID_B\n",
__func__);
}
}
retval = cx231xx_register_analog_devices(dev); retval = cx231xx_register_analog_devices(dev);
if (retval < 0) { if (retval < 0) {
cx231xx_release_resources(dev); cx231xx_release_resources(dev);
...@@ -552,8 +806,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -552,8 +806,8 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_devused |= 1 << nr; cx231xx_devused |= 1 << nr;
if (nr >= CX231XX_MAXBOARDS) { if (nr >= CX231XX_MAXBOARDS) {
cx231xx_err(DRIVER_NAME ": Supports only %i cx231xx boards.\n", cx231xx_err(DRIVER_NAME
CX231XX_MAXBOARDS); ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS);
cx231xx_devused &= ~(1 << nr); cx231xx_devused &= ~(1 << nr);
return -ENOMEM; return -ENOMEM;
} }
...@@ -578,6 +832,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -578,6 +832,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
dev->xc_fw_load_done = 0; dev->xc_fw_load_done = 0;
dev->has_alsa_audio = 1; dev->has_alsa_audio = 1;
dev->power_mode = -1; dev->power_mode = -1;
atomic_set(&dev->devlist_count, 0);
/* 0 - vbi ; 1 -sliced cc mode */ /* 0 - vbi ; 1 -sliced cc mode */
dev->vbi_or_sliced_cc_mode = 0; dev->vbi_or_sliced_cc_mode = 0;
...@@ -591,6 +846,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -591,6 +846,11 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
/* store the current interface */ /* store the current interface */
lif = interface; lif = interface;
/*mode_tv: digital=1 or analog=0*/
dev->mode_tv = 0;
dev->USE_ISO = transfer_mode;
switch (udev->speed) { switch (udev->speed) {
case USB_SPEED_LOW: case USB_SPEED_LOW:
speed = "1.5"; speed = "1.5";
...@@ -645,7 +905,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -645,7 +905,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
* set skip interface, for all interfaces but * set skip interface, for all interfaces but
* interface 1 and the last one * interface 1 and the last one
*/ */
if ((ifnum != 1) && ((dev->interface_count - 1) if ((ifnum != 1) && ((ifnum)
!= dev->max_iad_interface_count)) != dev->max_iad_interface_count))
skip_interface = 1; skip_interface = 1;
...@@ -667,7 +927,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -667,7 +927,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
/* save our data pointer in this interface device */ /* save our data pointer in this interface device */
usb_set_intfdata(lif, dev); usb_set_intfdata(lif, dev);
if ((dev->interface_count - 1) != dev->max_iad_interface_count) if ((ifnum) != dev->max_iad_interface_count)
return 0; return 0;
/* /*
...@@ -680,15 +940,18 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -680,15 +940,18 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_errdev("v4l2_device_register failed\n"); cx231xx_errdev("v4l2_device_register failed\n");
cx231xx_devused &= ~(1 << nr); cx231xx_devused &= ~(1 << nr);
kfree(dev); kfree(dev);
dev = NULL;
return -EIO; return -EIO;
} }
/* allocate device struct */ /* allocate device struct */
retval = cx231xx_init_dev(&dev, udev, nr); retval = cx231xx_init_dev(&dev, udev, nr);
if (retval) { if (retval) {
cx231xx_devused &= ~(1 << dev->devno); cx231xx_devused &= ~(1 << dev->devno);
v4l2_device_unregister(&dev->v4l2_dev); v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev); kfree(dev);
dev = NULL;
usb_set_intfdata(lif, NULL);
return retval; return retval;
} }
...@@ -711,6 +974,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -711,6 +974,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_devused &= ~(1 << nr); cx231xx_devused &= ~(1 << nr);
v4l2_device_unregister(&dev->v4l2_dev); v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev); kfree(dev);
dev = NULL;
return -ENOMEM; return -ENOMEM;
} }
...@@ -744,6 +1008,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -744,6 +1008,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_devused &= ~(1 << nr); cx231xx_devused &= ~(1 << nr);
v4l2_device_unregister(&dev->v4l2_dev); v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev); kfree(dev);
dev = NULL;
return -ENOMEM; return -ENOMEM;
} }
...@@ -778,6 +1043,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -778,6 +1043,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_devused &= ~(1 << nr); cx231xx_devused &= ~(1 << nr);
v4l2_device_unregister(&dev->v4l2_dev); v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev); kfree(dev);
dev = NULL;
return -ENOMEM; return -ENOMEM;
} }
...@@ -813,6 +1079,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -813,6 +1079,7 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
cx231xx_devused &= ~(1 << nr); cx231xx_devused &= ~(1 << nr);
v4l2_device_unregister(&dev->v4l2_dev); v4l2_device_unregister(&dev->v4l2_dev);
kfree(dev); kfree(dev);
dev = NULL;
return -ENOMEM; return -ENOMEM;
} }
...@@ -827,6 +1094,15 @@ static int cx231xx_usb_probe(struct usb_interface *interface, ...@@ -827,6 +1094,15 @@ static int cx231xx_usb_probe(struct usb_interface *interface,
} }
} }
if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
cx231xx_enable_OSC(dev);
cx231xx_reset_out(dev);
cx231xx_set_alt_setting(dev, INDEX_VIDEO, 3);
}
if (dev->model == CX231XX_BOARD_CNXT_RDE_253S)
cx231xx_sleep_s5h1432(dev);
/* load other modules required */ /* load other modules required */
request_modules(dev); request_modules(dev);
...@@ -867,7 +1143,10 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) ...@@ -867,7 +1143,10 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
video_device_node_name(dev->vdev)); video_device_node_name(dev->vdev));
dev->state |= DEV_MISCONFIGURED; dev->state |= DEV_MISCONFIGURED;
cx231xx_uninit_isoc(dev); if (dev->USE_ISO)
cx231xx_uninit_isoc(dev);
else
cx231xx_uninit_bulk(dev);
dev->state |= DEV_DISCONNECTED; dev->state |= DEV_DISCONNECTED;
wake_up_interruptible(&dev->wait_frame); wake_up_interruptible(&dev->wait_frame);
wake_up_interruptible(&dev->wait_stream); wake_up_interruptible(&dev->wait_stream);
...@@ -886,6 +1165,7 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface) ...@@ -886,6 +1165,7 @@ static void cx231xx_usb_disconnect(struct usb_interface *interface)
kfree(dev->sliced_cc_mode.alt_max_pkt_size); kfree(dev->sliced_cc_mode.alt_max_pkt_size);
kfree(dev->ts1_mode.alt_max_pkt_size); kfree(dev->ts1_mode.alt_max_pkt_size);
kfree(dev); kfree(dev);
dev = NULL;
} }
} }
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#define CIR_CAR_REG 0x38 #define CIR_CAR_REG 0x38
#define CIR_OT_CFG1 0x40 #define CIR_OT_CFG1 0x40
#define CIR_OT_CFG2 0x44 #define CIR_OT_CFG2 0x44
#define GBULK_BIT_EN 0x68
#define PWR_CTL_EN 0x74 #define PWR_CTL_EN 0x74
/* Polaris Endpoints capture mask for register EP_MODE_SET */ /* Polaris Endpoints capture mask for register EP_MODE_SET */
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/vmalloc.h> #include <linux/vmalloc.h>
#include <media/v4l2-common.h> #include <media/v4l2-common.h>
#include <media/tuner.h>
#include "cx231xx.h" #include "cx231xx.h"
#include "cx231xx-reg.h" #include "cx231xx-reg.h"
...@@ -64,7 +65,7 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint"); ...@@ -64,7 +65,7 @@ MODULE_PARM_DESC(alt, "alternate setting to use for video endpoint");
* Device control list functions * * Device control list functions *
******************************************************************/ ******************************************************************/
static LIST_HEAD(cx231xx_devlist); LIST_HEAD(cx231xx_devlist);
static DEFINE_MUTEX(cx231xx_devlist_mutex); static DEFINE_MUTEX(cx231xx_devlist_mutex);
/* /*
...@@ -74,15 +75,24 @@ static DEFINE_MUTEX(cx231xx_devlist_mutex); ...@@ -74,15 +75,24 @@ static DEFINE_MUTEX(cx231xx_devlist_mutex);
*/ */
void cx231xx_remove_from_devlist(struct cx231xx *dev) void cx231xx_remove_from_devlist(struct cx231xx *dev)
{ {
mutex_lock(&cx231xx_devlist_mutex); if (dev == NULL)
list_del(&dev->devlist); return;
mutex_unlock(&cx231xx_devlist_mutex); if (dev->udev == NULL)
return;
if (atomic_read(&dev->devlist_count) > 0) {
mutex_lock(&cx231xx_devlist_mutex);
list_del(&dev->devlist);
atomic_dec(&dev->devlist_count);
mutex_unlock(&cx231xx_devlist_mutex);
}
}; };
void cx231xx_add_into_devlist(struct cx231xx *dev) void cx231xx_add_into_devlist(struct cx231xx *dev)
{ {
mutex_lock(&cx231xx_devlist_mutex); mutex_lock(&cx231xx_devlist_mutex);
list_add_tail(&dev->devlist, &cx231xx_devlist); list_add_tail(&dev->devlist, &cx231xx_devlist);
atomic_inc(&dev->devlist_count);
mutex_unlock(&cx231xx_devlist_mutex); mutex_unlock(&cx231xx_devlist_mutex);
}; };
...@@ -114,6 +124,7 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops) ...@@ -114,6 +124,7 @@ void cx231xx_unregister_extension(struct cx231xx_ops *ops)
list_for_each_entry(dev, &cx231xx_devlist, devlist) list_for_each_entry(dev, &cx231xx_devlist, devlist)
ops->fini(dev); ops->fini(dev);
mutex_lock(&cx231xx_extension_devlist_lock); mutex_lock(&cx231xx_extension_devlist_lock);
printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name); printk(KERN_INFO DRIVER_NAME ": %s removed\n", ops->name);
list_del(&ops->next); list_del(&ops->next);
...@@ -285,7 +296,7 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg, ...@@ -285,7 +296,7 @@ int cx231xx_read_ctrl_reg(struct cx231xx *dev, u8 req, u16 reg,
val, reg, dev->urb_buf, len, HZ); val, reg, dev->urb_buf, len, HZ);
if (ret < 0) { if (ret < 0) {
cx231xx_isocdbg(" failed!\n"); cx231xx_isocdbg(" failed!\n");
/* mutex_unlock(&dev->ctrl_urb_lock); */ mutex_unlock(&dev->ctrl_urb_lock);
return ret; return ret;
} }
...@@ -311,6 +322,8 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev, ...@@ -311,6 +322,8 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev,
{ {
int ret; int ret;
int pipe = 0; int pipe = 0;
int unsend_size = 0;
u8 *pdata;
if (dev->state & DEV_DISCONNECTED) if (dev->state & DEV_DISCONNECTED)
return -ENODEV; return -ENODEV;
...@@ -340,13 +353,86 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev, ...@@ -340,13 +353,86 @@ int cx231xx_send_vendor_cmd(struct cx231xx *dev,
cx231xx_isocdbg("\n"); cx231xx_isocdbg("\n");
} }
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest, /*
ven_req-> If the cx23102 read more than 4 bytes with i2c bus,
direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, need chop to 4 byte per request
ven_req->wValue, ven_req->wIndex, ven_req->pBuff, */
ven_req->wLength, HZ); if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) ||
mutex_unlock(&dev->ctrl_urb_lock); (ven_req->bRequest == 0x5) ||
(ven_req->bRequest == 0x6))) {
unsend_size = 0;
pdata = ven_req->pBuff;
unsend_size = ven_req->wLength;
mutex_lock(&dev->ctrl_urb_lock);
/* the first package*/
ven_req->wValue = ven_req->wValue & 0xFFFB;
ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x2;
/*printk(KERN_INFO " !!!!! 0x%x 0x%x 0x%x 0x%x \n",
ven_req->bRequest,
ven_req->direction | USB_TYPE_VENDOR |
USB_RECIP_DEVICE,ven_req->wValue,ven_req->wIndex);*/
ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest,
ven_req->
direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
ven_req->wValue, ven_req->wIndex, pdata,
0x0004, HZ);
unsend_size = unsend_size - 4;
mutex_unlock(&dev->ctrl_urb_lock);
/* the middle package*/
ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x42;
while (unsend_size - 4 > 0) {
pdata = pdata + 4;
/*printk(KERN_INFO " !!!!! 0x%x 0x%x 0x%x 0x%x \n",
ven_req->bRequest,
ven_req->direction | USB_TYPE_VENDOR |
USB_RECIP_DEVICE,
ven_req->wValue,ven_req->wIndex);*/
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, pipe,
ven_req->bRequest,
ven_req->
direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
ven_req->wValue, ven_req->wIndex, pdata,
0x0004, HZ);
mutex_unlock(&dev->ctrl_urb_lock);
unsend_size = unsend_size - 4;
}
/* the last package*/
ven_req->wValue = (ven_req->wValue & 0xFFBD) | 0x40;
pdata = pdata + 4;
/*printk(KERN_INFO " !!!!! 0x%x 0x%x 0x%x 0x%x \n",
ven_req->bRequest,
ven_req->direction | USB_TYPE_VENDOR |
USB_RECIP_DEVICE,ven_req->wValue,ven_req->wIndex);*/
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest,
ven_req->
direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
ven_req->wValue, ven_req->wIndex, pdata,
unsend_size, HZ);
mutex_unlock(&dev->ctrl_urb_lock);
/*printk(KERN_INFO " @@@@@ temp_buffer[0]=0x%x 0x%x 0x%x 0x%x
0x%x 0x%x\n",ven_req->pBuff[0],ven_req->pBuff[1],
ven_req->pBuff[2], ven_req->pBuff[3],ven_req->pBuff[4],
ven_req->pBuff[5]);*/
} else {
mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest,
ven_req->
direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
ven_req->wValue, ven_req->wIndex,
ven_req->pBuff, ven_req->wLength, HZ);
mutex_unlock(&dev->ctrl_urb_lock);
}
return ret; return ret;
} }
...@@ -444,6 +530,11 @@ int cx231xx_set_video_alternate(struct cx231xx *dev) ...@@ -444,6 +530,11 @@ int cx231xx_set_video_alternate(struct cx231xx *dev)
dev->video_mode.alt = 0; dev->video_mode.alt = 0;
} }
if (dev->USE_ISO == 0)
dev->video_mode.alt = 0;
cx231xx_info("dev->video_mode.alt= %d\n", dev->video_mode.alt);
/* Get the correct video interface Index */ /* Get the correct video interface Index */
usb_interface_index = usb_interface_index =
dev->current_pcb_config.hs_config_info[0].interface_info. dev->current_pcb_config.hs_config_info[0].interface_info.
...@@ -452,8 +543,10 @@ int cx231xx_set_video_alternate(struct cx231xx *dev) ...@@ -452,8 +543,10 @@ int cx231xx_set_video_alternate(struct cx231xx *dev)
if (dev->video_mode.alt != prev_alt) { if (dev->video_mode.alt != prev_alt) {
cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n", cx231xx_coredbg("minimum isoc packet size: %u (alt=%d)\n",
min_pkt_size, dev->video_mode.alt); min_pkt_size, dev->video_mode.alt);
dev->video_mode.max_pkt_size =
dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; if (dev->video_mode.alt_max_pkt_size != NULL)
dev->video_mode.max_pkt_size =
dev->video_mode.alt_max_pkt_size[dev->video_mode.alt];
cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n", cx231xx_coredbg("setting alternate %d with wMaxPacketSize=%u\n",
dev->video_mode.alt, dev->video_mode.alt,
dev->video_mode.max_pkt_size); dev->video_mode.max_pkt_size);
...@@ -485,7 +578,7 @@ int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) ...@@ -485,7 +578,7 @@ int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt)
usb_interface_index = usb_interface_index =
dev->current_pcb_config.hs_config_info[0].interface_info. dev->current_pcb_config.hs_config_info[0].interface_info.
ts1_index + 1; ts1_index + 1;
dev->video_mode.alt = alt; dev->ts1_mode.alt = alt;
if (dev->ts1_mode.alt_max_pkt_size != NULL) if (dev->ts1_mode.alt_max_pkt_size != NULL)
max_pkt_size = dev->ts1_mode.max_pkt_size = max_pkt_size = dev->ts1_mode.max_pkt_size =
dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt]; dev->ts1_mode.alt_max_pkt_size[dev->ts1_mode.alt];
...@@ -542,7 +635,10 @@ int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt) ...@@ -542,7 +635,10 @@ int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt)
cx231xx_errdev cx231xx_errdev
("can't change interface %d alt no. to %d: Max. Pkt size = 0\n", ("can't change interface %d alt no. to %d: Max. Pkt size = 0\n",
usb_interface_index, alt); usb_interface_index, alt);
return -1; /*To workaround error number=-71 on EP0 for videograbber,
need add following codes.*/
if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
return -1;
} }
cx231xx_info cx231xx_info
...@@ -584,8 +680,53 @@ int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio) ...@@ -584,8 +680,53 @@ int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio)
return rc; return rc;
} }
int cx231xx_demod_reset(struct cx231xx *dev)
{
u8 status = 0;
u8 value[4] = { 0, 0, 0, 0 };
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
value[1], value[2], value[3]);
cx231xx_info("Enter cx231xx_demod_reset()\n");
value[1] = (u8) 0x3;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
PWR_CTL_EN, value, 4);
msleep(10);
value[1] = (u8) 0x0;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
PWR_CTL_EN, value, 4);
msleep(10);
value[1] = (u8) 0x3;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
PWR_CTL_EN, value, 4);
msleep(10);
status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER, PWR_CTL_EN,
value, 4);
cx231xx_info("reg0x%x=0x%x 0x%x 0x%x 0x%x\n", PWR_CTL_EN, value[0],
value[1], value[2], value[3]);
return status;
}
EXPORT_SYMBOL_GPL(cx231xx_demod_reset);
int is_fw_load(struct cx231xx *dev)
{
return cx231xx_check_fw(dev);
}
EXPORT_SYMBOL_GPL(is_fw_load);
int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
{ {
int errCode = 0;
if (dev->mode == set_mode) if (dev->mode == set_mode)
return 0; return 0;
...@@ -600,15 +741,70 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode) ...@@ -600,15 +741,70 @@ int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode)
dev->mode = set_mode; dev->mode = set_mode;
if (dev->mode == CX231XX_DIGITAL_MODE) if (dev->mode == CX231XX_DIGITAL_MODE)/* Set Digital power mode */ {
;/* Set Digital power mode */ /* set AGC mode to Digital */
else switch (dev->model) {
;/* Set Analog Power mode */ 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:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
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:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
break;
default:
break;
}
}
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(cx231xx_set_mode); EXPORT_SYMBOL_GPL(cx231xx_set_mode);
int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size)
{
int errCode = 0;
int actlen, ret = -ENOMEM;
u32 *buffer;
buffer = kzalloc(4096, GFP_KERNEL);
if (buffer == NULL) {
cx231xx_info("out of mem\n");
return -ENOMEM;
}
memcpy(&buffer[0], firmware, 4096);
ret = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, 5),
buffer, 4096, &actlen, 2000);
if (ret)
cx231xx_info("bulk message failed: %d (%d/%d)", ret,
size, actlen);
else {
errCode = actlen != size ? -1 : 0;
}
kfree(buffer);
return 0;
}
/***************************************************************** /*****************************************************************
* URB Streaming functions * * URB Streaming functions *
******************************************************************/ ******************************************************************/
...@@ -616,7 +812,7 @@ EXPORT_SYMBOL_GPL(cx231xx_set_mode); ...@@ -616,7 +812,7 @@ EXPORT_SYMBOL_GPL(cx231xx_set_mode);
/* /*
* IRQ callback, called by URB callback * IRQ callback, called by URB callback
*/ */
static void cx231xx_irq_callback(struct urb *urb) static void cx231xx_isoc_irq_callback(struct urb *urb)
{ {
struct cx231xx_dmaqueue *dma_q = urb->context; struct cx231xx_dmaqueue *dma_q = urb->context;
struct cx231xx_video_mode *vmode = struct cx231xx_video_mode *vmode =
...@@ -655,12 +851,54 @@ static void cx231xx_irq_callback(struct urb *urb) ...@@ -655,12 +851,54 @@ static void cx231xx_irq_callback(struct urb *urb)
urb->status); urb->status);
} }
} }
/*****************************************************************
* URB Streaming functions *
******************************************************************/
/*
* IRQ callback, called by URB callback
*/
static void cx231xx_bulk_irq_callback(struct urb *urb)
{
struct cx231xx_dmaqueue *dma_q = urb->context;
struct cx231xx_video_mode *vmode =
container_of(dma_q, struct cx231xx_video_mode, vidq);
struct cx231xx *dev = container_of(vmode, struct cx231xx, video_mode);
int rc;
switch (urb->status) {
case 0: /* success */
case -ETIMEDOUT: /* NAK */
break;
case -ECONNRESET: /* kill */
case -ENOENT:
case -ESHUTDOWN:
return;
default: /* error */
cx231xx_isocdbg("urb completition error %d.\n", urb->status);
break;
}
/* Copy data from URB */
spin_lock(&dev->video_mode.slock);
rc = dev->video_mode.bulk_ctl.bulk_copy(dev, urb);
spin_unlock(&dev->video_mode.slock);
/* Reset urb buffers */
urb->status = 0;
urb->status = usb_submit_urb(urb, GFP_ATOMIC);
if (urb->status) {
cx231xx_isocdbg("urb resubmit failed (error=%i)\n",
urb->status);
}
}
/* /*
* Stop and Deallocate URBs * Stop and Deallocate URBs
*/ */
void cx231xx_uninit_isoc(struct cx231xx *dev) void cx231xx_uninit_isoc(struct cx231xx *dev)
{ {
struct cx231xx_dmaqueue *dma_q = &dev->video_mode.vidq;
struct urb *urb; struct urb *urb;
int i; int i;
...@@ -690,15 +928,70 @@ void cx231xx_uninit_isoc(struct cx231xx *dev) ...@@ -690,15 +928,70 @@ void cx231xx_uninit_isoc(struct cx231xx *dev)
kfree(dev->video_mode.isoc_ctl.urb); kfree(dev->video_mode.isoc_ctl.urb);
kfree(dev->video_mode.isoc_ctl.transfer_buffer); kfree(dev->video_mode.isoc_ctl.transfer_buffer);
kfree(dma_q->p_left_data);
dev->video_mode.isoc_ctl.urb = NULL; dev->video_mode.isoc_ctl.urb = NULL;
dev->video_mode.isoc_ctl.transfer_buffer = NULL; dev->video_mode.isoc_ctl.transfer_buffer = NULL;
dev->video_mode.isoc_ctl.num_bufs = 0; dev->video_mode.isoc_ctl.num_bufs = 0;
dma_q->p_left_data = NULL;
if (dev->mode_tv == 0)
cx231xx_capture_start(dev, 0, Raw_Video);
else
cx231xx_capture_start(dev, 0, TS1_serial_mode);
cx231xx_capture_start(dev, 0, Raw_Video);
} }
EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc); EXPORT_SYMBOL_GPL(cx231xx_uninit_isoc);
/*
* Stop and Deallocate URBs
*/
void cx231xx_uninit_bulk(struct cx231xx *dev)
{
struct urb *urb;
int i;
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);
if (dev->video_mode.bulk_ctl.transfer_buffer[i]) {
usb_free_coherent(dev->udev,
urb->transfer_buffer_length,
dev->video_mode.isoc_ctl.
transfer_buffer[i],
urb->transfer_dma);
}
usb_free_urb(urb);
dev->video_mode.bulk_ctl.urb[i] = NULL;
}
dev->video_mode.bulk_ctl.transfer_buffer[i] = NULL;
}
kfree(dev->video_mode.bulk_ctl.urb);
kfree(dev->video_mode.bulk_ctl.transfer_buffer);
dev->video_mode.bulk_ctl.urb = NULL;
dev->video_mode.bulk_ctl.transfer_buffer = NULL;
dev->video_mode.bulk_ctl.num_bufs = 0;
if (dev->mode_tv == 0)
cx231xx_capture_start(dev, 0, Raw_Video);
else
cx231xx_capture_start(dev, 0, TS1_serial_mode);
}
EXPORT_SYMBOL_GPL(cx231xx_uninit_bulk);
/* /*
* Allocate URBs and start IRQ * Allocate URBs and start IRQ
*/ */
...@@ -713,8 +1006,6 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, ...@@ -713,8 +1006,6 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
int j, k; int j, k;
int rc; int rc;
cx231xx_isocdbg("cx231xx: called cx231xx_prepare_isoc\n");
dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
cx231xx_info("Setting Video mux to %d\n", dev->video_input); cx231xx_info("Setting Video mux to %d\n", dev->video_input);
...@@ -723,6 +1014,14 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, ...@@ -723,6 +1014,14 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
/* De-allocates all pending stuff */ /* De-allocates all pending stuff */
cx231xx_uninit_isoc(dev); cx231xx_uninit_isoc(dev);
dma_q->p_left_data = kzalloc(4096, GFP_KERNEL);
if (dma_q->p_left_data == NULL) {
cx231xx_info("out of mem\n");
return -ENOMEM;
}
dev->video_mode.isoc_ctl.isoc_copy = isoc_copy; dev->video_mode.isoc_ctl.isoc_copy = isoc_copy;
dev->video_mode.isoc_ctl.num_bufs = num_bufs; dev->video_mode.isoc_ctl.num_bufs = num_bufs;
dma_q->pos = 0; dma_q->pos = 0;
...@@ -733,6 +1032,14 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, ...@@ -733,6 +1032,14 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
dma_q->lines_per_field = dev->height / 2; dma_q->lines_per_field = dev->height / 2;
dma_q->bytes_left_in_line = dev->width << 1; dma_q->bytes_left_in_line = dev->width << 1;
dma_q->lines_completed = 0; dma_q->lines_completed = 0;
dma_q->mpeg_buffer_done = 0;
dma_q->left_data_count = 0;
dma_q->mpeg_buffer_completed = 0;
dma_q->add_ps_package_head = CX231XX_NEED_ADD_PS_PACKAGE_HEAD;
dma_q->ps_head[0] = 0x00;
dma_q->ps_head[1] = 0x00;
dma_q->ps_head[2] = 0x01;
dma_q->ps_head[3] = 0xBA;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
dma_q->partial_buf[i] = 0; dma_q->partial_buf[i] = 0;
...@@ -756,6 +1063,12 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, ...@@ -756,6 +1063,12 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size; sb_size = max_packets * dev->video_mode.isoc_ctl.max_pkt_size;
if (dev->mode_tv == 1)
dev->video_mode.end_point_addr = 0x81;
else
dev->video_mode.end_point_addr = 0x84;
/* allocate urbs and transfer buffers */ /* allocate urbs and transfer buffers */
for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) { for (i = 0; i < dev->video_mode.isoc_ctl.num_bufs; i++) {
urb = usb_alloc_urb(max_packets, GFP_KERNEL); urb = usb_alloc_urb(max_packets, GFP_KERNEL);
...@@ -784,7 +1097,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, ...@@ -784,7 +1097,7 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
usb_fill_int_urb(urb, dev->udev, pipe, usb_fill_int_urb(urb, dev->udev, pipe,
dev->video_mode.isoc_ctl.transfer_buffer[i], dev->video_mode.isoc_ctl.transfer_buffer[i],
sb_size, cx231xx_irq_callback, dma_q, 1); sb_size, cx231xx_isoc_irq_callback, dma_q, 1);
urb->number_of_packets = max_packets; urb->number_of_packets = max_packets;
urb->transfer_flags = URB_ISO_ASAP; urb->transfer_flags = URB_ISO_ASAP;
...@@ -812,12 +1125,175 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, ...@@ -812,12 +1125,175 @@ int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
} }
} }
cx231xx_capture_start(dev, 1, Raw_Video); if (dev->mode_tv == 0)
cx231xx_capture_start(dev, 1, Raw_Video);
else
cx231xx_capture_start(dev, 1, TS1_serial_mode);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(cx231xx_init_isoc); EXPORT_SYMBOL_GPL(cx231xx_init_isoc);
/*
* 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;
dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
cx231xx_info("Setting Video mux to %d\n", dev->video_input);
video_mux(dev, dev->video_input);
/* De-allocates all pending stuff */
cx231xx_uninit_bulk(dev);
dev->video_mode.bulk_ctl.bulk_copy = bulk_copy;
dev->video_mode.bulk_ctl.num_bufs = num_bufs;
dma_q->pos = 0;
dma_q->is_partial_line = 0;
dma_q->last_sav = 0;
dma_q->current_field = -1;
dma_q->field1_done = 0;
dma_q->lines_per_field = dev->height / 2;
dma_q->bytes_left_in_line = dev->width << 1;
dma_q->lines_completed = 0;
dma_q->mpeg_buffer_done = 0;
dma_q->left_data_count = 0;
dma_q->mpeg_buffer_completed = 0;
dma_q->ps_head[0] = 0x00;
dma_q->ps_head[1] = 0x00;
dma_q->ps_head[2] = 0x01;
dma_q->ps_head[3] = 0xBA;
for (i = 0; i < 8; i++)
dma_q->partial_buf[i] = 0;
dev->video_mode.bulk_ctl.urb =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->video_mode.bulk_ctl.urb) {
cx231xx_errdev("cannot alloc memory for usb buffers\n");
return -ENOMEM;
}
dev->video_mode.bulk_ctl.transfer_buffer =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->video_mode.bulk_ctl.transfer_buffer) {
cx231xx_errdev("cannot allocate memory for usbtransfer\n");
kfree(dev->video_mode.bulk_ctl.urb);
return -ENOMEM;
}
dev->video_mode.bulk_ctl.max_pkt_size = max_pkt_size;
dev->video_mode.bulk_ctl.buf = NULL;
sb_size = max_packets * dev->video_mode.bulk_ctl.max_pkt_size;
if (dev->mode_tv == 1)
dev->video_mode.end_point_addr = 0x81;
else
dev->video_mode.end_point_addr = 0x84;
/* 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_err("cannot alloc bulk_ctl.urb %i\n", i);
cx231xx_uninit_bulk(dev);
return -ENOMEM;
}
dev->video_mode.bulk_ctl.urb[i] = urb;
urb->transfer_flags = 0;
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]) {
cx231xx_err("unable to allocate %i bytes for transfer"
" buffer %i%s\n",
sb_size, i,
in_interrupt() ? " while in int" : "");
cx231xx_uninit_bulk(dev);
return -ENOMEM;
}
memset(dev->video_mode.bulk_ctl.transfer_buffer[i], 0, sb_size);
pipe = usb_rcvbulkpipe(dev->udev,
dev->video_mode.end_point_addr);
usb_fill_bulk_urb(urb, dev->udev, pipe,
dev->video_mode.bulk_ctl.transfer_buffer[i],
sb_size, cx231xx_bulk_irq_callback, dma_q);
}
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) {
cx231xx_err("submit of urb %i failed (error=%i)\n", i,
rc);
cx231xx_uninit_bulk(dev);
return rc;
}
}
if (dev->mode_tv == 0)
cx231xx_capture_start(dev, 1, Raw_Video);
else
cx231xx_capture_start(dev, 1, TS1_serial_mode);
return 0;
}
EXPORT_SYMBOL_GPL(cx231xx_init_bulk);
void cx231xx_stop_TS1(struct cx231xx *dev)
{
int status = 0;
u8 val[4] = { 0, 0, 0, 0 };
val[0] = 0x00;
val[1] = 0x03;
val[2] = 0x00;
val[3] = 0x00;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
TS_MODE_REG, val, 4);
val[0] = 0x00;
val[1] = 0x70;
val[2] = 0x04;
val[3] = 0x00;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
TS1_CFG_REG, val, 4);
}
/* EXPORT_SYMBOL_GPL(cx231xx_stop_TS1); */
void cx231xx_start_TS1(struct cx231xx *dev)
{
int status = 0;
u8 val[4] = { 0, 0, 0, 0 };
val[0] = 0x03;
val[1] = 0x03;
val[2] = 0x00;
val[3] = 0x00;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
TS_MODE_REG, val, 4);
val[0] = 0x04;
val[1] = 0xA3;
val[2] = 0x3B;
val[3] = 0x00;
status = cx231xx_write_ctrl_reg(dev, VRT_SET_REGISTER,
TS1_CFG_REG, val, 4);
}
/* EXPORT_SYMBOL_GPL(cx231xx_start_TS1); */
/***************************************************************** /*****************************************************************
* Device Init/UnInit functions * * Device Init/UnInit functions *
******************************************************************/ ******************************************************************/
...@@ -856,14 +1332,33 @@ int cx231xx_dev_init(struct cx231xx *dev) ...@@ -856,14 +1332,33 @@ int cx231xx_dev_init(struct cx231xx *dev)
/* init hardware */ /* init hardware */
/* Note : with out calling set power mode function, /* Note : with out calling set power mode function,
afe can not be set up correctly */ afe can not be set up correctly */
errCode = cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
if (errCode < 0) { errCode = cx231xx_set_power_mode(dev,
cx231xx_errdev POLARIS_AVMODE_ENXTERNAL_AV);
("%s: Failed to set Power - errCode [%d]!\n", if (errCode < 0) {
__func__, errCode); cx231xx_errdev
return errCode; ("%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) {
cx231xx_errdev
("%s: Failed to set Power - errCode [%d]!\n",
__func__, errCode);
return errCode;
}
} }
/* reset the Tuner */
if ((dev->model == CX231XX_BOARD_CNXT_CARRAERA) ||
(dev->model == CX231XX_BOARD_CNXT_RDE_250) ||
(dev->model == CX231XX_BOARD_CNXT_SHELBY) ||
(dev->model == CX231XX_BOARD_CNXT_RDU_250))
cx231xx_gpio_set(dev, dev->board.tuner_gpio);
/* initialize Colibri block */ /* initialize Colibri block */
errCode = cx231xx_afe_init_super_block(dev, 0x23c); errCode = cx231xx_afe_init_super_block(dev, 0x23c);
if (errCode < 0) { if (errCode < 0) {
...@@ -907,7 +1402,20 @@ int cx231xx_dev_init(struct cx231xx *dev) ...@@ -907,7 +1402,20 @@ int cx231xx_dev_init(struct cx231xx *dev)
} }
/* set AGC mode to Analog */ /* 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); errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 1);
break;
case CX231XX_BOARD_CNXT_RDE_253S:
case CX231XX_BOARD_CNXT_RDU_253S:
errCode = cx231xx_set_agc_analog_digital_mux_select(dev, 0);
break;
default:
break;
}
if (errCode < 0) { if (errCode < 0) {
cx231xx_errdev cx231xx_errdev
("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n", ("%s: cx231xx_AGC mode to Analog - errCode [%d]!\n",
...@@ -923,7 +1431,8 @@ int cx231xx_dev_init(struct cx231xx *dev) ...@@ -923,7 +1431,8 @@ int cx231xx_dev_init(struct cx231xx *dev)
cx231xx_set_alt_setting(dev, INDEX_TS1, 0); cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
/* set the I2C master port to 3 on channel 1 */ /* set the I2C master port to 3 on channel 1 */
errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3); if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3);
return errCode; return errCode;
} }
...@@ -941,7 +1450,7 @@ EXPORT_SYMBOL_GPL(cx231xx_dev_uninit); ...@@ -941,7 +1450,7 @@ EXPORT_SYMBOL_GPL(cx231xx_dev_uninit);
/***************************************************************** /*****************************************************************
* G P I O related functions * * G P I O related functions *
******************************************************************/ ******************************************************************/
int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 * gpio_val, int cx231xx_send_gpio_cmd(struct cx231xx *dev, u32 gpio_bit, u8 *gpio_val,
u8 len, u8 request, u8 direction) u8 len, u8 request, u8 direction)
{ {
int status = 0; int status = 0;
...@@ -1026,6 +1535,91 @@ int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode) ...@@ -1026,6 +1535,91 @@ int cx231xx_mode_register(struct cx231xx *dev, u16 address, u32 mode)
/***************************************************************** /*****************************************************************
* I 2 C Internal C O N T R O L functions * * 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";
if (saddr_len == 0)
saddr = 0;
else if (saddr_len == 0)
saddr &= 0xff;
/* prepare xfer_data struct */
req_data.dev_addr = dev_addr >> 1;
req_data.direction = I2C_M_RD;
req_data.saddr_len = saddr_len;
req_data.saddr_dat = saddr;
req_data.buf_size = data_len;
req_data.p_buffer = (u8 *) value;
/* usb send command */
if (master == 0)
status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],
&req_data);
else if (master == 1)
status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],
&req_data);
else if (master == 2)
status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],
&req_data);
if (status >= 0) {
/* Copy the data read back to main buffer */
if (data_len == 1)
*data = value[0];
else if (data_len == 4)
*data =
value[0] | value[1] << 8 | value[2] << 16 | value[3]
<< 24;
else if (data_len > 4)
*data = value[saddr];
}
return status;
}
int cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
u8 saddr_len, u32 data, u8 data_len, int master)
{
int status = 0;
u8 value[4] = { 0, 0, 0, 0 };
struct cx231xx_i2c_xfer_data req_data;
value[0] = (u8) data;
value[1] = (u8) (data >> 8);
value[2] = (u8) (data >> 16);
value[3] = (u8) (data >> 24);
if (saddr_len == 0)
saddr = 0;
else if (saddr_len == 0)
saddr &= 0xff;
/* prepare xfer_data struct */
req_data.dev_addr = dev_addr >> 1;
req_data.direction = 0;
req_data.saddr_len = saddr_len;
req_data.saddr_dat = saddr;
req_data.buf_size = data_len;
req_data.p_buffer = value;
/* usb send command */
if (master == 0)
status = dev->cx231xx_send_usb_command(&dev->i2c_bus[0],
&req_data);
else if (master == 1)
status = dev->cx231xx_send_usb_command(&dev->i2c_bus[1],
&req_data);
else if (master == 2)
status = dev->cx231xx_send_usb_command(&dev->i2c_bus[2],
&req_data);
return status;
}
int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr, int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, u16 saddr,
u8 saddr_len, u32 *data, u8 data_len) u8 saddr_len, u32 *data, u8 data_len)
{ {
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -29,6 +29,9 @@ ...@@ -29,6 +29,9 @@
#include "xc5000.h" #include "xc5000.h"
#include "dvb_dummy_fe.h" #include "dvb_dummy_fe.h"
#include "s5h1432.h"
#include "tda18271.h"
#include "s5h1411.h"
MODULE_DESCRIPTION("driver for cx231xx based DVB cards"); MODULE_DESCRIPTION("driver for cx231xx based DVB cards");
MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>"); MODULE_AUTHOR("Srinivasa Deevi <srinivasa.deevi@conexant.com>");
...@@ -65,6 +68,48 @@ struct cx231xx_dvb { ...@@ -65,6 +68,48 @@ struct cx231xx_dvb {
struct dvb_net net; struct dvb_net net;
}; };
static struct s5h1432_config dvico_s5h1432_config = {
.output_mode = S5H1432_SERIAL_OUTPUT,
.gpio = S5H1432_GPIO_ON,
.qam_if = S5H1432_IF_4000,
.vsb_if = S5H1432_IF_4000,
.inversion = S5H1432_INVERSION_OFF,
.status_mode = S5H1432_DEMODLOCKING,
.mpeg_timing = S5H1432_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
};
static struct tda18271_std_map cnxt_rde253s_tda18271_std_map = {
.dvbt_6 = { .if_freq = 4000, .agc_mode = 3, .std = 4,
.if_lvl = 1, .rfagc_top = 0x37, },
.dvbt_7 = { .if_freq = 4000, .agc_mode = 3, .std = 5,
.if_lvl = 1, .rfagc_top = 0x37, },
.dvbt_8 = { .if_freq = 4000, .agc_mode = 3, .std = 6,
.if_lvl = 1, .rfagc_top = 0x37, },
};
static struct tda18271_config cnxt_rde253s_tunerconfig = {
.std_map = &cnxt_rde253s_tda18271_std_map,
.gate = TDA18271_GATE_ANALOG,
};
static struct s5h1411_config tda18271_s5h1411_config = {
.output_mode = S5H1411_SERIAL_OUTPUT,
.gpio = S5H1411_GPIO_OFF,
.vsb_if = S5H1411_IF_3250,
.qam_if = S5H1411_IF_4000,
.inversion = S5H1411_INVERSION_ON,
.status_mode = S5H1411_DEMODLOCKING,
.mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
};
static struct s5h1411_config xc5000_s5h1411_config = {
.output_mode = S5H1411_SERIAL_OUTPUT,
.gpio = S5H1411_GPIO_OFF,
.vsb_if = S5H1411_IF_3250,
.qam_if = S5H1411_IF_3250,
.inversion = S5H1411_INVERSION_OFF,
.status_mode = S5H1411_DEMODLOCKING,
.mpeg_timing = S5H1411_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK,
};
static inline void print_err_status(struct cx231xx *dev, int packet, int status) static inline void print_err_status(struct cx231xx *dev, int packet, int status)
{ {
char *errmsg = "Unknown"; char *errmsg = "Unknown";
...@@ -128,34 +173,81 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb) ...@@ -128,34 +173,81 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
continue; continue;
} }
dvb_dmx_swfilter(&dev->dvb->demux, urb->transfer_buffer + dvb_dmx_swfilter(&dev->dvb->demux,
urb->iso_frame_desc[i].offset, urb->transfer_buffer +
urb->iso_frame_desc[i].actual_length); urb->iso_frame_desc[i].offset,
urb->iso_frame_desc[i].actual_length);
} }
return 0; return 0;
} }
static inline int dvb_bulk_copy(struct cx231xx *dev, struct urb *urb)
{
int i;
if (!dev)
return 0;
if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
return 0;
if (urb->status < 0) {
print_err_status(dev, -1, urb->status);
if (urb->status == -ENOENT)
return 0;
}
/* Feed the transport payload into the kernel demux */
dvb_dmx_swfilter(&dev->dvb->demux,
urb->transfer_buffer, urb->actual_length);
return 0;
}
static int start_streaming(struct cx231xx_dvb *dvb) static int start_streaming(struct cx231xx_dvb *dvb)
{ {
int rc; int rc;
struct cx231xx *dev = dvb->adapter.priv; struct cx231xx *dev = dvb->adapter.priv;
usb_set_interface(dev->udev, 0, 1); if (dev->USE_ISO) {
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); cx231xx_info("DVB transfer mode is ISO.\n");
if (rc < 0) mutex_lock(&dev->i2c_lock);
return rc; cx231xx_enable_i2c_for_tuner(dev, I2C_1);
cx231xx_set_alt_setting(dev, INDEX_TS1, 4);
cx231xx_enable_i2c_for_tuner(dev, I2C_3);
mutex_unlock(&dev->i2c_lock);
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
if (rc < 0)
return rc;
dev->mode_tv = 1;
return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
CX231XX_DVB_NUM_BUFS,
dev->ts1_mode.max_pkt_size,
dvb_isoc_copy);
} else {
cx231xx_info("DVB transfer mode is BULK.\n");
cx231xx_set_alt_setting(dev, INDEX_TS1, 0);
rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
if (rc < 0)
return rc;
dev->mode_tv = 1;
return cx231xx_init_bulk(dev, CX231XX_DVB_MAX_PACKETS,
CX231XX_DVB_NUM_BUFS,
dev->ts1_mode.max_pkt_size,
dvb_bulk_copy);
}
return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
CX231XX_DVB_NUM_BUFS,
CX231XX_DVB_MAX_PACKETSIZE, dvb_isoc_copy);
} }
static int stop_streaming(struct cx231xx_dvb *dvb) static int stop_streaming(struct cx231xx_dvb *dvb)
{ {
struct cx231xx *dev = dvb->adapter.priv; struct cx231xx *dev = dvb->adapter.priv;
cx231xx_uninit_isoc(dev); if (dev->USE_ISO)
cx231xx_uninit_isoc(dev);
else
cx231xx_uninit_bulk(dev);
cx231xx_set_mode(dev, CX231XX_SUSPEND); cx231xx_set_mode(dev, CX231XX_SUSPEND);
...@@ -216,7 +308,11 @@ static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire) ...@@ -216,7 +308,11 @@ static int cx231xx_dvb_bus_ctrl(struct dvb_frontend *fe, int acquire)
static struct xc5000_config cnxt_rde250_tunerconfig = { static struct xc5000_config cnxt_rde250_tunerconfig = {
.i2c_address = 0x61, .i2c_address = 0x61,
.if_khz = 5380, .if_khz = 4000,
};
static struct xc5000_config cnxt_rdu250_tunerconfig = {
.i2c_address = 0x61,
.if_khz = 3250,
}; };
/* ------------------------------------------------------------------ */ /* ------------------------------------------------------------------ */
...@@ -268,7 +364,6 @@ int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq) ...@@ -268,7 +364,6 @@ int cx231xx_set_analog_freq(struct cx231xx *dev, u32 freq)
/*params.audmode = ; */ /*params.audmode = ; */
/* Set the analog parameters to set the frequency */ /* Set the analog parameters to set the frequency */
cx231xx_info("Setting Frequency for XC5000\n");
dops->set_analog_params(dev->dvb->frontend, &params); dops->set_analog_params(dev->dvb->frontend, &params);
} }
...@@ -446,18 +541,19 @@ static int dvb_init(struct cx231xx *dev) ...@@ -446,18 +541,19 @@ static int dvb_init(struct cx231xx *dev)
dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner; dev->cx231xx_reset_analog_tuner = cx231xx_reset_analog_tuner;
cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE); cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
cx231xx_demod_reset(dev);
/* init frontend */ /* init frontend */
switch (dev->model) { switch (dev->model) {
case CX231XX_BOARD_CNXT_CARRAERA:
case CX231XX_BOARD_CNXT_RDE_250: case CX231XX_BOARD_CNXT_RDE_250:
/* dev->dvb->frontend = dvb_attach(s5h1411_attach, dev->dvb->frontend = dvb_attach(s5h1432_attach,
&dvico_s5h1411_config, &dvico_s5h1432_config,
&dev->i2c_bus[1].i2c_adap); */ &dev->i2c_bus[2].i2c_adap);
dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach);
if (dev->dvb->frontend == NULL) { if (dev->dvb->frontend == NULL) {
printk(DRIVER_NAME printk(DRIVER_NAME
": Failed to attach dummy front end\n"); ": Failed to attach s5h1432 front end\n");
result = -EINVAL; result = -EINVAL;
goto out_free; goto out_free;
} }
...@@ -473,9 +569,12 @@ static int dvb_init(struct cx231xx *dev) ...@@ -473,9 +569,12 @@ static int dvb_init(struct cx231xx *dev)
} }
break; break;
case CX231XX_BOARD_CNXT_SHELBY:
case CX231XX_BOARD_CNXT_RDU_250: case CX231XX_BOARD_CNXT_RDU_250:
dev->dvb->frontend = dvb_attach(dvb_dummy_fe_ofdm_attach); dev->dvb->frontend = dvb_attach(s5h1411_attach,
&xc5000_s5h1411_config,
&dev->i2c_bus[2].i2c_adap);
if (dev->dvb->frontend == NULL) { if (dev->dvb->frontend == NULL) {
printk(DRIVER_NAME printk(DRIVER_NAME
...@@ -489,7 +588,53 @@ static int dvb_init(struct cx231xx *dev) ...@@ -489,7 +588,53 @@ static int dvb_init(struct cx231xx *dev)
if (!dvb_attach(xc5000_attach, dev->dvb->frontend, if (!dvb_attach(xc5000_attach, dev->dvb->frontend,
&dev->i2c_bus[1].i2c_adap, &dev->i2c_bus[1].i2c_adap,
&cnxt_rde250_tunerconfig)) { &cnxt_rdu250_tunerconfig)) {
result = -EINVAL;
goto out_free;
}
break;
case CX231XX_BOARD_CNXT_RDE_253S:
dev->dvb->frontend = dvb_attach(s5h1432_attach,
&dvico_s5h1432_config,
&dev->i2c_bus[2].i2c_adap);
if (dev->dvb->frontend == NULL) {
printk(DRIVER_NAME
": Failed to attach s5h1432 front end\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend->callback = cx231xx_tuner_callback;
if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
0x60, &dev->i2c_bus[1].i2c_adap,
&cnxt_rde253s_tunerconfig)) {
result = -EINVAL;
goto out_free;
}
break;
case CX231XX_BOARD_CNXT_RDU_253S:
dev->dvb->frontend = dvb_attach(s5h1411_attach,
&tda18271_s5h1411_config,
&dev->i2c_bus[2].i2c_adap);
if (dev->dvb->frontend == NULL) {
printk(DRIVER_NAME
": Failed to attach dummy front end\n");
result = -EINVAL;
goto out_free;
}
/* define general-purpose callback pointer */
dvb->frontend->callback = cx231xx_tuner_callback;
if (!dvb_attach(tda18271_attach, dev->dvb->frontend,
0x60, &dev->i2c_bus[1].i2c_adap,
&cnxt_rde253s_tunerconfig)) {
result = -EINVAL; result = -EINVAL;
goto out_free; goto out_free;
} }
......
...@@ -359,7 +359,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -359,7 +359,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
if (num <= 0) if (num <= 0)
return 0; return 0;
mutex_lock(&dev->i2c_lock);
for (i = 0; i < num; i++) { for (i = 0; i < num; i++) {
addr = msgs[i].addr >> 1; addr = msgs[i].addr >> 1;
...@@ -372,6 +372,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -372,6 +372,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]); rc = cx231xx_i2c_check_for_device(i2c_adap, &msgs[i]);
if (rc < 0) { if (rc < 0) {
dprintk2(2, " no device\n"); dprintk2(2, " no device\n");
mutex_lock(&dev->i2c_lock);
return rc; return rc;
} }
...@@ -384,7 +385,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -384,7 +385,7 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
} }
} else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) && } else if (i + 1 < num && (msgs[i + 1].flags & I2C_M_RD) &&
msgs[i].addr == msgs[i + 1].addr msgs[i].addr == msgs[i + 1].addr
&& (msgs[i].len <= 2) && (bus->nr < 2)) { && (msgs[i].len <= 2) && (bus->nr < 3)) {
/* read bytes */ /* read bytes */
rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap, rc = cx231xx_i2c_recv_bytes_with_saddr(i2c_adap,
&msgs[i], &msgs[i],
...@@ -407,10 +408,11 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap, ...@@ -407,10 +408,11 @@ static int cx231xx_i2c_xfer(struct i2c_adapter *i2c_adap,
if (i2c_debug >= 2) if (i2c_debug >= 2)
printk("\n"); printk("\n");
} }
mutex_unlock(&dev->i2c_lock);
return num; return num;
err: err:
dprintk2(2, " ERROR: %i\n", rc); dprintk2(2, " ERROR: %i\n", rc);
mutex_unlock(&dev->i2c_lock);
return rc; return rc;
} }
......
...@@ -61,6 +61,7 @@ struct cx231xx_ir_poll_result { ...@@ -61,6 +61,7 @@ struct cx231xx_ir_poll_result {
struct cx231xx_IR { struct cx231xx_IR {
struct cx231xx *dev; struct cx231xx *dev;
struct input_dev *input; struct input_dev *input;
struct ir_input_state ir;
char name[32]; char name[32];
char phys[32]; char phys[32];
...@@ -68,7 +69,9 @@ struct cx231xx_IR { ...@@ -68,7 +69,9 @@ struct cx231xx_IR {
int polling; int polling;
struct work_struct work; struct work_struct work;
struct timer_list timer; struct timer_list timer;
unsigned int last_toggle:1;
unsigned int last_readcount; unsigned int last_readcount;
unsigned int repeat_interval;
int (*get_key) (struct cx231xx_IR *, struct cx231xx_ir_poll_result *); int (*get_key) (struct cx231xx_IR *, struct cx231xx_ir_poll_result *);
}; };
...@@ -80,6 +83,7 @@ struct cx231xx_IR { ...@@ -80,6 +83,7 @@ struct cx231xx_IR {
static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) static void cx231xx_ir_handle_key(struct cx231xx_IR *ir)
{ {
int result; int result;
int do_sendkey = 0;
struct cx231xx_ir_poll_result poll_result; struct cx231xx_ir_poll_result poll_result;
/* read the registers containing the IR status */ /* read the registers containing the IR status */
...@@ -93,23 +97,44 @@ static void cx231xx_ir_handle_key(struct cx231xx_IR *ir) ...@@ -93,23 +97,44 @@ static void cx231xx_ir_handle_key(struct cx231xx_IR *ir)
poll_result.toggle_bit, poll_result.read_count, poll_result.toggle_bit, poll_result.read_count,
ir->last_readcount, poll_result.rc_data[0]); ir->last_readcount, poll_result.rc_data[0]);
if (poll_result.read_count > 0 && if (ir->dev->chip_id == CHIP_ID_EM2874) {
poll_result.read_count != ir->last_readcount)
ir_keydown(ir->input,
poll_result.rc_data[0],
poll_result.toggle_bit);
if (ir->dev->chip_id == CHIP_ID_EM2874)
/* The em2874 clears the readcount field every time the /* The em2874 clears the readcount field every time the
register is read. The em2860/2880 datasheet says that it register is read. The em2860/2880 datasheet says that it
is supposed to clear the readcount, but it doesn't. So with is supposed to clear the readcount, but it doesn't. So with
the em2874, we are looking for a non-zero read count as the em2874, we are looking for a non-zero read count as
opposed to a readcount that is incrementing */ opposed to a readcount that is incrementing */
ir->last_readcount = 0; ir->last_readcount = 0;
else }
ir->last_readcount = poll_result.read_count;
if (poll_result.read_count == 0) {
/* The button has not been pressed since the last read */
} else if (ir->last_toggle != poll_result.toggle_bit) {
/* A button has been pressed */
dprintk("button has been pressed\n");
ir->last_toggle = poll_result.toggle_bit;
ir->repeat_interval = 0;
do_sendkey = 1;
} else if (poll_result.toggle_bit == ir->last_toggle &&
poll_result.read_count > 0 &&
poll_result.read_count != ir->last_readcount) {
/* The button is still being held down */
dprintk("button being held down\n");
/* Debouncer for first keypress */
if (ir->repeat_interval++ > 9) {
/* Start repeating after 1 second */
do_sendkey = 1;
}
}
if (do_sendkey) {
dprintk("sending keypress\n");
ir_input_keydown(ir->input, &ir->ir, poll_result.rc_data[0]);
ir_input_nokey(ir->input, &ir->ir);
} }
ir->last_readcount = poll_result.read_count;
return;
} }
static void ir_timer(unsigned long data) static void ir_timer(unsigned long data)
...@@ -175,6 +200,10 @@ int cx231xx_ir_init(struct cx231xx *dev) ...@@ -175,6 +200,10 @@ int cx231xx_ir_init(struct cx231xx *dev)
usb_make_path(dev->udev, ir->phys, sizeof(ir->phys)); usb_make_path(dev->udev, ir->phys, sizeof(ir->phys));
strlcat(ir->phys, "/input0", sizeof(ir->phys)); strlcat(ir->phys, "/input0", sizeof(ir->phys));
err = ir_input_init(input_dev, &ir->ir, IR_TYPE_OTHER);
if (err < 0)
goto err_out_free;
input_dev->name = ir->name; input_dev->name = ir->name;
input_dev->phys = ir->phys; input_dev->phys = ir->phys;
input_dev->id.bustype = BUS_USB; input_dev->id.bustype = BUS_USB;
...@@ -190,7 +219,7 @@ int cx231xx_ir_init(struct cx231xx *dev) ...@@ -190,7 +219,7 @@ int cx231xx_ir_init(struct cx231xx *dev)
cx231xx_ir_start(ir); cx231xx_ir_start(ir);
/* all done */ /* all done */
err = __ir_input_register(ir->input, dev->board.ir_codes, err = ir_input_register(ir->input, dev->board.ir_codes,
NULL, MODULE_NAME); NULL, MODULE_NAME);
if (err) if (err)
goto err_out_stop; goto err_out_stop;
......
...@@ -102,7 +102,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb) ...@@ -102,7 +102,7 @@ static inline int cx231xx_isoc_vbi_copy(struct cx231xx *dev, struct urb *urb)
return 0; return 0;
} }
buf = dev->vbi_mode.isoc_ctl.buf; buf = dev->vbi_mode.bulk_ctl.buf;
/* get buffer pointer and length */ /* get buffer pointer and length */
p_buffer = urb->transfer_buffer; p_buffer = urb->transfer_buffer;
...@@ -209,8 +209,8 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) ...@@ -209,8 +209,8 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
VIDEOBUF_ACTIVE, it won't be, though. VIDEOBUF_ACTIVE, it won't be, though.
*/ */
spin_lock_irqsave(&dev->vbi_mode.slock, flags); spin_lock_irqsave(&dev->vbi_mode.slock, flags);
if (dev->vbi_mode.isoc_ctl.buf == buf) if (dev->vbi_mode.bulk_ctl.buf == buf)
dev->vbi_mode.isoc_ctl.buf = NULL; dev->vbi_mode.bulk_ctl.buf = NULL;
spin_unlock_irqrestore(&dev->vbi_mode.slock, flags); spin_unlock_irqrestore(&dev->vbi_mode.slock, flags);
videobuf_vmalloc_free(&buf->vb); videobuf_vmalloc_free(&buf->vb);
...@@ -246,7 +246,7 @@ vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, ...@@ -246,7 +246,7 @@ vbi_buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
goto fail; goto fail;
} }
if (!dev->vbi_mode.isoc_ctl.num_bufs) if (!dev->vbi_mode.bulk_ctl.num_bufs)
urb_init = 1; urb_init = 1;
if (urb_init) { if (urb_init) {
...@@ -328,7 +328,7 @@ static void cx231xx_irq_vbi_callback(struct urb *urb) ...@@ -328,7 +328,7 @@ static void cx231xx_irq_vbi_callback(struct urb *urb)
/* Copy data from URB */ /* Copy data from URB */
spin_lock(&dev->vbi_mode.slock); spin_lock(&dev->vbi_mode.slock);
rc = dev->vbi_mode.isoc_ctl.isoc_copy(dev, urb); rc = dev->vbi_mode.bulk_ctl.bulk_copy(dev, urb);
spin_unlock(&dev->vbi_mode.slock); spin_unlock(&dev->vbi_mode.slock);
/* Reset status */ /* Reset status */
...@@ -351,34 +351,34 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev) ...@@ -351,34 +351,34 @@ void cx231xx_uninit_vbi_isoc(struct cx231xx *dev)
cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n"); cx231xx_info(DRIVER_NAME "cx231xx: called cx231xx_uninit_vbi_isoc\n");
dev->vbi_mode.isoc_ctl.nfields = -1; dev->vbi_mode.bulk_ctl.nfields = -1;
for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
urb = dev->vbi_mode.isoc_ctl.urb[i]; urb = dev->vbi_mode.bulk_ctl.urb[i];
if (urb) { if (urb) {
if (!irqs_disabled()) if (!irqs_disabled())
usb_kill_urb(urb); usb_kill_urb(urb);
else else
usb_unlink_urb(urb); usb_unlink_urb(urb);
if (dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { if (dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
kfree(dev->vbi_mode.isoc_ctl. kfree(dev->vbi_mode.bulk_ctl.
transfer_buffer[i]); transfer_buffer[i]);
dev->vbi_mode.isoc_ctl.transfer_buffer[i] = dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
NULL; NULL;
} }
usb_free_urb(urb); usb_free_urb(urb);
dev->vbi_mode.isoc_ctl.urb[i] = NULL; dev->vbi_mode.bulk_ctl.urb[i] = NULL;
} }
dev->vbi_mode.isoc_ctl.transfer_buffer[i] = NULL; dev->vbi_mode.bulk_ctl.transfer_buffer[i] = NULL;
} }
kfree(dev->vbi_mode.isoc_ctl.urb); kfree(dev->vbi_mode.bulk_ctl.urb);
kfree(dev->vbi_mode.isoc_ctl.transfer_buffer); kfree(dev->vbi_mode.bulk_ctl.transfer_buffer);
dev->vbi_mode.isoc_ctl.urb = NULL; dev->vbi_mode.bulk_ctl.urb = NULL;
dev->vbi_mode.isoc_ctl.transfer_buffer = NULL; dev->vbi_mode.bulk_ctl.transfer_buffer = NULL;
dev->vbi_mode.isoc_ctl.num_bufs = 0; dev->vbi_mode.bulk_ctl.num_bufs = 0;
cx231xx_capture_start(dev, 0, Vbi); cx231xx_capture_start(dev, 0, Vbi);
} }
...@@ -389,7 +389,7 @@ EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc); ...@@ -389,7 +389,7 @@ EXPORT_SYMBOL_GPL(cx231xx_uninit_vbi_isoc);
*/ */
int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
int num_bufs, int max_pkt_size, int num_bufs, int max_pkt_size,
int (*isoc_copy) (struct cx231xx *dev, int (*bulk_copy) (struct cx231xx *dev,
struct urb *urb)) struct urb *urb))
{ {
struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq; struct cx231xx_dmaqueue *dma_q = &dev->vbi_mode.vidq;
...@@ -408,8 +408,8 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, ...@@ -408,8 +408,8 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
usb_rcvbulkpipe(dev->udev, usb_rcvbulkpipe(dev->udev,
dev->vbi_mode.end_point_addr)); dev->vbi_mode.end_point_addr));
dev->vbi_mode.isoc_ctl.isoc_copy = isoc_copy; dev->vbi_mode.bulk_ctl.bulk_copy = bulk_copy;
dev->vbi_mode.isoc_ctl.num_bufs = num_bufs; dev->vbi_mode.bulk_ctl.num_bufs = num_bufs;
dma_q->pos = 0; dma_q->pos = 0;
dma_q->is_partial_line = 0; dma_q->is_partial_line = 0;
dma_q->last_sav = 0; dma_q->last_sav = 0;
...@@ -421,42 +421,42 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, ...@@ -421,42 +421,42 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
dma_q->partial_buf[i] = 0; dma_q->partial_buf[i] = 0;
dev->vbi_mode.isoc_ctl.urb = kzalloc(sizeof(void *) * num_bufs, dev->vbi_mode.bulk_ctl.urb = kzalloc(sizeof(void *) * num_bufs,
GFP_KERNEL); GFP_KERNEL);
if (!dev->vbi_mode.isoc_ctl.urb) { if (!dev->vbi_mode.bulk_ctl.urb) {
cx231xx_errdev("cannot alloc memory for usb buffers\n"); cx231xx_errdev("cannot alloc memory for usb buffers\n");
return -ENOMEM; return -ENOMEM;
} }
dev->vbi_mode.isoc_ctl.transfer_buffer = dev->vbi_mode.bulk_ctl.transfer_buffer =
kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL); kzalloc(sizeof(void *) * num_bufs, GFP_KERNEL);
if (!dev->vbi_mode.isoc_ctl.transfer_buffer) { if (!dev->vbi_mode.bulk_ctl.transfer_buffer) {
cx231xx_errdev("cannot allocate memory for usbtransfer\n"); cx231xx_errdev("cannot allocate memory for usbtransfer\n");
kfree(dev->vbi_mode.isoc_ctl.urb); kfree(dev->vbi_mode.bulk_ctl.urb);
return -ENOMEM; return -ENOMEM;
} }
dev->vbi_mode.isoc_ctl.max_pkt_size = max_pkt_size; dev->vbi_mode.bulk_ctl.max_pkt_size = max_pkt_size;
dev->vbi_mode.isoc_ctl.buf = NULL; dev->vbi_mode.bulk_ctl.buf = NULL;
sb_size = max_packets * dev->vbi_mode.isoc_ctl.max_pkt_size; sb_size = max_packets * dev->vbi_mode.bulk_ctl.max_pkt_size;
/* allocate urbs and transfer buffers */ /* allocate urbs and transfer buffers */
for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
urb = usb_alloc_urb(0, GFP_KERNEL); urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb) { if (!urb) {
cx231xx_err(DRIVER_NAME cx231xx_err(DRIVER_NAME
": cannot alloc isoc_ctl.urb %i\n", i); ": cannot alloc bulk_ctl.urb %i\n", i);
cx231xx_uninit_vbi_isoc(dev); cx231xx_uninit_vbi_isoc(dev);
return -ENOMEM; return -ENOMEM;
} }
dev->vbi_mode.isoc_ctl.urb[i] = urb; dev->vbi_mode.bulk_ctl.urb[i] = urb;
urb->transfer_flags = 0; urb->transfer_flags = 0;
dev->vbi_mode.isoc_ctl.transfer_buffer[i] = dev->vbi_mode.bulk_ctl.transfer_buffer[i] =
kzalloc(sb_size, GFP_KERNEL); kzalloc(sb_size, GFP_KERNEL);
if (!dev->vbi_mode.isoc_ctl.transfer_buffer[i]) { if (!dev->vbi_mode.bulk_ctl.transfer_buffer[i]) {
cx231xx_err(DRIVER_NAME cx231xx_err(DRIVER_NAME
": unable to allocate %i bytes for transfer" ": unable to allocate %i bytes for transfer"
" buffer %i%s\n", sb_size, i, " buffer %i%s\n", sb_size, i,
...@@ -467,15 +467,15 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, ...@@ -467,15 +467,15 @@ int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr); pipe = usb_rcvbulkpipe(dev->udev, dev->vbi_mode.end_point_addr);
usb_fill_bulk_urb(urb, dev->udev, pipe, usb_fill_bulk_urb(urb, dev->udev, pipe,
dev->vbi_mode.isoc_ctl.transfer_buffer[i], dev->vbi_mode.bulk_ctl.transfer_buffer[i],
sb_size, cx231xx_irq_vbi_callback, dma_q); sb_size, cx231xx_irq_vbi_callback, dma_q);
} }
init_waitqueue_head(&dma_q->wq); init_waitqueue_head(&dma_q->wq);
/* submit urbs and enables IRQ */ /* submit urbs and enables IRQ */
for (i = 0; i < dev->vbi_mode.isoc_ctl.num_bufs; i++) { for (i = 0; i < dev->vbi_mode.bulk_ctl.num_bufs; i++) {
rc = usb_submit_urb(dev->vbi_mode.isoc_ctl.urb[i], GFP_ATOMIC); rc = usb_submit_urb(dev->vbi_mode.bulk_ctl.urb[i], GFP_ATOMIC);
if (rc) { if (rc) {
cx231xx_err(DRIVER_NAME cx231xx_err(DRIVER_NAME
": submit of urb %i failed (error=%i)\n", i, ": submit of urb %i failed (error=%i)\n", i,
...@@ -536,7 +536,7 @@ static inline void vbi_buffer_filled(struct cx231xx *dev, ...@@ -536,7 +536,7 @@ static inline void vbi_buffer_filled(struct cx231xx *dev,
buf->vb.field_count++; buf->vb.field_count++;
do_gettimeofday(&buf->vb.ts); do_gettimeofday(&buf->vb.ts);
dev->vbi_mode.isoc_ctl.buf = NULL; dev->vbi_mode.bulk_ctl.buf = NULL;
list_del(&buf->vb.queue); list_del(&buf->vb.queue);
wake_up(&buf->vb.done); wake_up(&buf->vb.done);
...@@ -553,7 +553,7 @@ u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, ...@@ -553,7 +553,7 @@ u32 cx231xx_copy_vbi_line(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
cx231xx_reset_vbi_buffer(dev, dma_q); cx231xx_reset_vbi_buffer(dev, dma_q);
/* get the buffer pointer */ /* get the buffer pointer */
buf = dev->vbi_mode.isoc_ctl.buf; buf = dev->vbi_mode.bulk_ctl.buf;
/* Remember the field number for next time */ /* Remember the field number for next time */
dma_q->current_field = field_number; dma_q->current_field = field_number;
...@@ -618,7 +618,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, ...@@ -618,7 +618,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
if (list_empty(&dma_q->active)) { if (list_empty(&dma_q->active)) {
cx231xx_err(DRIVER_NAME ": No active queue to serve\n"); cx231xx_err(DRIVER_NAME ": No active queue to serve\n");
dev->vbi_mode.isoc_ctl.buf = NULL; dev->vbi_mode.bulk_ctl.buf = NULL;
*buf = NULL; *buf = NULL;
return; return;
} }
...@@ -630,7 +630,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q, ...@@ -630,7 +630,7 @@ static inline void get_next_vbi_buf(struct cx231xx_dmaqueue *dma_q,
outp = videobuf_to_vmalloc(&(*buf)->vb); outp = videobuf_to_vmalloc(&(*buf)->vb);
memset(outp, 0, (*buf)->vb.size); memset(outp, 0, (*buf)->vb.size);
dev->vbi_mode.isoc_ctl.buf = *buf; dev->vbi_mode.bulk_ctl.buf = *buf;
return; return;
} }
...@@ -640,7 +640,7 @@ void cx231xx_reset_vbi_buffer(struct cx231xx *dev, ...@@ -640,7 +640,7 @@ void cx231xx_reset_vbi_buffer(struct cx231xx *dev,
{ {
struct cx231xx_buffer *buf; struct cx231xx_buffer *buf;
buf = dev->vbi_mode.isoc_ctl.buf; buf = dev->vbi_mode.bulk_ctl.buf;
if (buf == NULL) { if (buf == NULL) {
/* first try to get the buffer */ /* first try to get the buffer */
...@@ -664,7 +664,7 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, ...@@ -664,7 +664,7 @@ int cx231xx_do_vbi_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
void *startwrite; void *startwrite;
int offset, lencopy; int offset, lencopy;
buf = dev->vbi_mode.isoc_ctl.buf; buf = dev->vbi_mode.bulk_ctl.buf;
if (buf == NULL) if (buf == NULL)
return -EINVAL; return -EINVAL;
......
...@@ -41,7 +41,7 @@ extern struct videobuf_queue_ops cx231xx_vbi_qops; ...@@ -41,7 +41,7 @@ extern struct videobuf_queue_ops cx231xx_vbi_qops;
/* stream functions */ /* stream functions */
int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets, int cx231xx_init_vbi_isoc(struct cx231xx *dev, int max_packets,
int num_bufs, int max_pkt_size, int num_bufs, int max_pkt_size,
int (*isoc_copy) (struct cx231xx *dev, int (*bulk_copy) (struct cx231xx *dev,
struct urb *urb)); struct urb *urb));
void cx231xx_uninit_vbi_isoc(struct cx231xx *dev); void cx231xx_uninit_vbi_isoc(struct cx231xx *dev);
......
...@@ -237,7 +237,10 @@ static inline void buffer_filled(struct cx231xx *dev, ...@@ -237,7 +237,10 @@ static inline void buffer_filled(struct cx231xx *dev,
buf->vb.field_count++; buf->vb.field_count++;
do_gettimeofday(&buf->vb.ts); do_gettimeofday(&buf->vb.ts);
dev->video_mode.isoc_ctl.buf = NULL; if (dev->USE_ISO)
dev->video_mode.isoc_ctl.buf = NULL;
else
dev->video_mode.bulk_ctl.buf = NULL;
list_del(&buf->vb.queue); list_del(&buf->vb.queue);
wake_up(&buf->vb.done); wake_up(&buf->vb.done);
...@@ -295,7 +298,10 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, ...@@ -295,7 +298,10 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
if (list_empty(&dma_q->active)) { if (list_empty(&dma_q->active)) {
cx231xx_isocdbg("No active queue to serve\n"); cx231xx_isocdbg("No active queue to serve\n");
dev->video_mode.isoc_ctl.buf = NULL; if (dev->USE_ISO)
dev->video_mode.isoc_ctl.buf = NULL;
else
dev->video_mode.bulk_ctl.buf = NULL;
*buf = NULL; *buf = NULL;
return; return;
} }
...@@ -307,7 +313,10 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q, ...@@ -307,7 +313,10 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
outp = videobuf_to_vmalloc(&(*buf)->vb); outp = videobuf_to_vmalloc(&(*buf)->vb);
memset(outp, 0, (*buf)->vb.size); memset(outp, 0, (*buf)->vb.size);
dev->video_mode.isoc_ctl.buf = *buf; if (dev->USE_ISO)
dev->video_mode.isoc_ctl.buf = *buf;
else
dev->video_mode.bulk_ctl.buf = *buf;
return; return;
} }
...@@ -418,6 +427,93 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb) ...@@ -418,6 +427,93 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
return rc; return rc;
} }
static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
{
struct cx231xx_buffer *buf;
struct cx231xx_dmaqueue *dma_q = urb->context;
unsigned char *outp = NULL;
int rc = 1;
unsigned char *p_buffer;
u32 bytes_parsed = 0, buffer_size = 0;
u8 sav_eav = 0;
if (!dev)
return 0;
if ((dev->state & DEV_DISCONNECTED) || (dev->state & DEV_MISCONFIGURED))
return 0;
if (urb->status < 0) {
print_err_status(dev, -1, urb->status);
if (urb->status == -ENOENT)
return 0;
}
buf = dev->video_mode.bulk_ctl.buf;
if (buf != NULL)
outp = videobuf_to_vmalloc(&buf->vb);
if (1) {
/* get buffer pointer and length */
p_buffer = urb->transfer_buffer;
buffer_size = urb->actual_length;
bytes_parsed = 0;
if (dma_q->is_partial_line) {
/* Handle the case of a partial line */
sav_eav = dma_q->last_sav;
} else {
/* Check for a SAV/EAV overlapping
the buffer boundary */
sav_eav =
cx231xx_find_boundary_SAV_EAV(p_buffer,
dma_q->partial_buf,
&bytes_parsed);
}
sav_eav &= 0xF0;
/* Get the first line if we have some portion of an SAV/EAV from
the last buffer or a partial line */
if (sav_eav) {
bytes_parsed += cx231xx_get_video_line(dev, dma_q,
sav_eav, /* SAV/EAV */
p_buffer + bytes_parsed, /* p_buffer */
buffer_size - bytes_parsed);/* buf size */
}
/* Now parse data that is completely in this buffer */
/* dma_q->is_partial_line = 0; */
while (bytes_parsed < buffer_size) {
u32 bytes_used = 0;
sav_eav = cx231xx_find_next_SAV_EAV(
p_buffer + bytes_parsed, /* p_buffer */
buffer_size - bytes_parsed, /* buf size */
&bytes_used);/* bytes used to get SAV/EAV */
bytes_parsed += bytes_used;
sav_eav &= 0xF0;
if (sav_eav && (bytes_parsed < buffer_size)) {
bytes_parsed += cx231xx_get_video_line(dev,
dma_q, sav_eav, /* SAV/EAV */
p_buffer + bytes_parsed,/* p_buffer */
buffer_size - bytes_parsed);/*buf size*/
}
}
/* Save the last four bytes of the buffer so we can check the
buffer boundary condition next time */
memcpy(dma_q->partial_buf, p_buffer + buffer_size - 4, 4);
bytes_parsed = 0;
}
return rc;
}
u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf, u8 cx231xx_find_boundary_SAV_EAV(u8 *p_buffer, u8 *partial_buf,
u32 *p_bytes_used) u32 *p_bytes_used)
{ {
...@@ -533,7 +629,10 @@ u32 cx231xx_copy_video_line(struct cx231xx *dev, ...@@ -533,7 +629,10 @@ u32 cx231xx_copy_video_line(struct cx231xx *dev,
cx231xx_reset_video_buffer(dev, dma_q); cx231xx_reset_video_buffer(dev, dma_q);
/* get the buffer pointer */ /* get the buffer pointer */
buf = dev->video_mode.isoc_ctl.buf; if (dev->USE_ISO)
buf = dev->video_mode.isoc_ctl.buf;
else
buf = dev->video_mode.bulk_ctl.buf;
/* Remember the field number for next time */ /* Remember the field number for next time */
dma_q->current_field = field_number; dma_q->current_field = field_number;
...@@ -596,7 +695,10 @@ void cx231xx_reset_video_buffer(struct cx231xx *dev, ...@@ -596,7 +695,10 @@ void cx231xx_reset_video_buffer(struct cx231xx *dev,
dma_q->field1_done = 0; dma_q->field1_done = 0;
} }
buf = dev->video_mode.isoc_ctl.buf; if (dev->USE_ISO)
buf = dev->video_mode.isoc_ctl.buf;
else
buf = dev->video_mode.bulk_ctl.buf;
if (buf == NULL) { if (buf == NULL) {
u8 *outp = NULL; u8 *outp = NULL;
...@@ -626,7 +728,10 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q, ...@@ -626,7 +728,10 @@ int cx231xx_do_copy(struct cx231xx *dev, struct cx231xx_dmaqueue *dma_q,
void *startwrite; void *startwrite;
int offset, lencopy; int offset, lencopy;
buf = dev->video_mode.isoc_ctl.buf; if (dev->USE_ISO)
buf = dev->video_mode.isoc_ctl.buf;
else
buf = dev->video_mode.bulk_ctl.buf;
if (buf == NULL) if (buf == NULL)
return -1; return -1;
...@@ -691,7 +796,6 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) ...@@ -691,7 +796,6 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
{ {
struct cx231xx_fh *fh = vq->priv_data; struct cx231xx_fh *fh = vq->priv_data;
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
struct v4l2_frequency f;
*size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3; *size = (fh->dev->width * fh->dev->height * dev->format->depth + 7)>>3;
if (0 == *count) if (0 == *count)
...@@ -700,13 +804,6 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size) ...@@ -700,13 +804,6 @@ buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
if (*count < CX231XX_MIN_BUF) if (*count < CX231XX_MIN_BUF)
*count = CX231XX_MIN_BUF; *count = CX231XX_MIN_BUF;
/* Ask tuner to go to analog mode */
memset(&f, 0, sizeof(f));
f.frequency = dev->ctl_freq;
f.type = fh->radio ? V4L2_TUNER_RADIO : V4L2_TUNER_ANALOG_TV;
call_all(dev, tuner, s_frequency, &f);
return 0; return 0;
} }
...@@ -730,8 +827,13 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf) ...@@ -730,8 +827,13 @@ static void free_buffer(struct videobuf_queue *vq, struct cx231xx_buffer *buf)
VIDEOBUF_ACTIVE, it won't be, though. VIDEOBUF_ACTIVE, it won't be, though.
*/ */
spin_lock_irqsave(&dev->video_mode.slock, flags); spin_lock_irqsave(&dev->video_mode.slock, flags);
if (dev->video_mode.isoc_ctl.buf == buf) if (dev->USE_ISO) {
dev->video_mode.isoc_ctl.buf = NULL; if (dev->video_mode.isoc_ctl.buf == buf)
dev->video_mode.isoc_ctl.buf = NULL;
} else {
if (dev->video_mode.bulk_ctl.buf == buf)
dev->video_mode.bulk_ctl.buf = NULL;
}
spin_unlock_irqrestore(&dev->video_mode.slock, flags); spin_unlock_irqrestore(&dev->video_mode.slock, flags);
videobuf_vmalloc_free(&buf->vb); videobuf_vmalloc_free(&buf->vb);
...@@ -764,14 +866,27 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb, ...@@ -764,14 +866,27 @@ buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
goto fail; goto fail;
} }
if (!dev->video_mode.isoc_ctl.num_bufs) if (dev->USE_ISO) {
urb_init = 1; if (!dev->video_mode.isoc_ctl.num_bufs)
urb_init = 1;
} else {
if (!dev->video_mode.bulk_ctl.num_bufs)
urb_init = 1;
}
/*cx231xx_info("urb_init=%d dev->video_mode.max_pkt_size=%d\n",
urb_init, dev->video_mode.max_pkt_size);*/
if (urb_init) { if (urb_init) {
rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, dev->mode_tv = 0;
if (dev->USE_ISO)
rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS,
CX231XX_NUM_BUFS, CX231XX_NUM_BUFS,
dev->video_mode.max_pkt_size, dev->video_mode.max_pkt_size,
cx231xx_isoc_copy); cx231xx_isoc_copy);
else
rc = cx231xx_init_bulk(dev, CX231XX_NUM_PACKETS,
CX231XX_NUM_BUFS,
dev->video_mode.max_pkt_size,
cx231xx_bulk_copy);
if (rc < 0) if (rc < 0)
goto fail; goto fail;
} }
...@@ -1039,7 +1154,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv, ...@@ -1039,7 +1154,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
return rc; return rc;
} }
static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id * id) static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *id)
{ {
struct cx231xx_fh *fh = priv; struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
...@@ -1138,6 +1253,19 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i) ...@@ -1138,6 +1253,19 @@ static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
int rc; int rc;
if (i == 10) {
dev->USE_ISO = 0;
cx231xx_info("trans-mode=BULK. USE_ISO = %d\n", dev->USE_ISO);
return 0;
}
if (i == 11) {
dev->USE_ISO = 1;
cx231xx_info("trans-mode=ISOC. USE_ISO = %d\n", dev->USE_ISO);
return 0;
}
dev->mode_tv = 0;
rc = check_dev(dev); rc = check_dev(dev);
if (rc < 0) if (rc < 0)
return rc; return rc;
...@@ -1337,6 +1465,11 @@ static int vidioc_s_frequency(struct file *file, void *priv, ...@@ -1337,6 +1465,11 @@ static int vidioc_s_frequency(struct file *file, void *priv,
struct cx231xx_fh *fh = priv; struct cx231xx_fh *fh = priv;
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
int rc; int rc;
u32 if_frequency = 5400000;
cx231xx_info("Enter vidioc_s_frequency()f->frequency=%d;f->type=%d\n",
f->frequency, f->type);
/*cx231xx_info("f->type: 1-radio 2-analogTV 3-digitalTV\n");*/
rc = check_dev(dev); rc = check_dev(dev);
if (rc < 0) if (rc < 0)
...@@ -1356,18 +1489,35 @@ static int vidioc_s_frequency(struct file *file, void *priv, ...@@ -1356,18 +1489,35 @@ static int vidioc_s_frequency(struct file *file, void *priv,
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
dev->ctl_freq = f->frequency; dev->ctl_freq = f->frequency;
call_all(dev, tuner, s_frequency, f);
if (dev->tuner_type == TUNER_XC5000) {
if (dev->cx231xx_set_analog_freq != NULL)
dev->cx231xx_set_analog_freq(dev, f->frequency);
} else
call_all(dev, tuner, s_frequency, f);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
/* set post channel change settings in DIF first */ /* set post channel change settings in DIF first */
rc = cx231xx_tuner_post_channel_change(dev); rc = cx231xx_tuner_post_channel_change(dev);
if (dev->tuner_type == TUNER_NXP_TDA18271) {
if (dev->norm & (V4L2_STD_MN | V4L2_STD_NTSC_443))
if_frequency = 5400000; /*5.4MHz */
else if (dev->norm & V4L2_STD_B)
if_frequency = 6000000; /*6.0MHz */
else if (dev->norm & (V4L2_STD_PAL_DK | V4L2_STD_SECAM_DK))
if_frequency = 6900000; /*6.9MHz */
else if (dev->norm & V4L2_STD_GH)
if_frequency = 7100000; /*7.1MHz */
else if (dev->norm & V4L2_STD_PAL_I)
if_frequency = 7250000; /*7.25MHz */
else if (dev->norm & V4L2_STD_SECAM_L)
if_frequency = 6900000; /*6.9MHz */
else if (dev->norm & V4L2_STD_SECAM_LC)
if_frequency = 1250000; /*1.25MHz */
cx231xx_info("if_frequency is set to %d\n", if_frequency);
cx231xx_set_Colibri_For_LowIF(dev, if_frequency, 1, 1);
update_HH_register_after_set_DIF(dev);
}
cx231xx_info("Set New FREQUENCY to %d\n", f->frequency); cx231xx_info("Set New FREQUENCY to %d\n", f->frequency);
return rc; return rc;
...@@ -1445,9 +1595,86 @@ static int vidioc_g_register(struct file *file, void *priv, ...@@ -1445,9 +1595,86 @@ static int vidioc_g_register(struct file *file, void *priv,
case V4L2_CHIP_MATCH_I2C_DRIVER: case V4L2_CHIP_MATCH_I2C_DRIVER:
call_all(dev, core, g_register, reg); call_all(dev, core, g_register, reg);
return 0; return 0;
case V4L2_CHIP_MATCH_I2C_ADDR: case V4L2_CHIP_MATCH_I2C_ADDR:/*for register debug*/
/* Not supported yet */ switch (reg->match.addr) {
return -EINVAL; case 0: /* Cx231xx - internal registers */
ret = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
(u16)reg->reg, value, 4);
reg->val = value[0] | value[1] << 8 |
value[2] << 16 | value[3] << 24;
break;
case 0x600:/* AFE - read byte */
ret = cx231xx_read_i2c_master(dev, AFE_DEVICE_ADDRESS,
(u16)reg->reg, 2,
&data, 1 , 0);
reg->val = le32_to_cpu(data & 0xff);
break;
case 0x880:/* Video Block - read byte */
if (reg->reg < 0x0b) {
ret = cx231xx_read_i2c_master(dev,
VID_BLK_I2C_ADDRESS,
(u16)reg->reg, 2,
&data, 1 , 0);
reg->val = le32_to_cpu(data & 0xff);
} else {
ret = cx231xx_read_i2c_master(dev,
VID_BLK_I2C_ADDRESS,
(u16)reg->reg, 2,
&data, 4 , 0);
reg->val = le32_to_cpu(data);
}
break;
case 0x980:
ret = cx231xx_read_i2c_master(dev,
I2S_BLK_DEVICE_ADDRESS,
(u16)reg->reg, 1,
&data, 1 , 0);
reg->val = le32_to_cpu(data & 0xff);
break;
case 0x400:
ret =
cx231xx_read_i2c_master(dev, 0x40,
(u16)reg->reg, 1,
&data, 1 , 0);
reg->val = le32_to_cpu(data & 0xff);
break;
case 0xc01:
ret =
cx231xx_read_i2c_master(dev, 0xc0,
(u16)reg->reg, 2,
&data, 38, 1);
reg->val = le32_to_cpu(data);
break;
case 0x022:
ret =
cx231xx_read_i2c_master(dev, 0x02,
(u16)reg->reg, 1,
&data, 1, 2);
reg->val = le32_to_cpu(data & 0xff);
break;
case 0x322:
ret = cx231xx_read_i2c_master(dev,
0x32,
(u16)reg->reg, 1,
&data, 4 , 2);
reg->val = le32_to_cpu(data);
break;
case 0x342:
ret = cx231xx_read_i2c_master(dev,
0x34,
(u16)reg->reg, 1,
&data, 4 , 2);
reg->val = le32_to_cpu(data);
break;
default:
cx231xx_info("no match device address!!\n");
break;
}
return ret < 0 ? ret : 0;
/*return -EINVAL;*/
default: default:
if (!v4l2_chip_match_host(&reg->match)) if (!v4l2_chip_match_host(&reg->match))
return -EINVAL; return -EINVAL;
...@@ -1531,7 +1758,91 @@ static int vidioc_s_register(struct file *file, void *priv, ...@@ -1531,7 +1758,91 @@ static int vidioc_s_register(struct file *file, void *priv,
} }
} }
return ret < 0 ? ret : 0; return ret < 0 ? ret : 0;
case V4L2_CHIP_MATCH_I2C_ADDR:
{
value = (u32) buf & 0xffffffff;
switch (reg->match.addr) {
case 0:/*cx231xx internal registers*/
data[0] = (u8) value;
data[1] = (u8) (value >> 8);
data[2] = (u8) (value >> 16);
data[3] = (u8) (value >> 24);
ret = cx231xx_write_ctrl_reg(dev,
VRT_SET_REGISTER,
(u16)reg->reg, data,
4);
break;
case 0x600:/* AFE - read byte */
ret = cx231xx_write_i2c_master(dev,
AFE_DEVICE_ADDRESS,
(u16)reg->reg, 2,
value, 1 , 0);
break;
case 0x880:/* Video Block - read byte */
if (reg->reg < 0x0b)
cx231xx_write_i2c_master(dev,
VID_BLK_I2C_ADDRESS,
(u16)reg->reg, 2,
value, 1, 0);
else
cx231xx_write_i2c_master(dev,
VID_BLK_I2C_ADDRESS,
(u16)reg->reg, 2,
value, 4, 0);
break;
case 0x980:
ret =
cx231xx_write_i2c_master(dev,
I2S_BLK_DEVICE_ADDRESS,
(u16)reg->reg, 1,
value, 1, 0);
break;
case 0x400:
ret =
cx231xx_write_i2c_master(dev,
0x40,
(u16)reg->reg, 1,
value, 1, 0);
break;
case 0xc01:
ret =
cx231xx_write_i2c_master(dev,
0xc0,
(u16)reg->reg, 1,
value, 1, 1);
break;
case 0x022:
ret =
cx231xx_write_i2c_master(dev,
0x02,
(u16)reg->reg, 1,
value, 1, 2);
case 0x322:
ret =
cx231xx_write_i2c_master(dev,
0x32,
(u16)reg->reg, 1,
value, 4, 2);
break;
case 0x342:
ret =
cx231xx_write_i2c_master(dev,
0x34,
(u16)reg->reg, 1,
value, 4, 2);
break;
default:
cx231xx_info("no match device address, "
"the value is %x\n", reg->match.addr);
break;
}
}
default: default:
break; break;
} }
...@@ -1975,7 +2286,11 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -1975,7 +2286,11 @@ static int cx231xx_v4l2_open(struct file *filp)
dev->vscale = 0; dev->vscale = 0;
/* Power up in Analog TV mode */ /* Power up in Analog TV mode */
cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV); if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER)
cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ENXTERNAL_AV);
else
cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
#if 0 #if 0
cx231xx_set_mode(dev, CX231XX_ANALOG_MODE); cx231xx_set_mode(dev, CX231XX_ANALOG_MODE);
...@@ -1991,7 +2306,6 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -1991,7 +2306,6 @@ static int cx231xx_v4l2_open(struct file *filp)
/* device needs to be initialized before isoc transfer */ /* device needs to be initialized before isoc transfer */
dev->video_input = dev->video_input > 2 ? 2 : dev->video_input; dev->video_input = dev->video_input > 2 ? 2 : dev->video_input;
video_mux(dev, dev->video_input);
} }
if (fh->radio) { if (fh->radio) {
...@@ -2013,7 +2327,8 @@ static int cx231xx_v4l2_open(struct file *filp) ...@@ -2013,7 +2327,8 @@ static int cx231xx_v4l2_open(struct file *filp)
if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
/* Set the required alternate setting VBI interface works in /* Set the required alternate setting VBI interface works in
Bulk mode only */ Bulk mode only */
cx231xx_set_alt_setting(dev, INDEX_VANC, 0); if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops, videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
NULL, &dev->vbi_mode.slock, NULL, &dev->vbi_mode.slock,
...@@ -2056,6 +2371,10 @@ void cx231xx_release_analog_resources(struct cx231xx *dev) ...@@ -2056,6 +2371,10 @@ void cx231xx_release_analog_resources(struct cx231xx *dev)
if (dev->vdev) { if (dev->vdev) {
cx231xx_info("V4L2 device %s deregistered\n", cx231xx_info("V4L2 device %s deregistered\n",
video_device_node_name(dev->vdev)); video_device_node_name(dev->vdev));
if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER)
cx231xx_417_unregister(dev);
if (video_is_registered(dev->vdev)) if (video_is_registered(dev->vdev))
video_unregister_device(dev->vdev); video_unregister_device(dev->vdev);
else else
...@@ -2077,39 +2396,47 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2077,39 +2396,47 @@ static int cx231xx_v4l2_close(struct file *filp)
cx231xx_videodbg("users=%d\n", dev->users); cx231xx_videodbg("users=%d\n", dev->users);
mutex_lock(&dev->lock); mutex_lock(&dev->lock);
cx231xx_videodbg("users=%d\n", dev->users);
if (res_check(fh)) if (res_check(fh))
res_free(fh); res_free(fh);
if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { /*To workaround error number=-71 on EP0 for VideoGrabber,
videobuf_stop(&fh->vb_vidq); need exclude following.*/
videobuf_mmap_free(&fh->vb_vidq); if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
videobuf_stop(&fh->vb_vidq);
videobuf_mmap_free(&fh->vb_vidq);
/* the device is already disconnect,
free the remaining resources */
if (dev->state & DEV_DISCONNECTED) {
if (atomic_read(&dev->devlist_count) > 0) {
cx231xx_release_resources(dev);
mutex_unlock(&dev->lock);
kfree(dev);
dev = NULL;
return 0;
}
mutex_unlock(&dev->lock);
return 0;
}
/* the device is already disconnect, /* do this before setting alternate! */
free the remaining resources */ cx231xx_uninit_vbi_isoc(dev);
if (dev->state & DEV_DISCONNECTED) {
cx231xx_release_resources(dev); /* set alternate 0 */
if (!dev->vbi_or_sliced_cc_mode)
cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
else
cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
kfree(fh);
dev->users--;
wake_up_interruptible_nr(&dev->open, 1);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
kfree(dev);
return 0; return 0;
} }
/* do this before setting alternate! */
cx231xx_uninit_vbi_isoc(dev);
/* set alternate 0 */
if (!dev->vbi_or_sliced_cc_mode)
cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
else
cx231xx_set_alt_setting(dev, INDEX_HANC, 0);
kfree(fh);
dev->users--;
wake_up_interruptible_nr(&dev->open, 1);
mutex_unlock(&dev->lock);
return 0;
}
if (dev->users == 1) { if (dev->users == 1) {
videobuf_stop(&fh->vb_vidq); videobuf_stop(&fh->vb_vidq);
videobuf_mmap_free(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq);
...@@ -2120,6 +2447,7 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2120,6 +2447,7 @@ static int cx231xx_v4l2_close(struct file *filp)
cx231xx_release_resources(dev); cx231xx_release_resources(dev);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
kfree(dev); kfree(dev);
dev = NULL;
return 0; return 0;
} }
...@@ -2127,7 +2455,10 @@ static int cx231xx_v4l2_close(struct file *filp) ...@@ -2127,7 +2455,10 @@ static int cx231xx_v4l2_close(struct file *filp)
call_all(dev, core, s_power, 0); call_all(dev, core, s_power, 0);
/* do this before setting alternate! */ /* do this before setting alternate! */
cx231xx_uninit_isoc(dev); if (dev->USE_ISO)
cx231xx_uninit_isoc(dev);
else
cx231xx_uninit_bulk(dev);
cx231xx_set_mode(dev, CX231XX_SUSPEND); cx231xx_set_mode(dev, CX231XX_SUSPEND);
/* set alternate 0 */ /* set alternate 0 */
...@@ -2175,7 +2506,7 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count, ...@@ -2175,7 +2506,7 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
* cx231xx_v4l2_poll() * cx231xx_v4l2_poll()
* will allocate buffers when called for the first time * will allocate buffers when called for the first time
*/ */
static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table * wait) static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
{ {
struct cx231xx_fh *fh = filp->private_data; struct cx231xx_fh *fh = filp->private_data;
struct cx231xx *dev = fh->dev; struct cx231xx *dev = fh->dev;
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <media/cx2341x.h>
#include <media/videobuf-vmalloc.h> #include <media/videobuf-vmalloc.h>
#include <media/v4l2-device.h> #include <media/v4l2-device.h>
...@@ -49,12 +50,18 @@ ...@@ -49,12 +50,18 @@
#define AFE_DEVICE_ADDRESS 0x60 #define AFE_DEVICE_ADDRESS 0x60
#define I2S_BLK_DEVICE_ADDRESS 0x98 #define I2S_BLK_DEVICE_ADDRESS 0x98
#define VID_BLK_I2C_ADDRESS 0x88 #define VID_BLK_I2C_ADDRESS 0x88
#define VERVE_I2C_ADDRESS 0x40
#define DIF_USE_BASEBAND 0xFFFFFFFF #define DIF_USE_BASEBAND 0xFFFFFFFF
/* Boards supported by driver */ /* Boards supported by driver */
#define CX231XX_BOARD_UNKNOWN 0 #define CX231XX_BOARD_UNKNOWN 0
#define CX231XX_BOARD_CNXT_RDE_250 1 #define CX231XX_BOARD_CNXT_CARRAERA 1
#define CX231XX_BOARD_CNXT_RDU_250 2 #define CX231XX_BOARD_CNXT_SHELBY 2
#define CX231XX_BOARD_CNXT_RDE_253S 3
#define CX231XX_BOARD_CNXT_RDU_253S 4
#define CX231XX_BOARD_CNXT_VIDEO_GRABBER 5
#define CX231XX_BOARD_CNXT_RDE_250 6
#define CX231XX_BOARD_CNXT_RDU_250 7
/* Limits minimum and default number of buffers */ /* Limits minimum and default number of buffers */
#define CX231XX_MIN_BUF 4 #define CX231XX_MIN_BUF 4
...@@ -95,6 +102,24 @@ ...@@ -95,6 +102,24 @@
#define CX231XX_URB_TIMEOUT \ #define CX231XX_URB_TIMEOUT \
msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS) msecs_to_jiffies(CX231XX_NUM_BUFS * CX231XX_NUM_PACKETS)
#define CX231xx_NORMS (\
V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_JP | V4L2_STD_NTSC_443 | \
V4L2_STD_PAL_BG | V4L2_STD_PAL_DK | V4L2_STD_PAL_I | \
V4L2_STD_PAL_M | V4L2_STD_PAL_N | V4L2_STD_PAL_Nc | \
V4L2_STD_PAL_60 | V4L2_STD_SECAM_L | V4L2_STD_SECAM_DK)
#define CX231xx_VERSION_CODE KERNEL_VERSION(0, 0, 2)
#define SLEEP_S5H1432 30
#define CX23417_OSC_EN 8
#define CX23417_RESET 9
struct cx23417_fmt {
char *name;
u32 fourcc; /* v4l2 format id */
int depth;
int flags;
u32 cxformat;
};
enum cx231xx_mode { enum cx231xx_mode {
CX231XX_SUSPEND, CX231XX_SUSPEND,
CX231XX_ANALOG_MODE, CX231XX_ANALOG_MODE,
...@@ -114,7 +139,7 @@ enum cx231xx_stream_state { ...@@ -114,7 +139,7 @@ enum cx231xx_stream_state {
struct cx231xx; struct cx231xx;
struct cx231xx_usb_isoc_ctl { struct cx231xx_isoc_ctl {
/* max packet size of isoc transaction */ /* max packet size of isoc transaction */
int max_pkt_size; int max_pkt_size;
...@@ -148,6 +173,40 @@ struct cx231xx_usb_isoc_ctl { ...@@ -148,6 +173,40 @@ struct cx231xx_usb_isoc_ctl {
int (*isoc_copy) (struct cx231xx *dev, struct urb *urb); int (*isoc_copy) (struct cx231xx *dev, struct urb *urb);
}; };
struct cx231xx_bulk_ctl {
/* max packet size of bulk transaction */
int max_pkt_size;
/* number of allocated urbs */
int num_bufs;
/* urb for bulk transfers */
struct urb **urb;
/* transfer buffers for bulk transfer */
char **transfer_buffer;
/* Last buffer command and region */
u8 cmd;
int pos, size, pktsize;
/* Last field: ODD or EVEN? */
int field;
/* Stores incomplete commands */
u32 tmp_buf;
int tmp_buf_len;
/* Stores already requested buffers */
struct cx231xx_buffer *buf;
/* Stores the number of received fields */
int nfields;
/* bulk urb callback */
int (*bulk_copy) (struct cx231xx *dev, struct urb *urb);
};
struct cx231xx_fmt { struct cx231xx_fmt {
char *name; char *name;
u32 fourcc; /* v4l2 format id */ u32 fourcc; /* v4l2 format id */
...@@ -165,6 +224,11 @@ struct cx231xx_buffer { ...@@ -165,6 +224,11 @@ struct cx231xx_buffer {
int receiving; int receiving;
}; };
enum ps_package_head {
CX231XX_NEED_ADD_PS_PACKAGE_HEAD = 0,
CX231XX_NONEED_PS_PACKAGE_HEAD
};
struct cx231xx_dmaqueue { struct cx231xx_dmaqueue {
struct list_head active; struct list_head active;
struct list_head queued; struct list_head queued;
...@@ -181,6 +245,14 @@ struct cx231xx_dmaqueue { ...@@ -181,6 +245,14 @@ struct cx231xx_dmaqueue {
u32 lines_completed; u32 lines_completed;
u8 field1_done; u8 field1_done;
u32 lines_per_field; u32 lines_per_field;
/*Mpeg2 control buffer*/
u8 *p_left_data;
u32 left_data_count;
u8 mpeg_buffer_done;
u32 mpeg_buffer_completed;
enum ps_package_head add_ps_package_head;
char ps_head[10];
}; };
/* inputs */ /* inputs */
...@@ -309,7 +381,8 @@ enum AUDIO_INPUT { ...@@ -309,7 +381,8 @@ enum AUDIO_INPUT {
}; };
#define CX231XX_AUDIO_BUFS 5 #define CX231XX_AUDIO_BUFS 5
#define CX231XX_NUM_AUDIO_PACKETS 64 #define CX231XX_NUM_AUDIO_PACKETS 16
#define CX231XX_ISO_NUM_AUDIO_PACKETS 64
#define CX231XX_CAPTURE_STREAM_EN 1 #define CX231XX_CAPTURE_STREAM_EN 1
#define CX231XX_STOP_AUDIO 0 #define CX231XX_STOP_AUDIO 0
#define CX231XX_START_AUDIO 1 #define CX231XX_START_AUDIO 1
...@@ -331,6 +404,7 @@ struct cx231xx_audio { ...@@ -331,6 +404,7 @@ struct cx231xx_audio {
int users, shutdown; int users, shutdown;
enum cx231xx_stream_state capture_stream; enum cx231xx_stream_state capture_stream;
/* locks */
spinlock_t slock; spinlock_t slock;
int alt; /* alternate */ int alt; /* alternate */
...@@ -350,6 +424,28 @@ struct cx231xx_fh { ...@@ -350,6 +424,28 @@ struct cx231xx_fh {
struct videobuf_queue vb_vidq; struct videobuf_queue vb_vidq;
enum v4l2_buf_type type; enum v4l2_buf_type type;
/*following is copyed from cx23885.h*/
u32 resources;
/* video overlay */
struct v4l2_window win;
struct v4l2_clip *clips;
unsigned int nclips;
/* video capture */
struct cx23417_fmt *fmt;
unsigned int width, height;
/* vbi capture */
struct videobuf_queue vidq;
struct videobuf_queue vbiq;
/* MPEG Encoder specifics ONLY */
atomic_t v4l_reading;
}; };
/*****************************************************************/ /*****************************************************************/
...@@ -403,6 +499,13 @@ struct VENDOR_REQUEST_IN { ...@@ -403,6 +499,13 @@ struct VENDOR_REQUEST_IN {
u8 *pBuff; u8 *pBuff;
}; };
struct cx231xx_tvnorm {
char *name;
v4l2_std_id id;
u32 cxiformat;
u32 cxoformat;
};
struct cx231xx_ctrl { struct cx231xx_ctrl {
struct v4l2_queryctrl v; struct v4l2_queryctrl v;
u32 off; u32 off;
...@@ -424,7 +527,9 @@ enum TRANSFER_TYPE { ...@@ -424,7 +527,9 @@ enum TRANSFER_TYPE {
struct cx231xx_video_mode { struct cx231xx_video_mode {
/* Isoc control struct */ /* Isoc control struct */
struct cx231xx_dmaqueue vidq; struct cx231xx_dmaqueue vidq;
struct cx231xx_usb_isoc_ctl isoc_ctl; struct cx231xx_isoc_ctl isoc_ctl;
struct cx231xx_bulk_ctl bulk_ctl;
/* locks */
spinlock_t slock; spinlock_t slock;
/* usb transfer */ /* usb transfer */
...@@ -434,6 +539,64 @@ struct cx231xx_video_mode { ...@@ -434,6 +539,64 @@ struct cx231xx_video_mode {
unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */ unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
u16 end_point_addr; u16 end_point_addr;
}; };
/*
struct cx23885_dmaqueue {
struct list_head active;
struct list_head queued;
struct timer_list timeout;
struct btcx_riscmem stopper;
u32 count;
};
*/
struct cx231xx_tsport {
struct cx231xx *dev;
int nr;
int sram_chno;
struct videobuf_dvb_frontends frontends;
/* dma queues */
u32 ts_packet_size;
u32 ts_packet_count;
int width;
int height;
/* locks */
spinlock_t slock;
/* registers */
u32 reg_gpcnt;
u32 reg_gpcnt_ctl;
u32 reg_dma_ctl;
u32 reg_lngth;
u32 reg_hw_sop_ctrl;
u32 reg_gen_ctrl;
u32 reg_bd_pkt_status;
u32 reg_sop_status;
u32 reg_fifo_ovfl_stat;
u32 reg_vld_misc;
u32 reg_ts_clk_en;
u32 reg_ts_int_msk;
u32 reg_ts_int_stat;
u32 reg_src_sel;
/* Default register vals */
int pci_irqmask;
u32 dma_ctl_val;
u32 ts_int_msk_val;
u32 gen_ctrl_val;
u32 ts_clk_en_val;
u32 src_sel_val;
u32 vld_misc_val;
u32 hw_sop_ctrl_val;
/* Allow a single tsport to have multiple frontends */
u32 num_frontends;
void *port_priv;
};
/* main device struct */ /* main device struct */
struct cx231xx { struct cx231xx {
...@@ -465,7 +628,9 @@ struct cx231xx { ...@@ -465,7 +628,9 @@ struct cx231xx {
/* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */ /* I2C adapters: Master 1 & 2 (External) & Master 3 (Internal only) */
struct cx231xx_i2c i2c_bus[3]; struct cx231xx_i2c i2c_bus[3];
unsigned int xc_fw_load_done:1; unsigned int xc_fw_load_done:1;
/* locks */
struct mutex gpio_i2c_lock; struct mutex gpio_i2c_lock;
struct mutex i2c_lock;
/* video for linux */ /* video for linux */
int users; /* user count for exclusive use */ int users; /* user count for exclusive use */
...@@ -505,6 +670,8 @@ struct cx231xx { ...@@ -505,6 +670,8 @@ struct cx231xx {
struct cx231xx_video_mode sliced_cc_mode; struct cx231xx_video_mode sliced_cc_mode;
struct cx231xx_video_mode ts1_mode; struct cx231xx_video_mode ts1_mode;
atomic_t devlist_count;
struct usb_device *udev; /* the usb device */ struct usb_device *udev; /* the usb device */
char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */ char urb_buf[URB_MAX_CTRL_SIZE]; /* urb control msg buffer */
...@@ -550,8 +717,24 @@ struct cx231xx { ...@@ -550,8 +717,24 @@ struct cx231xx {
u8 vbi_or_sliced_cc_mode; /* 0 - vbi ; 1 - sliced cc mode */ u8 vbi_or_sliced_cc_mode; /* 0 - vbi ; 1 - sliced cc mode */
enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */ enum cx231xx_std_mode std_mode; /* 0 - Air; 1 - cable */
/*mode: digital=1 or analog=0*/
u8 mode_tv;
u8 USE_ISO;
struct cx231xx_tvnorm encodernorm;
struct cx231xx_tsport ts1, ts2;
struct cx2341x_mpeg_params mpeg_params;
struct video_device *v4l_device;
atomic_t v4l_reader_count;
u32 freq;
unsigned int input;
u32 cx23417_mailbox;
u32 __iomem *lmmio;
u8 __iomem *bmmio;
}; };
extern struct list_head cx231xx_devlist;
#define cx25840_call(cx231xx, o, f, args...) \ #define cx25840_call(cx231xx, o, f, args...) \
v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args) v4l2_subdev_call(cx231xx->sd_cx25840, o, f, ##args)
#define tuner_call(cx231xx, o, f, args...) \ #define tuner_call(cx231xx, o, f, args...) \
...@@ -577,6 +760,10 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus); ...@@ -577,6 +760,10 @@ int cx231xx_i2c_register(struct cx231xx_i2c *bus);
int cx231xx_i2c_unregister(struct cx231xx_i2c *bus); int cx231xx_i2c_unregister(struct cx231xx_i2c *bus);
/* Internal block control functions */ /* Internal block control 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 cx231xx_write_i2c_master(struct cx231xx *dev, u8 dev_addr, u16 saddr,
u8 saddr_len, u32 data, u8 data_len, int master);
int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr, int cx231xx_read_i2c_data(struct cx231xx *dev, u8 dev_addr,
u16 saddr, u8 saddr_len, u32 *data, u8 data_len); u16 saddr, u8 saddr_len, u32 *data, u8 data_len);
int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr, int cx231xx_write_i2c_data(struct cx231xx *dev, u8 dev_addr,
...@@ -588,6 +775,9 @@ int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr, ...@@ -588,6 +775,9 @@ int cx231xx_read_modify_write_i2c_dword(struct cx231xx *dev, u8 dev_addr,
u16 saddr, u32 mask, u32 value); u16 saddr, u32 mask, u32 value);
u32 cx231xx_set_field(u32 field_mask, u32 data); u32 cx231xx_set_field(u32 field_mask, u32 data);
/*verve r/w*/
void initGPIO(struct cx231xx *dev);
void uninitGPIO(struct cx231xx *dev);
/* afe related functions */ /* afe related functions */
int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count); int cx231xx_afe_init_super_block(struct cx231xx *dev, u32 ref_count);
int cx231xx_afe_init_channels(struct cx231xx *dev); int cx231xx_afe_init_channels(struct cx231xx *dev);
...@@ -607,6 +797,19 @@ int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input); ...@@ -607,6 +797,19 @@ int cx231xx_i2s_blk_set_audio_input(struct cx231xx *dev, u8 audio_input);
/* DIF related functions */ /* DIF related functions */
int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode, int cx231xx_dif_configure_C2HH_for_low_IF(struct cx231xx *dev, u32 mode,
u32 function_mode, u32 standard); u32 function_mode, u32 standard);
void cx231xx_set_Colibri_For_LowIF(struct cx231xx *dev, u32 if_freq,
u8 spectral_invert, u32 mode);
u32 cx231xx_Get_Colibri_CarrierOffset(u32 mode, u32 standerd);
void cx231xx_set_DIF_bandpass(struct cx231xx *dev, u32 if_freq,
u8 spectral_invert, u32 mode);
void cx231xx_Setup_AFE_for_LowIF(struct cx231xx *dev);
void reset_s5h1432_demod(struct cx231xx *dev);
void cx231xx_dump_HH_reg(struct cx231xx *dev);
void update_HH_register_after_set_DIF(struct cx231xx *dev);
void cx231xx_dump_SC_reg(struct cx231xx *dev);
int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard); int cx231xx_dif_set_standard(struct cx231xx *dev, u32 standard);
int cx231xx_tuner_pre_channel_change(struct cx231xx *dev); int cx231xx_tuner_pre_channel_change(struct cx231xx *dev);
int cx231xx_tuner_post_channel_change(struct cx231xx *dev); int cx231xx_tuner_post_channel_change(struct cx231xx *dev);
...@@ -675,12 +878,26 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type); ...@@ -675,12 +878,26 @@ int cx231xx_capture_start(struct cx231xx *dev, int start, u8 media_type);
int cx231xx_resolution_set(struct cx231xx *dev); int cx231xx_resolution_set(struct cx231xx *dev);
int cx231xx_set_video_alternate(struct cx231xx *dev); int cx231xx_set_video_alternate(struct cx231xx *dev);
int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt); int cx231xx_set_alt_setting(struct cx231xx *dev, u8 index, u8 alt);
int is_fw_load(struct cx231xx *dev);
int cx231xx_check_fw(struct cx231xx *dev);
int cx231xx_init_isoc(struct cx231xx *dev, int max_packets, int cx231xx_init_isoc(struct cx231xx *dev, int max_packets,
int num_bufs, int max_pkt_size, int num_bufs, int max_pkt_size,
int (*isoc_copy) (struct cx231xx *dev, int (*isoc_copy) (struct cx231xx *dev,
struct urb *urb)); struct urb *urb));
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));
void cx231xx_stop_TS1(struct cx231xx *dev);
void cx231xx_start_TS1(struct cx231xx *dev);
void cx231xx_uninit_isoc(struct cx231xx *dev); void cx231xx_uninit_isoc(struct cx231xx *dev);
void cx231xx_uninit_bulk(struct cx231xx *dev);
int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode); int cx231xx_set_mode(struct cx231xx *dev, enum cx231xx_mode set_mode);
int cx231xx_unmute_audio(struct cx231xx *dev);
int cx231xx_ep5_bulkout(struct cx231xx *dev, u8 *firmware, u16 size);
void cx231xx_disable656(struct cx231xx *dev);
void cx231xx_enable656(struct cx231xx *dev);
int cx231xx_demod_reset(struct cx231xx *dev);
int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio); int cx231xx_gpio_set(struct cx231xx *dev, struct cx231xx_reg_seq *gpio);
/* Device list functions */ /* Device list functions */
...@@ -740,6 +957,10 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg); ...@@ -740,6 +957,10 @@ int cx231xx_tuner_callback(void *ptr, int component, int command, int arg);
int cx231xx_ir_init(struct cx231xx *dev); int cx231xx_ir_init(struct cx231xx *dev);
int cx231xx_ir_fini(struct cx231xx *dev); int cx231xx_ir_fini(struct cx231xx *dev);
/* cx23885-417.c */
extern int cx231xx_417_register(struct cx231xx *dev);
extern void cx231xx_417_unregister(struct cx231xx *dev);
/* printk macros */ /* printk macros */
#define cx231xx_err(fmt, arg...) do {\ #define cx231xx_err(fmt, arg...) do {\
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment