From 450ead099a065f8a7e00b476aee04508940856ce Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 17 Jul 2007 14:29:41 -0700 Subject: zr36067: clean up debug function From: Jean Delvare Debugging cleanups to the zr36067 driver: * Use module_param_named() to declare the debug parameter, so we can use a single global variable to handle the debug level. This makes the driver a bit smaller (by 648 bytes on x86_64), thanks to one less level of indirection on every use. * Change the debug parameter sysfs permissions, so that the debug level can be adjusted at runtime, as is done in many other media/video drivers. * The debug level is between 0 and 5, not 0 and 4. * Move the zr_debug export and dprintk macro definition to a header file so that we don't have to define them in each source file. * Simplify a duplicate test on zr_debug. Note that zr_debug was subsequently renamed to debug_zr36067 to avoid possible conflicts with other Zoran device drivers, on a suggestion by Trent Piepho. Signed-off-by: Jean Delvare Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran_card.c | 19 ++++++------------- linux/drivers/media/video/zoran_card.h | 8 ++++++++ linux/drivers/media/video/zoran_device.c | 17 +++++------------ linux/drivers/media/video/zoran_driver.c | 20 +++++--------------- linux/drivers/media/video/zoran_procfs.c | 9 +-------- 5 files changed, 25 insertions(+), 48 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran_card.c b/linux/drivers/media/video/zoran_card.c index 498e37e9f..cd12fee7b 100644 --- a/linux/drivers/media/video/zoran_card.c +++ b/linux/drivers/media/video/zoran_card.c @@ -148,10 +148,9 @@ module_param(pass_through, int, 0); MODULE_PARM_DESC(pass_through, "Pass TV signal through to TV-out when idling"); -static int debug = 1; -int *zr_debug = &debug; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0-4)"); +int zr36067_debug = 1; +module_param_named(debug, zr36067_debug, int, 0644); +MODULE_PARM_DESC(debug, "Debug level (0-5)"); MODULE_DESCRIPTION("Zoran-36057/36067 JPEG codec driver"); MODULE_AUTHOR("Serguei Miridonov"); @@ -164,12 +163,6 @@ static struct pci_device_id zr36067_pci_tbl[] = { }; MODULE_DEVICE_TABLE(pci, zr36067_pci_tbl); -#define dprintk(num, format, args...) \ - do { \ - if (*zr_debug >= num) \ - printk(format, ##args); \ - } while (0) - int zoran_num; /* number of Buzs in use */ struct zoran zoran[BUZ_MAX]; @@ -1078,7 +1071,7 @@ test_interrupts (struct zoran *zr) if (timeout) { dprintk(1, ": time spent: %d\n", 1 * HZ - timeout); } - if (*zr_debug > 1) + if (zr36067_debug > 1) print_interrupts(zr); btwrite(icr, ZR36057_ICR); } @@ -1161,7 +1154,7 @@ zr36057_init (struct zoran *zr) goto exit_unregister; zoran_init_hardware(zr); - if (*zr_debug > 2) + if (zr36067_debug > 2) detect_guest_activity(zr); test_interrupts(zr); if (!pass_through) { @@ -1623,7 +1616,7 @@ init_dc10_cards (void) } /* random nonsense */ - dprintk(5, KERN_DEBUG "Jotti is een held!\n"); + dprintk(6, KERN_DEBUG "Jotti is een held!\n"); /* some mainboards might not do PCI-PCI data transfer well */ if (pci_pci_problems & (PCIPCI_FAIL|PCIAGP_FAIL|PCIPCI_ALIMAGIK)) { diff --git a/linux/drivers/media/video/zoran_card.h b/linux/drivers/media/video/zoran_card.h index ad997c30b..8444ca0a5 100644 --- a/linux/drivers/media/video/zoran_card.h +++ b/linux/drivers/media/video/zoran_card.h @@ -30,6 +30,14 @@ #ifndef __ZORAN_CARD_H__ #define __ZORAN_CARD_H__ +extern int zr36067_debug; + +#define dprintk(num, format, args...) \ + do { \ + if (zr36067_debug >= num) \ + printk(format, ##args); \ + } while (0) + /* Anybody who uses more than four? */ #define BUZ_MAX 4 extern int zoran_num; diff --git a/linux/drivers/media/video/zoran_device.c b/linux/drivers/media/video/zoran_device.c index db0a9bd48..fd5c5ee3b 100644 --- a/linux/drivers/media/video/zoran_device.c +++ b/linux/drivers/media/video/zoran_device.c @@ -53,6 +53,7 @@ #include "videocodec.h" #include "zoran.h" #include "zoran_device.h" +#include "zoran_card.h" #define IRQ_MASK ( ZR36057_ISR_GIRQ0 | \ ZR36057_ISR_GIRQ1 | \ @@ -60,14 +61,6 @@ extern const struct zoran_format zoran_formats[]; -extern int *zr_debug; - -#define dprintk(num, format, args...) \ - do { \ - if (*zr_debug >= num) \ - printk(format, ##args); \ - } while (0) - static int lml33dpath = 0; /* 1 will use digital path in capture * mode instead of analog. It can be * used for picture adjustments using @@ -175,7 +168,7 @@ post_office_read (struct zoran *zr, static void dump_guests (struct zoran *zr) { - if (*zr_debug > 2) { + if (zr36067_debug > 2) { int i, guest[8]; for (i = 1; i < 8; i++) { // Don't read jpeg codec here @@ -1296,7 +1289,7 @@ error_handler (struct zoran *zr, zr->num_errors++; /* Report error */ - if (*zr_debug > 1 && zr->num_errors <= 8) { + if (zr36067_debug > 1 && zr->num_errors <= 8) { long frame; frame = zr->jpg_pend[zr->jpg_dma_tail & BUZ_MASK_FRAME]; @@ -1561,7 +1554,7 @@ zoran_irq (int irq, if (zr->codec_mode == BUZ_MODE_MOTION_DECOMPRESS || zr->codec_mode == BUZ_MODE_MOTION_COMPRESS) { - if (*zr_debug > 1 && + if (zr36067_debug > 1 && (!zr->frame_num || zr->JPEG_error)) { printk(KERN_INFO "%s: first frame ready: state=0x%08x odd_even=%d field_per_buff=%d delay=%d\n", @@ -1598,7 +1591,7 @@ zoran_irq (int irq, zr->JPEG_missed; } - if (*zr_debug > 2 && zr->frame_num < 6) { + if (zr36067_debug > 2 && zr->frame_num < 6) { int i; printk("%s: seq=%ld stat_com:", ZR_DEVNAME(zr), zr->jpg_seq_num); diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index d7b6d7c96..2fbb02a52 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -195,14 +195,6 @@ static const int zoran_num_formats = # include #endif -extern int *zr_debug; - -#define dprintk(num, format, args...) \ - do { \ - if (*zr_debug >= num) \ - printk(format, ##args); \ - } while (0) - extern int v4l_nbufs; extern int v4l_bufsize; extern int jpg_nbufs; @@ -1159,12 +1151,10 @@ jpg_sync (struct file *file, frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; /* buffer should now be in BUZ_STATE_DONE */ - if (*zr_debug > 0) - if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) - dprintk(2, - KERN_ERR - "%s: jpg_sync() - internal state error\n", - ZR_DEVNAME(zr)); + if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE) + dprintk(2, + KERN_ERR "%s: jpg_sync() - internal state error\n", + ZR_DEVNAME(zr)); *bs = zr->jpg_buffers.buffer[frame].bs; bs->frame = frame; @@ -1438,7 +1428,7 @@ zoran_close (struct inode *inode, /* disable interrupts */ btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR); - if (*zr_debug > 1) + if (zr36067_debug > 1) print_interrupts(zr); /* Overlay off */ diff --git a/linux/drivers/media/video/zoran_procfs.c b/linux/drivers/media/video/zoran_procfs.c index 010842a20..5aa285bdc 100644 --- a/linux/drivers/media/video/zoran_procfs.c +++ b/linux/drivers/media/video/zoran_procfs.c @@ -49,14 +49,7 @@ #include "videocodec.h" #include "zoran.h" #include "zoran_procfs.h" - -extern int *zr_debug; - -#define dprintk(num, format, args...) \ - do { \ - if (*zr_debug >= num) \ - printk(format, ##args); \ - } while (0) +#include "zoran_card.h" #ifdef CONFIG_PROC_FS struct procfs_params_zr36067 { -- cgit v1.2.3 From 1c33921b7105f6b68adf3ac7977b242250b968ca Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 14:29:42 -0700 Subject: zr36067: Fix problems with module parameters From: Trent Piepho Add permissions to all the module parameters so they can be queried and set (when possible) via sysfs. Add description for the vidmem parameter. Change the video_nr parameter to an array, so that the video number can be specified when a user has more than one card. The driver would try to give all cards the same number otherwise, which will fail for all cards after the first. The default_input option would only allow values of 0 or 1, contrary to the description. Allow values up to the number of inputs defined for the card. Add description of lock_norm's different behavior for 1 and >1. Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran_card.c | 45 +++++++++++++++++++------------- linux/drivers/media/video/zoran_device.c | 2 +- linux/drivers/media/video/zoran_driver.c | 4 +-- 3 files changed, 30 insertions(+), 21 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran_card.c b/linux/drivers/media/video/zoran_card.c index cd12fee7b..ee8dbf0a2 100644 --- a/linux/drivers/media/video/zoran_card.c +++ b/linux/drivers/media/video/zoran_card.c @@ -67,15 +67,15 @@ extern const struct zoran_format zoran_formats[]; static int card[BUZ_MAX] = { -1, -1, -1, -1 }; -module_param_array(card, int, NULL, 0); +module_param_array(card, int, NULL, 0444); MODULE_PARM_DESC(card, "The type of card"); static int encoder[BUZ_MAX] = { -1, -1, -1, -1 }; -module_param_array(encoder, int, NULL, 0); +module_param_array(encoder, int, NULL, 0444); MODULE_PARM_DESC(encoder, "i2c TV encoder"); static int decoder[BUZ_MAX] = { -1, -1, -1, -1 }; -module_param_array(decoder, int, NULL, 0); +module_param_array(decoder, int, NULL, 0444); MODULE_PARM_DESC(decoder, "i2c TV decoder"); /* @@ -87,29 +87,31 @@ MODULE_PARM_DESC(decoder, "i2c TV decoder"); */ static unsigned long vidmem = 0; /* Video memory base address */ -module_param(vidmem, ulong, 0); +module_param(vidmem, ulong, 0444); +MODULE_PARM_DESC(vidmem, "Default video memory base address"); /* Default input and video norm at startup of the driver. */ -static int default_input = 0; /* 0=Composite, 1=S-Video */ -module_param(default_input, int, 0); +static unsigned int default_input = 0; /* 0=Composite, 1=S-Video */ +module_param(default_input, uint, 0444); MODULE_PARM_DESC(default_input, "Default input (0=Composite, 1=S-Video, 2=Internal)"); static int default_mux = 1; /* 6 Eyes input selection */ -module_param(default_mux, int, 0); +module_param(default_mux, int, 0644); MODULE_PARM_DESC(default_mux, "Default 6 Eyes mux setting (Input selection)"); static int default_norm = 0; /* 0=PAL, 1=NTSC 2=SECAM */ -module_param(default_norm, int, 0); +module_param(default_norm, int, 0444); MODULE_PARM_DESC(default_norm, "Default norm (0=PAL, 1=NTSC, 2=SECAM)"); -static int video_nr = -1; /* /dev/videoN, -1 for autodetect */ -module_param(video_nr, int, 0); -MODULE_PARM_DESC(video_nr, "video device number"); +/* /dev/videoN, -1 for autodetect */ +static int video_nr[BUZ_MAX] = {-1, -1, -1, -1}; +module_param_array(video_nr, int, NULL, 0444); +MODULE_PARM_DESC(video_nr, "video device number (-1=Auto)"); /* Number and size of grab buffers for Video 4 Linux @@ -130,21 +132,21 @@ MODULE_PARM_DESC(video_nr, "video device number"); int v4l_nbufs = 2; int v4l_bufsize = 128; /* Everybody should be able to work with this setting */ -module_param(v4l_nbufs, int, 0); +module_param(v4l_nbufs, int, 0644); MODULE_PARM_DESC(v4l_nbufs, "Maximum number of V4L buffers to use"); -module_param(v4l_bufsize, int, 0); +module_param(v4l_bufsize, int, 0644); MODULE_PARM_DESC(v4l_bufsize, "Maximum size per V4L buffer (in kB)"); int jpg_nbufs = 32; int jpg_bufsize = 512; /* max size for 100% quality full-PAL frame */ -module_param(jpg_nbufs, int, 0); +module_param(jpg_nbufs, int, 0644); MODULE_PARM_DESC(jpg_nbufs, "Maximum number of JPG buffers to use"); -module_param(jpg_bufsize, int, 0); +module_param(jpg_bufsize, int, 0644); MODULE_PARM_DESC(jpg_bufsize, "Maximum size per JPG buffer (in kB)"); int pass_through = 0; /* 1=Pass through TV signal when device is not used */ /* 0=Show color bar when device is not used (LML33: only if lml33dpath=1) */ -module_param(pass_through, int, 0); +module_param(pass_through, int, 0644); MODULE_PARM_DESC(pass_through, "Pass TV signal through to TV-out when idling"); @@ -1117,7 +1119,14 @@ zr36057_init (struct zoran *zr) zr->timing = zr->card.tvn[zr->norm]; } - zr->input = default_input = (default_input ? 1 : 0); + if (default_input > zr->card.inputs-1) { + dprintk(1, + KERN_WARNING + "%s: default_input value %d out of range (0-%d)\n", + ZR_DEVNAME(zr), default_input, zr->card.inputs-1); + default_input = 0; + } + zr->input = default_input; /* Should the following be reset at every open ? */ zr->hue = 32768; @@ -1149,7 +1158,7 @@ zr36057_init (struct zoran *zr) */ memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template)); strcpy(zr->video_dev->name, ZR_DEVNAME(zr)); - err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr); + err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]); if (err < 0) goto exit_unregister; diff --git a/linux/drivers/media/video/zoran_device.c b/linux/drivers/media/video/zoran_device.c index fd5c5ee3b..2906592d0 100644 --- a/linux/drivers/media/video/zoran_device.c +++ b/linux/drivers/media/video/zoran_device.c @@ -70,7 +70,7 @@ static int lml33dpath = 0; /* 1 will use digital path in capture * load on Bt819 input, there will be * some image imperfections */ -module_param(lml33dpath, bool, 0); +module_param(lml33dpath, bool, 0644); MODULE_PARM_DESC(lml33dpath, "Use digital path capture mode (on LML33 cards)"); diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index 2fbb02a52..9fede04f4 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -202,8 +202,8 @@ extern int jpg_bufsize; extern int pass_through; static int lock_norm = 0; /* 1=Don't change TV standard (norm) */ -module_param(lock_norm, int, 0); -MODULE_PARM_DESC(lock_norm, "Users can't change norm"); +module_param(lock_norm, int, 0644); +MODULE_PARM_DESC(lock_norm, "Prevent norm changes (1 = ignore, >1 = fail)"); #ifdef CONFIG_VIDEO_V4L2 /* small helper function for calculating buffersizes for v4l2 -- cgit v1.2.3 From c3fd829ebc0a4aa1fae9c049f0384f11652566d9 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 14:29:42 -0700 Subject: zr36067: Fix problem setting norms From: Trent Piepho The zr36067 driver doesn't make a distinction between the different sub-types of NTSC, PAL, or SECAM norms. For example, when the enum std ioctl returns the PAL standard it returns PAL_BG|PAL_DK|PAL_H|PAL_I. When setting the norm, it required the bitmask to match exactly the set of norms used during the enumeration. If just one norm was specified, for example PAL_BG or NTSC_M, it would fail. This violates the V4L2 spec, "VIDIOC_S_STD accepts *one* or more flags..." The key thing to realize is that V4L2_STD_PAL is not one bit, it is multiple bits. It's ok to call S_STD with any *one* of those bits, but the driver was requiring *all* of them. This fixes the S_STD function so that it will accept any set of one or more PAL norms as PAL, and the same for NTSC and SECAM. Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index 9fede04f4..117693ed0 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -3762,11 +3762,11 @@ zoran_do_ioctl (struct inode *inode, dprintk(3, KERN_DEBUG "%s: VIDIOC_S_STD - norm=0x%llx\n", ZR_DEVNAME(zr), (unsigned long long)*std); - if (*std == V4L2_STD_PAL) + if ((*std & V4L2_STD_PAL) && !(*std & ~V4L2_STD_PAL)) norm = VIDEO_MODE_PAL; - else if (*std == V4L2_STD_NTSC) + else if ((*std & V4L2_STD_NTSC) && !(*std & ~V4L2_STD_NTSC)) norm = VIDEO_MODE_NTSC; - else if (*std == V4L2_STD_SECAM) + else if ((*std & V4L2_STD_SECAM) && !(*std & ~V4L2_STD_SECAM)) norm = VIDEO_MODE_SECAM; else if (*std == V4L2_STD_ALL) norm = VIDEO_MODE_AUTO; -- cgit v1.2.3 From 00392f42737f3848e8c9e33a86480049b38a35fe Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 14:29:43 -0700 Subject: zr36067: Fix poll() operation From: Trent Piepho During uncompressed capture, the poll() function was looking the wrong frame. It was using the frame the driver was going to capture into next (pend_tail), when it should have been looking at the next frame to be de-queued with DQBUF/SYNC (sync_tail). It also wasn't looking in the right spot. It was looking at the file handle's copy of the buffer status, rather than the driver core copy. The interrupt routine marks frames as done in the driver core copy, the file handle copy isn't updated. So even if poll() looked at the right frame, it would never see it transition to done and return POLLIN. The compressed capture code has this same problem, looking in fh->jpg_buffers when it should have used zr->jpg_buffers. There was some logic to detect when there was no current capture in process nor any frames queued and try to return an error, which ends up being a bad idea. It's possible to call select() from one thread while no capture is in process, or no frames queued, and then start a capture or queue frames from another thread. The buffer state variables are protected by a spin lock, which the code wasn't acquiring. That is fixed too. Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran_driver.c | 59 ++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 26 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index 117693ed0..2d0a7cd9d 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -4271,8 +4271,8 @@ zoran_poll (struct file *file, { struct zoran_fh *fh = file->private_data; struct zoran *zr = fh->zr; - wait_queue_head_t *queue = NULL; int res = 0, frame; + unsigned long flags; /* we should check whether buffers are ready to be synced on * (w/o waits - O_NONBLOCK) here @@ -4286,51 +4286,58 @@ zoran_poll (struct file *file, switch (fh->map_mode) { case ZORAN_MAP_MODE_RAW: - if (fh->v4l_buffers.active == ZORAN_FREE || - zr->v4l_pend_head == zr->v4l_pend_tail) { - dprintk(1, - "%s: zoran_poll() - no buffers queued\n", - ZR_DEVNAME(zr)); - res = POLLNVAL; - goto poll_unlock_and_return; - } - queue = &zr->v4l_capq; - frame = zr->v4l_pend[zr->v4l_pend_tail & V4L_MASK_FRAME]; - poll_wait(file, queue, wait); - if (fh->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) + poll_wait(file, &zr->v4l_capq, wait); + frame = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME]; + + spin_lock_irqsave(&zr->spinlock, flags); + dprintk(3, + KERN_DEBUG + "%s: %s() raw - active=%c, sync_tail=%lu/%c, pend_tail=%lu, pend_head=%lu\n", + ZR_DEVNAME(zr), __FUNCTION__, + "FAL"[fh->v4l_buffers.active], zr->v4l_sync_tail, + "UPMD"[zr->v4l_buffers.buffer[frame].state], + zr->v4l_pend_tail, zr->v4l_pend_head); + /* Process is the one capturing? */ + if (fh->v4l_buffers.active != ZORAN_FREE && + /* Buffer ready to DQBUF? */ + zr->v4l_buffers.buffer[frame].state == BUZ_STATE_DONE) res = POLLIN | POLLRDNORM; + spin_unlock_irqrestore(&zr->spinlock, flags); + break; case ZORAN_MAP_MODE_JPG_REC: case ZORAN_MAP_MODE_JPG_PLAY: - if (fh->jpg_buffers.active == ZORAN_FREE || - zr->jpg_que_head == zr->jpg_que_tail) { - dprintk(1, - "%s: zoran_poll() - no buffers queued\n", - ZR_DEVNAME(zr)); - res = POLLNVAL; - goto poll_unlock_and_return; - } - queue = &zr->jpg_capq; + poll_wait(file, &zr->jpg_capq, wait); frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME]; - poll_wait(file, queue, wait); - if (fh->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { + + spin_lock_irqsave(&zr->spinlock, flags); + dprintk(3, + KERN_DEBUG + "%s: %s() jpg - active=%c, que_tail=%lu/%c, que_head=%lu, dma=%lu/%lu\n", + ZR_DEVNAME(zr), __FUNCTION__, + "FAL"[fh->jpg_buffers.active], zr->jpg_que_tail, + "UPMD"[zr->jpg_buffers.buffer[frame].state], + zr->jpg_que_head, zr->jpg_dma_tail, zr->jpg_dma_head); + if (fh->jpg_buffers.active != ZORAN_FREE && + zr->jpg_buffers.buffer[frame].state == BUZ_STATE_DONE) { if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) res = POLLIN | POLLRDNORM; else res = POLLOUT | POLLWRNORM; } + spin_unlock_irqrestore(&zr->spinlock, flags); + break; default: dprintk(1, + KERN_ERR "%s: zoran_poll() - internal error, unknown map_mode=%d\n", ZR_DEVNAME(zr), fh->map_mode); res = POLLNVAL; - goto poll_unlock_and_return; } -poll_unlock_and_return: mutex_unlock(&zr->resource_lock); return res; -- cgit v1.2.3 From 85ad95829f3aa0429a0adce713ee9b5fd79421ff Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 14:29:43 -0700 Subject: zr36067: Driver was not returning correct image size From: Trent Piepho The driver was returning the size of the (fixed) buffer it allocated as the sizeimage field in the v4l2 pixel format, rather than the actual size of the image. For example, a 192x128 YUYV image is 49152 bytes but the driver would always return 131072 bytes since if that was the size of the v4l buffer. This violates the v4l2 spec, which says that sizeimage should be the actual size of the image for uncompressed formats. It also caused mplayer to crash. Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran_driver.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index 2d0a7cd9d..b71407821 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -2795,7 +2795,8 @@ zoran_do_ioctl (struct inode *inode, fmt->fmt.pix.height = fh->v4l_settings.height; fmt->fmt.pix.sizeimage = - fh->v4l_buffers.buffer_size; + fh->v4l_settings.bytesperline * + fh->v4l_settings.height; fmt->fmt.pix.pixelformat = fh->v4l_settings.format->fourcc; fmt->fmt.pix.colorspace = @@ -3042,8 +3043,9 @@ zoran_do_ioctl (struct inode *inode, /* tell the user the * results/missing stuff */ - fmt->fmt.pix.sizeimage = fh->v4l_buffers.buffer_size /*zr->gbpl * zr->gheight */ - ; + fmt->fmt.pix.sizeimage = + fh->v4l_settings.height * + fh->v4l_settings.bytesperline; if (BUZ_MAX_HEIGHT < (fh->v4l_settings.height * 2)) fmt->fmt.pix.field = -- cgit v1.2.3 From a7c2eaeee1d6c3fa170da934dff101687560abfe Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 17 Jul 2007 14:29:44 -0700 Subject: zr36067: fix x86_64 warnings From: Jean Delvare Fix the following warning on x86_64: drivers/media/video/zoran_driver.c: In function "v4l_fbuffer_alloc": drivers/media/video/zoran_driver.c:387: warning: cast from pointer to integer of different size Signed-off-by: Jean Delvare Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran_driver.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index b71407821..e3a045af4 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -389,9 +389,8 @@ v4l_fbuffer_alloc (struct file *file) virt_to_bus(mem); dprintk(4, KERN_INFO - "%s: Bigphysarea frame %d mem 0x%x (bus: 0x%x)\n", - ZR_DEVNAME(zr), i, (unsigned) mem, - (unsigned) virt_to_bus(mem)); + "%s: Bigphysarea frame %d mem %p (bus: 0x%lx)\n", + ZR_DEVNAME(zr), i, mem, virt_to_bus(mem)); /* Zero out the allocated memory */ memset(fh->v4l_buffers.buffer[i].fbuffer, 0, -- cgit v1.2.3 From b7faeafd9f3af3a7bfa99fce5a82d961669388cc Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 14:29:44 -0700 Subject: zr36067: Add UYVY, RGB555X, RGB565X, and RGB32 formats From: Trent Piepho Add support for the UYVY and the other big endian output formats. The driver was naming formats based on the host endianess. This is different that all the other drivers appear to work and not what software appears to expect. Use ARRAY_SIZE() to find the the size of the zoran_formats array. Change the way the driver handles setting the video format register. Rather than use some if and switch statements to set to register by looking at the format id, the format list simply has a field with the proper bits to set. Adds a bit of ifdef to make a driver without V4L1 support more possible. Also create a macro for defining formats that handles vl41 and/or vl42 support to avoid repeated ifdefs in the format list. Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran.h | 5 ++ linux/drivers/media/video/zoran_device.c | 33 +------ linux/drivers/media/video/zoran_driver.c | 145 +++++++++++++++++-------------- 3 files changed, 86 insertions(+), 97 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran.h b/linux/drivers/media/video/zoran.h index 7528ff967..19810ca14 100644 --- a/linux/drivers/media/video/zoran.h +++ b/linux/drivers/media/video/zoran.h @@ -240,11 +240,16 @@ enum gpcs_type { struct zoran_format { char *name; +#ifdef CONFIG_VIDEO_V4L1_COMPAT int palette; +#endif +#ifdef CONFIG_VIDEO_V4L2 __u32 fourcc; int colorspace; +#endif int depth; __u32 flags; + __u32 vfespfr; }; /* flags */ #define ZORAN_FORMAT_COMPRESSED 1<<0 diff --git a/linux/drivers/media/video/zoran_device.c b/linux/drivers/media/video/zoran_device.c index 2906592d0..84c04645d 100644 --- a/linux/drivers/media/video/zoran_device.c +++ b/linux/drivers/media/video/zoran_device.c @@ -423,8 +423,6 @@ zr36057_set_vfe (struct zoran *zr, reg |= (HorDcm << ZR36057_VFESPFR_HorDcm); reg |= (VerDcm << ZR36057_VFESPFR_VerDcm); reg |= (DispMode << ZR36057_VFESPFR_DispMode); - if (format->palette != VIDEO_PALETTE_YUV422 && format->palette != VIDEO_PALETTE_YUYV) - reg |= ZR36057_VFESPFR_LittleEndian; /* RJ: I don't know, why the following has to be the opposite * of the corresponding ZR36060 setting, but only this way * we get the correct colors when uncompressing to the screen */ @@ -433,36 +431,6 @@ zr36057_set_vfe (struct zoran *zr, if (zr->norm != VIDEO_MODE_NTSC) reg |= ZR36057_VFESPFR_ExtFl; // NEEDED!!!!!!! Wolfgang reg |= ZR36057_VFESPFR_TopField; - switch (format->palette) { - - case VIDEO_PALETTE_YUYV: - case VIDEO_PALETTE_YUV422: - reg |= ZR36057_VFESPFR_YUV422; - break; - - case VIDEO_PALETTE_RGB555: - reg |= ZR36057_VFESPFR_RGB555 | ZR36057_VFESPFR_ErrDif; - break; - - case VIDEO_PALETTE_RGB565: - reg |= ZR36057_VFESPFR_RGB565 | ZR36057_VFESPFR_ErrDif; - break; - - case VIDEO_PALETTE_RGB24: - reg |= ZR36057_VFESPFR_RGB888 | ZR36057_VFESPFR_Pack24; - break; - - case VIDEO_PALETTE_RGB32: - reg |= ZR36057_VFESPFR_RGB888; - break; - - default: - dprintk(1, - KERN_INFO "%s: set_vfe() - unknown color_fmt=%x\n", - ZR_DEVNAME(zr), format->palette); - return; - - } if (HorDcm >= 48) { reg |= 3 << ZR36057_VFESPFR_HFilter; /* 5 tap filter */ } else if (HorDcm >= 32) { @@ -470,6 +438,7 @@ zr36057_set_vfe (struct zoran *zr, } else if (HorDcm >= 16) { reg |= 1 << ZR36057_VFESPFR_HFilter; /* 3 tap filter */ } + reg |= format->vfespfr; btwrite(reg, ZR36057_VFESPFR); /* display configuration */ diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index e3a045af4..70a118f23 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -102,88 +102,103 @@ #include -const struct zoran_format zoran_formats[] = { - { - .name = "15-bit RGB", - .palette = VIDEO_PALETTE_RGB555, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_RGB555, +#if defined(CONFIG_VIDEO_V4L2) && defined(CONFIG_VIDEO_V4L1_COMPAT) +#define ZFMT(pal, fcc, cs) \ + .palette = (pal), .fourcc = (fcc), .colorspace = (cs) +#elif defined(CONFIG_VIDEO_V4L2) +#define ZFMT(pal, fcc, cs) \ + .fourcc = (fcc), .colorspace = (cs) #else - .fourcc = V4L2_PIX_FMT_RGB555X, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, +#define ZFMT(pal, fcc, cs) \ + .palette = (pal) #endif + +const struct zoran_format zoran_formats[] = { + { + .name = "15-bit RGB LE", + ZFMT(VIDEO_PALETTE_RGB555, + V4L2_PIX_FMT_RGB555, V4L2_COLORSPACE_SRGB), .depth = 15, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif| + ZR36057_VFESPFR_LittleEndian, }, { - .name = "16-bit RGB", - .palette = VIDEO_PALETTE_RGB565, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_RGB565, -#else - .fourcc = V4L2_PIX_FMT_RGB565X, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, -#endif + .name = "15-bit RGB BE", + ZFMT(-1, + V4L2_PIX_FMT_RGB555X, V4L2_COLORSPACE_SRGB), + .depth = 15, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB555|ZR36057_VFESPFR_ErrDif, + }, { + .name = "16-bit RGB LE", + ZFMT(VIDEO_PALETTE_RGB565, + V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB), .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif| + ZR36057_VFESPFR_LittleEndian, + }, { + .name = "16-bit RGB BE", + ZFMT(-1, + V4L2_PIX_FMT_RGB565, V4L2_COLORSPACE_SRGB), + .depth = 16, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB565|ZR36057_VFESPFR_ErrDif, }, { .name = "24-bit RGB", - .palette = VIDEO_PALETTE_RGB24, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_BGR24, -#else - .fourcc = V4L2_PIX_FMT_RGB24, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, -#endif + ZFMT(VIDEO_PALETTE_RGB24, + V4L2_PIX_FMT_BGR24, V4L2_COLORSPACE_SRGB), .depth = 24, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_Pack24, }, { - .name = "32-bit RGB", - .palette = VIDEO_PALETTE_RGB32, -#ifdef CONFIG_VIDEO_V4L2 -#ifdef __LITTLE_ENDIAN - .fourcc = V4L2_PIX_FMT_BGR32, -#else - .fourcc = V4L2_PIX_FMT_RGB32, -#endif - .colorspace = V4L2_COLORSPACE_SRGB, -#endif + .name = "32-bit RGB LE", + ZFMT(VIDEO_PALETTE_RGB32, + V4L2_PIX_FMT_BGR32, V4L2_COLORSPACE_SRGB), .depth = 32, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB888|ZR36057_VFESPFR_LittleEndian, + }, { + .name = "32-bit RGB BE", + ZFMT(-1, + V4L2_PIX_FMT_RGB32, V4L2_COLORSPACE_SRGB), + .depth = 32, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_RGB888, }, { .name = "4:2:2, packed, YUYV", - .palette = VIDEO_PALETTE_YUV422, -#ifdef CONFIG_VIDEO_V4L2 - .fourcc = V4L2_PIX_FMT_YUYV, - .colorspace = V4L2_COLORSPACE_SMPTE170M, -#endif + ZFMT(VIDEO_PALETTE_YUV422, + V4L2_PIX_FMT_YUYV, V4L2_COLORSPACE_SMPTE170M), .depth = 16, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_YUV422, + }, { + .name = "4:2:2, packed, UYVY", + ZFMT(VIDEO_PALETTE_UYVY, + V4L2_PIX_FMT_UYVY, V4L2_COLORSPACE_SMPTE170M), + .depth = 16, + .flags = ZORAN_FORMAT_CAPTURE | + ZORAN_FORMAT_OVERLAY, + .vfespfr = ZR36057_VFESPFR_YUV422|ZR36057_VFESPFR_LittleEndian, }, { .name = "Hardware-encoded Motion-JPEG", - .palette = -1, -#ifdef CONFIG_VIDEO_V4L2 - .fourcc = V4L2_PIX_FMT_MJPEG, - .colorspace = V4L2_COLORSPACE_SMPTE170M, -#endif + ZFMT(-1, + V4L2_PIX_FMT_MJPEG, V4L2_COLORSPACE_SMPTE170M), .depth = 0, .flags = ZORAN_FORMAT_CAPTURE | ZORAN_FORMAT_PLAYBACK | ZORAN_FORMAT_COMPRESSED, } }; -static const int zoran_num_formats = - (sizeof(zoran_formats) / sizeof(struct zoran_format)); +#define NUM_FORMATS ARRAY_SIZE(zoran_formats) // RJ: Test only - want to test BUZ_USE_HIMEM even when CONFIG_BIGPHYS_AREA is defined #if !defined(CONFIG_BIGPHYS_AREA) && !defined(BUZ_USE_HIMEM) @@ -827,13 +842,13 @@ v4l_grab (struct file *file, struct zoran *zr = fh->zr; int res = 0, i; - for (i = 0; i < zoran_num_formats; i++) { + for (i = 0; i < NUM_FORMATS; i++) { if (zoran_formats[i].palette == mp->format && zoran_formats[i].flags & ZORAN_FORMAT_CAPTURE && !(zoran_formats[i].flags & ZORAN_FORMAT_COMPRESSED)) break; } - if (i == zoran_num_formats || zoran_formats[i].depth == 0) { + if (i == NUM_FORMATS || zoran_formats[i].depth == 0) { dprintk(1, KERN_ERR "%s: v4l_grab() - wrong bytes-per-pixel format\n", @@ -2164,7 +2179,7 @@ zoran_do_ioctl (struct inode *inode, vpict->colour, vpict->contrast, vpict->depth, vpict->palette); - for (i = 0; i < zoran_num_formats; i++) { + for (i = 0; i < NUM_FORMATS; i++) { const struct zoran_format *fmt = &zoran_formats[i]; if (fmt->palette != -1 && @@ -2173,7 +2188,7 @@ zoran_do_ioctl (struct inode *inode, fmt->depth == vpict->depth) break; } - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOCSPICT - Invalid palette %d\n", @@ -2277,10 +2292,10 @@ zoran_do_ioctl (struct inode *inode, ZR_DEVNAME(zr), vbuf->base, vbuf->width, vbuf->height, vbuf->depth, vbuf->bytesperline); - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (zoran_formats[i].depth == vbuf->depth) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOCSFBUF - invalid fbuf depth %d\n", @@ -2729,14 +2744,14 @@ zoran_do_ioctl (struct inode *inode, return -EINVAL; } - for (i = 0; i < zoran_num_formats; i++) { + for (i = 0; i < NUM_FORMATS; i++) { if (zoran_formats[i].flags & flag) num++; if (num == fmt->index) break; } if (fmt->index < 0 /* late, but not too late */ || - i == zoran_num_formats) + i == NUM_FORMATS) return -EINVAL; memset(fmt, 0, sizeof(*fmt)); @@ -2999,11 +3014,11 @@ zoran_do_ioctl (struct inode *inode, sfmtjpg_unlock_and_return: mutex_unlock(&zr->resource_lock); } else { - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (fmt->fmt.pix.pixelformat == zoran_formats[i].fourcc) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FMT - unknown/unsupported format 0x%x (%4.4s)\n", @@ -3112,10 +3127,10 @@ zoran_do_ioctl (struct inode *inode, fb->fmt.bytesperline, fb->fmt.pixelformat, (char *) &printformat); - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (zoran_formats[i].fourcc == fb->fmt.pixelformat) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { dprintk(1, KERN_ERR "%s: VIDIOC_S_FBUF - format=0x%x (%4.4s) not allowed\n", @@ -4208,11 +4223,11 @@ zoran_do_ioctl (struct inode *inode, V4L2_BUF_TYPE_VIDEO_CAPTURE) { int i; - for (i = 0; i < zoran_num_formats; i++) + for (i = 0; i < NUM_FORMATS; i++) if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat) break; - if (i == zoran_num_formats) { + if (i == NUM_FORMATS) { res = -EINVAL; goto tryfmt_unlock_and_return; } -- cgit v1.2.3 From 673be99d573553c9d6360e2c8b0184a480158c16 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 14:29:45 -0700 Subject: zr36067: Turn off raw capture properly From: Trent Piepho When raw capture was turned off, the current capturing frame (v4l_grab_frame) wasn't reset to NO_GRAB_ACTIVE. If capture was turned back on, the driver would think this frame was currently being captured, and wait for it to complete before starting a new frame. The hardware on the other hand would not be actively capturing a frame. The result was the driver would wait forever for v4l_grab_frame to be captured. Some calls to zr36057_set_memgrab(0) were missing spin-locks, which have been added. Signed-off-by: Trent Piepho Acked-by: Ronald S. Bultje --- linux/drivers/media/video/zoran_device.c | 17 ++++++++++++----- linux/drivers/media/video/zoran_driver.c | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) (limited to 'linux') diff --git a/linux/drivers/media/video/zoran_device.c b/linux/drivers/media/video/zoran_device.c index 84c04645d..f7f8e78ec 100644 --- a/linux/drivers/media/video/zoran_device.c +++ b/linux/drivers/media/video/zoran_device.c @@ -614,11 +614,17 @@ zr36057_set_memgrab (struct zoran *zr, int mode) { if (mode) { - if (btread(ZR36057_VSSFGR) & - (ZR36057_VSSFGR_SnapShot | ZR36057_VSSFGR_FrameGrab)) + /* We only check SnapShot and not FrameGrab here. SnapShot==1 + * means a capture is already in progress, but FrameGrab==1 + * doesn't necessary mean that. It's more correct to say a 1 + * to 0 transition indicates a capture completed. If a + * capture is pending when capturing is tuned off, FrameGrab + * will be stuck at 1 until capturing is turned back on. + */ + if (btread(ZR36057_VSSFGR) & ZR36057_VSSFGR_SnapShot) dprintk(1, KERN_WARNING - "%s: zr36057_set_memgrab(1) with SnapShot or FrameGrab on!?\n", + "%s: zr36057_set_memgrab(1) with SnapShot on!?\n", ZR_DEVNAME(zr)); /* switch on VSync interrupts */ @@ -635,11 +641,12 @@ zr36057_set_memgrab (struct zoran *zr, zr->v4l_memgrab_active = 1; } else { - zr->v4l_memgrab_active = 0; - /* switch off VSync interrupts */ btand(~zr->card.vsync_int, ZR36057_ICR); // SW + zr->v4l_memgrab_active = 0; + zr->v4l_grab_frame = NO_GRAB_ACTIVE; + /* reenable grabbing to screen if it was running */ if (zr->v4l_overlay_active) { zr36057_overlay(zr, 1); diff --git a/linux/drivers/media/video/zoran_driver.c b/linux/drivers/media/video/zoran_driver.c index 70a118f23..6e598a3c5 100644 --- a/linux/drivers/media/video/zoran_driver.c +++ b/linux/drivers/media/video/zoran_driver.c @@ -1245,10 +1245,14 @@ zoran_close_end_session (struct file *file) /* v4l capture */ if (fh->v4l_buffers.active != ZORAN_FREE) { + long flags; + + spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); zr->v4l_buffers.allocated = 0; zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); } /* v4l buffers */ @@ -3513,8 +3517,13 @@ zoran_do_ioctl (struct inode *inode, goto strmoff_unlock_and_return; /* unload capture */ - if (zr->v4l_memgrab_active) + if (zr->v4l_memgrab_active) { + long flags; + + spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); + spin_unlock_irqrestore(&zr->spinlock, flags); + } for (i = 0; i < fh->v4l_buffers.num_buffers; i++) zr->v4l_buffers.buffer[i].state = @@ -4449,11 +4458,15 @@ zoran_vm_close (struct vm_area_struct *vma) mutex_lock(&zr->resource_lock); if (fh->v4l_buffers.active != ZORAN_FREE) { + long flags; + + spin_lock_irqsave(&zr->spinlock, flags); zr36057_set_memgrab(zr, 0); zr->v4l_buffers.allocated = 0; zr->v4l_buffers.active = fh->v4l_buffers.active = ZORAN_FREE; + spin_unlock_irqrestore(&zr->spinlock, flags); } //v4l_fbuffer_free(file); fh->v4l_buffers.allocated = 0; -- cgit v1.2.3