提交 fd8b281a 编写于 作者: H Hans Verkuil 提交者: Mauro Carvalho Chehab

V4L/DVB (6093): ivtv: reorganized and cleanup ivtv struct

Signed-off-by: NHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 33c0fcad
......@@ -667,7 +667,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
cx2341x_fill_defaults(&itv->params);
itv->params.port = CX2341X_PORT_MEMORY;
itv->params.capabilities = CX2341X_CAP_HAS_SLICED_VBI;
init_waitqueue_head(&itv->cap_w);
init_waitqueue_head(&itv->eos_waitq);
init_waitqueue_head(&itv->event_waitq);
init_waitqueue_head(&itv->vsync_waitq);
init_waitqueue_head(&itv->dma_waitq);
......@@ -713,14 +713,6 @@ static void __devinit ivtv_init_struct2(struct ivtv *itv)
break;
itv->nof_audio_inputs = i;
/* 0x00EF = saa7114(239) 0x00F0 = saa7115(240) 0x0106 = micro */
if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X))
itv->digitizer = 0xF1;
else if (itv->card->hw_all & IVTV_HW_SAA7114)
itv->digitizer = 0xEF;
else /* cx25840 */
itv->digitizer = 0x140;
if (itv->card->hw_all & IVTV_HW_CX25840) {
itv->vbi.sliced_size = 288; /* multiple of 16, real size = 284 */
} else {
......@@ -749,6 +741,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
u16 cmd;
u8 card_rev;
unsigned char pci_latency;
IVTV_DEBUG_INFO("Enabling pci device\n");
......@@ -795,7 +788,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
}
IVTV_DEBUG_INFO("Bus Mastering Enabled.\n");
pci_read_config_byte(dev, PCI_CLASS_REVISION, &itv->card_rev);
pci_read_config_byte(dev, PCI_CLASS_REVISION, &card_rev);
pci_read_config_byte(dev, PCI_LATENCY_TIMER, &pci_latency);
if (pci_latency < 64 && ivtv_pci_latency) {
......@@ -812,7 +805,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
IVTV_DEBUG_INFO("%d (rev %d) at %02x:%02x.%x, "
"irq: %d, latency: %d, memory: 0x%lx\n",
itv->dev->device, itv->card_rev, dev->bus->number,
itv->dev->device, card_rev, dev->bus->number,
PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
itv->dev->irq, pci_latency, (unsigned long)itv->base_addr);
......
......@@ -550,133 +550,134 @@ struct ivtv_card;
/* Struct to hold info about ivtv cards */
struct ivtv {
int num; /* board number, -1 during init! */
char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */
struct pci_dev *dev; /* PCI device */
/* General fixed card data */
int num; /* board number, -1 during init! */
char name[8]; /* board name for printk and interrupts (e.g. 'ivtv0') */
struct pci_dev *dev; /* PCI device */
const struct ivtv_card *card; /* card information */
const char *card_name; /* full name of the card */
u8 has_cx23415; /* 1 if it is a cx23415 based card, 0 for cx23416 */
u8 is_50hz;
u8 is_60hz;
u8 is_out_50hz;
u8 is_out_60hz;
u8 pvr150_workaround; /* 1 if the cx25840 needs to workaround a PVR150 bug */
u8 nof_inputs; /* number of video inputs */
u8 nof_audio_inputs; /* number of audio inputs */
u32 v4l2_cap; /* V4L2 capabilities of card */
u32 hw_flags; /* Hardware description of the board */
int tunerid; /* Userspace tuner ID for experimental Xceive tuner support */
/* controlling Video decoder function */
const char *card_name; /* full name of the card */
u8 has_cx23415; /* 1 if it is a cx23415 based card, 0 for cx23416 */
u8 pvr150_workaround; /* 1 if the cx25840 needs to workaround a PVR150 bug */
u8 nof_inputs; /* number of video inputs */
u8 nof_audio_inputs; /* number of audio inputs */
u32 v4l2_cap; /* V4L2 capabilities of card */
u32 hw_flags; /* hardware description of the board */
int tunerid; /* userspace tuner ID for experimental Xceive tuner support */
v4l2_std_id tuner_std; /* the norm of the card's tuner (fixed) */
/* controlling video decoder function */
int (*video_dec_func)(struct ivtv *, unsigned int, void *);
u32 base_addr; /* PCI resource base address */
volatile void __iomem *enc_mem; /* pointer to mapped encoder memory */
volatile void __iomem *dec_mem; /* pointer to mapped decoder memory */
volatile void __iomem *reg_mem; /* pointer to mapped registers */
struct ivtv_options options; /* user options */
/* High-level state info */
unsigned long i_flags; /* global ivtv flags */
u8 is_50hz; /* 1 if the current capture standard is 50 Hz */
u8 is_60hz /* 1 if the current capture standard is 60 Hz */;
u8 is_out_50hz /* 1 if the current TV output standard is 50 Hz */;
u8 is_out_60hz /* 1 if the current TV output standard is 60 Hz */;
int output_mode; /* decoder output mode: NONE, MPG, YUV, UDMA YUV, passthrough */
u32 audio_input; /* current audio input */
u32 active_input; /* current video input */
u32 active_output; /* current video output */
v4l2_std_id std; /* current capture TV standard */
v4l2_std_id std_out; /* current TV output standard */
u8 audio_stereo_mode; /* decoder setting how to handle stereo MPEG audio */
u8 audio_bilingual_mode; /* decoder setting how to handle bilingual MPEG audio */
struct cx2341x_mpeg_params params; /* current encoder parameters */
/* Locking */
spinlock_t lock; /* lock access to this struct */
/* mutex used to serialize open/close/start/stop/ioctl operations */
struct mutex serialize_lock;
/* Streams */
int stream_buf_size[IVTV_MAX_STREAMS]; /* stream buffer size */
struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* stream data */
atomic_t capturing; /* count number of active capture streams */
atomic_t decoding; /* count number of active decoding streams */
/* Interrupts & DMA */
u32 irqmask; /* active interrupts */
u32 irq_rr_idx; /* round-robin stream index */
struct workqueue_struct *irq_work_queues; /* workqueue for PIO/YUV/VBI actions */
struct work_struct irq_work_queue; /* work entry */
spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
int cur_dma_stream; /* index of current stream doing DMA (-1 if none) */
int cur_pio_stream; /* index of current stream doing PIO (-1 if none) */
u32 dma_data_req_offset; /* store offset in decoder memory of current DMA request */
u32 dma_data_req_size; /* store size of current DMA request */
int dma_retries; /* current DMA retry attempt */
struct ivtv_user_dma udma; /* user based DMA for OSD */
struct timer_list dma_timer; /* timer used to catch unfinished DMAs */
u32 last_vsync_frame; /* last seen vsync field */
wait_queue_head_t dma_waitq; /* wake up when the current DMA is finished */
wait_queue_head_t eos_waitq; /* wake up when EOS arrives */
wait_queue_head_t event_waitq; /* wake up when the next decoder event arrives */
wait_queue_head_t vsync_waitq; /* wake up when the next decoder vsync arrives */
/* Mailbox */
struct ivtv_mailbox_data enc_mbox; /* encoder mailboxes */
struct ivtv_mailbox_data dec_mbox; /* decoder mailboxes */
struct ivtv_api_cache api_cache[256]; /* cached API commands */
/* I2C */
struct i2c_adapter i2c_adap;
struct i2c_algo_bit_data i2c_algo;
struct i2c_client i2c_client;
struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];/* pointers to all I2C clients */
int i2c_state; /* i2c bit state */
struct mutex i2c_bus_lock; /* lock i2c bus */
/* Program Index information */
u32 pgm_info_offset; /* start of pgm info in encoder memory */
u32 pgm_info_num; /* number of elements in the pgm cyclic buffer in encoder memory */
u32 pgm_info_write_idx; /* last index written by the card that was transferred to pgm_info[] */
u32 pgm_info_read_idx; /* last index in pgm_info read by the application */
struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX]; /* filled from the pgm cyclic buffer on the card */
/* Miscellaneous */
u32 open_id; /* incremented each time an open occurs, is >= 1 */
struct v4l2_prio_state prio; /* priority state */
int search_pack_header; /* 1 if ivtv_copy_buf_to_user() is scanning for a pack header (0xba) */
int speed; /* current playback speed setting */
u8 speed_mute_audio; /* 1 if audio should be muted when fast forward */
u64 mpg_data_received; /* number of bytes received from the MPEG stream */
u64 vbi_data_inserted; /* number of VBI bytes inserted into the MPEG stream */
u32 last_dec_timing[3]; /* cache last retrieved pts/scr/frame values */
unsigned long dualwatch_jiffies;/* jiffies value of the previous dualwatch check */
u16 dualwatch_stereo_mode; /* current detected dualwatch stereo mode */
/* VBI state info */
struct vbi_info vbi; /* VBI-specific data */
/* YUV playback */
struct yuv_playback_info yuv_info; /* YUV playback data */
struct ivtv_options options; /* User options */
int stream_buf_size[IVTV_MAX_STREAMS]; /* Stream buffer size */
struct ivtv_stream streams[IVTV_MAX_STREAMS]; /* Stream data */
int speed;
u8 speed_mute_audio;
unsigned long i_flags; /* global ivtv flags */
atomic_t capturing; /* count number of active capture streams */
atomic_t decoding; /* count number of active decoding streams */
u32 irq_rr_idx; /* Round-robin stream index */
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_size;
int dma_retries;
int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */
spinlock_t lock; /* lock access to this struct */
int search_pack_header;
spinlock_t dma_reg_lock; /* lock access to DMA engine registers */
struct mutex serialize_lock; /* lock used to serialize starting streams */
/* User based DMA for OSD */
struct ivtv_user_dma udma;
int open_id; /* incremented each time an open occurs, used as unique ID.
starts at 1, so 0 can be used as uninitialized value
in the stream->id. */
u32 base_addr;
u32 irqmask;
struct v4l2_prio_state prio;
struct workqueue_struct *irq_work_queues;
struct work_struct irq_work_queue;
struct timer_list dma_timer; /* Timer used to catch unfinished DMAs */
struct vbi_info vbi;
struct ivtv_mailbox_data enc_mbox;
struct ivtv_mailbox_data dec_mbox;
struct ivtv_api_cache api_cache[256]; /* Cached API Commands */
u8 card_rev;
volatile void __iomem *enc_mem, *dec_mem, *reg_mem;
u32 pgm_info_offset;
u32 pgm_info_num;
u32 pgm_info_write_idx;
u32 pgm_info_read_idx;
struct v4l2_enc_idx_entry pgm_info[IVTV_MAX_PGM_INDEX];
u64 mpg_data_received;
u64 vbi_data_inserted;
wait_queue_head_t cap_w;
/* when the next decoder event arrives this queue is woken up */
wait_queue_head_t event_waitq;
/* when the next decoder vsync arrives this queue is woken up */
wait_queue_head_t vsync_waitq;
/* when the current DMA is finished this queue is woken up */
wait_queue_head_t dma_waitq;
/* OSD support */
unsigned long osd_video_pbase;
int osd_global_alpha_state; /* 0=off : 1=on */
int osd_local_alpha_state; /* 0=off : 1=on */
int osd_color_key_state; /* 0=off : 1=on */
u8 osd_global_alpha; /* Current global alpha */
u32 osd_color_key; /* Current color key */
u32 osd_pixelformat; /* Current pixel format */
struct v4l2_rect osd_rect; /* Current OSD position and size */
struct v4l2_rect main_rect; /* Current Main window position and size */
u32 last_dec_timing[3]; /* Store last retrieved pts/scr/frame values */
/* i2c */
struct i2c_adapter i2c_adap;
struct i2c_algo_bit_data i2c_algo;
struct i2c_client i2c_client;
struct mutex i2c_bus_lock;
int i2c_state;
struct i2c_client *i2c_clients[I2C_CLIENTS_MAX];
/* v4l2 and User settings */
/* codec settings */
struct cx2341x_mpeg_params params;
u32 audio_input;
u32 active_input;
u32 active_output;
v4l2_std_id std;
v4l2_std_id std_out;
v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */
u8 audio_stereo_mode;
u8 audio_bilingual_mode;
/* dualwatch */
unsigned long dualwatch_jiffies;
u16 dualwatch_stereo_mode;
/* Digitizer type */
int digitizer; /* 0x00EF = saa7114 0x00FO = saa7115 0x0106 = mic */
u32 lastVsyncFrame;
struct yuv_playback_info yuv_info;
struct osd_info *osd_info;
int osd_global_alpha_state; /* 1 = global alpha is on */
int osd_local_alpha_state; /* 1 = local alpha is on */
int osd_chroma_key_state; /* 1 = chroma-keying is on */
u8 osd_global_alpha; /* current global alpha */
u32 osd_chroma_key; /* current chroma key */
u32 osd_pixelformat; /* current pixel format */
struct v4l2_rect osd_rect; /* current OSD position and size */
struct v4l2_rect main_rect; /* current Main window position and size */
struct osd_info *osd_info; /* ivtv-fb private OSD info */
};
/* Globals */
......
......@@ -405,7 +405,7 @@ static int ivtvfb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long ar
if (itv->is_50hz && trace > 312) trace -= 312;
else if (itv->is_60hz && trace > 262) trace -= 262;
if (trace == 1) vblank.flags |= FB_VBLANK_VSYNCING;
vblank.count = itv->lastVsyncFrame;
vblank.count = itv->last_vsync_frame;
vblank.vcount = trace;
vblank.hcount = 0;
if (copy_to_user((void __user *)arg, &vblank, sizeof(vblank)))
......
......@@ -163,7 +163,7 @@ void ivtv_set_osd_alpha(struct ivtv *itv)
{
ivtv_vapi(itv, CX2341X_OSD_SET_GLOBAL_ALPHA, 3,
itv->osd_global_alpha_state, itv->osd_global_alpha, !itv->osd_local_alpha_state);
ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_color_key_state, itv->osd_color_key);
ivtv_vapi(itv, CX2341X_OSD_SET_CHROMA_KEY, 2, itv->osd_chroma_key_state, itv->osd_chroma_key);
}
int ivtv_set_speed(struct ivtv *itv, int speed)
......@@ -426,7 +426,7 @@ static int ivtv_get_fmt(struct ivtv *itv, int streamtype, struct v4l2_format *fm
case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL;
fmt->fmt.win.chromakey = itv->osd_color_key;
fmt->fmt.win.chromakey = itv->osd_chroma_key;
fmt->fmt.win.global_alpha = itv->osd_global_alpha;
break;
......@@ -546,7 +546,7 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
return -EINVAL;
if (set_fmt) {
itv->osd_color_key = fmt->fmt.win.chromakey;
itv->osd_chroma_key = fmt->fmt.win.chromakey;
itv->osd_global_alpha = fmt->fmt.win.global_alpha;
ivtv_set_osd_alpha(itv);
}
......@@ -1197,7 +1197,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
fb->flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
if (itv->osd_local_alpha_state)
fb->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
if (itv->osd_color_key_state)
if (itv->osd_chroma_key_state)
fb->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
break;
}
......@@ -1209,7 +1209,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
return -EINVAL;
itv->osd_global_alpha_state = (fb->flags & V4L2_FBUF_FLAG_GLOBAL_ALPHA) != 0;
itv->osd_local_alpha_state = (fb->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) != 0;
itv->osd_color_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
ivtv_set_osd_alpha(itv);
break;
}
......
......@@ -750,8 +750,8 @@ static void ivtv_irq_vsync(struct ivtv *itv)
if (0) IVTV_DEBUG_IRQ("DEC VSYNC\n");
if (((frame ^ itv->yuv_info.sync_field[last_dma_frame]) == 0 &&
((itv->lastVsyncFrame & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) ||
(frame != (itv->lastVsyncFrame & 1) && !itv->yuv_info.frame_interlaced)) {
((itv->last_vsync_frame & 1) ^ itv->yuv_info.sync_field[last_dma_frame])) ||
(frame != (itv->last_vsync_frame & 1) && !itv->yuv_info.frame_interlaced)) {
int next_dma_frame = last_dma_frame;
if (!(itv->yuv_info.frame_interlaced && itv->yuv_info.field_delay[next_dma_frame] && itv->yuv_info.fields_lapsed < 1)) {
......@@ -766,10 +766,10 @@ static void ivtv_irq_vsync(struct ivtv *itv)
}
}
}
if (frame != (itv->lastVsyncFrame & 1)) {
if (frame != (itv->last_vsync_frame & 1)) {
struct ivtv_stream *s = ivtv_get_output_stream(itv);
itv->lastVsyncFrame += 1;
itv->last_vsync_frame += 1;
if (frame == 0) {
clear_bit(IVTV_F_I_VALID_DEC_TIMINGS, &itv->i_flags);
clear_bit(IVTV_F_I_EV_VSYNC_FIELD, &itv->i_flags);
......@@ -834,7 +834,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
*/
if (~itv->irqmask & IVTV_IRQ_DEC_VSYNC) {
/* vsync is enabled, see if we're in a new field */
if ((itv->lastVsyncFrame & 1) != (read_reg(0x28c0) & 1)) {
if ((itv->last_vsync_frame & 1) != (read_reg(0x28c0) & 1)) {
/* New field, looks like we missed it */
IVTV_DEBUG_YUV("VSync interrupt missed %d\n",read_reg(0x28c0)>>16);
vsync_force = 1;
......@@ -888,7 +888,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
if (combo & IVTV_IRQ_ENC_EOS) {
IVTV_DEBUG_IRQ("ENC EOS\n");
set_bit(IVTV_F_I_EOS, &itv->i_flags);
wake_up(&itv->cap_w);
wake_up(&itv->eos_waitq);
}
if (combo & IVTV_IRQ_DEC_DATA_REQ) {
......
......@@ -404,8 +404,8 @@ static void ivtv_vbi_setup(struct ivtv *itv)
if (!itv->vbi.fpi)
itv->vbi.fpi = 1;
IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d lines 0x%08x\n",
itv->vbi.enc_start, data[1], itv->vbi.fpi, itv->digitizer);
IVTV_DEBUG_INFO("Setup VBI start 0x%08x frames %d fpi %d\n",
itv->vbi.enc_start, data[1], itv->vbi.fpi);
/* select VBI lines.
Note that the sliced argument seems to have no effect. */
......@@ -494,6 +494,8 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
clear_bit(IVTV_F_S_STREAMOFF, &s->s_flags);
if (atomic_read(&itv->capturing) == 0) {
int digitizer;
/* Always use frame based mode. Experiments have demonstrated that byte
stream based mode results in dropped frames and corruption. Not often,
but occasionally. Many thanks go to Leonard Orb who spent a lot of
......@@ -519,7 +521,14 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
ivtv_vapi(itv, CX2341X_ENC_SET_PLACEHOLDER, 12,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, itv->digitizer, itv->digitizer);
if (itv->card->hw_all & (IVTV_HW_SAA7115 | IVTV_HW_SAA717X))
digitizer = 0xF1;
else if (itv->card->hw_all & IVTV_HW_SAA7114)
digitizer = 0xEF;
else /* cx25840 */
digitizer = 0x140;
ivtv_vapi(itv, CX2341X_ENC_SET_NUM_VSYNC_LINES, 2, digitizer, digitizer);
/* Setup VBI */
if (itv->v4l2_cap & V4L2_CAP_VBI_CAPTURE) {
......@@ -761,7 +770,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
unsigned long duration;
then = jiffies;
add_wait_queue(&itv->cap_w, &wait);
add_wait_queue(&itv->eos_waitq, &wait);
set_current_state(TASK_INTERRUPTIBLE);
......@@ -787,7 +796,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
IVTV_DEBUG_INFO("%s: EOS took %lu ms to occur.\n", s->name, duration);
}
set_current_state(TASK_RUNNING);
remove_wait_queue(&itv->cap_w, &wait);
remove_wait_queue(&itv->eos_waitq, &wait);
}
then = jiffies;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册