Skip to content

Commit

Permalink
V4L/DVB (10756): cx18: Slim down instance handling, build names from …
Browse files Browse the repository at this point in the history
…v4l2_device.name

Convert card instance handling to a lighter weight mechanism like ivtv.
Also convert name strings and debug messages to use v4l2_device.name.

Signed-off-by: Andy Walls <awalls@radix.net>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Andy Walls authored and Mauro Carvalho Chehab committed Mar 30, 2009
1 parent 1a26704 commit 5811cf9
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 119 deletions.
107 changes: 41 additions & 66 deletions drivers/media/video/cx18/cx18-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,23 +39,13 @@

#include <media/tveeprom.h>


/* var to keep track of the number of array elements in use */
int cx18_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 Compro H900 with. Normally this would give a
video1 device together with a radio0 device for the Compro. By
setting this to 1 you ensure that radio0 is now also radio1. */
int cx18_first_minor;

/* Master variable for all cx18 info */
struct cx18 *cx18_cards[CX18_MAX_CARDS];

/* Protects cx18_cards_active */
DEFINE_SPINLOCK(cx18_cards_lock);

/* add your revision and whatnot here */
static struct pci_device_id cx18_pci_tbl[] __devinitdata = {
{PCI_VENDOR_ID_CX, PCI_DEVICE_ID_CX23418,
Expand All @@ -65,6 +55,8 @@ static struct pci_device_id cx18_pci_tbl[] __devinitdata = {

MODULE_DEVICE_TABLE(pci, cx18_pci_tbl);

static atomic_t cx18_instance = ATOMIC_INIT(0);

/* Parameter declarations */
static int cardtype[CX18_MAX_CARDS];
static int tuner[CX18_MAX_CARDS] = { -1, -1, -1, -1, -1, -1, -1, -1,
Expand Down Expand Up @@ -491,9 +483,9 @@ static void cx18_process_options(struct cx18 *cx)
cx->stream_buf_size[i] *= 1024; /* convert from kB to bytes */
}

cx->options.cardtype = cardtype[cx->num];
cx->options.tuner = tuner[cx->num];
cx->options.radio = radio[cx->num];
cx->options.cardtype = cardtype[cx->instance];
cx->options.tuner = tuner[cx->instance];
cx->options.radio = radio[cx->instance];

cx->std = cx18_parse_std(cx);
if (cx->options.cardtype == -1) {
Expand Down Expand Up @@ -550,7 +542,7 @@ static void cx18_process_options(struct cx18 *cx)
}

/* Precondition: the cx18 structure has been memset to 0. Only
the dev and num fields have been filled in.
the dev and instance fields have been filled in.
No assumptions on the card type may be made here (see cx18_init_struct2
for that).
*/
Expand All @@ -567,7 +559,7 @@ static int __devinit cx18_init_struct1(struct cx18 *cx)
mutex_init(&cx->epu2apu_mb_lock);
mutex_init(&cx->epu2cpu_mb_lock);

cx->work_queue = create_singlethread_workqueue(cx->name);
cx->work_queue = create_singlethread_workqueue(cx->v4l2_dev.name);
if (cx->work_queue == NULL) {
CX18_ERR("Unable to create work hander thread\n");
return -ENOMEM;
Expand Down Expand Up @@ -647,15 +639,16 @@ static int cx18_setup_pci(struct cx18 *cx, struct pci_dev *pci_dev,
CX18_DEBUG_INFO("Enabling pci device\n");

if (pci_enable_device(pci_dev)) {
CX18_ERR("Can't enable device %d!\n", cx->num);
CX18_ERR("Can't enable device %d!\n", cx->instance);
return -EIO;
}
if (pci_set_dma_mask(pci_dev, 0xffffffff)) {
CX18_ERR("No suitable DMA available on card %d.\n", cx->num);
CX18_ERR("No suitable DMA available, card %d\n", cx->instance);
return -EIO;
}
if (!request_mem_region(cx->base_addr, CX18_MEM_SIZE, "cx18 encoder")) {
CX18_ERR("Cannot request encoder memory region on card %d.\n", cx->num);
CX18_ERR("Cannot request encoder memory region, card %d\n",
cx->instance);
return -EIO;
}

Expand Down Expand Up @@ -741,44 +734,42 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
u32 devtype;
struct cx18 *cx;

spin_lock(&cx18_cards_lock);

/* Make sure we've got a place for this card */
if (cx18_cards_active == CX18_MAX_CARDS) {
printk(KERN_ERR "cx18: Maximum number of cards detected (%d).\n",
cx18_cards_active);
spin_unlock(&cx18_cards_lock);
/* FIXME - module parameter arrays constrain max instances */
i = atomic_inc_return(&cx18_instance) - 1;
if (i >= CX18_MAX_CARDS) {
printk(KERN_ERR "cx18: cannot manage card %d, driver has a "
"limit of 0 - %d\n", i, CX18_MAX_CARDS - 1);
return -ENOMEM;
}

cx = kzalloc(sizeof(struct cx18), GFP_ATOMIC);
if (!cx) {
spin_unlock(&cx18_cards_lock);
if (cx == NULL) {
printk(KERN_ERR "cx18: cannot manage card %d, out of memory\n",
i);
return -ENOMEM;
}
cx18_cards[cx18_cards_active] = cx;
cx->num = cx18_cards_active++;
snprintf(cx->name, sizeof(cx->name), "cx18-%d", cx->num);
CX18_INFO("Initializing card #%d\n", cx->num);

spin_unlock(&cx18_cards_lock);

cx->pci_dev = pci_dev;
cx->instance = i;

retval = v4l2_device_register(&pci_dev->dev, &cx->v4l2_dev);
if (retval) {
CX18_ERR("Call to v4l2_device_register() failed\n");
goto err;
printk(KERN_ERR "cx18: v4l2_device_register of card %d failed"
"\n", cx->instance);
kfree(cx);
return retval;
}
CX18_DEBUG_INFO("registered v4l2_device name: %s\n", cx->v4l2_dev.name);
snprintf(cx->v4l2_dev.name, sizeof(cx->v4l2_dev.name), "cx18-%d",
cx->instance);
CX18_INFO("Initializing card %d\n", cx->instance);

cx18_process_options(cx);
if (cx->options.cardtype == -1) {
retval = -ENODEV;
goto unregister_v4l2;
goto err;
}
if (cx18_init_struct1(cx)) {
retval = -ENOMEM;
goto unregister_v4l2;
goto err;
}

CX18_DEBUG_INFO("base addr: 0x%08x\n", cx->base_addr);
Expand Down Expand Up @@ -829,8 +820,6 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
goto free_map;
}

CX18_DEBUG_INFO("Active card count: %d.\n", cx18_cards_active);

if (cx->card->hw_all & CX18_HW_TVEEPROM) {
/* Based on the model number the cardtype may be changed.
The PCI IDs are not always reliable. */
Expand All @@ -847,7 +836,8 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,

/* Register IRQ */
retval = request_irq(cx->pci_dev->irq, cx18_irq_handler,
IRQF_SHARED | IRQF_DISABLED, cx->name, (void *)cx);
IRQF_SHARED | IRQF_DISABLED,
cx->v4l2_dev.name, (void *)cx);
if (retval) {
CX18_ERR("Failed to register irq %d\n", retval);
goto free_i2c;
Expand Down Expand Up @@ -933,8 +923,7 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
goto free_streams;
}

CX18_INFO("Initialized card #%d: %s\n", cx->num, cx->card_name);

CX18_INFO("Initialized card: %s\n", cx->card_name);
return 0;

free_streams:
Expand All @@ -949,18 +938,13 @@ static int __devinit cx18_probe(struct pci_dev *pci_dev,
release_mem_region(cx->base_addr, CX18_MEM_SIZE);
free_workqueue:
destroy_workqueue(cx->work_queue);
unregister_v4l2:
v4l2_device_unregister(&cx->v4l2_dev);
err:
if (retval == 0)
retval = -ENODEV;
CX18_ERR("Error %d on initialization\n", retval);

i = cx->num;
spin_lock(&cx18_cards_lock);
kfree(cx18_cards[i]);
cx18_cards[i] = NULL;
spin_unlock(&cx18_cards_lock);
v4l2_device_unregister(&cx->v4l2_dev);
kfree(cx);
return retval;
}

Expand Down Expand Up @@ -1069,9 +1053,9 @@ static void cx18_cancel_epu_work_orders(struct cx18 *cx)
static void cx18_remove(struct pci_dev *pci_dev)
{
struct v4l2_device *v4l2_dev = pci_get_drvdata(pci_dev);
struct cx18 *cx = container_of(v4l2_dev, struct cx18, v4l2_dev);
struct cx18 *cx = to_cx18(v4l2_dev);

CX18_DEBUG_INFO("Removing Card #%d\n", cx->num);
CX18_DEBUG_INFO("Removing Card\n");

/* Stop all captures */
CX18_DEBUG_INFO("Stopping all streams\n");
Expand Down Expand Up @@ -1099,10 +1083,12 @@ static void cx18_remove(struct pci_dev *pci_dev)
release_mem_region(cx->base_addr, CX18_MEM_SIZE);

pci_disable_device(cx->pci_dev);
/* FIXME - we leak cx->vbi.sliced_mpeg_data[i] allocations */

v4l2_device_unregister(v4l2_dev);
CX18_INFO("Removed %s\n", cx->card_name);

CX18_INFO("Removed %s, card #%d\n", cx->card_name, cx->num);
v4l2_device_unregister(v4l2_dev);
kfree(cx);
}

/* define a pci_driver for card detection */
Expand All @@ -1117,8 +1103,6 @@ static int module_start(void)
{
printk(KERN_INFO "cx18: Start initialization, version %s\n", CX18_VERSION);

memset(cx18_cards, 0, sizeof(cx18_cards));

/* Validate parameters */
if (cx18_first_minor < 0 || cx18_first_minor >= CX18_MAX_CARDS) {
printk(KERN_ERR "cx18: Exiting, cx18_first_minor must be between 0 and %d\n",
Expand All @@ -1141,16 +1125,7 @@ static int module_start(void)

static void module_cleanup(void)
{
int i;

pci_unregister_driver(&cx18_pci_driver);

for (i = 0; i < cx18_cards_active; i++) {
if (cx18_cards[i] == NULL)
continue;
kfree(cx18_cards[i]);
}

}

module_init(module_start);
Expand Down
27 changes: 14 additions & 13 deletions drivers/media/video/cx18/cx18-driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,12 +144,12 @@
/* Flag to turn on high volume debugging */
#define CX18_DBGFLG_HIGHVOL (1 << 8)

/* NOTE: extra space before comma in 'cx->num , ## args' is required for
/* NOTE: extra space before comma in 'fmt , ## args' is required for
gcc-2.95, otherwise it won't compile. */
#define CX18_DEBUG(x, type, fmt, args...) \
do { \
if ((x) & cx18_debug) \
printk(KERN_INFO "cx18-%d " type ": " fmt, cx->num , ## args); \
v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
} while (0)
#define CX18_DEBUG_WARN(fmt, args...) CX18_DEBUG(CX18_DBGFLG_WARN, "warning", fmt , ## args)
#define CX18_DEBUG_INFO(fmt, args...) CX18_DEBUG(CX18_DBGFLG_INFO, "info", fmt , ## args)
Expand All @@ -163,7 +163,7 @@
#define CX18_DEBUG_HIGH_VOL(x, type, fmt, args...) \
do { \
if (((x) & cx18_debug) && (cx18_debug & CX18_DBGFLG_HIGHVOL)) \
printk(KERN_INFO "cx18%d " type ": " fmt, cx->num , ## args); \
v4l2_info(&cx->v4l2_dev, " " type ": " fmt , ## args); \
} while (0)
#define CX18_DEBUG_HI_WARN(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_WARN, "warning", fmt , ## args)
#define CX18_DEBUG_HI_INFO(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_INFO, "info", fmt , ## args)
Expand All @@ -175,9 +175,9 @@
#define CX18_DEBUG_HI_IRQ(fmt, args...) CX18_DEBUG_HIGH_VOL(CX18_DBGFLG_IRQ, "irq", fmt , ## args)

/* Standard kernel messages */
#define CX18_ERR(fmt, args...) printk(KERN_ERR "cx18-%d: " fmt, cx->num , ## args)
#define CX18_WARN(fmt, args...) printk(KERN_WARNING "cx18-%d: " fmt, cx->num , ## args)
#define CX18_INFO(fmt, args...) printk(KERN_INFO "cx18-%d: " fmt, cx->num , ## args)
#define CX18_ERR(fmt, args...) v4l2_err(&cx->v4l2_dev, fmt , ## args)
#define CX18_WARN(fmt, args...) v4l2_warn(&cx->v4l2_dev, fmt , ## args)
#define CX18_INFO(fmt, args...) v4l2_info(&cx->v4l2_dev, fmt , ## args)

/* Values for CX18_API_DEC_PLAYBACK_SPEED mpeg_frame_type_mask parameter: */
#define MPEG_FRAME_TYPE_IFRAME 1
Expand Down Expand Up @@ -445,8 +445,7 @@ struct cx18_i2c_algo_callback_data {

/* Struct to hold info about cx18 cards */
struct cx18 {
int num; /* board number, -1 during init! */
char name[8]; /* board name for printk and interrupts (e.g. 'cx180') */
int instance;
struct pci_dev *pci_dev;
struct v4l2_device v4l2_dev;

Expand All @@ -455,8 +454,8 @@ struct cx18 {
const struct cx18_card_tuner_i2c *card_i2c; /* i2c addresses to probe for tuner */
u8 is_50hz;
u8 is_60hz;
u8 is_out_50hz;
u8 is_out_60hz;
u8 is_out_50hz; /* FIXME - remove, we don't have an output decoder */
u8 is_out_60hz; /* FIXME - remove, we don't have an output decoder */
u8 nof_inputs; /* number of video inputs */
u8 nof_audio_inputs; /* number of audio inputs */
u16 buffer_id; /* buffer ID counter */
Expand Down Expand Up @@ -547,11 +546,13 @@ struct cx18 {
v4l2_std_id tuner_std; /* The norm of the tuner (fixed) */
};

static inline struct cx18 *to_cx18(struct v4l2_device *v4l2_dev)
{
return container_of(v4l2_dev, struct cx18, v4l2_dev);
}

/* Globals */
extern struct cx18 *cx18_cards[];
extern int cx18_cards_active;
extern int cx18_first_minor;
extern spinlock_t cx18_cards_lock;

/*==============Prototypes==================*/

Expand Down
35 changes: 6 additions & 29 deletions drivers/media/video/cx18/cx18-fileops.c
Original file line number Diff line number Diff line change
Expand Up @@ -682,38 +682,15 @@ static int cx18_serialized_open(struct cx18_stream *s, struct file *filp)

int cx18_v4l2_open(struct file *filp)
{
int res, x, y = 0;
struct cx18 *cx = NULL;
struct cx18_stream *s = NULL;
int minor = video_devdata(filp)->minor;

/* Find which card this open was on */
spin_lock(&cx18_cards_lock);
for (x = 0; cx == NULL && x < cx18_cards_active; x++) {
/* find out which stream this open was on */
for (y = 0; y < CX18_MAX_STREAMS; y++) {
if (cx18_cards[x] == NULL)
continue;
s = &cx18_cards[x]->streams[y];
if (s->video_dev && s->video_dev->minor == minor) {
cx = cx18_cards[x];
break;
}
}
}
spin_unlock(&cx18_cards_lock);

if (cx == NULL) {
/* Couldn't find a device registered
on that minor, shouldn't happen! */
printk(KERN_WARNING "No cx18 device found on minor %d\n",
minor);
return -ENXIO;
}
int res;
struct video_device *video_dev = video_devdata(filp);
struct cx18_stream *s = video_get_drvdata(video_dev);
struct cx18 *cx = s->cx;;

mutex_lock(&cx->serialize_lock);
if (cx18_init_on_first_open(cx)) {
CX18_ERR("Failed to initialize on minor %d\n", minor);
CX18_ERR("Failed to initialize on minor %d\n",
video_dev->minor);
mutex_unlock(&cx->serialize_lock);
return -ENXIO;
}
Expand Down
2 changes: 1 addition & 1 deletion drivers/media/video/cx18/cx18-i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ int init_cx18_i2c(struct cx18 *cx)
cx->i2c_adap[i].algo_data = &cx->i2c_algo[i];

sprintf(cx->i2c_adap[i].name + strlen(cx->i2c_adap[i].name),
" #%d-%d", cx->num, i);
" #%d-%d", cx->instance, i);
i2c_set_adapdata(&cx->i2c_adap[i], cx);

memcpy(&cx->i2c_client[i], &cx18_i2c_client_template,
Expand Down
Loading

0 comments on commit 5811cf9

Please sign in to comment.