V4L/DVB (5922): ivtv, cx25840: postpone fw load until first use
authorHans Verkuil <hverkuil@xs4all.nl>
Sun, 22 Jul 2007 15:52:40 +0000 (12:52 -0300)
committerMauro Carvalho Chehab <mchehab@infradead.org>
Wed, 10 Oct 2007 01:03:20 +0000 (22:03 -0300)
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>
drivers/media/video/Makefile
drivers/media/video/cx25840/cx25840-core.c
drivers/media/video/cx25840/cx25840-core.h
drivers/media/video/ivtv/ivtv-driver.c
drivers/media/video/ivtv/ivtv-driver.h
drivers/media/video/ivtv/ivtv-fileops.c

index 8f7205b558f645b1f37a3e33d50220fd7815302f..c5286bfba44768c763ec5b95434b39785f4b4aa0 100644 (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
index 67bda9f9a44bfa48998de9f3566ef57da7222ded..9c12bd39cfb5682ac4e70428ffe41d66eb36af27 100644 (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;
 }
 
index f4b56d2fd6b6cee76c936c1ed645f9e1c628d8da..8c1fbd9b87c1bdb165c3a7b5d9cd1a2f10c1585b 100644 (file)
@@ -46,6 +46,7 @@ struct cx25840_state {
        u32 id;
        u32 rev;
        int is_cx25836;
+       int is_initialized;
 };
 
 /* ----------------------------------------------------------------------- */
index 81cbaf7dd51c9daa2e539500c6f45d27879708a9..00bdcc2e8f53afd903d94a38ef4144ad3e1a4c01 100644 (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);
-
-       /* 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_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;
+
+                       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)
index 8fe9d9c7a18ec29ab8d4dee75f642c33c5c3cd03..6e53a1f04f7e18e58d81f985ff533abfa18d3b79 100644 (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
index 66ea3cbc369c209f2ae4cc52d03253479f16052b..498860841644ab798ccd9d095613ccba5659934d 100644 (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;