[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: Palash Bandyopadhyay <palash.bandyopadhyay@conexant.com>
Signed-off-by: Devin Heitmueller <dheitmueller@hauppauge.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
Palash Bandyopadhyay 2010-07-06 18:12:25 -03:00 committed by Mauro Carvalho Chehab
parent 47b75ec146
commit 64fbf44455
15 changed files with 7996 additions and 237 deletions

View File

@ -1,5 +1,5 @@
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

File diff suppressed because it is too large Load Diff

View File

@ -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)
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)
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)
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)
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)
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;
if (is_fw_load(dev) == 0)
cx25840_call(dev, core, load_fw);
if (dev->USE_ISO)
cx231xx_init_audio_isoc(dev); 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)
/* set alternate setting for audio interface */ /* set alternate setting for audio interface */
/* 1 - 48000 samples per sec */ /* 1 - 48000 samples per sec */
if (dev->USE_ISO)
ret = cx231xx_set_alt_setting(dev, INDEX_AUDIO, 1); 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)
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)
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)
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)
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");

View File

@ -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 @@
[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)
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,
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)
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)
return status; return status;
} }
} }
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, 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,
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,
/* 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,
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)
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)
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)
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)
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,
/* 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,
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,
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)
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)
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,
{ {
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,
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)
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)
{ {
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)) {
if (dev->tuner_type == TUNER_NXP_TDA18271) {
dwval &= ~FLD_DIF_IF_REF;
dwval |= 0x88000300;
} else
dwval |= 0x88000000; dwval |= 0x88000000;
else } else {
if (dev->tuner_type == TUNER_NXP_TDA18271) {
dwval &= ~FLD_DIF_IF_REF;
dwval |= 0xCC000300;
} else
dwval |= 0x44000000; 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)
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)
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)
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)
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)
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)
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)
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__);

View File

@ -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[] = {
} }
}, },
}, },
[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[] = {
} }
}, },
}, },
[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[] = {
} }
}, },
}, },
[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[] = {
{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)
} }
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)
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)
/* 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,15 +540,39 @@ void cx231xx_card_setup(struct cx231xx *dev)
} }
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:
if (dev->board.tuner_type != TUNER_ABSENT) { if (dev->board.tuner_type != TUNER_ABSENT) {
dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev, dev->sd_tuner = v4l2_i2c_new_subdev(&dev->v4l2_dev,
&dev->i2c_bus[1].i2c_adap, &dev->i2c_bus[1].i2c_adap,
"tuner", "tuner", 0xc2 >> 1, NULL); "tuner", "tuner", 0xc2 >> 1, NULL);
if (dev->sd_tuner == NULL) if (dev->sd_tuner == NULL)
cx231xx_info("tuner subdev registration failure\n"); cx231xx_info(
"tuner subdev registration failure\n");
cx231xx_config_tuner(dev); 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,
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,
/* 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,
/* 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,
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,
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,
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,
/* 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,
* 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,
/* 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,
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,
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,
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,
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,
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,
} }
} }
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)
video_device_node_name(dev->vdev)); video_device_node_name(dev->vdev));
dev->state |= DEV_MISCONFIGURED; dev->state |= DEV_MISCONFIGURED;
if (dev->USE_ISO)
cx231xx_uninit_isoc(dev); 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)
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;
} }
} }

View File

@ -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 */

View File

@ -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");
* 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);
*/ */
void cx231xx_remove_from_devlist(struct cx231xx *dev) void cx231xx_remove_from_devlist(struct cx231xx *dev)
{ {
if (dev == NULL)
return;
if (dev->udev == NULL)
return;
if (atomic_read(&dev->devlist_count) > 0) {
mutex_lock(&cx231xx_devlist_mutex); mutex_lock(&cx231xx_devlist_mutex);
list_del(&dev->devlist); list_del(&dev->devlist);
atomic_dec(&dev->devlist_count);
mutex_unlock(&cx231xx_devlist_mutex); 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)
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,
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,
{ {
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,
cx231xx_isocdbg("\n"); cx231xx_isocdbg("\n");
} }
/*
If the cx23102 read more than 4 bytes with i2c bus,
need chop to 4 byte per request
*/
if ((ven_req->wLength > 4) && ((ven_req->bRequest == 0x4) ||
(ven_req->bRequest == 0x5) ||
(ven_req->bRequest == 0x6))) {
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); mutex_lock(&dev->ctrl_urb_lock);
ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest, ret = usb_control_msg(dev->udev, pipe, ven_req->bRequest,
ven_req-> ven_req->
direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE, direction | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
ven_req->wValue, ven_req->wIndex, ven_req->pBuff, ven_req->wValue, ven_req->wIndex, pdata,
ven_req->wLength, HZ); unsend_size, HZ);
mutex_unlock(&dev->ctrl_urb_lock); 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)
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,6 +543,8 @@ 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);
if (dev->video_mode.alt_max_pkt_size != NULL)
dev->video_mode.max_pkt_size = dev->video_mode.max_pkt_size =
dev->video_mode.alt_max_pkt_size[dev->video_mode.alt]; 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",
@ -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,6 +635,9 @@ 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);
/*To workaround error number=-71 on EP0 for videograbber,
need add following codes.*/
if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
return -1; return -1;
} }
@ -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)
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);
/* /*
* 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)
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)
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); cx231xx_capture_start(dev, 0, Raw_Video);
else
cx231xx_capture_start(dev, 0, TS1_serial_mode);
} }
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,
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,
/* 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,
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,
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,
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,
} }
} }
if (dev->mode_tv == 0)
cx231xx_capture_start(dev, 1, Raw_Video); 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,13 +1332,32 @@ 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) {
errCode = cx231xx_set_power_mode(dev,
POLARIS_AVMODE_ENXTERNAL_AV);
if (errCode < 0) { if (errCode < 0) {
cx231xx_errdev cx231xx_errdev
("%s: Failed to set Power - errCode [%d]!\n", ("%s: Failed to set Power - errCode [%d]!\n",
__func__, errCode); __func__, errCode);
return 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);
@ -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,6 +1431,7 @@ 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 */
if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3); errCode = cx231xx_enable_i2c_for_tuner(dev, I2C_3);
return errCode; return errCode;
@ -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)
{ {

File diff suppressed because it is too large Load Diff

View File

@ -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 {
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,7 +173,8 @@ 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->transfer_buffer +
urb->iso_frame_desc[i].offset, urb->iso_frame_desc[i].offset,
urb->iso_frame_desc[i].actual_length); urb->iso_frame_desc[i].actual_length);
} }
@ -136,26 +182,72 @@ static inline int dvb_isoc_copy(struct cx231xx *dev, struct urb *urb)
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) {
cx231xx_info("DVB transfer mode is ISO.\n");
mutex_lock(&dev->i2c_lock);
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); rc = cx231xx_set_mode(dev, CX231XX_DIGITAL_MODE);
if (rc < 0) if (rc < 0)
return rc; return rc;
dev->mode_tv = 1;
return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS, return cx231xx_init_isoc(dev, CX231XX_DVB_MAX_PACKETS,
CX231XX_DVB_NUM_BUFS, CX231XX_DVB_NUM_BUFS,
CX231XX_DVB_MAX_PACKETSIZE, dvb_isoc_copy); 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);
}
} }
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;
if (dev->USE_ISO)
cx231xx_uninit_isoc(dev); 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)
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)
/*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)
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)
} }
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)
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;
} }

View File

@ -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,
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,
} }
} 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,
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;
} }

View File

@ -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 {
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 {
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)
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)
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)
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;

View File

@ -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)
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,
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)
/* 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)
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);
*/ */
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,
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,
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,
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,
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,
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,
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,
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,
{ {
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,
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;

View File

@ -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);

View File

@ -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);
if (dev->USE_ISO)
dev->video_mode.isoc_ctl.buf = NULL; 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,
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");
if (dev->USE_ISO)
dev->video_mode.isoc_ctl.buf = NULL; 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,
outp = videobuf_to_vmalloc(&(*buf)->vb); outp = videobuf_to_vmalloc(&(*buf)->vb);
memset(outp, 0, (*buf)->vb.size); memset(outp, 0, (*buf)->vb.size);
if (dev->USE_ISO)
dev->video_mode.isoc_ctl.buf = *buf; 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)
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,
cx231xx_reset_video_buffer(dev, dma_q); cx231xx_reset_video_buffer(dev, dma_q);
/* get the buffer pointer */ /* get the buffer pointer */
if (dev->USE_ISO)
buf = dev->video_mode.isoc_ctl.buf; 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,
dma_q->field1_done = 0; dma_q->field1_done = 0;
} }
if (dev->USE_ISO)
buf = dev->video_mode.isoc_ctl.buf; 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,
void *startwrite; void *startwrite;
int offset, lencopy; int offset, lencopy;
if (dev->USE_ISO)
buf = dev->video_mode.isoc_ctl.buf; 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)
{ {
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)
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)
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->USE_ISO) {
if (dev->video_mode.isoc_ctl.buf == buf) if (dev->video_mode.isoc_ctl.buf == buf)
dev->video_mode.isoc_ctl.buf = NULL; 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,
goto fail; goto fail;
} }
if (dev->USE_ISO) {
if (!dev->video_mode.isoc_ctl.num_bufs) if (!dev->video_mode.isoc_ctl.num_bufs)
urb_init = 1; 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) {
dev->mode_tv = 0;
if (dev->USE_ISO)
rc = cx231xx_init_isoc(dev, CX231XX_NUM_PACKETS, 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;
} }
@ -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,
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,11 +1489,6 @@ 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;
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); call_all(dev, tuner, s_frequency, f);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
@ -1368,6 +1496,28 @@ static int vidioc_s_frequency(struct file *file, void *priv,
/* 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,
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,
} }
} }
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,6 +2286,10 @@ 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 */
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); cx231xx_set_power_mode(dev, POLARIS_AVMODE_ANALOGT_TV);
#if 0 #if 0
@ -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,6 +2327,7 @@ 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 */
if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
cx231xx_set_alt_setting(dev, INDEX_VANC, 0); 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,
@ -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,10 +2396,13 @@ 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);
/*To workaround error number=-71 on EP0 for VideoGrabber,
need exclude following.*/
if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER)
if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) { if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
videobuf_stop(&fh->vb_vidq); videobuf_stop(&fh->vb_vidq);
videobuf_mmap_free(&fh->vb_vidq); videobuf_mmap_free(&fh->vb_vidq);
@ -2088,9 +2410,14 @@ static int cx231xx_v4l2_close(struct file *filp)
/* the device is already disconnect, /* the device is already disconnect,
free the remaining resources */ free the remaining resources */
if (dev->state & DEV_DISCONNECTED) { if (dev->state & DEV_DISCONNECTED) {
if (atomic_read(&dev->devlist_count) > 0) {
cx231xx_release_resources(dev); cx231xx_release_resources(dev);
mutex_unlock(&dev->lock); mutex_unlock(&dev->lock);
kfree(dev); kfree(dev);
dev = NULL;
return 0;
}
mutex_unlock(&dev->lock);
return 0; return 0;
} }
@ -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)
call_all(dev, core, s_power, 0); call_all(dev, core, s_power, 0);
/* do this before setting alternate! */ /* do this before setting alternate! */
if (dev->USE_ISO)
cx231xx_uninit_isoc(dev); 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 */

View File

@ -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 @@
#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 @@
#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 {
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 {
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 {
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 {
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 {
}; };
#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 {
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 {
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 {
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 {
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 {
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 {
/* 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 {
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 {
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);
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,
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);
/* 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);
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);
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 {\