Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb

* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/v4l-dvb:
  V4L/DVB (5751): Ivtv: fix ia64 printk format warnings.
  V4L/DVB (5761): Fix broken b2c2 dependency on non x86 architectures
  V4L/DVB (5673): Fix audio stuttering for saa711x/ivtv when in radio mode.
  V4L/DVB (5736): Add V4L2_FBUF_CAP/FLAG_LOCAL/GLOBAL_INV_ALPHA
  V4L/DVB (5732): Add ivtv CROPCAP support and fix ivtv S_CROP for video output.
  V4L/DVB (5730): Remove unused V4L2_CAP_VIDEO_OUTPUT_POS
  V4L/DVB (5720): Usbvision: fix urb allocation and submits
  V4L/DVB (5716): Tda10086,tda826x: fix tuning, STR/SNR values
  V4L/DVB (5675): Move big PIO accesses from the interrupt handler to a workhandler
  V4L/DVB (5699): Cinergyt2: fix file release handler
  V4L/DVB (5700): Saa7111: fix picture settings cache bug
  V4L/DVB (5702): Fix Kconfig items to avoid linkedition errors
This commit is contained in:
Linus Torvalds 2007-06-11 11:32:28 -07:00
commit b44c0267b7
21 changed files with 369 additions and 170 deletions

View File

@ -4,5 +4,6 @@ config VIDEO_SAA7146
config VIDEO_SAA7146_VV config VIDEO_SAA7146_VV
tristate tristate
depends on VIDEO_DEV
select VIDEO_BUF select VIDEO_BUF
select VIDEO_SAA7146 select VIDEO_SAA7146

View File

@ -1,8 +1,11 @@
b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
flexcop-dma.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
b2c2-flexcop-objs += flexcop-dma.o
endif
b2c2-flexcop-pci-objs = flexcop-pci.o b2c2-flexcop-pci-objs = flexcop-pci.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o

View File

@ -519,8 +519,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv; struct cinergyt2 *cinergyt2 = dvbdev->priv;
if (mutex_lock_interruptible(&cinergyt2->sem)) mutex_lock(&cinergyt2->sem);
return -ERESTARTSYS;
if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
cancel_delayed_work(&cinergyt2->query_work); cancel_delayed_work(&cinergyt2->query_work);

View File

@ -41,6 +41,7 @@ struct tda10086_state {
/* private demod data */ /* private demod data */
u32 frequency; u32 frequency;
u32 symbol_rate; u32 symbol_rate;
bool has_lock;
}; };
static int debug = 0; static int debug = 0;
@ -116,7 +117,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// misc setup // misc setup
tda10086_write_byte(state, 0x01, 0x94); tda10086_write_byte(state, 0x01, 0x94);
tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
tda10086_write_byte(state, 0x03, 0x64); tda10086_write_byte(state, 0x03, 0xe4);
tda10086_write_byte(state, 0x04, 0x43); tda10086_write_byte(state, 0x04, 0x43);
tda10086_write_byte(state, 0x0c, 0x0c); tda10086_write_byte(state, 0x0c, 0x0c);
tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
@ -146,7 +147,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// setup AGC // setup AGC
tda10086_write_byte(state, 0x05, 0x0B); tda10086_write_byte(state, 0x05, 0x0B);
tda10086_write_byte(state, 0x37, 0x63); tda10086_write_byte(state, 0x37, 0x63);
tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
tda10086_write_byte(state, 0x40, 0x64); tda10086_write_byte(state, 0x40, 0x64);
tda10086_write_byte(state, 0x41, 0x4f); tda10086_write_byte(state, 0x41, 0x4f);
tda10086_write_byte(state, 0x42, 0x43); tda10086_write_byte(state, 0x42, 0x43);
@ -398,6 +399,10 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
// modify parameters for tuning
tda10086_write_byte(state, 0x02, 0x35);
state->has_lock = false;
// set params // set params
if (fe->ops.tuner_ops.set_params) { if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, fe_params); fe->ops.tuner_ops.set_params(fe, fe_params);
@ -542,8 +547,14 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
*fe_status |= FE_HAS_VITERBI; *fe_status |= FE_HAS_VITERBI;
if (val & 0x08) if (val & 0x08)
*fe_status |= FE_HAS_SYNC; *fe_status |= FE_HAS_SYNC;
if (val & 0x10) if (val & 0x10) {
*fe_status |= FE_HAS_LOCK; *fe_status |= FE_HAS_LOCK;
if (!state->has_lock) {
state->has_lock = true;
// modify parameters for stable reception
tda10086_write_byte(state, 0x02, 0x00);
}
}
return 0; return 0;
} }
@ -555,7 +566,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
_str = tda10086_read_byte(state, 0x43); _str = 0xff - tda10086_read_byte(state, 0x43);
*signal = (_str << 8) | _str; *signal = (_str << 8) | _str;
return 0; return 0;
@ -568,7 +579,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
_snr = tda10086_read_byte(state, 0x1c); _snr = 0xff - tda10086_read_byte(state, 0x1c);
*snr = (_snr << 8) | _snr; *snr = (_snr << 8) | _snr;
return 0; return 0;

View File

@ -89,8 +89,8 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
buf[3] = div >> 7; buf[3] = div >> 7;
buf[4] = div << 1; buf[4] = div << 1;
buf[5] = 0xff; // basedband filter to max buf[5] = 0x77; // baseband cut-off 19 MHz
buf[6] = 0xfe; // gains at max + no RF attenuation buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
buf[7] = 0x83; // charge pumps at high, tests off buf[7] = 0x83; // charge pumps at high, tests off
buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports. buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL

View File

@ -347,7 +347,7 @@ endmenu # encoder / decoder chips
config VIDEO_VIVI config VIDEO_VIVI
tristate "Virtual Video Driver" tristate "Virtual Video Driver"
depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI && VIDEO_DEV
select VIDEO_BUF select VIDEO_BUF
default n default n
---help--- ---help---

View File

@ -86,7 +86,7 @@
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
V4L2_CAP_SLICED_VBI_CAPTURE) V4L2_CAP_SLICED_VBI_CAPTURE)
#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ #define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \
V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_POS) V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
struct ivtv_card_video_input { struct ivtv_card_video_input {
u8 video_type; /* video input type */ u8 video_type; /* video input type */

View File

@ -652,6 +652,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
itv->dma_timer.data = (unsigned long)itv; itv->dma_timer.data = (unsigned long)itv;
itv->cur_dma_stream = -1; itv->cur_dma_stream = -1;
itv->cur_pio_stream = -1;
itv->audio_stereo_mode = AUDIO_STEREO; itv->audio_stereo_mode = AUDIO_STEREO;
itv->audio_bilingual_mode = AUDIO_MONO_LEFT; itv->audio_bilingual_mode = AUDIO_MONO_LEFT;

View File

@ -237,6 +237,7 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) #define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29)
#define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) #define IVTV_IRQ_ENC_VIM_RST (0x1 << 28)
#define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) #define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27)
#define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25)
#define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) #define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24)
#define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) #define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22)
#define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) #define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20)
@ -247,7 +248,8 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_DEC_VSYNC (0x1 << 10) #define IVTV_IRQ_DEC_VSYNC (0x1 << 10)
/* IRQ Masks */ /* IRQ Masks */
#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ) #define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
#define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) #define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
@ -374,6 +376,9 @@ struct ivtv_mailbox_data {
#define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */ #define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */
#define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ #define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */
#define IVTV_F_S_PIO_PENDING 9 /* this stream has pending PIO */
#define IVTV_F_S_PIO_HAS_VBI 1 /* the current PIO request also requests VBI data */
/* per-ivtv, i_flags */ /* per-ivtv, i_flags */
#define IVTV_F_I_DMA 0 /* DMA in progress */ #define IVTV_F_I_DMA 0 /* DMA in progress */
#define IVTV_F_I_UDMA 1 /* UDMA in progress */ #define IVTV_F_I_UDMA 1 /* UDMA in progress */
@ -390,8 +395,11 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */
#define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ #define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */
#define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */
#define IVTV_F_I_WORK_HANDLER_VBI 15 /* there is work to be done for VBI */ #define IVTV_F_I_HAVE_WORK 15 /* Used in the interrupt handler: there is work to be done */
#define IVTV_F_I_WORK_HANDLER_YUV 16 /* there is work to be done for YUV */ #define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */
#define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */
#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */
#define IVTV_F_I_PIO 19 /* PIO in progress */
/* Event notifications */ /* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
@ -484,6 +492,7 @@ struct ivtv_stream {
/* Base Dev SG Array for cx23415/6 */ /* Base Dev SG Array for cx23415/6 */
struct ivtv_SG_element *SGarray; struct ivtv_SG_element *SGarray;
struct ivtv_SG_element *PIOarray;
dma_addr_t SG_handle; dma_addr_t SG_handle;
int SG_length; int SG_length;
@ -706,6 +715,7 @@ struct ivtv {
atomic_t decoding; /* count number of active decoding streams */ atomic_t decoding; /* count number of active decoding streams */
u32 irq_rr_idx; /* Round-robin stream index */ u32 irq_rr_idx; /* Round-robin stream index */
int cur_dma_stream; /* index of stream doing DMA */ int cur_dma_stream; /* index of stream doing DMA */
int cur_pio_stream; /* index of stream doing PIO */
u32 dma_data_req_offset; u32 dma_data_req_offset;
u32 dma_data_req_size; u32 dma_data_req_size;
int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */ int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */

View File

@ -32,6 +32,8 @@
#include "ivtv-yuv.h" #include "ivtv-yuv.h"
#include "ivtv-controls.h" #include "ivtv-controls.h"
#include "ivtv-ioctl.h" #include "ivtv-ioctl.h"
#include "ivtv-cards.h"
#include <media/saa7115.h>
/* This function tries to claim the stream for a specific file descriptor. /* This function tries to claim the stream for a specific file descriptor.
If no one else is using this stream then the stream is claimed and If no one else is using this stream then the stream is claimed and
@ -786,6 +788,13 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
/* Select correct audio input (i.e. TV tuner or Line in) */ /* Select correct audio input (i.e. TV tuner or Line in) */
ivtv_audio_set_io(itv); ivtv_audio_set_io(itv);
if (itv->hw_flags & IVTV_HW_SAA711X)
{
struct v4l2_crystal_freq crystal_freq;
crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
crystal_freq.flags = 0;
ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
}
/* Done! Unmute and continue. */ /* Done! Unmute and continue. */
ivtv_unmute(itv); ivtv_unmute(itv);
ivtv_release_stream(s); ivtv_release_stream(s);
@ -872,6 +881,13 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
/* Select the correct audio input (i.e. radio tuner) */ /* Select the correct audio input (i.e. radio tuner) */
ivtv_audio_set_io(itv); ivtv_audio_set_io(itv);
if (itv->hw_flags & IVTV_HW_SAA711X)
{
struct v4l2_crystal_freq crystal_freq;
crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
crystal_freq.flags = SAA7115_FREQ_FL_APLL;
ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
}
/* Done! Unmute and continue. */ /* Done! Unmute and continue. */
ivtv_unmute(itv); ivtv_unmute(itv);
} }

View File

@ -532,11 +532,6 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
itv->yuv_info.yuv_forced_update = 1; itv->yuv_info.yuv_forced_update = 1;
return 0; return 0;
} }
if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
r.width, r.height, r.left, r.top))
itv->main_rect = r;
else
return -EINVAL;
} }
return 0; return 0;
} }
@ -799,9 +794,39 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
return ivtv_get_fmt(itv, id->type, fmt); return ivtv_get_fmt(itv, id->type, fmt);
} }
case VIDIOC_CROPCAP: {
struct v4l2_cropcap *cropcap = arg;
if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
return -EINVAL;
cropcap->bounds.top = cropcap->bounds.left = 0;
cropcap->bounds.width = 720;
if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
cropcap->bounds.height = itv->is_50hz ? 576 : 480;
cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
} else {
cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
}
cropcap->defrect = cropcap->bounds;
return 0;
}
case VIDIOC_S_CROP: { case VIDIOC_S_CROP: {
struct v4l2_crop *crop = arg; struct v4l2_crop *crop = arg;
if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
itv->main_rect = crop->c;
return 0;
}
return -EINVAL;
}
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_S_CROP, arg); return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
@ -810,6 +835,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_G_CROP: { case VIDIOC_G_CROP: {
struct v4l2_crop *crop = arg; struct v4l2_crop *crop = arg;
if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
crop->c = itv->main_rect;
return 0;
}
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_G_CROP, arg); return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
@ -977,7 +1007,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
if (itv->hw_flags & IVTV_HW_CX25840) { if (itv->hw_flags & IVTV_HW_CX25840) {
itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
} }
IVTV_DEBUG_INFO("Switching standard to %llx.\n", itv->std); IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
/* Tuner */ /* Tuner */
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
@ -1207,7 +1237,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
(s->buffers - s->q_free.buffers) * 100 / s->buffers, (s->buffers - s->q_free.buffers) * 100 / s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers); (s->buffers * s->buf_size) / 1024, s->buffers);
} }
IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", itv->mpg_data_received, itv->vbi_data_inserted); IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
break; break;
} }
@ -1455,6 +1485,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_S_FMT: case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT: case VIDIOC_TRY_FMT:
case VIDIOC_ENUM_FMT: case VIDIOC_ENUM_FMT:
case VIDIOC_CROPCAP:
case VIDIOC_G_CROP: case VIDIOC_G_CROP:
case VIDIOC_S_CROP: case VIDIOC_S_CROP:
case VIDIOC_G_FREQUENCY: case VIDIOC_G_FREQUENCY:

View File

@ -31,8 +31,6 @@
#define DMA_MAGIC_COOKIE 0x000001fe #define DMA_MAGIC_COOKIE 0x000001fe
#define SLICED_VBI_PIO 1
static void ivtv_dma_dec_start(struct ivtv_stream *s); static void ivtv_dma_dec_start(struct ivtv_stream *s);
static const int ivtv_stream_map[] = { static const int ivtv_stream_map[] = {
@ -42,12 +40,40 @@ static const int ivtv_stream_map[] = {
IVTV_ENC_STREAM_TYPE_VBI, IVTV_ENC_STREAM_TYPE_VBI,
}; };
static inline int ivtv_use_pio(struct ivtv_stream *s)
{
struct ivtv *itv = s->itv;
return s->dma == PCI_DMA_NONE || static void ivtv_pio_work_handler(struct ivtv *itv)
(SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); {
struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
struct ivtv_buffer *buf;
struct list_head *p;
int i = 0;
IVTV_DEBUG_DMA("ivtv_pio_work_handler\n");
if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
s->v4l2dev == NULL || !ivtv_use_pio(s)) {
itv->cur_pio_stream = -1;
/* trigger PIO complete user interrupt */
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
return;
}
IVTV_DEBUG_DMA("Process PIO %s\n", s->name);
buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list);
list_for_each(p, &s->q_dma.list) {
struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
u32 size = s->PIOarray[i].size & 0x3ffff;
/* Copy the data from the card to the buffer */
if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size);
}
else {
memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size);
}
if (s->PIOarray[i].size & 0x80000000)
break;
i++;
}
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
} }
void ivtv_irq_work_handler(struct work_struct *work) void ivtv_irq_work_handler(struct work_struct *work)
@ -56,8 +82,11 @@ void ivtv_irq_work_handler(struct work_struct *work)
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
ivtv_pio_work_handler(itv);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags)) if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
vbi_work_handler(itv); ivtv_vbi_work_handler(itv);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
ivtv_yuv_work_handler(itv); ivtv_yuv_work_handler(itv);
@ -173,8 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
} }
s->buffers_stolen = rc; s->buffers_stolen = rc;
/* got the buffers, now fill in SGarray (DMA) or copy the data from the card /* got the buffers, now fill in SGarray (DMA) */
to the buffers (PIO). */
buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
memset(buf->buf, 0, 128); memset(buf->buf, 0, 128);
list_for_each(p, &s->q_predma.list) { list_for_each(p, &s->q_predma.list) {
@ -182,21 +210,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
if (skip_bufs-- > 0) if (skip_bufs-- > 0)
continue; continue;
if (!ivtv_use_pio(s)) {
s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
s->SGarray[idx].src = cpu_to_le32(offset); s->SGarray[idx].src = cpu_to_le32(offset);
s->SGarray[idx].size = cpu_to_le32(s->buf_size); s->SGarray[idx].size = cpu_to_le32(s->buf_size);
}
buf->bytesused = (size < s->buf_size) ? size : s->buf_size; buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
/* If PIO, then copy the data from the card to the buffer */
if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused);
}
else if (ivtv_use_pio(s)) {
memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused);
}
s->q_predma.bytesused += buf->bytesused; s->q_predma.bytesused += buf->bytesused;
size -= buf->bytesused; size -= buf->bytesused;
offset += s->buf_size; offset += s->buf_size;
@ -224,11 +242,6 @@ static void dma_post(struct ivtv_stream *s)
u32 *u32buf; u32 *u32buf;
int x = 0; int x = 0;
if (ivtv_use_pio(s)) {
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
s->SG_length = 0;
}
IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
s->name, s->dma_offset); s->name, s->dma_offset);
list_for_each(p, &s->q_dma.list) { list_for_each(p, &s->q_dma.list) {
@ -278,10 +291,14 @@ static void dma_post(struct ivtv_stream *s)
if (buf) if (buf)
buf->bytesused += s->dma_last_offset; buf->bytesused += s->dma_last_offset;
if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
list_for_each(p, &s->q_dma.list) {
buf = list_entry(p, struct ivtv_buffer, list);
/* Parse and Groom VBI Data */ /* Parse and Groom VBI Data */
s->q_dma.bytesused -= buf->bytesused; s->q_dma.bytesused -= buf->bytesused;
ivtv_process_vbi_data(itv, buf, 0, s->type); ivtv_process_vbi_data(itv, buf, 0, s->type);
s->q_dma.bytesused += buf->bytesused; s->q_dma.bytesused += buf->bytesused;
}
if (s->id == -1) { if (s->id == -1) {
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
return; return;
@ -351,10 +368,14 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
int i; int i;
IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
if (s->q_predma.bytesused) if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
IVTV_DEBUG_DMA("start DMA for %s\n", s->name);
s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); if (ivtv_use_dma(s))
s->SGarray[s->SG_length - 1].size =
cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
/* If this is an MPEG stream, and VBI data is also pending, then append the /* If this is an MPEG stream, and VBI data is also pending, then append the
VBI DMA to the MPEG DMA and transfer both sets of data at once. VBI DMA to the MPEG DMA and transfer both sets of data at once.
@ -368,6 +389,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length && if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length &&
s->SG_length + s_vbi->SG_length <= s->buffers) { s->SG_length + s_vbi->SG_length <= s->buffers) {
ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
if (ivtv_use_dma(s_vbi))
s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
for (i = 0; i < s_vbi->SG_length; i++) { for (i = 0; i < s_vbi->SG_length; i++) {
s->SGarray[s->SG_length++] = s_vbi->SGarray[i]; s->SGarray[s->SG_length++] = s_vbi->SGarray[i];
@ -381,6 +403,17 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
/* Mark last buffer size for Interrupt flag */ /* Mark last buffer size for Interrupt flag */
s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
if (ivtv_use_pio(s)) {
for (i = 0; i < s->SG_length; i++) {
s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src);
s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size);
}
set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
set_bit(IVTV_F_I_PIO, &itv->i_flags);
itv->cur_pio_stream = s->type;
}
else {
/* Sync Hardware SG List of buffers */ /* Sync Hardware SG List of buffers */
ivtv_stream_sync_for_device(s); ivtv_stream_sync_for_device(s);
write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
@ -390,6 +423,7 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
itv->dma_timer.expires = jiffies + HZ / 10; itv->dma_timer.expires = jiffies + HZ / 10;
add_timer(&itv->dma_timer); add_timer(&itv->dma_timer);
} }
}
static void ivtv_dma_dec_start(struct ivtv_stream *s) static void ivtv_dma_dec_start(struct ivtv_stream *s)
{ {
@ -489,6 +523,40 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
wake_up(&itv->dma_waitq); wake_up(&itv->dma_waitq);
} }
static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
{
struct ivtv_stream *s;
if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
itv->cur_pio_stream = -1;
return;
}
s = &itv->streams[itv->cur_pio_stream];
IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name);
s->SG_length = 0;
clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
clear_bit(IVTV_F_I_PIO, &itv->i_flags);
itv->cur_pio_stream = -1;
dma_post(s);
if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
clear_bit(IVTV_F_I_PIO, &itv->i_flags);
if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
u32 tmp;
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
tmp = s->dma_offset;
s->dma_offset = itv->vbi.dma_offset;
dma_post(s);
s->dma_offset = tmp;
}
wake_up(&itv->dma_waitq);
}
static void ivtv_irq_dma_err(struct ivtv *itv) static void ivtv_irq_dma_err(struct ivtv *itv)
{ {
u32 data[CX2341X_MBOX_MAX_DATA]; u32 data[CX2341X_MBOX_MAX_DATA];
@ -532,13 +600,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
s = &itv->streams[ivtv_stream_map[data[0]]]; s = &itv->streams[ivtv_stream_map[data[0]]];
if (!stream_enc_dma_append(s, data)) { if (!stream_enc_dma_append(s, data)) {
if (ivtv_use_pio(s)) { set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
dma_post(s);
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]);
}
else {
set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
}
} }
} }
@ -551,15 +613,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
IVTV_DEBUG_IRQ("ENC START VBI CAP\n"); IVTV_DEBUG_IRQ("ENC START VBI CAP\n");
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
if (ivtv_use_pio(s)) {
if (stream_enc_dma_append(s, data))
return;
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
s->SG_length = 0;
dma_post(s);
return;
}
/* If more than two VBI buffers are pending, then /* If more than two VBI buffers are pending, then
clear the old ones and start with this new one. clear the old ones and start with this new one.
This can happen during transition stages when MPEG capturing is This can happen during transition stages when MPEG capturing is
@ -582,11 +635,11 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
if (!stream_enc_dma_append(s, data) && if (!stream_enc_dma_append(s, data) &&
!test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
} }
} }
static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
{ {
u32 data[CX2341X_MBOX_MAX_DATA]; u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
@ -594,7 +647,7 @@ static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv)
IVTV_DEBUG_IRQ("DEC VBI REINSERT\n"); IVTV_DEBUG_IRQ("DEC VBI REINSERT\n");
if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) && if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
!stream_enc_dma_append(s, data)) { !stream_enc_dma_append(s, data)) {
dma_post(s); set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
} }
} }
@ -657,7 +710,6 @@ static void ivtv_irq_vsync(struct ivtv *itv)
} }
if (frame != (itv->lastVsyncFrame & 1)) { if (frame != (itv->lastVsyncFrame & 1)) {
struct ivtv_stream *s = ivtv_get_output_stream(itv); struct ivtv_stream *s = ivtv_get_output_stream(itv);
int work = 0;
itv->lastVsyncFrame += 1; itv->lastVsyncFrame += 1;
if (frame == 0) { if (frame == 0) {
@ -678,7 +730,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
/* Send VBI to saa7127 */ /* Send VBI to saa7127 */
if (frame) { if (frame) {
set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
work = 1; set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
} }
/* Check if we need to update the yuv registers */ /* Check if we need to update the yuv registers */
@ -691,11 +743,9 @@ static void ivtv_irq_vsync(struct ivtv *itv)
itv->yuv_info.new_frame_info[last_dma_frame].update = 0; itv->yuv_info.new_frame_info[last_dma_frame].update = 0;
itv->yuv_info.yuv_forced_update = 0; itv->yuv_info.yuv_forced_update = 0;
set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
work = 1; set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
} }
} }
if (work)
queue_work(itv->irq_work_queues, &itv->irq_work_queue);
} }
} }
@ -755,6 +805,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
ivtv_irq_enc_dma_complete(itv); ivtv_irq_enc_dma_complete(itv);
} }
if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
ivtv_irq_enc_pio_complete(itv);
}
if (combo & IVTV_IRQ_DMA_ERR) { if (combo & IVTV_IRQ_DMA_ERR) {
ivtv_irq_dma_err(itv); ivtv_irq_dma_err(itv);
} }
@ -768,7 +822,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
} }
if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) { if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
ivtv_irq_dev_vbi_reinsert(itv); ivtv_irq_dec_vbi_reinsert(itv);
} }
if (combo & IVTV_IRQ_ENC_EOS) { if (combo & IVTV_IRQ_ENC_EOS) {
@ -813,6 +867,22 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
} }
} }
if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
for (i = 0; i < IVTV_MAX_STREAMS; i++) {
int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS;
struct ivtv_stream *s = &itv->streams[idx];
if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
continue;
if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
ivtv_dma_enc_start(s);
break;
}
}
if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags))
queue_work(itv->irq_work_queues, &itv->irq_work_queue);
spin_unlock(&itv->dma_reg_lock); spin_unlock(&itv->dma_reg_lock);
/* If we've just handled a 'forced' vsync, it's safest to say it /* If we've just handled a 'forced' vsync, it's safest to say it

View File

@ -195,14 +195,26 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
s->dma != PCI_DMA_NONE ? "DMA " : "", s->dma != PCI_DMA_NONE ? "DMA " : "",
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
if (ivtv_might_use_pio(s)) {
s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
if (s->PIOarray == NULL) {
IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name);
return -ENOMEM;
}
}
/* Allocate DMA SG Arrays */ /* Allocate DMA SG Arrays */
if (s->dma != PCI_DMA_NONE) {
s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
if (s->SGarray == NULL) { if (s->SGarray == NULL) {
IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name); IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
if (ivtv_might_use_pio(s)) {
kfree(s->PIOarray);
s->PIOarray = NULL;
}
return -ENOMEM; return -ENOMEM;
} }
s->SG_length = 0; s->SG_length = 0;
if (ivtv_might_use_dma(s)) {
s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma); s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma);
ivtv_stream_sync_for_cpu(s); ivtv_stream_sync_for_cpu(s);
} }
@ -219,7 +231,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
break; break;
} }
INIT_LIST_HEAD(&buf->list); INIT_LIST_HEAD(&buf->list);
if (s->dma != PCI_DMA_NONE) { if (ivtv_might_use_dma(s)) {
buf->dma_handle = pci_map_single(s->itv->dev, buf->dma_handle = pci_map_single(s->itv->dev,
buf->buf, s->buf_size + 256, s->dma); buf->buf, s->buf_size + 256, s->dma);
ivtv_buf_sync_for_cpu(s, buf); ivtv_buf_sync_for_cpu(s, buf);
@ -242,7 +254,7 @@ void ivtv_stream_free(struct ivtv_stream *s)
/* empty q_free */ /* empty q_free */
while ((buf = ivtv_dequeue(s, &s->q_free))) { while ((buf = ivtv_dequeue(s, &s->q_free))) {
if (s->dma != PCI_DMA_NONE) if (ivtv_might_use_dma(s))
pci_unmap_single(s->itv->dev, buf->dma_handle, pci_unmap_single(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma); s->buf_size + 256, s->dma);
kfree(buf->buf); kfree(buf->buf);
@ -256,6 +268,9 @@ void ivtv_stream_free(struct ivtv_stream *s)
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
s->SG_handle = IVTV_DMA_UNMAPPED; s->SG_handle = IVTV_DMA_UNMAPPED;
} }
kfree(s->SGarray);
kfree(s->PIOarray);
s->PIOarray = NULL;
s->SGarray = NULL; s->SGarray = NULL;
s->SG_length = 0; s->SG_length = 0;
} }

View File

@ -20,18 +20,43 @@
*/ */
#define IVTV_DMA_UNMAPPED ((u32) -1) #define IVTV_DMA_UNMAPPED ((u32) -1)
#define SLICED_VBI_PIO 1
/* ivtv_buffer utility functions */ /* ivtv_buffer utility functions */
static inline int ivtv_might_use_pio(struct ivtv_stream *s)
{
return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
}
static inline int ivtv_use_pio(struct ivtv_stream *s)
{
struct ivtv *itv = s->itv;
return s->dma == PCI_DMA_NONE ||
(SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
}
static inline int ivtv_might_use_dma(struct ivtv_stream *s)
{
return s->dma != PCI_DMA_NONE;
}
static inline int ivtv_use_dma(struct ivtv_stream *s)
{
return !ivtv_use_pio(s);
}
static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
{ {
if (s->dma != PCI_DMA_NONE) if (ivtv_use_dma(s))
pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle, pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma); s->buf_size + 256, s->dma);
} }
static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
{ {
if (s->dma != PCI_DMA_NONE) if (ivtv_use_dma(s))
pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle, pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma); s->buf_size + 256, s->dma);
} }
@ -53,12 +78,14 @@ void ivtv_stream_free(struct ivtv_stream *s);
static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
{ {
if (ivtv_use_dma(s))
pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
} }
static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
{ {
if (ivtv_use_dma(s))
pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
} }

View File

@ -868,7 +868,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags)) if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
return 0; return 0;
IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", pts, flags); IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
/* Stop Decoder */ /* Stop Decoder */
if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) {

View File

@ -450,7 +450,7 @@ void ivtv_disable_vbi(struct ivtv *itv)
} }
void vbi_work_handler(struct ivtv *itv) void ivtv_vbi_work_handler(struct ivtv *itv)
{ {
struct v4l2_sliced_vbi_data data; struct v4l2_sliced_vbi_data data;

View File

@ -23,4 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
int ivtv_used_line(struct ivtv *itv, int line, int field); int ivtv_used_line(struct ivtv *itv, int line, int field);
void ivtv_disable_vbi(struct ivtv *itv); void ivtv_disable_vbi(struct ivtv *itv);
void ivtv_set_vbi(unsigned long arg); void ivtv_set_vbi(unsigned long arg);
void vbi_work_handler(struct ivtv *itv); void ivtv_vbi_work_handler(struct ivtv *itv);

View File

@ -75,10 +75,6 @@ struct saa7111 {
int norm; int norm;
int input; int input;
int enable; int enable;
int bright;
int contrast;
int hue;
int sat;
}; };
#define I2C_SAA7111 0x48 #define I2C_SAA7111 0x48
@ -96,6 +92,17 @@ saa7111_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value); return i2c_smbus_write_byte_data(client, reg, value);
} }
static inline void
saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
if (decoder->reg[reg] != value) {
decoder->reg[reg] = value;
i2c_smbus_write_byte_data(client, reg, value);
}
}
static int static int
saa7111_write_block (struct i2c_client *client, saa7111_write_block (struct i2c_client *client,
const u8 *data, const u8 *data,
@ -439,28 +446,14 @@ saa7111_command (struct i2c_client *client,
{ {
struct video_picture *pic = arg; struct video_picture *pic = arg;
if (decoder->bright != pic->brightness) {
/* We want 0 to 255 we get 0-65535 */ /* We want 0 to 255 we get 0-65535 */
decoder->bright = pic->brightness; saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
saa7111_write(client, 0x0a, decoder->bright >> 8);
}
if (decoder->contrast != pic->contrast) {
/* We want 0 to 127 we get 0-65535 */ /* We want 0 to 127 we get 0-65535 */
decoder->contrast = pic->contrast; saa7111_write(client, 0x0b, pic->contrast >> 9);
saa7111_write(client, 0x0b,
decoder->contrast >> 9);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 127 we get 0-65535 */ /* We want 0 to 127 we get 0-65535 */
decoder->sat = pic->colour; saa7111_write(client, 0x0c, pic->colour >> 9);
saa7111_write(client, 0x0c, decoder->sat >> 9);
}
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */ /* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue; saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
saa7111_write(client, 0x0d,
(decoder->hue - 32768) >> 8);
}
} }
break; break;
@ -524,10 +517,6 @@ saa7111_detect_client (struct i2c_adapter *adapter,
decoder->norm = VIDEO_MODE_NTSC; decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0; decoder->input = 0;
decoder->enable = 1; decoder->enable = 1;
decoder->bright = 32768;
decoder->contrast = 32768;
decoder->hue = 32768;
decoder->sat = 32768;
i2c_set_clientdata(client, decoder); i2c_set_clientdata(client, decoder);
i = i2c_attach_client(client); i = i2c_attach_client(client);

View File

@ -1414,6 +1414,11 @@ static void usbvision_isocIrq(struct urb *urb)
if (!USBVISION_IS_OPERATIONAL(usbvision)) if (!USBVISION_IS_OPERATIONAL(usbvision))
return; return;
/* any urb with wrong status is ignored without acknowledgement */
if (urb->status == -ENOENT) {
return;
}
f = &usbvision->curFrame; f = &usbvision->curFrame;
/* Manage streaming interruption */ /* Manage streaming interruption */
@ -1436,20 +1441,23 @@ static void usbvision_isocIrq(struct urb *urb)
if (usbvision->streaming == Stream_On) { if (usbvision->streaming == Stream_On) {
/* If we collected enough data let's parse! */ /* If we collected enough data let's parse! */
if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) &&
/*If we don't have a frame we're current working on, complain */ (!list_empty(&(usbvision->inqueue))) ) {
if(!list_empty(&(usbvision->inqueue))) {
if (!(*f)) { if (!(*f)) {
(*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); (*f) = list_entry(usbvision->inqueue.next,
struct usbvision_frame,
frame);
} }
usbvision_parse_data(usbvision); usbvision_parse_data(usbvision);
} }
else { else {
PDEBUG(DBG_IRQ, "received data, but no one needs it"); /*If we don't have a frame
we're current working on, complain */
PDEBUG(DBG_IRQ,
"received data, but no one needs it");
scratch_reset(usbvision); scratch_reset(usbvision);
} }
} }
}
else { else {
PDEBUG(DBG_IRQ, "received data, but no one needs it"); PDEBUG(DBG_IRQ, "received data, but no one needs it");
scratch_reset(usbvision); scratch_reset(usbvision);
@ -1466,10 +1474,10 @@ static void usbvision_isocIrq(struct urb *urb)
urb->dev = usbvision->dev; urb->dev = usbvision->dev;
errCode = usb_submit_urb (urb, GFP_ATOMIC); errCode = usb_submit_urb (urb, GFP_ATOMIC);
/* Disable this warning. By design of the driver. */ if(errCode) {
// if(errCode) { err("%s: usb_submit_urb failed: error %d",
// err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); __FUNCTION__, errCode);
// } }
return; return;
} }
@ -2394,7 +2402,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
{ {
struct usb_device *dev = usbvision->dev; struct usb_device *dev = usbvision->dev;
int bufIdx, errCode, regValue; int bufIdx, errCode, regValue;
const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; int sb_size;
if (!USBVISION_IS_OPERATIONAL(usbvision)) if (!USBVISION_IS_OPERATIONAL(usbvision))
return -EFAULT; return -EFAULT;
@ -2408,11 +2416,14 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
usbvision->last_error = errCode; usbvision->last_error = errCode;
return -EBUSY; return -EBUSY;
} }
sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; regValue = (16 - usbvision_read_reg(usbvision,
USBVISION_ALTER_REG)) & 0x0F;
usbvision->usb_bandwidth = regValue >> 1; usbvision->usb_bandwidth = regValue >> 1;
PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
usbvision->usb_bandwidth);
@ -2428,7 +2439,11 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
return -ENOMEM; return -ENOMEM;
} }
usbvision->sbuf[bufIdx].urb = urb; usbvision->sbuf[bufIdx].urb = urb;
usbvision->sbuf[bufIdx].data = usb_buffer_alloc(usbvision->dev, sb_size, GFP_KERNEL,&urb->transfer_dma); usbvision->sbuf[bufIdx].data =
usb_buffer_alloc(usbvision->dev,
sb_size,
GFP_KERNEL,
&urb->transfer_dma);
urb->dev = dev; urb->dev = dev;
urb->context = usbvision; urb->context = usbvision;
urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
@ -2442,21 +2457,26 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
for (j = k = 0; j < USBVISION_URB_FRAMES; j++, for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
k += usbvision->isocPacketSize) { k += usbvision->isocPacketSize) {
urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].offset = k;
urb->iso_frame_desc[j].length = usbvision->isocPacketSize; urb->iso_frame_desc[j].length =
usbvision->isocPacketSize;
} }
} }
/* Submit all URBs */ /* Submit all URBs */
for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
GFP_KERNEL);
if (errCode) { if (errCode) {
err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode); err("%s: usb_submit_urb(%d) failed: error %d",
__FUNCTION__, bufIdx, errCode);
} }
} }
usbvision->streaming = Stream_Idle; usbvision->streaming = Stream_Idle;
PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
__FUNCTION__,
usbvision->video_endp);
return 0; return 0;
} }
@ -2470,7 +2490,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
void usbvision_stop_isoc(struct usb_usbvision *usbvision) void usbvision_stop_isoc(struct usb_usbvision *usbvision)
{ {
int bufIdx, errCode, regValue; int bufIdx, errCode, regValue;
const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
return; return;
@ -2499,15 +2519,19 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
errCode = usb_set_interface(usbvision->dev, usbvision->iface, errCode = usb_set_interface(usbvision->dev, usbvision->iface,
usbvision->ifaceAlt); usbvision->ifaceAlt);
if (errCode < 0) { if (errCode < 0) {
err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); err("%s: usb_set_interface() failed: error %d",
__FUNCTION__, errCode);
usbvision->last_error = errCode; usbvision->last_error = errCode;
} }
regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; usbvision->isocPacketSize =
PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); (regValue == 0) ? 0 : (regValue * 64) - 1;
PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
usbvision->isocPacketSize);
usbvision->usb_bandwidth = regValue >> 1; usbvision->usb_bandwidth = regValue >> 1;
PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
usbvision->usb_bandwidth);
} }
} }

View File

@ -146,7 +146,6 @@
#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask #define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
#define USBVISION_URB_FRAMES 32 #define USBVISION_URB_FRAMES 32
#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023
#define USBVISION_NUM_HEADERMARKER 20 #define USBVISION_NUM_HEADERMARKER 20
#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */

View File

@ -243,8 +243,7 @@ struct v4l2_capability
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ #define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ #define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ #define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
#define V4L2_CAP_VIDEO_OUTPUT_POS 0x00000200 /* Video output can have x,y coords */ #define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000400 /* Can do video output overlay */
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ #define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ #define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
@ -616,12 +615,16 @@ struct v4l2_framebuffer
#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 #define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008
#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 #define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010
#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 #define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020
#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040
#define V4L2_FBUF_CAP_GLOBAL_INV_ALPHA 0x0080
/* Flags for the 'flags' field. */ /* Flags for the 'flags' field. */
#define V4L2_FBUF_FLAG_PRIMARY 0x0001 #define V4L2_FBUF_FLAG_PRIMARY 0x0001
#define V4L2_FBUF_FLAG_OVERLAY 0x0002 #define V4L2_FBUF_FLAG_OVERLAY 0x0002
#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 #define V4L2_FBUF_FLAG_CHROMAKEY 0x0004
#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 #define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008
#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 #define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010
#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020
#define V4L2_FBUF_FLAG_GLOBAL_INV_ALPHA 0x0040
struct v4l2_clip struct v4l2_clip
{ {