From c812b67ca4ed13fa5ec60f06c4ed8f648722a186 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 18:29:42 -0300 Subject: V4L/DVB (5886): zr36067: Fix problem setting norms 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_driver.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 17118a490f81..fac97cb5a828 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -3704,11 +3704,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-70-g09d2 From e42af83f4874ebb2c6af59a05dbe5d45114fb0ed Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 18:29:43 -0300 Subject: V4L/DVB (5887): zr36067: Fix poll() operation 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_driver.c | 59 +++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 26 deletions(-) diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index fac97cb5a828..37e25c25279b 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -4213,8 +4213,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 @@ -4228,51 +4228,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-70-g09d2 From bb2e033913f14b2f9f6745e206c3ea5df481b4fd Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 18:29:43 -0300 Subject: V4L/DVB (5888): zr36067: Driver was not returning correct image size 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_driver.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 37e25c25279b..06446311564a 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -2737,7 +2737,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 = @@ -2984,8 +2985,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-70-g09d2 From 603d6f2c8f9f3604f9c6c1f8903efc2df30a000f Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 18:29:44 -0300 Subject: V4L/DVB (5890): zr36067: Add UYVY, RGB555X, RGB565X, and RGB32 formats 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran.h | 5 ++ drivers/media/video/zoran_device.c | 33 +-------- drivers/media/video/zoran_driver.c | 145 ++++++++++++++++++++----------------- 3 files changed, 86 insertions(+), 97 deletions(-) diff --git a/drivers/media/video/zoran.h b/drivers/media/video/zoran.h index 8fb4a3414e0a..937c4a616c0e 100644 --- a/drivers/media/video/zoran.h +++ b/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/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index b0752767ee4f..d9640ec4b9b0 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -429,8 +429,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 */ @@ -439,36 +437,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) { @@ -476,6 +444,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/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index 06446311564a..ec9ae6c61bd5 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -99,88 +99,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 @@ -768,13 +783,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", @@ -2107,7 +2122,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 && @@ -2116,7 +2131,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", @@ -2220,10 +2235,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", @@ -2672,14 +2687,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)); @@ -2942,11 +2957,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", @@ -3055,10 +3070,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", @@ -4151,11 +4166,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-70-g09d2 From 9896bbc1972e3a0595f06c23692a20150a789308 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Tue, 17 Jul 2007 18:29:45 -0300 Subject: V4L/DVB (5891): zr36067: Turn off raw capture properly 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 Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran_device.c | 17 ++++++++++++----- drivers/media/video/zoran_driver.c | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/zoran_device.c b/drivers/media/video/zoran_device.c index d9640ec4b9b0..ba2f4ed29483 100644 --- a/drivers/media/video/zoran_device.c +++ b/drivers/media/video/zoran_device.c @@ -620,11 +620,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 */ @@ -641,11 +647,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/drivers/media/video/zoran_driver.c b/drivers/media/video/zoran_driver.c index ec9ae6c61bd5..72a037b75d63 100644 --- a/drivers/media/video/zoran_driver.c +++ b/drivers/media/video/zoran_driver.c @@ -1188,10 +1188,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 */ @@ -3456,8 +3460,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 = @@ -4392,11 +4401,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-70-g09d2 From 89f50bf63778018708e29ca0a874c72cb81f77f9 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Fri, 20 Jul 2007 17:18:10 -0300 Subject: V4L/DVB (5893): DVB: fix includes of video.h when __KERNEL__ is undefined linux/dvb/video.h uses types __u32, __s32, etc., but does not include any header defining those when __KERNEL__ is not defined. Fix this by including asm/types.h when __KERNEL__ is not defined. Signed-off-by: Anssi Hannula Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- include/linux/dvb/video.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/linux/dvb/video.h b/include/linux/dvb/video.h index 93e4c3a6d190..50839fe9e39e 100644 --- a/include/linux/dvb/video.h +++ b/include/linux/dvb/video.h @@ -29,6 +29,7 @@ #ifdef __KERNEL__ #include #else +#include #include #include #endif -- cgit v1.2.3-70-g09d2 From cf784d554fdb94f21671830135dba56b507126cf Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Sat, 21 Jul 2007 21:26:40 -0300 Subject: V4L/DVB (5899): bttv: Fix Viewcast Osprey 440 support Various gpio and mux settings for the Osprey 440 weren't correct. Fix them and provide some documentation about how the gpios work. The osprey eeprom routine wasn't run for the 440, add it. It was also crap, re-written to be better. Add the Osprey 440 to the Bt878 ALSA driver's whitelist. Currently the sample rate is fixed at 32kHz, as the driver doesn't support different rates for digital input mode, though the card can select the rate from 32, 44.1, or 48 kHz via gpio. Setting the audio gain via ALSA isn't supported yet; a userspace tool that programs the X9221 via i2c-dev must be used. The Bt878 digital audio format isn't programmed correctly for the CS5331A ADC used, resulting in extremely garbled sound. That is fixed in a followup patch. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 238 +++++++++++++++++++-------------- sound/pci/bt87x.c | 2 + 2 files changed, 136 insertions(+), 104 deletions(-) diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 387cb2122d4f..f6715007d409 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -45,7 +46,7 @@ static void boot_msp34xx(struct bttv *btv, int pin); static void boot_bt832(struct bttv *btv); static void hauppauge_eeprom(struct bttv *btv); static void avermedia_eeprom(struct bttv *btv); -static void osprey_eeprom(struct bttv *btv); +static void osprey_eeprom(struct bttv *btv, const u8 ee[256]); static void modtec_eeprom(struct bttv *btv); static void init_PXC200(struct bttv *btv); static void init_RTV24(struct bttv *btv); @@ -2843,13 +2844,28 @@ struct tvcard bttv_tvcards[] = { .has_remote = 1, }, /* ---- card 0x8c ---------------------------------- */ + /* Has four Bt878 chips behind a PCI bridge, each chip has: + one external BNC composite input (mux 2) + three internal composite inputs (unknown muxes) + an 18-bit stereo A/D (CS5331A), which has: + one external stereo unblanced (RCA) audio connection + one (or 3?) internal stereo balanced (XLR) audio connection + input is selected via gpio to a 14052B mux + (mask=0x300, unbal=0x000, bal=0x100, ??=0x200,0x300) + gain is controlled via an X9221A chip on the I2C bus @0x28 + sample rate is controlled via gpio to an MK1413S + (mask=0x3, 32kHz=0x0, 44.1kHz=0x1, 48kHz=0x2, ??=0x3) + There is neither a tuner nor an svideo input. */ [BTTV_BOARD_OSPREY440] = { .name = "Osprey 440", - .video_inputs = 1, - .audio_inputs = 1, + .video_inputs = 4, + .audio_inputs = 2, /* this is meaningless */ .tuner = UNSET, - .svhs = 1, - .muxsel = { 2 }, + .svhs = UNSET, + .muxsel = { 2, 3, 0, 1 }, /* 3,0,1 are guesses */ + .gpiomask = 0x303, + .gpiomute = 0x000, /* int + 32kHz */ + .gpiomux = { 0, 0, 0x000, 0x100}, .pll = PLL_28, .tuner_type = UNSET, .tuner_addr = ADDR_UNSET, @@ -3453,11 +3469,12 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_OSPREY2xx: case BTTV_BOARD_OSPREY2x0_SVID: case BTTV_BOARD_OSPREY2x0: + case BTTV_BOARD_OSPREY440: case BTTV_BOARD_OSPREY500: case BTTV_BOARD_OSPREY540: case BTTV_BOARD_OSPREY2000: bttv_readee(btv,eeprom_data,0xa0); - osprey_eeprom(btv); + osprey_eeprom(btv, eeprom_data); break; case BTTV_BOARD_IDS_EAGLE: init_ids_eagle(btv); @@ -3748,106 +3765,119 @@ static int __devinit pvr_boot(struct bttv *btv) /* ----------------------------------------------------------------------- */ /* some osprey specific stuff */ -static void __devinit osprey_eeprom(struct bttv *btv) +static void __devinit osprey_eeprom(struct bttv *btv, const u8 ee[256]) { - int i = 0; - unsigned char *ee = eeprom_data; - unsigned long serial = 0; - - if (btv->c.type == 0) { - /* this might be an antique... check for MMAC label in eeprom */ - if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { - unsigned char checksum = 0; - for (i = 0; i < 21; i++) - checksum += ee[i]; - if (checksum != ee[21]) - return; - btv->c.type = BTTV_BOARD_OSPREY1x0_848; - for (i = 12; i < 21; i++) - serial *= 10, serial += ee[i] - '0'; - } + int i; + u32 serial = 0; + int cardid = -1; + + /* This code will nevery actually get called in this case.... */ + if (btv->c.type == BTTV_BOARD_UNKNOWN) { + /* this might be an antique... check for MMAC label in eeprom */ + if (!strncmp(ee, "MMAC", 4)) { + u8 checksum = 0; + for (i = 0; i < 21; i++) + checksum += ee[i]; + if (checksum != ee[21]) + return; + cardid = BTTV_BOARD_OSPREY1x0_848; + for (i = 12; i < 21; i++) + serial *= 10, serial += ee[i] - '0'; + } } else { - unsigned short type; - int offset = 4*16; - - for (; offset < 8*16; offset += 16) { - unsigned short checksum = 0; - /* verify the checksum */ - for (i = 0; i < 14; i++) - checksum += ee[i+offset]; - checksum = ~checksum; /* no idea why */ - if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { - break; - } - } - - if (offset >= 8*16) - return; - - /* found a valid descriptor */ - type = (ee[offset+4]<<8) | (ee[offset+5]); - - switch(type) { - /* 848 based */ - case 0x0004: - btv->c.type = BTTV_BOARD_OSPREY1x0_848; - break; - case 0x0005: - btv->c.type = BTTV_BOARD_OSPREY101_848; - break; - - /* 878 based */ - case 0x0012: - case 0x0013: - btv->c.type = BTTV_BOARD_OSPREY1x0; - break; - case 0x0014: - case 0x0015: - btv->c.type = BTTV_BOARD_OSPREY1x1; - break; - case 0x0016: - case 0x0017: - case 0x0020: - btv->c.type = BTTV_BOARD_OSPREY1x1_SVID; - break; - case 0x0018: - case 0x0019: - case 0x001E: - case 0x001F: - btv->c.type = BTTV_BOARD_OSPREY2xx; - break; - case 0x001A: - case 0x001B: - btv->c.type = BTTV_BOARD_OSPREY2x0_SVID; - break; - case 0x0040: - btv->c.type = BTTV_BOARD_OSPREY500; - break; - case 0x0050: - case 0x0056: - btv->c.type = BTTV_BOARD_OSPREY540; - /* bttv_osprey_540_init(btv); */ - break; - case 0x0060: - case 0x0070: - case 0x00A0: - btv->c.type = BTTV_BOARD_OSPREY2x0; - /* enable output on select control lines */ - gpio_inout(0xffffff,0x000303); - break; - default: - /* unknown...leave generic, but get serial # */ - break; - } - serial = (ee[offset+6] << 24) - | (ee[offset+7] << 16) - | (ee[offset+8] << 8) - | (ee[offset+9]); - } - - printk(KERN_INFO "bttv%d: osprey eeprom: card=%d name=%s serial=%ld\n", - btv->c.nr, btv->c.type, bttv_tvcards[btv->c.type].name,serial); + unsigned short type; + + for (i = 4*16; i < 8*16; i += 16) { + u16 checksum = ip_compute_csum(ee + i, 16); + + if ((checksum&0xff) + (checksum>>8) == 0xff) + break; + } + if (i >= 8*16) + return; + ee += i; + + /* found a valid descriptor */ + type = be16_to_cpup((u16*)(ee+4)); + + switch(type) { + /* 848 based */ + case 0x0004: + cardid = BTTV_BOARD_OSPREY1x0_848; + break; + case 0x0005: + cardid = BTTV_BOARD_OSPREY101_848; + break; + + /* 878 based */ + case 0x0012: + case 0x0013: + cardid = BTTV_BOARD_OSPREY1x0; + break; + case 0x0014: + case 0x0015: + cardid = BTTV_BOARD_OSPREY1x1; + break; + case 0x0016: + case 0x0017: + case 0x0020: + cardid = BTTV_BOARD_OSPREY1x1_SVID; + break; + case 0x0018: + case 0x0019: + case 0x001E: + case 0x001F: + cardid = BTTV_BOARD_OSPREY2xx; + break; + case 0x001A: + case 0x001B: + cardid = BTTV_BOARD_OSPREY2x0_SVID; + break; + case 0x0040: + cardid = BTTV_BOARD_OSPREY500; + break; + case 0x0050: + case 0x0056: + cardid = BTTV_BOARD_OSPREY540; + /* bttv_osprey_540_init(btv); */ + break; + case 0x0060: + case 0x0070: + case 0x00A0: + cardid = BTTV_BOARD_OSPREY2x0; + /* enable output on select control lines */ + gpio_inout(0xffffff,0x000303); + break; + case 0x00D8: + cardid = BTTV_BOARD_OSPREY440; + break; + default: + /* unknown...leave generic, but get serial # */ + printk(KERN_INFO "bttv%d: " + "osprey eeprom: unknown card type 0x%04x\n", + btv->c.nr, type); + break; + } + serial = be32_to_cpup((u32*)(ee+6)); + } + + printk(KERN_INFO "bttv%d: osprey eeprom: card=%d '%s' serial=%u\n", + btv->c.nr, cardid, + cardid>0 ? bttv_tvcards[cardid].name : "Unknown", serial); + + if (cardid<0 || btv->c.type == cardid) + return; + + /* card type isn't set correctly */ + if (card[btv->c.nr] < bttv_num_tvcards) { + printk(KERN_WARNING "bttv%d: osprey eeprom: " + "Not overriding user specified card type\n", btv->c.nr); + } else { + printk(KERN_INFO "bttv%d: osprey eeprom: " + "Changing card type from %d to %d\n", btv->c.nr, + btv->c.type, cardid); + btv->c.type = cardid; + } } /* ----------------------------------------------------------------------- */ diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c index 6523ba07db96..188c7cf21b82 100644 --- a/sound/pci/bt87x.c +++ b/sound/pci/bt87x.c @@ -781,6 +781,8 @@ static struct pci_device_id snd_bt87x_ids[] = { BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_879, 0x0070, 0x13eb, 32000), /* Viewcast Osprey 200 */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff01, 44100), + /* Viewcast Osprey 440 (rate is configurable via gpio) */ + BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x0070, 0xff07, 32000), /* ATI TV-Wonder */ BT_DEVICE(PCI_DEVICE_ID_BROOKTREE_878, 0x1002, 0x0001, 32000), /* Leadtek Winfast tv 2000xp delux */ -- cgit v1.2.3-70-g09d2 From bc147135bc410bdd9da684646af75a188d882d56 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 23 Jul 2007 06:58:31 -0300 Subject: V4L/DVB (5900): usbvision: fix bugs [sg]_register functions s_register was assigning the return code to (unsigned)reg->val, rather than errCode, which it what it would return. Except reg->val can't be < 0, so it would never actually return an error. g_register never actually put the value it read into reg->val. Signed-off-by: Trent Piepho Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/usbvision/usbvision-video.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c index 868b6886fe7f..e3371f972240 100644 --- a/drivers/media/video/usbvision/usbvision-video.c +++ b/drivers/media/video/usbvision/usbvision-video.c @@ -517,6 +517,7 @@ static int vidioc_g_register (struct file *file, void *priv, __FUNCTION__, errCode); return errCode; } + reg->val = errCode; return 0; } @@ -531,8 +532,8 @@ static int vidioc_s_register (struct file *file, void *priv, if (!v4l2_chip_match_host(reg->match_type, reg->match_chip)) return -EINVAL; /* NT100x has a 8-bit register space */ - reg->val = (u8)usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); - if (reg->val < 0) { + errCode = usbvision_write_reg(usbvision, reg->reg&0xff, reg->val); + if (errCode < 0) { err("%s: VIDIOC_DBG_S_REGISTER failed: error %d", __FUNCTION__, errCode); return errCode; -- cgit v1.2.3-70-g09d2 From ac4251445d7302697814351f1d9f548f5aa49342 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 22 Jul 2007 08:46:38 -0300 Subject: V4L/DVB (5916): ivtv: fix pause/continue/play handling Pausing a decoder followed by a Play command would do nothing. Fixed. Pausing a decoder running at non-standard speed following by a Continue would reset the speed to 100%. Fixed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-driver.h | 1 + drivers/media/video/ivtv/ivtv-fileops.c | 1 + drivers/media/video/ivtv/ivtv-ioctl.c | 11 +++++++++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-driver.h b/drivers/media/video/ivtv/ivtv-driver.h index 91b588d261ae..8abb34a35816 100644 --- a/drivers/media/video/ivtv/ivtv-driver.h +++ b/drivers/media/video/ivtv/ivtv-driver.h @@ -417,6 +417,7 @@ struct ivtv_mailbox_data { #define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */ #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 */ /* Event notifications */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index 8e97a938398f..baa17cbee5e1 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -757,6 +757,7 @@ static void ivtv_stop_decoding(struct ivtv_open_id *id, int flags, u64 pts) itv->output_mode = OUT_NONE; itv->speed = 0; + clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); ivtv_release_stream(s); } diff --git a/drivers/media/video/ivtv/ivtv-ioctl.c b/drivers/media/video/ivtv/ivtv-ioctl.c index 4773453e8dab..047624b9e271 100644 --- a/drivers/media/video/ivtv/ivtv-ioctl.c +++ b/drivers/media/video/ivtv/ivtv-ioctl.c @@ -285,6 +285,10 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, if (ivtv_set_output_mode(itv, OUT_MPG) != OUT_MPG) return -EBUSY; + if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { + /* forces ivtv_set_speed to be called */ + itv->speed = 0; + } return ivtv_start_decoding(id, vc->play.speed); } @@ -309,6 +313,7 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, if (atomic_read(&itv->decoding) > 0) { ivtv_vapi(itv, CX2341X_DEC_PAUSE_PLAYBACK, 1, (vc->flags & VIDEO_CMD_FREEZE_TO_BLACK) ? 1 : 0); + set_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags); } break; @@ -317,8 +322,10 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id, if (try) break; if (itv->output_mode != OUT_MPG) return -EBUSY; - if (atomic_read(&itv->decoding) > 0) { - ivtv_vapi(itv, CX2341X_DEC_START_PLAYBACK, 2, 0, 0); + if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) { + int speed = itv->speed; + itv->speed = 0; + return ivtv_start_decoding(id, speed); } break; -- cgit v1.2.3-70-g09d2 From 0b3e29e6d75cbfb8417f449555d40921fd656186 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 22 Jul 2007 08:49:32 -0300 Subject: V4L/DVB (5917): ivtv: improve mailbox responsiveness. First try polling for the result of a mailbox command, then switch to a test/sleep loop. Also reduce the sleep time from 10 ms to 1 ms. Improves the responsiveness of the mailbox handling. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-mailbox.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-mailbox.c b/drivers/media/video/ivtv/ivtv-mailbox.c index 814a673712b3..5e3b679202ae 100644 --- a/drivers/media/video/ivtv/ivtv-mailbox.c +++ b/drivers/media/video/ivtv/ivtv-mailbox.c @@ -40,6 +40,7 @@ #define API_HIGH_VOL (1 << 5) /* High volume command (i.e. called during encoding or decoding) */ #define API_NO_WAIT_MB (1 << 4) /* Command may not wait for a free mailbox */ #define API_NO_WAIT_RES (1 << 5) /* Command may not wait for the result */ +#define API_NO_POLL (1 << 6) /* Avoid pointless polling */ struct ivtv_api_info { int flags; /* Flags, see above */ @@ -51,7 +52,7 @@ struct ivtv_api_info { static const struct ivtv_api_info api_info[256] = { /* MPEG encoder API */ API_ENTRY(CX2341X_ENC_PING_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_ENC_START_CAPTURE, API_RESULT), + API_ENTRY(CX2341X_ENC_START_CAPTURE, API_RESULT | API_NO_POLL), API_ENTRY(CX2341X_ENC_STOP_CAPTURE, API_RESULT), API_ENTRY(CX2341X_ENC_SET_AUDIO_ID, API_CACHE), API_ENTRY(CX2341X_ENC_SET_VIDEO_ID, API_CACHE), @@ -96,7 +97,7 @@ static const struct ivtv_api_info api_info[256] = { /* MPEG decoder API */ API_ENTRY(CX2341X_DEC_PING_FW, API_FAST_RESULT), - API_ENTRY(CX2341X_DEC_START_PLAYBACK, API_RESULT), + API_ENTRY(CX2341X_DEC_START_PLAYBACK, API_RESULT | API_NO_POLL), API_ENTRY(CX2341X_DEC_STOP_PLAYBACK, API_RESULT), API_ENTRY(CX2341X_DEC_SET_PLAYBACK_SPEED, API_RESULT), API_ENTRY(CX2341X_DEC_STEP_VIDEO, API_RESULT), @@ -290,6 +291,13 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) /* Get results */ then = jiffies; + if (!(flags & API_NO_POLL)) { + /* First try to poll, then switch to delays */ + for (i = 0; i < 100; i++) { + if (readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE) + break; + } + } while (!(readl(&mbox->flags) & IVTV_MBOX_FIRMWARE_DONE)) { if (jiffies - then > api_timeout) { IVTV_DEBUG_WARN("Could not get result (%s)\n", api_info[cmd].name); @@ -301,7 +309,7 @@ static int ivtv_api_call(struct ivtv *itv, int cmd, int args, u32 data[]) if (flags & API_NO_WAIT_RES) mdelay(1); else - ivtv_msleep_timeout(10, 0); + ivtv_msleep_timeout(1, 0); } if (jiffies - then > msecs_to_jiffies(100)) IVTV_DEBUG_WARN("%s took %u jiffies\n", -- cgit v1.2.3-70-g09d2 From 5a338c38ced1569a2e67e3c163505cc95429d508 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 22 Jul 2007 09:39:56 -0300 Subject: V4L/DVB (5918): ivtv: fix TV-out VBI handling, only reset on last close. While decoding (MPEG or YUV) is active or when VBI output is in use, then do not clear the VBI output of the saa7127. Only after the last user is gone can we clear it. This fixes the case where playback was stopped, another channel was chosen and playback was restarted, while /dev/vbi16 was used to set the WSS (widescreen) setting. Without this fix the WSS was reset on every stop instead of just keeping the last value. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-fileops.c | 9 +++++++++ drivers/media/video/ivtv/ivtv-streams.c | 11 +---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/drivers/media/video/ivtv/ivtv-fileops.c b/drivers/media/video/ivtv/ivtv-fileops.c index baa17cbee5e1..5dd519caf81d 100644 --- a/drivers/media/video/ivtv/ivtv-fileops.c +++ b/drivers/media/video/ivtv/ivtv-fileops.c @@ -800,7 +800,16 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) ivtv_unmute(itv); ivtv_release_stream(s); } else if (s->type >= IVTV_DEC_STREAM_TYPE_MPG) { + struct ivtv_stream *s_vout = &itv->streams[IVTV_DEC_STREAM_TYPE_VOUT]; + ivtv_stop_decoding(id, VIDEO_CMD_STOP_TO_BLACK | VIDEO_CMD_STOP_IMMEDIATELY, 0); + + /* If all output streams are closed, and if the user doesn't have + IVTV_DEC_STREAM_TYPE_VOUT open, then disable VBI on TV-out. */ + if (itv->output_mode == OUT_NONE && !test_bit(IVTV_F_S_APPL_IO, &s_vout->s_flags)) { + /* disable VBI on TV-out */ + ivtv_disable_vbi(itv); + } } else { ivtv_stop_capture(id, 0); } diff --git a/drivers/media/video/ivtv/ivtv-streams.c b/drivers/media/video/ivtv/ivtv-streams.c index 322b347b67c2..51df3f855031 100644 --- a/drivers/media/video/ivtv/ivtv-streams.c +++ b/drivers/media/video/ivtv/ivtv-streams.c @@ -603,10 +603,6 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) IVTV_DEBUG_INFO("Setting some initial decoder settings\n"); - /* disable VBI signals, if the MPEG stream contains VBI data, - then that data will be processed automatically for you. */ - ivtv_disable_vbi(itv); - /* set audio mode to left/stereo for dual/stereo mode. */ ivtv_vapi(itv, CX2341X_DEC_SET_AUDIO_MODE, 2, itv->audio_bilingual_mode, itv->audio_stereo_mode); @@ -639,7 +635,7 @@ static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s) } if (ivtv_vapi(itv, CX2341X_DEC_SET_DECODER_SOURCE, 4, datatype, itv->params.width, itv->params.height, itv->params.audio_properties)) { - IVTV_DEBUG_WARN("COULDN'T INITIALIZE DECODER SOURCE\n"); + IVTV_DEBUG_WARN("Couldn't initialize decoder source\n"); } return 0; } @@ -909,11 +905,6 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) clear_bit(IVTV_F_S_STREAMING, &s->s_flags); ivtv_flush_queues(s); - if (!test_bit(IVTV_F_S_PASSTHROUGH, &s->s_flags)) { - /* disable VBI on TV-out */ - ivtv_disable_vbi(itv); - } - /* decrement decoding */ atomic_dec(&itv->decoding); -- cgit v1.2.3-70-g09d2 From be9a5c7d9a04349c137610c72e3a74a5352dccf5 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 22 Jul 2007 11:12:26 -0300 Subject: V4L/DVB (5920): ivtv: fix incorrect fw size report. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/ivtv/ivtv-firmware.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/ivtv/ivtv-firmware.c b/drivers/media/video/ivtv/ivtv-firmware.c index d0feabf93080..425eb1063904 100644 --- a/drivers/media/video/ivtv/ivtv-firmware.c +++ b/drivers/media/video/ivtv/ivtv-firmware.c @@ -72,8 +72,8 @@ retry: dst++; src++; } - release_firmware(fw); IVTV_INFO("Loaded %s firmware (%zd bytes)\n", fn, fw->size); + release_firmware(fw); return size; } IVTV_ERR("Unable to open firmware %s (must be %ld bytes)\n", fn, size); -- cgit v1.2.3-70-g09d2 From 639ffd2d9038d34725b752147a0f1a8536146851 Mon Sep 17 00:00:00 2001 From: Luca Olivetti Date: Fri, 27 Jul 2007 10:27:47 -0300 Subject: V4L/DVB (5932): Af9005 fix tuner module unload This patch removes the useless tuner field and avoids a double free of the tuner (either mt2060 or qt1010). Signed-off-by: Luca Olivetti Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9005-fe.c | 37 ++++++++++++----------------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c index 7195c9461524..6809c6024d46 100644 --- a/drivers/media/dvb/dvb-usb/af9005-fe.c +++ b/drivers/media/dvb/dvb-usb/af9005-fe.c @@ -29,8 +29,6 @@ struct af9005_fe_state { struct dvb_usb_device *d; - struct dvb_frontend *tuner; - fe_status_t stat; /* retraining parameters */ @@ -447,7 +445,7 @@ static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat) u8 temp; int ret; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; *stat = 0; @@ -493,7 +491,7 @@ static int af9005_fe_read_status(struct dvb_frontend *fe, fe_status_t * stat) static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber) { struct af9005_fe_state *state = fe->demodulator_priv; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; af9005_fe_refresh_state(fe); *ber = state->ber; @@ -503,7 +501,7 @@ static int af9005_fe_read_ber(struct dvb_frontend *fe, u32 * ber) static int af9005_fe_read_unc_blocks(struct dvb_frontend *fe, u32 * unc) { struct af9005_fe_state *state = fe->demodulator_priv; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; af9005_fe_refresh_state(fe); *unc = state->unc; @@ -517,7 +515,7 @@ static int af9005_fe_read_signal_strength(struct dvb_frontend *fe, int ret; u8 if_gain, rf_gain; - if (state->tuner == NULL) + if (fe->ops.tuner_ops.release == NULL) return -ENODEV; ret = af9005_read_ofdm_register(state->d, xd_r_reg_aagc_rf_gain, @@ -1041,7 +1039,7 @@ static int af9005_fe_init(struct dvb_frontend *fe) return ret; /* attach tuner and init */ - if (state->tuner == NULL) { + if (fe->ops.tuner_ops.release == NULL) { /* read tuner and board id from eeprom */ ret = af9005_read_eeprom(adap->dev, 0xc6, buf, 2); if (ret) { @@ -1058,20 +1056,16 @@ static int af9005_fe_init(struct dvb_frontend *fe) return ret; } if1 = (u16) (buf[0] << 8) + buf[1]; - state->tuner = - dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap, - &af9005_mt2060_config, if1); - if (state->tuner == NULL) { + if (dvb_attach(mt2060_attach, fe, &adap->dev->i2c_adap, + &af9005_mt2060_config, if1) == NULL) { deb_info("MT2060 attach failed\n"); return -ENODEV; } break; case 3: /* QT1010 */ case 9: /* QT1010B */ - state->tuner = - dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap, - &af9005_qt1010_config); - if (state->tuner == NULL) { + if (dvb_attach(qt1010_attach, fe, &adap->dev->i2c_adap, + &af9005_qt1010_config) ==NULL) { deb_info("QT1010 attach failed\n"); return -ENODEV; } @@ -1080,7 +1074,7 @@ static int af9005_fe_init(struct dvb_frontend *fe) err("Unsupported tuner type %d", buf[0]); return -ENODEV; } - ret = state->tuner->ops.tuner_ops.init(state->tuner); + ret = fe->ops.tuner_ops.init(fe); if (ret) return ret; } @@ -1118,7 +1112,7 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe, deb_info("af9005_fe_set_frontend freq %d bw %d\n", fep->frequency, fep->u.ofdm.bandwidth); - if (state->tuner == NULL) { + if (fe->ops.tuner_ops.release == NULL) { err("Tuner not attached"); return -ENODEV; } @@ -1199,7 +1193,7 @@ static int af9005_fe_set_frontend(struct dvb_frontend *fe, return ret; /* set tuner */ deb_info("set tuner\n"); - ret = state->tuner->ops.tuner_ops.set_params(state->tuner, fep); + ret = fe->ops.tuner_ops.set_params(fe, fep); if (ret) return ret; @@ -1435,12 +1429,6 @@ static void af9005_fe_release(struct dvb_frontend *fe) { struct af9005_fe_state *state = (struct af9005_fe_state *)fe->demodulator_priv; - if (state->tuner != NULL && state->tuner->ops.tuner_ops.release != NULL) { - state->tuner->ops.tuner_ops.release(state->tuner); -#ifdef CONFIG_DVB_CORE_ATTACH - symbol_put_addr(state->tuner->ops.tuner_ops.release); -#endif - } kfree(state); } @@ -1458,7 +1446,6 @@ struct dvb_frontend *af9005_fe_attach(struct dvb_usb_device *d) deb_info("attaching frontend af9005\n"); state->d = d; - state->tuner = NULL; state->opened = 0; memcpy(&state->frontend.ops, &af9005_fe_ops, -- cgit v1.2.3-70-g09d2 From 4bc4365291bc27798d760c87f3aada39d9a74f43 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 27 Jul 2007 11:09:57 -0300 Subject: V4L/DVB (5933): Dvb-usb/af9005-fe.c: error check fixes This patch: - adds a missing error check and - removes an error check that could never be true Both spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Acked-by: Luca Olivetti Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/af9005-fe.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/af9005-fe.c b/drivers/media/dvb/dvb-usb/af9005-fe.c index 6809c6024d46..b1a9c4cdec93 100644 --- a/drivers/media/dvb/dvb-usb/af9005-fe.c +++ b/drivers/media/dvb/dvb-usb/af9005-fe.c @@ -343,8 +343,8 @@ static int af9005_reset_pre_viterbi(struct dvb_frontend *fe) 1 & 0xff); if (ret) return ret; - af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8, - 1 >> 8); + ret = af9005_write_ofdm_register(state->d, xd_p_fec_super_frm_unit_15_8, + 1 >> 8); if (ret) return ret; /* reset pre viterbi error count */ @@ -879,10 +879,8 @@ static int af9005_fe_init(struct dvb_frontend *fe) af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, reg_ofdm_rst_pos, reg_ofdm_rst_len, 1))) return ret; - if ((ret = - af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, - reg_ofdm_rst_pos, reg_ofdm_rst_len, 0))) - return ret; + ret = af9005_write_register_bits(state->d, xd_I2C_reg_ofdm_rst, + reg_ofdm_rst_pos, reg_ofdm_rst_len, 0); if (ret) return ret; -- cgit v1.2.3-70-g09d2 From 0a0f2c87cd689857f2b0b82c5322650f7d9b5923 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 29 Jul 2007 12:40:48 -0300 Subject: V4L/DVB (5939): dvb-pll: make struct dvb_pll_fcv1236d static The fcv1236d support patch was created before the "dvb: remove static dependencies on dvb-pll" patch was applied, but the fcv1236d patch didn't get merged until after the fact. struct dvb_pll_fcv1236d can become static. Signed-off-by: Adrian Bunk Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index 0c0b94767bc1..ca99e439c97c 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -501,7 +501,7 @@ static struct dvb_pll_desc dvb_pll_opera1 = { /* Philips FCV1236D */ -struct dvb_pll_desc dvb_pll_fcv1236d = { +static struct dvb_pll_desc dvb_pll_fcv1236d = { /* Bit_0: RF Input select * Bit_1: 0=digital, 1=analog */ -- cgit v1.2.3-70-g09d2