|
@@ -60,9 +60,6 @@
|
|
|
#include <media/v4l2-chip-ident.h>
|
|
|
#include "tuner-xc2028.h"
|
|
|
|
|
|
-/* var to keep track of the number of array elements in use */
|
|
|
-int ivtv_cards_active;
|
|
|
-
|
|
|
/* If you have already X v4l cards, then set this to X. This way
|
|
|
the device numbers stay matched. Example: you have a WinTV card
|
|
|
without radio and a PVR-350 with. Normally this would give a
|
|
@@ -70,12 +67,6 @@ int ivtv_cards_active;
|
|
|
setting this to 1 you ensure that radio0 is now also radio1. */
|
|
|
int ivtv_first_minor;
|
|
|
|
|
|
-/* Master variable for all ivtv info */
|
|
|
-struct ivtv *ivtv_cards[IVTV_MAX_CARDS];
|
|
|
-
|
|
|
-/* Protects ivtv_cards_active */
|
|
|
-DEFINE_SPINLOCK(ivtv_cards_lock);
|
|
|
-
|
|
|
/* add your revision and whatnot here */
|
|
|
static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
|
|
|
{PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15,
|
|
@@ -87,6 +78,9 @@ static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
|
|
|
|
|
|
MODULE_DEVICE_TABLE(pci,ivtv_pci_tbl);
|
|
|
|
|
|
+/* ivtv instance counter */
|
|
|
+static atomic_t ivtv_instance = ATOMIC_INIT(0);
|
|
|
+
|
|
|
/* Parameter declarations */
|
|
|
static int cardtype[IVTV_MAX_CARDS];
|
|
|
static int tuner[IVTV_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
|
|
@@ -599,9 +593,9 @@ static void ivtv_process_options(struct ivtv *itv)
|
|
|
itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_MPG] = dec_mpg_buffers * 1024;
|
|
|
itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_YUV] = dec_yuv_buffers * 1024;
|
|
|
itv->options.kilobytes[IVTV_DEC_STREAM_TYPE_VBI] = dec_vbi_buffers;
|
|
|
- itv->options.cardtype = cardtype[itv->num];
|
|
|
- itv->options.tuner = tuner[itv->num];
|
|
|
- itv->options.radio = radio[itv->num];
|
|
|
+ itv->options.cardtype = cardtype[itv->instance];
|
|
|
+ itv->options.tuner = tuner[itv->instance];
|
|
|
+ itv->options.radio = radio[itv->instance];
|
|
|
itv->options.newi2c = newi2c;
|
|
|
if (tunertype < -1 || tunertype > 1) {
|
|
|
IVTV_WARN("Invalid tunertype argument, will autodetect instead\n");
|
|
@@ -688,7 +682,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
|
|
|
spin_lock_init(&itv->lock);
|
|
|
spin_lock_init(&itv->dma_reg_lock);
|
|
|
|
|
|
- itv->irq_work_queues = create_singlethread_workqueue(itv->name);
|
|
|
+ itv->irq_work_queues = create_singlethread_workqueue(itv->device.name);
|
|
|
if (itv->irq_work_queues == NULL) {
|
|
|
IVTV_ERR("Could not create ivtv workqueue\n");
|
|
|
return -1;
|
|
@@ -770,12 +764,6 @@ static void __devinit ivtv_init_struct2(struct ivtv *itv)
|
|
|
i = 0;
|
|
|
itv->active_input = i;
|
|
|
itv->audio_input = itv->card->video_inputs[i].audio_index;
|
|
|
- if (itv->card->hw_all & IVTV_HW_CX25840)
|
|
|
- itv->video_dec_func = ivtv_cx25840;
|
|
|
- else if (itv->card->hw_all & IVTV_HW_SAA717X)
|
|
|
- itv->video_dec_func = ivtv_saa717x;
|
|
|
- else
|
|
|
- itv->video_dec_func = ivtv_saa7115;
|
|
|
}
|
|
|
|
|
|
static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
|
|
@@ -788,21 +776,21 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
|
|
|
IVTV_DEBUG_INFO("Enabling pci device\n");
|
|
|
|
|
|
if (pci_enable_device(dev)) {
|
|
|
- IVTV_ERR("Can't enable device %d!\n", itv->num);
|
|
|
+ IVTV_ERR("Can't enable device!\n");
|
|
|
return -EIO;
|
|
|
}
|
|
|
if (pci_set_dma_mask(dev, 0xffffffff)) {
|
|
|
- IVTV_ERR("No suitable DMA available on card %d.\n", itv->num);
|
|
|
+ IVTV_ERR("No suitable DMA available.\n");
|
|
|
return -EIO;
|
|
|
}
|
|
|
if (!request_mem_region(itv->base_addr, IVTV_ENCODER_SIZE, "ivtv encoder")) {
|
|
|
- IVTV_ERR("Cannot request encoder memory region on card %d.\n", itv->num);
|
|
|
+ IVTV_ERR("Cannot request encoder memory region.\n");
|
|
|
return -EIO;
|
|
|
}
|
|
|
|
|
|
if (!request_mem_region(itv->base_addr + IVTV_REG_OFFSET,
|
|
|
IVTV_REG_SIZE, "ivtv registers")) {
|
|
|
- IVTV_ERR("Cannot request register memory region on card %d.\n", itv->num);
|
|
|
+ IVTV_ERR("Cannot request register memory region.\n");
|
|
|
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
|
|
|
return -EIO;
|
|
|
}
|
|
@@ -810,7 +798,7 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
|
|
|
if (itv->has_cx23415 &&
|
|
|
!request_mem_region(itv->base_addr + IVTV_DECODER_OFFSET,
|
|
|
IVTV_DECODER_SIZE, "ivtv decoder")) {
|
|
|
- IVTV_ERR("Cannot request decoder memory region on card %d.\n", itv->num);
|
|
|
+ IVTV_ERR("Cannot request decoder memory region.\n");
|
|
|
release_mem_region(itv->base_addr, IVTV_ENCODER_SIZE);
|
|
|
release_mem_region(itv->base_addr + IVTV_REG_OFFSET, IVTV_REG_SIZE);
|
|
|
return -EIO;
|
|
@@ -853,69 +841,11 @@ static int ivtv_setup_pci(struct ivtv *itv, struct pci_dev *dev,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-#ifdef MODULE
|
|
|
-static u32 ivtv_request_module(struct ivtv *itv, u32 hw,
|
|
|
- const char *name, u32 id)
|
|
|
-{
|
|
|
- if ((hw & id) == 0)
|
|
|
- return hw;
|
|
|
- if (request_module(name) != 0) {
|
|
|
- IVTV_ERR("Failed to load module %s\n", name);
|
|
|
- return hw & ~id;
|
|
|
- }
|
|
|
- IVTV_DEBUG_INFO("Loaded module %s\n", name);
|
|
|
- return hw;
|
|
|
-}
|
|
|
-#endif
|
|
|
-
|
|
|
static void ivtv_load_and_init_modules(struct ivtv *itv)
|
|
|
{
|
|
|
u32 hw = itv->card->hw_all;
|
|
|
unsigned i;
|
|
|
|
|
|
-#ifdef MODULE
|
|
|
- /* load modules */
|
|
|
-#ifdef CONFIG_MEDIA_TUNER_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "tuner", IVTV_HW_TUNER);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_CX25840_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "cx25840", IVTV_HW_CX25840);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_SAA711X_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "saa7115", IVTV_HW_SAA711X);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_SAA7127_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "saa7127", IVTV_HW_SAA7127);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_SAA717X_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "saa717x", IVTV_HW_SAA717X);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_UPD64031A_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "upd64031a", IVTV_HW_UPD64031A);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_UPD64083_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "upd64083", IVTV_HW_UPD6408X);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_MSP3400_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "msp3400", IVTV_HW_MSP34XX);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_VP27SMPX_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "vp27smpx", IVTV_HW_VP27SMPX);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_WM8775_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "wm8775", IVTV_HW_WM8775);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_WM8739_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "wm8739", IVTV_HW_WM8739);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_CS53L32A_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "cs53l32a", IVTV_HW_CS53L32A);
|
|
|
-#endif
|
|
|
-#ifdef CONFIG_VIDEO_M52790_MODULE
|
|
|
- hw = ivtv_request_module(itv, hw, "m52790", IVTV_HW_M52790);
|
|
|
-#endif
|
|
|
-#endif
|
|
|
-
|
|
|
/* check which i2c devices are actually found */
|
|
|
for (i = 0; i < 32; i++) {
|
|
|
u32 device = 1 << i;
|
|
@@ -927,11 +857,21 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
|
|
|
itv->hw_flags |= device;
|
|
|
continue;
|
|
|
}
|
|
|
- ivtv_i2c_register(itv, i);
|
|
|
- if (ivtv_i2c_hw_addr(itv, device) > 0)
|
|
|
+ if (ivtv_i2c_register(itv, i) == 0)
|
|
|
itv->hw_flags |= device;
|
|
|
}
|
|
|
|
|
|
+ if (itv->card->hw_all & IVTV_HW_CX25840)
|
|
|
+ itv->sd_video = ivtv_find_hw(itv, IVTV_HW_CX25840);
|
|
|
+ else if (itv->card->hw_all & IVTV_HW_SAA717X)
|
|
|
+ itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA717X);
|
|
|
+ else if (itv->card->hw_all & IVTV_HW_SAA7114)
|
|
|
+ itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7114);
|
|
|
+ else
|
|
|
+ itv->sd_video = ivtv_find_hw(itv, IVTV_HW_SAA7115);
|
|
|
+ itv->sd_audio = ivtv_find_hw(itv, itv->card->hw_audio_ctrl);
|
|
|
+ itv->sd_muxer = ivtv_find_hw(itv, itv->card->hw_muxer);
|
|
|
+
|
|
|
hw = itv->hw_flags;
|
|
|
|
|
|
if (itv->card->type == IVTV_CARD_CX23416GYC) {
|
|
@@ -949,7 +889,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
|
|
|
/* The crystal frequency of GVMVPRX is 24.576MHz */
|
|
|
crystal_freq.freq = SAA7115_FREQ_24_576_MHZ;
|
|
|
crystal_freq.flags = SAA7115_FREQ_FL_UCGC;
|
|
|
- itv->video_dec_func(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
|
|
|
+ v4l2_subdev_call(itv->sd_video, video, s_crystal_freq, &crystal_freq);
|
|
|
}
|
|
|
|
|
|
if (hw & IVTV_HW_CX25840) {
|
|
@@ -967,7 +907,7 @@ static void ivtv_load_and_init_modules(struct ivtv *itv)
|
|
|
/* determine the exact saa711x model */
|
|
|
itv->hw_flags &= ~IVTV_HW_SAA711X;
|
|
|
|
|
|
- ivtv_saa7115(itv, VIDIOC_G_CHIP_IDENT, &v);
|
|
|
+ ivtv_call_hw(itv, IVTV_HW_SAA711X, core, g_chip_ident, &v);
|
|
|
if (v.ident == V4L2_IDENT_SAA7114) {
|
|
|
itv->hw_flags |= IVTV_HW_SAA7114;
|
|
|
/* VBI is not yet supported by the saa7114 driver. */
|
|
@@ -1001,28 +941,20 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
int vbi_buf_size;
|
|
|
struct ivtv *itv;
|
|
|
|
|
|
- spin_lock(&ivtv_cards_lock);
|
|
|
-
|
|
|
- /* Make sure we've got a place for this card */
|
|
|
- if (ivtv_cards_active == IVTV_MAX_CARDS) {
|
|
|
- printk(KERN_ERR "ivtv: Maximum number of cards detected (%d)\n",
|
|
|
- ivtv_cards_active);
|
|
|
- spin_unlock(&ivtv_cards_lock);
|
|
|
- return -ENOMEM;
|
|
|
- }
|
|
|
-
|
|
|
itv = kzalloc(sizeof(struct ivtv), GFP_ATOMIC);
|
|
|
- if (itv == NULL) {
|
|
|
- spin_unlock(&ivtv_cards_lock);
|
|
|
+ if (itv == NULL)
|
|
|
return -ENOMEM;
|
|
|
- }
|
|
|
- ivtv_cards[ivtv_cards_active] = itv;
|
|
|
itv->dev = dev;
|
|
|
- itv->num = ivtv_cards_active++;
|
|
|
- snprintf(itv->name, sizeof(itv->name), "ivtv%d", itv->num);
|
|
|
- IVTV_INFO("Initializing card #%d\n", itv->num);
|
|
|
+ itv->instance = atomic_inc_return(&ivtv_instance) - 1;
|
|
|
|
|
|
- spin_unlock(&ivtv_cards_lock);
|
|
|
+ retval = v4l2_device_register(&dev->dev, &itv->device);
|
|
|
+ if (retval)
|
|
|
+ return retval;
|
|
|
+ /* "ivtv + PCI ID" is a bit of a mouthful, so use
|
|
|
+ "ivtv + instance" instead. */
|
|
|
+ snprintf(itv->device.name, sizeof(itv->device.name),
|
|
|
+ "ivtv%d", itv->instance);
|
|
|
+ IVTV_INFO("Initializing card %d\n", itv->instance);
|
|
|
|
|
|
ivtv_process_options(itv);
|
|
|
if (itv->options.cardtype == -1) {
|
|
@@ -1043,8 +975,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
else if (retval == -ENXIO)
|
|
|
goto free_mem;
|
|
|
}
|
|
|
- /* save itv in the pci struct for later use */
|
|
|
- pci_set_drvdata(dev, itv);
|
|
|
|
|
|
/* map io memory */
|
|
|
IVTV_DEBUG_INFO("attempting ioremap at 0x%08x len 0x%08x\n",
|
|
@@ -1086,7 +1016,9 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
goto free_io;
|
|
|
}
|
|
|
|
|
|
- ivtv_gpio_init(itv);
|
|
|
+ retval = ivtv_gpio_init(itv);
|
|
|
+ if (retval)
|
|
|
+ goto free_io;
|
|
|
|
|
|
/* active i2c */
|
|
|
IVTV_DEBUG_INFO("activating i2c...\n");
|
|
@@ -1095,8 +1027,6 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
goto free_io;
|
|
|
}
|
|
|
|
|
|
- IVTV_DEBUG_INFO("Active card count: %d.\n", ivtv_cards_active);
|
|
|
-
|
|
|
if (itv->card->hw_all & IVTV_HW_TVEEPROM) {
|
|
|
/* Based on the model number the cardtype may be changed.
|
|
|
The PCI IDs are not always reliable. */
|
|
@@ -1191,7 +1121,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
setup.mode_mask = T_ANALOG_TV; /* matches TV tuners */
|
|
|
setup.tuner_callback = (setup.type == TUNER_XC2028) ?
|
|
|
ivtv_reset_tuner_gpio : NULL;
|
|
|
- ivtv_call_i2c_clients(itv, TUNER_SET_TYPE_ADDR, &setup);
|
|
|
+ ivtv_call_all(itv, tuner, s_type_addr, &setup);
|
|
|
if (setup.type == TUNER_XC2028) {
|
|
|
static struct xc2028_ctrl ctrl = {
|
|
|
.fname = XC2028_DEFAULT_FIRMWARE,
|
|
@@ -1201,7 +1131,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
.tuner = itv->options.tuner,
|
|
|
.priv = &ctrl,
|
|
|
};
|
|
|
- ivtv_call_i2c_clients(itv, TUNER_SET_CONFIG, &cfg);
|
|
|
+ ivtv_call_all(itv, tuner, s_config, &cfg);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -1210,11 +1140,11 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
itv->tuner_std = itv->std;
|
|
|
|
|
|
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT) {
|
|
|
- ivtv_call_i2c_clients(itv, VIDIOC_INT_S_STD_OUTPUT, &itv->std);
|
|
|
+ ivtv_call_all(itv, video, s_std_output, itv->std);
|
|
|
/* Turn off the output signal. The mpeg decoder is not yet
|
|
|
active so without this you would get a green image until the
|
|
|
mpeg decoder becomes active. */
|
|
|
- ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
|
|
|
+ ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
|
|
|
}
|
|
|
|
|
|
/* clear interrupt mask, effectively disabling interrupts */
|
|
@@ -1222,7 +1152,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
|
|
|
/* Register IRQ */
|
|
|
retval = request_irq(itv->dev->irq, ivtv_irq_handler,
|
|
|
- IRQF_SHARED | IRQF_DISABLED, itv->name, (void *)itv);
|
|
|
+ IRQF_SHARED | IRQF_DISABLED, itv->device.name, (void *)itv);
|
|
|
if (retval) {
|
|
|
IVTV_ERR("Failed to register irq %d\n", retval);
|
|
|
goto free_i2c;
|
|
@@ -1238,7 +1168,7 @@ static int __devinit ivtv_probe(struct pci_dev *dev,
|
|
|
IVTV_ERR("Error %d registering devices\n", retval);
|
|
|
goto free_streams;
|
|
|
}
|
|
|
- IVTV_INFO("Initialized card #%d: %s\n", itv->num, itv->card_name);
|
|
|
+ IVTV_INFO("Initialized card: %s\n", itv->card_name);
|
|
|
return 0;
|
|
|
|
|
|
free_streams:
|
|
@@ -1261,10 +1191,8 @@ err:
|
|
|
retval = -ENODEV;
|
|
|
IVTV_ERR("Error %d on initialization\n", retval);
|
|
|
|
|
|
- spin_lock(&ivtv_cards_lock);
|
|
|
- kfree(ivtv_cards[ivtv_cards_active]);
|
|
|
- ivtv_cards[ivtv_cards_active] = NULL;
|
|
|
- spin_unlock(&ivtv_cards_lock);
|
|
|
+ v4l2_device_unregister(&itv->device);
|
|
|
+ kfree(itv);
|
|
|
return retval;
|
|
|
}
|
|
|
|
|
@@ -1304,10 +1232,11 @@ int ivtv_init_on_first_open(struct ivtv *itv)
|
|
|
if (itv->card->hw_all & IVTV_HW_CX25840) {
|
|
|
struct v4l2_control ctrl;
|
|
|
|
|
|
+ v4l2_subdev_call(itv->sd_video, core, init, 0);
|
|
|
/* 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);
|
|
|
+ v4l2_subdev_call(itv->sd_video, core, s_ctrl, &ctrl);
|
|
|
}
|
|
|
|
|
|
vf.tuner = 0;
|
|
@@ -1337,7 +1266,7 @@ int ivtv_init_on_first_open(struct ivtv *itv)
|
|
|
/* Turn on the TV-out: ivtv_init_mpeg_decoder() initializes
|
|
|
the mpeg decoder so now the saa7127 receives a proper
|
|
|
signal. */
|
|
|
- ivtv_saa7127(itv, VIDIOC_STREAMON, NULL);
|
|
|
+ ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 1);
|
|
|
ivtv_init_mpeg_decoder(itv);
|
|
|
}
|
|
|
ivtv_s_std(NULL, &fh, &itv->tuner_std);
|
|
@@ -1362,9 +1291,11 @@ int ivtv_init_on_first_open(struct ivtv *itv)
|
|
|
|
|
|
static void ivtv_remove(struct pci_dev *pci_dev)
|
|
|
{
|
|
|
- struct ivtv *itv = pci_get_drvdata(pci_dev);
|
|
|
+ struct v4l2_device *dev = dev_get_drvdata(&pci_dev->dev);
|
|
|
+ struct ivtv *itv = to_ivtv(dev);
|
|
|
+ int i;
|
|
|
|
|
|
- IVTV_DEBUG_INFO("Removing Card #%d\n", itv->num);
|
|
|
+ IVTV_DEBUG_INFO("Removing card\n");
|
|
|
|
|
|
if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) {
|
|
|
/* Stop all captures */
|
|
@@ -1377,7 +1308,7 @@ static void ivtv_remove(struct pci_dev *pci_dev)
|
|
|
|
|
|
/* Turn off the TV-out */
|
|
|
if (itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)
|
|
|
- ivtv_saa7127(itv, VIDIOC_STREAMOFF, NULL);
|
|
|
+ ivtv_call_hw(itv, IVTV_HW_SAA7127, video, s_stream, 0);
|
|
|
if (atomic_read(&itv->decoding) > 0) {
|
|
|
int type;
|
|
|
|
|
@@ -1402,6 +1333,8 @@ static void ivtv_remove(struct pci_dev *pci_dev)
|
|
|
ivtv_streams_cleanup(itv, 1);
|
|
|
ivtv_udma_free(itv);
|
|
|
|
|
|
+ v4l2_device_unregister(&itv->device);
|
|
|
+
|
|
|
exit_ivtv_i2c(itv);
|
|
|
|
|
|
free_irq(itv->dev->irq, (void *)itv);
|
|
@@ -1413,8 +1346,11 @@ static void ivtv_remove(struct pci_dev *pci_dev)
|
|
|
release_mem_region(itv->base_addr + IVTV_DECODER_OFFSET, IVTV_DECODER_SIZE);
|
|
|
|
|
|
pci_disable_device(itv->dev);
|
|
|
+ for (i = 0; i < IVTV_VBI_FRAMES; i++)
|
|
|
+ kfree(itv->vbi.sliced_mpeg_data[i]);
|
|
|
|
|
|
- IVTV_INFO("Removed %s, card #%d\n", itv->card_name, itv->num);
|
|
|
+ printk(KERN_INFO "ivtv: Removed %s\n", itv->card_name);
|
|
|
+ kfree(itv);
|
|
|
}
|
|
|
|
|
|
/* define a pci_driver for card detection */
|
|
@@ -1427,54 +1363,36 @@ static struct pci_driver ivtv_pci_driver = {
|
|
|
|
|
|
static int module_start(void)
|
|
|
{
|
|
|
- printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION);
|
|
|
-
|
|
|
- memset(ivtv_cards, 0, sizeof(ivtv_cards));
|
|
|
+ printk(KERN_INFO "ivtv: Start initialization, version %s\n", IVTV_VERSION);
|
|
|
|
|
|
/* Validate parameters */
|
|
|
if (ivtv_first_minor < 0 || ivtv_first_minor >= IVTV_MAX_CARDS) {
|
|
|
- printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n",
|
|
|
+ printk(KERN_ERR "ivtv: Exiting, ivtv_first_minor must be between 0 and %d\n",
|
|
|
IVTV_MAX_CARDS - 1);
|
|
|
return -1;
|
|
|
}
|
|
|
|
|
|
if (ivtv_debug < 0 || ivtv_debug > 2047) {
|
|
|
ivtv_debug = 0;
|
|
|
- printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n");
|
|
|
+ printk(KERN_INFO "ivtv: Debug value must be >= 0 and <= 2047\n");
|
|
|
}
|
|
|
|
|
|
if (pci_register_driver(&ivtv_pci_driver)) {
|
|
|
- printk(KERN_ERR "ivtv: Error detecting PCI card\n");
|
|
|
+ printk(KERN_ERR "ivtv: Error detecting PCI card\n");
|
|
|
return -ENODEV;
|
|
|
}
|
|
|
- printk(KERN_INFO "ivtv: End initialization\n");
|
|
|
+ printk(KERN_INFO "ivtv: End initialization\n");
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
static void module_cleanup(void)
|
|
|
{
|
|
|
- int i, j;
|
|
|
-
|
|
|
pci_unregister_driver(&ivtv_pci_driver);
|
|
|
-
|
|
|
- spin_lock(&ivtv_cards_lock);
|
|
|
- for (i = 0; i < ivtv_cards_active; i++) {
|
|
|
- if (ivtv_cards[i] == NULL)
|
|
|
- continue;
|
|
|
- for (j = 0; j < IVTV_VBI_FRAMES; j++) {
|
|
|
- kfree(ivtv_cards[i]->vbi.sliced_mpeg_data[j]);
|
|
|
- }
|
|
|
- kfree(ivtv_cards[i]);
|
|
|
- }
|
|
|
- spin_unlock(&ivtv_cards_lock);
|
|
|
}
|
|
|
|
|
|
/* Note: These symbols are exported because they are used by the ivtvfb
|
|
|
framebuffer module and an infrared module for the IR-blaster. */
|
|
|
EXPORT_SYMBOL(ivtv_set_irq_mask);
|
|
|
-EXPORT_SYMBOL(ivtv_cards_active);
|
|
|
-EXPORT_SYMBOL(ivtv_cards);
|
|
|
-EXPORT_SYMBOL(ivtv_cards_lock);
|
|
|
EXPORT_SYMBOL(ivtv_api);
|
|
|
EXPORT_SYMBOL(ivtv_vapi);
|
|
|
EXPORT_SYMBOL(ivtv_vapi_result);
|