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: Hans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
This commit is contained in:
Hans Verkuil 2007-07-22 12:52:40 -03:00 committed by Mauro Carvalho Chehab
parent fa8a7529ba
commit c976bc8233
6 changed files with 127 additions and 101 deletions

View File

@ -64,7 +64,6 @@ obj-$(CONFIG_VIDEO_CPIA_USB) += cpia_usb.o
obj-$(CONFIG_VIDEO_MEYE) += meye.o
obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
obj-$(CONFIG_VIDEO_CX88) += cx88/
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
@ -117,6 +116,8 @@ obj-$(CONFIG_USB_KONICAWC) += usbvideo/
obj-$(CONFIG_USB_VICAM) += usbvideo/
obj-$(CONFIG_USB_QUICKCAM_MESSENGER) += usbvideo/
obj-$(CONFIG_VIDEO_IVTV) += ivtv/
obj-$(CONFIG_VIDEO_VIVI) += vivi.o
EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core

View File

@ -625,6 +625,22 @@ static int cx25840_command(struct i2c_client *client, unsigned int cmd,
struct v4l2_tuner *vt = 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) {
#ifdef CONFIG_VIDEO_ADV_DEBUG
/* ioctls to allow direct access to the
@ -906,11 +922,6 @@ static int cx25840_detect_client(struct i2c_adapter *adapter, int address,
i2c_attach_client(client);
if (state->is_cx25836)
cx25836_initialize(client);
else
cx25840_initialize(client, 1);
return 0;
}

View File

@ -46,6 +46,7 @@ struct cx25840_state {
u32 id;
u32 rev;
int is_cx25836;
int is_initialized;
};
/* ----------------------------------------------------------------------- */

View File

@ -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)
{
struct v4l2_control ctrl;
u32 hw = itv->card->hw_all;
int i;
@ -896,11 +895,6 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
}
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_sav_odd_field = 0x20;
itv->vbi.raw_decoder_sav_even_field = 0x60;
@ -946,12 +940,9 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
const struct pci_device_id *pci_id)
{
int retval = 0;
int video_input;
int yuv_buf_size;
int vbi_buf_size;
int fw_retry_count = 3;
struct ivtv *itv;
struct v4l2_frequency vf;
spin_lock(&ivtv_cards_lock);
@ -1038,22 +1029,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
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 */
if (itv->has_cx23415) ivtv_yuv_filter_check(itv);
@ -1157,44 +1132,16 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
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)
are not. */
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);
if (retval) {
IVTV_ERR("Error %d setting up streams\n", retval);
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");
/* clear interrupt mask, effectively disabling interrupts */
ivtv_set_irq_mask(itv, 0xffffffff);
@ -1206,26 +1153,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
IVTV_ERR("Failed to register irq %d\n", retval);
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);
return 0;
free_irq:
@ -1255,55 +1183,126 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
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)
{
struct ivtv *itv = pci_get_drvdata(pci_dev);
IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num);
/* Stop all captures */
IVTV_DEBUG_INFO("Stopping all streams\n");
if (atomic_read(&itv->capturing) > 0)
ivtv_stop_all_captures(itv);
if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) {
/* Stop all captures */
IVTV_DEBUG_INFO("Stopping all streams\n");
if (atomic_read(&itv->capturing) > 0)
ivtv_stop_all_captures(itv);
/* Stop all decoding */
IVTV_DEBUG_INFO("Stopping decoding\n");
if (atomic_read(&itv->decoding) > 0) {
int type;
/* Stop all decoding */
IVTV_DEBUG_INFO("Stopping decoding\n");
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;
else
type = IVTV_DEC_STREAM_TYPE_MPG;
ivtv_stop_v4l2_decode_stream(&itv->streams[type],
VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
if (test_bit(IVTV_F_I_DEC_YUV, &itv->i_flags))
type = IVTV_DEC_STREAM_TYPE_YUV;
else
type = IVTV_DEC_STREAM_TYPE_MPG;
ivtv_stop_v4l2_decode_stream(&itv->streams[type],
VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0);
}
ivtv_halt_firmware(itv);
}
/* Interrupts */
IVTV_DEBUG_INFO("Disabling interrupts\n");
ivtv_set_irq_mask(itv, 0xffffffff);
del_timer_sync(&itv->dma_timer);
/* Stop all Work Queues */
IVTV_DEBUG_INFO("Stop Work Queues\n");
flush_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_DEBUG_INFO("Freeing dma resources\n");
ivtv_udma_free(itv);
exit_ivtv_i2c(itv);
IVTV_DEBUG_INFO(" Releasing irq\n");
free_irq(itv->dev->irq, (void *)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_REG_OFFSET, IVTV_REG_SIZE);
if (itv->has_cx23415)

View File

@ -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_PIO 19 /* PIO in progress */
#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 */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
@ -838,6 +840,9 @@ int ivtv_waitq(wait_queue_head_t *waitq);
struct tveeprom; /* forward reference */
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
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

View File

@ -850,6 +850,15 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
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 &&
test_bit(IVTV_F_S_CLAIMED, &itv->streams[IVTV_DEC_STREAM_TYPE_YUV].s_flags))
return -EBUSY;