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

V4L/DVB (5922): ivtv, cx25840: postpone fw load until first use

The firmware is now loaded when the driver is actually used for the first
time. This allows the driver to be compiled in-kernel instead of as a module.
Signed-off-by: NHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: NMauro Carvalho Chehab <mchehab@infradead.org>
上级 fa8a7529
...@@ -64,7 +64,6 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o ...@@ -64,7 +64,6 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
obj-$(CONFIG_VIDEO_MEYE) += meye.o obj-$(CONFIG_VIDEO_MEYE) += meye.o
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/ obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_CX88) += cx88/ obj-$(CONFIG_VIDEO_CX88) += cx88/
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/ obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/ obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
...@@ -117,6 +116,8 @@ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ ...@@ -117,6 +116,8 @@ obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/ obj-$(CONFIG_USB_VICAM) += usbvideo/
obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/ obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
obj-$(CONFIG_VIDEO_VIVI) += vivi.o obj-$(CONFIG_VIDEO_VIVI) += vivi.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
...@@ -625,6 +625,22 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd, ...@@ -625,6 +625,22 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
struct v4l2_tuner *vt = arg; struct v4l2_tuner *vt = arg;
struct v4l2_routing *route = arg; struct v4l2_routing *route = arg;
/* ignore these commands */
switch (cmd) {
case TUNER_SET_TYPE_ADDR:
return 0;
}
if (!state->is_initialized) {
v4l_dbg(1, cx25840_debug, client, "cmd %08x triggered fw load\n", cmd);
/* initialize on first use */
state->is_initialized = 1;
if (state->is_cx25836)
cx25836_initialize(client);
else
cx25840_initialize(client, 1);
}
switch (cmd) { switch (cmd) {
#ifdef CONFIG_VIDEO_ADV_DEBUG #ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct access to the /* ioctls to allow direct access to the
...@@ -906,11 +922,6 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address, ...@@ -906,11 +922,6 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
i2c_attach_client(client); i2c_attach_client(client);
if (state->is_cx25836)
cx25836_initialize(client);
else
cx25840_initialize(client, 1);
return 0; return 0;
} }
......
...@@ -46,6 +46,7 @@ struct cx25840_state { ...@@ -46,6 +46,7 @@ struct cx25840_state {
u32 id; u32 id;
u32 rev; u32 rev;
int is_cx25836; int is_cx25836;
int is_initialized;
}; };
/* ----------------------------------------------------------------------- */ /* ----------------------------------------------------------------------- */
......
...@@ -814,7 +814,6 @@ static void ivtv_request_module(struct ivtv *itv, const char *name) ...@@ -814,7 +814,6 @@ static void ivtv_request_module(struct ivtv *itv, const char *name)
static void ivtv_load_and_init_modules(struct ivtv *itv) static void ivtv_load_and_init_modules(struct ivtv *itv)
{ {
struct v4l2_control ctrl;
u32 hw = itv->card->hw_all; u32 hw = itv->card->hw_all;
int i; int i;
...@@ -896,11 +895,6 @@ static void ivtv_load_and_init_modules(struct ivtv *itv) ...@@ -896,11 +895,6 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
} }
if (hw & IVTV_HW_CX25840) { if (hw & IVTV_HW_CX25840) {
/* CX25840_CID_ENABLE_PVR150_WORKAROUND */
ctrl.id = V4L2_CID_PRIVATE_BASE;
ctrl.value = itv->pvr150_workaround;
itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl);
itv->vbi.raw_decoder_line_size = 1444; itv->vbi.raw_decoder_line_size = 1444;
itv->vbi.raw_decoder_sav_odd_field = 0x20; itv->vbi.raw_decoder_sav_odd_field = 0x20;
itv->vbi.raw_decoder_sav_even_field = 0x60; itv->vbi.raw_decoder_sav_even_field = 0x60;
...@@ -946,12 +940,9 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ...@@ -946,12 +940,9 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id) const struct pci_device_id *pci_id)
{ {
int retval = 0; int retval = 0;
int video_input;
int yuv_buf_size; int yuv_buf_size;
int vbi_buf_size; int vbi_buf_size;
int fw_retry_count = 3;
struct ivtv *itv; struct ivtv *itv;
struct v4l2_frequency vf;
spin_lock(&ivtv_cards_lock); spin_lock(&ivtv_cards_lock);
...@@ -1038,22 +1029,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ...@@ -1038,22 +1029,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
goto free_io; goto free_io;
} }
while (--fw_retry_count > 0) {
/* load firmware */
if (ivtv_firmware_init(itv) == 0)
break;
if (fw_retry_count > 1)
IVTV_WARN("Retry loading firmware\n");
}
if (fw_retry_count == 0) {
IVTV_ERR("Error initializing firmware\n");
goto free_i2c;
}
/* Try and get firmware versions */
IVTV_DEBUG_INFO("Getting firmware version..\n");
ivtv_firmware_versions(itv);
/* Check yuv output filter table */ /* Check yuv output filter table */
if (itv->has_cx23415) ivtv_yuv_filter_check(itv); if (itv->has_cx23415) ivtv_yuv_filter_check(itv);
...@@ -1157,44 +1132,16 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ...@@ -1157,44 +1132,16 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup); ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup);
} }
vf.tuner = 0;
vf.type = V4L2_TUNER_ANALOG_TV;
vf.frequency = 6400; /* the tuner 'baseline' frequency */
/* Set initial frequency. For PAL/SECAM broadcasts no
'default' channel exists AFAIK. */
if (itv->std == V4L2_STD_NTSC_M_JP) {
vf.frequency = 1460; /* ch. 1 91250*16/1000 */
}
else if (itv->std & V4L2_STD_NTSC_M) {
vf.frequency = 1076; /* ch. 4 67250*16/1000 */
}
/* The tuner is fixed to the standard. The other inputs (e.g. S-Video) /* The tuner is fixed to the standard. The other inputs (e.g. S-Video)
are not. */ are not. */
itv->tuner_std = itv->std; itv->tuner_std = itv->std;
video_input = itv->active_input;
itv->active_input++; /* Force update of input */
ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &video_input);
/* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
in one place. */
itv->std++; /* Force full standard initialization */
itv->std_out = itv->std;
ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf);
retval = ivtv_streams_setup(itv); retval = ivtv_streams_setup(itv);
if (retval) { if (retval) {
IVTV_ERR("Error %d setting up streams\n", retval); IVTV_ERR("Error %d setting up streams\n", retval);
goto free_i2c; goto free_i2c;
} }
if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
ivtv_init_mpeg_decoder(itv);
}
ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std);
IVTV_DEBUG_IRQ("Masking interrupts\n"); IVTV_DEBUG_IRQ("Masking interrupts\n");
/* clear interrupt mask, effectively disabling interrupts */ /* clear interrupt mask, effectively disabling interrupts */
ivtv_set_irq_mask(itv, 0xffffffff); ivtv_set_irq_mask(itv, 0xffffffff);
...@@ -1206,26 +1153,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ...@@ -1206,26 +1153,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_ERR("Failed to register irq %d\n", retval); IVTV_ERR("Failed to register irq %d\n", retval);
goto free_streams; goto free_streams;
} }
/* On a cx23416 this seems to be able to enable DMA to the chip? */
if (!itv->has_cx23415)
write_reg_sync(0x03, IVTV_REG_DMACONTROL);
/* Default interrupts enabled. For the PVR350 this includes the
decoder VSYNC interrupt, which is always on. It is not only used
during decoding but also by the OSD.
Some old PVR250 cards had a cx23415, so testing for that is too
general. Instead test if the card has video output capability. */
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
else
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
if (itv->has_cx23415)
ivtv_set_osd_alpha(itv);
IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name); IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
return 0; return 0;
free_irq: free_irq:
...@@ -1255,55 +1183,126 @@ static int __devinit ivtv_probe(struct pci_dev *dev, ...@@ -1255,55 +1183,126 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
return retval; return retval;
} }
int ivtv_init_on_first_open(struct ivtv *itv)
{
struct v4l2_frequency vf;
int fw_retry_count = 3;
int video_input;
while (--fw_retry_count > 0) {
/* load firmware */
if (ivtv_firmware_init(itv) == 0)
break;
if (fw_retry_count > 1)
IVTV_WARN("Retry loading firmware\n");
}
if (fw_retry_count == 0) {
IVTV_ERR("Error initializing firmware\n");
return -1;
}
/* Try and get firmware versions */
IVTV_DEBUG_INFO("Getting firmware version..\n");
ivtv_firmware_versions(itv);
if (itv->card->hw_all & IVTV_HW_CX25840) {
struct v4l2_control ctrl;
/* CX25840_CID_ENABLE_PVR150_WORKAROUND */
ctrl.id = V4L2_CID_PRIVATE_BASE;
ctrl.value = itv->pvr150_workaround;
itv->video_dec_func(itv, VIDIOC_S_CTRL, &ctrl);
}
vf.tuner = 0;
vf.type = V4L2_TUNER_ANALOG_TV;
vf.frequency = 6400; /* the tuner 'baseline' frequency */
/* Set initial frequency. For PAL/SECAM broadcasts no
'default' channel exists AFAIK. */
if (itv->std == V4L2_STD_NTSC_M_JP) {
vf.frequency = 1460; /* ch. 1 91250*16/1000 */
}
else if (itv->std & V4L2_STD_NTSC_M) {
vf.frequency = 1076; /* ch. 4 67250*16/1000 */
}
video_input = itv->active_input;
itv->active_input++; /* Force update of input */
ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_INPUT, &video_input);
/* Let the VIDIOC_S_STD ioctl do all the work, keeps the code
in one place. */
itv->std++; /* Force full standard initialization */
itv->std_out = itv->std;
ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_FREQUENCY, &vf);
if (itv->card->v4l2_capabilities & V4L2_CAP_VIDEO_OUTPUT) {
ivtv_init_mpeg_decoder(itv);
}
ivtv_v4l2_ioctls(itv, NULL, VIDIOC_S_STD, &itv->tuner_std);
/* On a cx23416 this seems to be able to enable DMA to the chip? */
if (!itv->has_cx23415)
write_reg_sync(0x03, IVTV_REG_DMACONTROL);
/* Default interrupts enabled. For the PVR350 this includes the
decoder VSYNC interrupt, which is always on. It is not only used
during decoding but also by the OSD.
Some old PVR250 cards had a cx23415, so testing for that is too
general. Instead test if the card has video output capability. */
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT | IVTV_IRQ_DEC_VSYNC);
ivtv_set_osd_alpha(itv);
}
else
ivtv_clear_irq_mask(itv, IVTV_IRQ_MASK_INIT);
return 0;
}
static void ivtv_remove(struct pci_dev *pci_dev) static void ivtv_remove(struct pci_dev *pci_dev)
{ {
struct ivtv *itv = pci_get_drvdata(pci_dev); struct ivtv *itv = pci_get_drvdata(pci_dev);
IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num); IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num);
/* Stop all captures */ if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) {
IVTV_DEBUG_INFO("Stopping all streams\n"); /* Stop all captures */
if (atomic_read(&itv->capturing) > 0) IVTV_DEBUG_INFO("Stopping all streams\n");
ivtv_stop_all_captures(itv); if (atomic_read(&itv->capturing) > 0)
ivtv_stop_all_captures(itv);
/* Stop all decoding */
IVTV_DEBUG_INFO("Stopping decoding\n"); /* Stop all decoding */
if (atomic_read(&itv->decoding) > 0) { IVTV_DEBUG_INFO("Stopping decoding\n");
int type; if (atomic_read(&itv->decoding) > 0) {
int type;
if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
type = IVTV_DEC_STREAM_TYPE_YUV; if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
else type = IVTV_DEC_STREAM_TYPE_YUV;
type = IVTV_DEC_STREAM_TYPE_MPG; else
ivtv_stop_v4l2_decode_stream(&itv->streams[type], type = IVTV_DEC_STREAM_TYPE_MPG;
VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); ivtv_stop_v4l2_decode_stream(&itv->streams[type],
VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
}
ivtv_halt_firmware(itv);
} }
/* Interrupts */ /* Interrupts */
IVTV_DEBUG_INFO("Disabling interrupts\n");
ivtv_set_irq_mask(itv, 0xffffffff); ivtv_set_irq_mask(itv, 0xffffffff);
del_timer_sync(&itv->dma_timer); del_timer_sync(&itv->dma_timer);
/* Stop all Work Queues */ /* Stop all Work Queues */
IVTV_DEBUG_INFO("Stop Work Queues\n");
flush_workqueue(itv->irq_work_queues); flush_workqueue(itv->irq_work_queues);
destroy_workqueue(itv->irq_work_queues); destroy_workqueue(itv->irq_work_queues);
IVTV_DEBUG_INFO("Stopping Firmware\n");
ivtv_halt_firmware(itv);
IVTV_DEBUG_INFO("Unregistering v4l devices\n");
ivtv_streams_cleanup(itv); ivtv_streams_cleanup(itv);
IVTV_DEBUG_INFO("Freeing dma resources\n");
ivtv_udma_free(itv); ivtv_udma_free(itv);
exit_ivtv_i2c(itv); exit_ivtv_i2c(itv);
IVTV_DEBUG_INFO(" Releasing irq\n");
free_irq(itv->dev->irq, (void *)itv); free_irq(itv->dev->irq, (void *)itv);
ivtv_iounmap(itv); ivtv_iounmap(itv);
IVTV_DEBUG_INFO(" Releasing mem\n");
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE); release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE); release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
if (itv->has_cx23415) if (itv->has_cx23415)
......
...@@ -398,6 +398,8 @@ struct ivtv_mailbox_data { ...@@ -398,6 +398,8 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */ #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 */ #define IVTV_F_I_PIO 19 /* PIO in progress */
#define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */ #define IVTV_F_I_DEC_PAUSED 20 /* the decoder is paused */
#define IVTV_F_I_INITED 21 /* set after first open */
#define IVTV_F_I_FAILED 22 /* set if first open failed */
/* 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 */
...@@ -838,6 +840,9 @@ int ivtv_waitq(wait_queue_head_t *waitq); ...@@ -838,6 +840,9 @@ int ivtv_waitq(wait_queue_head_t *waitq);
struct tveeprom; /* forward reference */ struct tveeprom; /* forward reference */
void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv); void ivtv_read_eeprom(struct ivtv *itv, struct tveeprom *tv);
/* First-open initialization: load firmware, init cx25840, etc. */
int ivtv_init_on_first_open(struct ivtv *itv);
/* This is a PCI post thing, where if the pci register is not read, then /* This is a PCI post thing, where if the pci register is not read, then
the write doesn't always take effect right away. By reading back the the write doesn't always take effect right away. By reading back the
register any pending PCI writes will be performed (in order), and so register any pending PCI writes will be performed (in order), and so
......
...@@ -850,6 +850,15 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) ...@@ -850,6 +850,15 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
return -ENXIO; return -ENXIO;
} }
if (!test_and_set_bit(IVTV_F_I_INITED, &itv->i_flags))
if (ivtv_init_on_first_open(itv))
set_bit(IVTV_F_I_FAILED, &itv->i_flags);
if (test_bit(IVTV_F_I_FAILED, &itv->i_flags)) {
printk(KERN_WARNING "ivtv: failed to initialize on minor %d\n", minor);
return -ENXIO;
}
if (y == IVTV_DEC_STREAM_TYPE_MPG && if (y == IVTV_DEC_STREAM_TYPE_MPG &&
test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags)) test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
return -EBUSY; return -EBUSY;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册