summaryrefslogtreecommitdiffstats
path: root/drivers/staging/media/zoran/zoran_driver.c
diff options
context:
space:
mode:
authorCorentin Labbe <clabbe@baylibre.com>2020-09-25 20:30:56 +0200
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2020-10-01 10:05:09 +0200
commit83f89a8bcbc3c520a889b5fc7c4b95669d712f65 (patch)
tree59d5d84f4967f6d2769f7c53df89304faba9a293 /drivers/staging/media/zoran/zoran_driver.c
parent8cb356d4eaae111ac525d4e476b7ca23561ddad5 (diff)
media: zoran: convert to vb2
This is it! the ultimate last step, the vb2 conversion. Signed-off-by: Corentin Labbe <clabbe@baylibre.com> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
Diffstat (limited to 'drivers/staging/media/zoran/zoran_driver.c')
-rw-r--r--drivers/staging/media/zoran/zoran_driver.c1453
1 files changed, 46 insertions, 1407 deletions
diff --git a/drivers/staging/media/zoran/zoran_driver.c b/drivers/staging/media/zoran/zoran_driver.c
index a6fb41d03186..c5b2ccb00ca9 100644
--- a/drivers/staging/media/zoran/zoran_driver.c
+++ b/drivers/staging/media/zoran/zoran_driver.c
@@ -35,7 +35,6 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
-#include <linux/vmalloc.h>
#include <linux/wait.h>
#include <linux/interrupt.h>
@@ -50,7 +49,6 @@
#include <media/v4l2-event.h>
#include "videocodec.h"
-#include <asm/byteorder.h>
#include <linux/io.h>
#include <linux/uaccess.h>
@@ -159,234 +157,8 @@ static __u32 zoran_v4l2_calc_bufsize(struct zoran_jpg_settings *settings)
return jpg_bufsize;
if (result < 8192)
return 8192;
- return result;
-}
-
-/* forward references */
-static void v4l_fbuffer_free(struct zoran_fh *fh);
-static void jpg_fbuffer_free(struct zoran_fh *fh);
-
-/* Set mapping mode */
-static void map_mode_raw(struct zoran_fh *fh)
-{
- struct zoran *zr = fh->zr;
- fh->map_mode = ZORAN_MAP_MODE_RAW;
- zr->buffer_size = v4l_bufsize;
- fh->buffers.num_buffers = v4l_nbufs;
-}
-
-static void map_mode_jpg(struct zoran_fh *fh, int play)
-{
- struct zoran *zr = fh->zr;
-
- fh->map_mode = play ? ZORAN_MAP_MODE_JPG_PLAY : ZORAN_MAP_MODE_JPG_REC;
- zr->buffer_size = jpg_bufsize;
- fh->buffers.num_buffers = jpg_nbufs;
-}
-
-static inline const char *mode_name(enum zoran_map_mode mode)
-{
- return mode == ZORAN_MAP_MODE_RAW ? "V4L" : "JPG";
-}
-
-/*
- * Allocate the V4L grab buffers
- *
- * These have to be pysically contiguous.
- */
-
-static int v4l_fbuffer_alloc(struct zoran_fh *fh)
-{
- struct zoran *zr = fh->zr;
- int i, off;
- unsigned char *mem;
-
- for (i = 0; i < fh->buffers.num_buffers; i++) {
- if (fh->buffers.buffer[i].v4l.fbuffer)
- pci_warn(zr->pci_dev, "%s - buffer %d already allocated!?\n", __func__, i);
-
- //udelay(20);
- mem = kmalloc(zr->buffer_size, GFP_KERNEL | __GFP_NOWARN);
- if (!mem) {
- pci_err(zr->pci_dev, "%s - kmalloc for V4L buf %d failed\n", __func__, i);
- v4l_fbuffer_free(fh);
- return -ENOBUFS;
- }
- fh->buffers.buffer[i].v4l.fbuffer = mem;
- fh->buffers.buffer[i].v4l.fbuffer_phys = virt_to_phys(mem);
- fh->buffers.buffer[i].v4l.fbuffer_bus = virt_to_bus(mem);
- for (off = 0; off < zr->buffer_size;
- off += PAGE_SIZE)
- SetPageReserved(virt_to_page(mem + off));
- pci_info(zr->pci_dev, "%s - V4L frame %d mem %p (bus: 0x%llx)\n", __func__, i, mem,
- (unsigned long long)virt_to_bus(mem));
- }
-
- fh->buffers.allocated = 1;
-
- return 0;
-}
-
-/* free the V4L grab buffers */
-static void v4l_fbuffer_free(struct zoran_fh *fh)
-{
- struct zoran *zr = fh->zr;
- int i, off;
- unsigned char *mem;
-
- pci_dbg(zr->pci_dev, "%s\n", __func__);
-
- for (i = 0; i < fh->buffers.num_buffers; i++) {
- if (!fh->buffers.buffer[i].v4l.fbuffer)
- continue;
-
- mem = fh->buffers.buffer[i].v4l.fbuffer;
- for (off = 0; off < zr->buffer_size;
- off += PAGE_SIZE)
- ClearPageReserved(virt_to_page(mem + off));
- kfree(fh->buffers.buffer[i].v4l.fbuffer);
- fh->buffers.buffer[i].v4l.fbuffer = NULL;
- }
- fh->buffers.allocated = 0;
-}
-
-/*
- * Allocate the MJPEG grab buffers.
- *
- * If a Natoma chipset is present and this is a revision 1 zr36057,
- * each MJPEG buffer needs to be physically contiguous.
- * (RJ: This statement is from Dave Perks' original driver,
- * I could never check it because I have a zr36067)
- *
- * RJ: The contents grab buffers needs never be accessed in the driver.
- * Therefore there is no need to allocate them with vmalloc in order
- * to get a contiguous virtual memory space.
- * I don't understand why many other drivers first allocate them with
- * vmalloc (which uses internally also get_zeroed_page, but delivers you
- * virtual addresses) and then again have to make a lot of efforts
- * to get the physical address.
- *
- * Ben Capper:
- * On big-endian architectures (such as ppc) some extra steps
- * are needed. When reading and writing to the stat_com array
- * and fragment buffers, the device expects to see little-
- * endian values. The use of cpu_to_le32() and le32_to_cpu()
- * in this function (and one or two others in zoran_device.c)
- * ensure that these values are always stored in little-endian
- * form, regardless of architecture. The zr36057 does Very Bad
- * Things on big endian architectures if the stat_com array
- * and fragment buffers are not little-endian.
- */
-
-static int jpg_fbuffer_alloc(struct zoran_fh *fh)
-{
- struct zoran *zr = fh->zr;
- int i, j, off;
- u8 *mem;
-
- for (i = 0; i < fh->buffers.num_buffers; i++) {
- if (fh->buffers.buffer[i].jpg.frag_tab)
- pci_warn(zr->pci_dev, "%s - buffer %d already allocated!?\n", __func__, i);
-
- /* Allocate fragment table for this buffer */
-
- mem = (void *)get_zeroed_page(GFP_KERNEL);
- if (!mem) {
- pci_err(zr->pci_dev, "%s - get_zeroed_page (frag_tab) failed for buffer %d\n", __func__, i);
- jpg_fbuffer_free(fh);
- return -ENOBUFS;
- }
- fh->buffers.buffer[i].jpg.frag_tab = (__le32 *)mem;
- fh->buffers.buffer[i].jpg.frag_tab_bus = virt_to_bus(mem);
-
- if (fh->buffers.need_contiguous) {
- mem = kmalloc(zr->buffer_size, GFP_KERNEL);
- if (!mem) {
- pci_err(zr->pci_dev, "%s - kmalloc failed for buffer %d\n", __func__, i);
- jpg_fbuffer_free(fh);
- return -ENOBUFS;
- }
- fh->buffers.buffer[i].jpg.frag_tab[0] =
- cpu_to_le32(virt_to_bus(mem));
- fh->buffers.buffer[i].jpg.frag_tab[1] =
- cpu_to_le32((zr->buffer_size >> 1) | 1);
- for (off = 0; off < zr->buffer_size; off += PAGE_SIZE)
- SetPageReserved(virt_to_page(mem + off));
- } else {
- /* jpg_bufsize is already page aligned */
- for (j = 0; j < zr->buffer_size / PAGE_SIZE; j++) {
- mem = (void *)get_zeroed_page(GFP_KERNEL);
- if (!mem) {
- pci_err(zr->pci_dev, "%s - get_zeroed_page failed for buffer %d\n", __func__, i);
- jpg_fbuffer_free(fh);
- return -ENOBUFS;
- }
-
- fh->buffers.buffer[i].jpg.frag_tab[2 * j] =
- cpu_to_le32(virt_to_bus(mem));
- fh->buffers.buffer[i].jpg.frag_tab[2 * j + 1] =
- cpu_to_le32((PAGE_SIZE >> 2) << 1);
- SetPageReserved(virt_to_page(mem));
- }
-
- fh->buffers.buffer[i].jpg.frag_tab[2 * j - 1] |= cpu_to_le32(1);
- }
- }
-
- pci_dbg(zr->pci_dev, "%s - %d KB allocated\n", __func__,
- (fh->buffers.num_buffers * zr->buffer_size) >> 10);
-
- fh->buffers.allocated = 1;
-
- return 0;
-}
-
-/* free the MJPEG grab buffers */
-static void jpg_fbuffer_free(struct zoran_fh *fh)
-{
- struct zoran *zr = fh->zr;
- int i, j, off;
- unsigned char *mem;
- __le32 frag_tab;
- struct zoran_buffer *buffer;
-
- pci_dbg(zr->pci_dev, "%s\n", __func__);
-
- for (i = 0, buffer = &fh->buffers.buffer[0];
- i < fh->buffers.num_buffers; i++, buffer++) {
- if (!buffer->jpg.frag_tab)
- continue;
-
- if (fh->buffers.need_contiguous) {
- frag_tab = buffer->jpg.frag_tab[0];
-
- if (frag_tab) {
- mem = bus_to_virt(le32_to_cpu(frag_tab));
- for (off = 0; off < zr->buffer_size; off += PAGE_SIZE)
- ClearPageReserved(virt_to_page(mem + off));
- kfree(mem);
- buffer->jpg.frag_tab[0] = 0;
- buffer->jpg.frag_tab[1] = 0;
- }
- } else {
- for (j = 0; j < zr->buffer_size / PAGE_SIZE; j++) {
- frag_tab = buffer->jpg.frag_tab[2 * j];
-
- if (!frag_tab)
- break;
- ClearPageReserved(virt_to_page(bus_to_virt(le32_to_cpu(frag_tab))));
- free_page((unsigned long)bus_to_virt(le32_to_cpu(frag_tab)));
- buffer->jpg.frag_tab[2 * j] = 0;
- buffer->jpg.frag_tab[2 * j + 1] = 0;
- }
- }
-
- free_page((unsigned long)buffer->jpg.frag_tab);
- buffer->jpg.frag_tab = NULL;
- }
-
- fh->buffers.allocated = 0;
+ return result;
}
/*
@@ -431,561 +203,8 @@ static int zoran_v4l_set_format(struct zoran *zr, int width, int height,
return 0;
}
-static int zoran_v4l_queue_frame(struct zoran_fh *fh, int num)
-{
- struct zoran *zr = fh->zr;
- unsigned long flags;
- int res = 0;
-
- if (!fh->buffers.allocated) {
- pci_err(zr->pci_dev, "%s - buffers not yet allocated\n", __func__);
- res = -ENOMEM;
- }
-
- /* No grabbing outside the buffer range! */
- if (num >= fh->buffers.num_buffers || num < 0) {
- pci_err(zr->pci_dev, "%s - buffer %d is out of range\n", __func__, num);
- res = -EINVAL;
- }
-
- spin_lock_irqsave(&zr->spinlock, flags);
-
- if (fh->buffers.active == ZORAN_FREE) {
- if (zr->v4l_buffers.active == ZORAN_FREE) {
- zr->v4l_buffers = fh->buffers;
- fh->buffers.active = ZORAN_ACTIVE;
- } else {
- pci_err(zr->pci_dev, "%s - another session is already capturing\n", __func__);
- res = -EBUSY;
- }
- }
-
- /* make sure a grab isn't going on currently with this buffer */
- if (!res) {
- switch (zr->v4l_buffers.buffer[num].state) {
- default:
- case BUZ_STATE_PEND:
- if (zr->v4l_buffers.active == ZORAN_FREE) {
- fh->buffers.active = ZORAN_FREE;
- zr->v4l_buffers.allocated = 0;
- }
- res = -EBUSY; /* what are you doing? */
- break;
- case BUZ_STATE_DONE:
- pci_warn(zr->pci_dev, "%s - queueing buffer %d in state DONE!?\n", __func__, num);
- /* fallthrough */
- case BUZ_STATE_USER:
- /* since there is at least one unused buffer there's room for at least
- * one more pend[] entry */
- zr->v4l_pend[zr->v4l_pend_head++ & V4L_MASK_FRAME] = num;
- zr->v4l_buffers.buffer[num].state = BUZ_STATE_PEND;
- zr->v4l_buffers.buffer[num].bs.length =
- zr->v4l_settings.bytesperline *
- zr->v4l_settings.height;
- fh->buffers.buffer[num] = zr->v4l_buffers.buffer[num];
- break;
- }
- }
-
- spin_unlock_irqrestore(&zr->spinlock, flags);
-
- if (!res && zr->v4l_buffers.active == ZORAN_FREE)
- zr->v4l_buffers.active = fh->buffers.active;
-
- return res;
-}
-
-/*
- * Sync on a V4L buffer
- */
-
-static int v4l_sync(struct zoran_fh *fh, int frame)
-{
- struct zoran *zr = fh->zr;
- unsigned long flags;
-
- if (fh->buffers.active == ZORAN_FREE) {
- pci_err(zr->pci_dev, "%s - no grab active for this session\n", __func__);
- return -EINVAL;
- }
-
- /* check passed-in frame number */
- if (frame >= fh->buffers.num_buffers || frame < 0) {
- pci_err(zr->pci_dev, "%s - frame %d is invalid\n", __func__, frame);
- return -EINVAL;
- }
-
- /* Check if is buffer was queued at all */
- if (zr->v4l_buffers.buffer[frame].state == BUZ_STATE_USER) {
- pci_err(zr->pci_dev, "%s - attempt to sync on a buffer which was not queued?\n", __func__);
- return -EPROTO;
- }
-
- mutex_unlock(&zr->lock);
- /* wait on this buffer to get ready */
- if (!wait_event_interruptible_timeout(zr->v4l_capq,
- (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_PEND), 10 * HZ)) {
- mutex_lock(&zr->lock);
- return -ETIME;
- }
- mutex_lock(&zr->lock);
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- /* buffer should now be in BUZ_STATE_DONE */
- if (zr->v4l_buffers.buffer[frame].state != BUZ_STATE_DONE)
- pci_err(zr->pci_dev, "%s - internal state error\n", __func__);
-
- zr->v4l_buffers.buffer[frame].state = BUZ_STATE_USER;
- fh->buffers.buffer[frame] = zr->v4l_buffers.buffer[frame];
-
- spin_lock_irqsave(&zr->spinlock, flags);
-
- /* Check if streaming capture has finished */
- if (zr->v4l_pend_tail == zr->v4l_pend_head) {
- zr36057_set_memgrab(zr, 0);
- if (zr->v4l_buffers.active == ZORAN_ACTIVE) {
- fh->buffers.active = zr->v4l_buffers.active = ZORAN_FREE;
- zr->v4l_buffers.allocated = 0;
- }
- }
-
- spin_unlock_irqrestore(&zr->spinlock, flags);
-
- return 0;
-}
-
-/*
- * Queue a MJPEG buffer for capture/playback
- */
-static int zoran_jpg_queue_frame(struct zoran_fh *fh, int num,
- enum zoran_codec_mode mode)
-{
- struct zoran *zr = fh->zr;
- unsigned long flags;
- int res = 0;
-
- /* Check if buffers are allocated */
- if (!fh->buffers.allocated) {
- pci_err(zr->pci_dev, "%s - buffers not yet allocated\n", __func__);
- return -ENOMEM;
- }
-
- /* No grabbing outside the buffer range! */
- if (num >= fh->buffers.num_buffers || num < 0) {
- pci_err(zr->pci_dev, "%s - buffer %d out of range\n", __func__, num);
- return -EINVAL;
- }
-
- /* what is the codec mode right now? */
- if (zr->codec_mode != BUZ_MODE_IDLE && zr->codec_mode != mode) {
- /* wrong codec mode active - invalid */
- pci_err(zr->pci_dev, "%s - codec in wrong mode\n", __func__);
- return -EINVAL;
- }
-
- if (fh->buffers.active == ZORAN_FREE) {
- if (zr->jpg_buffers.active == ZORAN_FREE) {
- zr->jpg_buffers = fh->buffers;
- fh->buffers.active = ZORAN_ACTIVE;
- } else {
- pci_err(zr->pci_dev, "%s - another session is already capturing\n", __func__);
- res = -EBUSY;
- }
- }
-
- if (!res && zr->codec_mode == BUZ_MODE_IDLE) {
- /* Ok load up the jpeg codec */
- zr36057_enable_jpg(zr, mode);
- }
-
- spin_lock_irqsave(&zr->spinlock, flags);
-
- if (!res) {
- switch (zr->jpg_buffers.buffer[num].state) {
- case BUZ_STATE_DONE:
- pci_warn(zr->pci_dev, "%s - queuing frame in BUZ_STATE_DONE state!?\n", __func__);
- /* fallthrough */
- case BUZ_STATE_USER:
- /* since there is at least one unused buffer there's room for at
- *least one more pend[] entry */
- zr->jpg_pend[zr->jpg_que_head++ & BUZ_MASK_FRAME] = num;
- zr->jpg_buffers.buffer[num].state = BUZ_STATE_PEND;
- fh->buffers.buffer[num] = zr->jpg_buffers.buffer[num];
- zoran_feed_stat_com(zr);
- break;
- default:
- case BUZ_STATE_DMA:
- case BUZ_STATE_PEND:
- if (zr->jpg_buffers.active == ZORAN_FREE) {
- fh->buffers.active = ZORAN_FREE;
- zr->jpg_buffers.allocated = 0;
- }
- res = -EBUSY; /* what are you doing? */
- break;
- }
- }
-
- spin_unlock_irqrestore(&zr->spinlock, flags);
-
- if (!res && zr->jpg_buffers.active == ZORAN_FREE)
- zr->jpg_buffers.active = fh->buffers.active;
-
- return res;
-}
-
-static int jpg_qbuf(struct zoran_fh *fh, int frame, enum zoran_codec_mode mode)
-{
- struct zoran *zr = fh->zr;
- int res = 0;
-
- /* Does the user want to stop streaming? */
- if (frame < 0) {
- if (zr->codec_mode == mode) {
- if (fh->buffers.active == ZORAN_FREE) {
- pci_err(zr->pci_dev, "%s(-1) - session not active\n", __func__);
- return -EINVAL;
- }
- fh->buffers.active = zr->jpg_buffers.active = ZORAN_FREE;
- zr->jpg_buffers.allocated = 0;
- zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
- return 0;
- } else {
- pci_err(zr->pci_dev, "%s - stop streaming but not in streaming mode\n", __func__);
- return -EINVAL;
- }
- }
-
- res = zoran_jpg_queue_frame(fh, frame, mode);
- if (res)
- return res;
-
- /* Start the jpeg codec when the first frame is queued */
- if (!res && zr->jpg_que_head == 1)
- jpeg_start(zr);
-
- return res;
-}
-
-/*
- * Sync on a MJPEG buffer
- */
-
-static int jpg_sync(struct zoran_fh *fh, struct zoran_sync *bs)
-{
- struct zoran *zr = fh->zr;
- unsigned long flags;
- int frame;
-
- if (fh->buffers.active == ZORAN_FREE) {
- pci_err(zr->pci_dev, "%s - capture is not currently active\n", __func__);
- return -EINVAL;
- }
- if (zr->codec_mode != BUZ_MODE_MOTION_DECOMPRESS &&
- zr->codec_mode != BUZ_MODE_MOTION_COMPRESS) {
- pci_err(zr->pci_dev, "%s - codec not in streaming mode\n", __func__);
- return -EINVAL;
- }
- mutex_unlock(&zr->lock);
- if (!wait_event_interruptible_timeout(zr->jpg_capq,
- (zr->jpg_que_tail != zr->jpg_dma_tail ||
- zr->jpg_dma_tail == zr->jpg_dma_head),
- 10 * HZ)) {
- int isr;
-
- btand(~ZR36057_JMC_Go_en, ZR36057_JMC);
- udelay(1);
- zr->codec->control(zr->codec, CODEC_G_STATUS, sizeof(isr), &isr);
- mutex_lock(&zr->lock);
- pci_err(zr->pci_dev, "%s - timeout: codec isr=0x%02x\n", __func__, isr);
-
- return -ETIME;
- }
- mutex_lock(&zr->lock);
- if (signal_pending(current))
- return -ERESTARTSYS;
-
- spin_lock_irqsave(&zr->spinlock, flags);
-
- if (zr->jpg_dma_tail != zr->jpg_dma_head)
- frame = zr->jpg_pend[zr->jpg_que_tail++ & BUZ_MASK_FRAME];
- else
- frame = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-
- /* buffer should now be in BUZ_STATE_DONE */
- if (zr->jpg_buffers.buffer[frame].state != BUZ_STATE_DONE)
- pci_err(zr->pci_dev, "%s - internal state error\n", __func__);
-
- *bs = zr->jpg_buffers.buffer[frame].bs;
- bs->frame = frame;
- zr->jpg_buffers.buffer[frame].state = BUZ_STATE_USER;
- fh->buffers.buffer[frame] = zr->jpg_buffers.buffer[frame];
-
- spin_unlock_irqrestore(&zr->spinlock, flags);
-
- return 0;
-}
-
-static void zoran_open_init_session(struct zoran_fh *fh)
-{
- int i;
-
- /* Per default, map the V4L Buffers */
- map_mode_raw(fh);
-
- /* buffers */
- memset(&fh->buffers, 0, sizeof(fh->buffers));
- for (i = 0; i < MAX_FRAME; i++) {
- fh->buffers.buffer[i].state = BUZ_STATE_USER; /* nothing going on */
- fh->buffers.buffer[i].bs.frame = i;
- }
- fh->buffers.allocated = 0;
- fh->buffers.active = ZORAN_FREE;
-}
-
-static void zoran_close_end_session(struct zoran_fh *fh)
-{
- struct zoran *zr = fh->zr;
-
- if (fh->map_mode == ZORAN_MAP_MODE_RAW) {
- /* v4l capture */
- if (fh->buffers.active != ZORAN_FREE) {
- unsigned long flags;
-
- spin_lock_irqsave(&zr->spinlock, flags);
- zr36057_set_memgrab(zr, 0);
- zr->v4l_buffers.allocated = 0;
- zr->v4l_buffers.active = fh->buffers.active = ZORAN_FREE;
- spin_unlock_irqrestore(&zr->spinlock, flags);
- }
-
- /* v4l buffers */
- if (fh->buffers.allocated)
- v4l_fbuffer_free(fh);
- } else {
- /* jpg capture */
- if (fh->buffers.active != ZORAN_FREE) {
- zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
- zr->jpg_buffers.allocated = 0;
- zr->jpg_buffers.active = fh->buffers.active = ZORAN_FREE;
- }
-
- /* jpg buffers */
- if (fh->buffers.allocated)
- jpg_fbuffer_free(fh);
- }
-}
-
-/*
- * Open a zoran card. Right now the flags stuff is just playing
- */
-static int zoran_open(struct file *file)
-{
- struct zoran *zr = video_drvdata(file);
- struct zoran_fh *fh;
- int res, first_open = 0;
-
- pci_info(zr->pci_dev, "%s(%s, pid=[%d]), users(-)=%d\n", __func__, current->comm,
- task_pid_nr(current), zr->user + 1);
-
- mutex_lock(&zr->lock);
-
- if (zr->user >= 2048) {
- pci_err(zr->pci_dev, "too many users (%d) on device\n", zr->user);
- res = -EBUSY;
- goto fail_unlock;
- }
-
- /* now, create the open()-specific file_ops struct */
- fh = kzalloc(sizeof(*fh), GFP_KERNEL);
- if (!fh) {
- res = -ENOMEM;
- goto fail_unlock;
- }
- v4l2_fh_init(&fh->fh, video_devdata(file));
-
- if (zr->user++ == 0)
- first_open = 1;
-
- /* default setup - TODO: look at flags */
- if (first_open) { /* First device open */
- zr36057_restart(zr);
- zoran_open_init_params(zr);
- zoran_init_hardware(zr);
-
- btor(ZR36057_ICR_IntPinEn, ZR36057_ICR);
- }
-
- /* set file_ops stuff */
- file->private_data = fh;
- fh->zr = zr;
- zoran_open_init_session(fh);
- v4l2_fh_add(&fh->fh);
- mutex_unlock(&zr->lock);
-
- return 0;
-
-fail_unlock:
- mutex_unlock(&zr->lock);
-
- pci_info(zr->pci_dev, "open failed (%d), users(-)=%d\n", res, zr->user);
-
- return res;
-}
-
-static int zoran_close(struct file *file)
-{
- struct zoran_fh *fh = file->private_data;
- struct zoran *zr = fh->zr;
-
- pci_info(zr->pci_dev, "%s(%s, pid=[%d]), users(+)=%d\n", __func__, current->comm,
- task_pid_nr(current), zr->user - 1);
-
- /* kernel locks (fs/device.c), so don't do that ourselves
- * (prevents deadlocks) */
- mutex_lock(&zr->lock);
-
- zoran_close_end_session(fh);
-
- if (zr->user-- == 1) { /* Last process */
- /* Clean up JPEG process */
- wake_up_interruptible(&zr->jpg_capq);
- zr36057_enable_jpg(zr, BUZ_MODE_IDLE);
- zr->jpg_buffers.allocated = 0;
- zr->jpg_buffers.active = ZORAN_FREE;
-
- /* disable interrupts */
- btand(~ZR36057_ICR_IntPinEn, ZR36057_ICR);
-
- if (zr36067_debug > 1)
- print_interrupts(zr);
-
- /* capture off */
- wake_up_interruptible(&zr->v4l_capq);
- zr36057_set_memgrab(zr, 0);
- zr->v4l_buffers.allocated = 0;
- zr->v4l_buffers.active = ZORAN_FREE;
- zoran_set_pci_master(zr, 0);
-
- if (!pass_through) { /* Switch to color bar */
- decoder_call(zr, video, s_stream, 0);
- encoder_call(zr, video, s_routing, 2, 0, 0);
- }
- }
- mutex_unlock(&zr->lock);
-
- v4l2_fh_del(&fh->fh);
- v4l2_fh_exit(&fh->fh);
- kfree(fh);
-
- pci_dbg(zr->pci_dev, "%s done\n", __func__);
-
- return 0;
-}
-
-/* get the status of a buffer in the clients buffer queue */
-static int zoran_v4l2_buffer_status(struct zoran_fh *fh,
- struct v4l2_buffer *buf, int num)
-{
- struct zoran *zr = fh->zr;
- unsigned long flags;
-
- buf->flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
-
- switch (fh->map_mode) {
- case ZORAN_MAP_MODE_RAW:
- /* check range */
- if (num < 0 || num >= fh->buffers.num_buffers ||
- !fh->buffers.allocated) {
- pci_err(zr->pci_dev, "%s - wrong number or buffers not allocated\n", __func__);
- return -EINVAL;
- }
-
- spin_lock_irqsave(&zr->spinlock, flags);
- pci_dbg(zr->pci_dev, "%s() - raw active=%c, buffer %d: state=%c, map=%c\n", __func__,
- "FAL"[fh->buffers.active], num,
- "UPMD"[zr->v4l_buffers.buffer[num].state],
- fh->buffers.buffer[num].map ? 'Y' : 'N');
- spin_unlock_irqrestore(&zr->spinlock, flags);
-
- buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- buf->length = zr->buffer_size;
-
- /* get buffer */
- buf->bytesused = fh->buffers.buffer[num].bs.length;
- if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
- fh->buffers.buffer[num].state == BUZ_STATE_USER) {
- buf->sequence = fh->buffers.buffer[num].bs.seq;
- buf->flags |= V4L2_BUF_FLAG_DONE;
- v4l2_buffer_set_timestamp(buf, fh->buffers.buffer[num].bs.ts);
- } else {
- buf->flags |= V4L2_BUF_FLAG_QUEUED;
- }
-
- if (zr->v4l_settings.height <= BUZ_MAX_HEIGHT / 2)
- buf->field = V4L2_FIELD_TOP;
- else
- buf->field = V4L2_FIELD_INTERLACED;
-
- break;
-
- case ZORAN_MAP_MODE_JPG_REC:
- case ZORAN_MAP_MODE_JPG_PLAY:
-
- /* check range */
- if (num < 0 || num >= fh->buffers.num_buffers ||
- !fh->buffers.allocated) {
- pci_err(zr->pci_dev, "%s - wrong number or buffers not allocated\n", __func__);
- return -EINVAL;
- }
-
- buf->type = (fh->map_mode == ZORAN_MAP_MODE_JPG_REC) ?
- V4L2_BUF_TYPE_VIDEO_CAPTURE :
- V4L2_BUF_TYPE_VIDEO_OUTPUT;
- buf->length = zr->buffer_size;
-
- /* these variables are only written after frame has been captured */
- if (fh->buffers.buffer[num].state == BUZ_STATE_DONE ||
- fh->buffers.buffer[num].state == BUZ_STATE_USER) {
- buf->sequence = fh->buffers.buffer[num].bs.seq;
- v4l2_buffer_set_timestamp(buf, fh->buffers.buffer[num].bs.ts);
- buf->bytesused = fh->buffers.buffer[num].bs.length;
- buf->flags |= V4L2_BUF_FLAG_DONE;
- } else {
- buf->flags |= V4L2_BUF_FLAG_QUEUED;
- }
-
- /* which fields are these? */
- if (zr->jpg_settings.TmpDcm != 1)
- buf->field = zr->jpg_settings.odd_even ?
- V4L2_FIELD_TOP : V4L2_FIELD_BOTTOM;
- else
- buf->field = zr->jpg_settings.odd_even ?
- V4L2_FIELD_SEQ_TB : V4L2_FIELD_SEQ_BT;
-
- break;
-
- default:
-
- pci_err(zr->pci_dev, "%s - invalid buffer type|map_mode (%d|%d)\n",
- __func__, buf->type, fh->map_mode);
- return -EINVAL;
- }
-
- buf->memory = V4L2_MEMORY_MMAP;
- buf->index = num;
- buf->m.offset = buf->length * num;
-
- return 0;
-}
-
static int zoran_set_norm(struct zoran *zr, v4l2_std_id norm)
{
- if (zr->v4l_buffers.active != ZORAN_FREE ||
- zr->jpg_buffers.active != ZORAN_FREE) {
- pr_warn("%s: %s called while in playback/capture mode\n", ZR_DEVNAME(zr), __func__);
- return -EBUSY;
- }
if (!(norm & zr->card.norms)) {
pci_err(zr->pci_dev, "%s - unsupported norm %llx\n", __func__, norm);
@@ -1013,12 +232,6 @@ static int zoran_set_input(struct zoran *zr, int input)
if (input == zr->input)
return 0;
- if (zr->v4l_buffers.active != ZORAN_FREE ||
- zr->jpg_buffers.active != ZORAN_FREE) {
- pci_warn(zr->pci_dev, "%s called while in playback/capture mode\n", __func__);
- return -EBUSY;
- }
-
if (input < 0 || input >= zr->card.inputs) {
pci_err(zr->pci_dev, "%s - unsupported input %d\n", __func__, input);
return -EINVAL;
@@ -1119,12 +332,10 @@ static int zoran_g_fmt_vid_out(struct file *file, void *__fh,
static int zoran_g_fmt_vid_cap(struct file *file, void *__fh,
struct v4l2_format *fmt)
{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
-
- if (fh->map_mode != ZORAN_MAP_MODE_RAW)
- return zoran_g_fmt_vid_out(file, fh, fmt);
+ struct zoran *zr = video_drvdata(file);
+ if (zr->map_mode != ZORAN_MAP_MODE_RAW)
+ return zoran_g_fmt_vid_out(file, __fh, fmt);
fmt->fmt.pix.width = zr->v4l_settings.width;
fmt->fmt.pix.height = zr->v4l_settings.height;
fmt->fmt.pix.sizeimage = zr->buffer_size;
@@ -1205,13 +416,12 @@ static int zoran_try_fmt_vid_out(struct file *file, void *__fh,
static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
struct v4l2_format *fmt)
{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
+ struct zoran *zr = video_drvdata(file);
int bpp;
int i;
if (fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_MJPEG)
- return zoran_try_fmt_vid_out(file, fh, fmt);
+ return zoran_try_fmt_vid_out(file, __fh, fmt);
for (i = 0; i < NUM_FORMATS; i++)
if (zoran_formats[i].fourcc == fmt->fmt.pix.pixelformat)
@@ -1238,8 +448,7 @@ static int zoran_try_fmt_vid_cap(struct file *file, void *__fh,
static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
struct v4l2_format *fmt)
{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
+ struct zoran *zr = video_drvdata(file);
__le32 printformat = __cpu_to_le32(fmt->fmt.pix.pixelformat);
struct zoran_jpg_settings settings;
int res = 0;
@@ -1251,12 +460,6 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
if (fmt->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG)
return -EINVAL;
- if (fh->buffers.allocated) {
- pci_err(zr->pci_dev, "VIDIOC_S_FMT - cannot change capture mode\n");
- res = -EBUSY;
- return res;
- }
-
if (!fmt->fmt.pix.height || !fmt->fmt.pix.width)
return -EINVAL;
@@ -1299,7 +502,11 @@ static int zoran_s_fmt_vid_out(struct file *file, void *__fh,
/* it's ok, so set them */
zr->jpg_settings = settings;
- map_mode_jpg(fh, fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
+ if (fmt->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ zr->map_mode = ZORAN_MAP_MODE_JPG_REC;
+ else
+ zr->map_mode = ZORAN_MAP_MODE_JPG_PLAY;
+
zr->buffer_size = zoran_v4l2_calc_bufsize(&zr->jpg_settings);
/* tell the user what we actually did */
@@ -1339,13 +546,6 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
return -EINVAL;
}
- if ((fh->map_mode != ZORAN_MAP_MODE_RAW && fh->buffers.allocated) ||
- fh->buffers.active != ZORAN_FREE) {
- pci_err(zr->pci_dev, "VIDIOC_S_FMT - cannot change capture mode\n");
- res = -EBUSY;
- return res;
- }
-
fmt->fmt.pix.pixelformat = zoran_formats[i].fourcc;
if (fmt->fmt.pix.height > BUZ_MAX_HEIGHT)
fmt->fmt.pix.height = BUZ_MAX_HEIGHT;
@@ -1356,7 +556,7 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
if (fmt->fmt.pix.width < BUZ_MIN_WIDTH)
fmt->fmt.pix.width = BUZ_MIN_WIDTH;
- map_mode_raw(fh);
+ zr->map_mode = ZORAN_MAP_MODE_RAW;
res = zoran_v4l_set_format(zr, fmt->fmt.pix.width, fmt->fmt.pix.height,
&zoran_formats[i]);
@@ -1374,309 +574,6 @@ static int zoran_s_fmt_vid_cap(struct file *file, void *__fh,
return res;
}
-static int zoran_streamoff(struct file *file, void *__fh, enum v4l2_buf_type type);
-
-static int zoran_reqbufs(struct file *file, void *__fh, struct v4l2_requestbuffers *req)
-{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
- int res = 0;
-
- if (req->memory != V4L2_MEMORY_MMAP) {
- pci_err(zr->pci_dev, "only MEMORY_MMAP capture is supported, not %d\n", req->memory);
- return -EINVAL;
- }
-
- if (req->count == 0)
- return zoran_streamoff(file, fh, req->type);
-
- if (fh->buffers.allocated) {
- pr_warn("%s: VIDIOC_REQBUFS - buffers already allocated\n", ZR_DEVNAME(zr));
- res = -EBUSY;
- return res;
- }
-
- if (fh->map_mode == ZORAN_MAP_MODE_RAW &&
- req->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- /* control user input */
- if (req->count < 2)
- req->count = 2;
- if (req->count > v4l_nbufs)
- req->count = v4l_nbufs;
-
- /* The next mmap will map the V4L buffers */
- map_mode_raw(fh);
- fh->buffers.num_buffers = req->count;
-
- if (v4l_fbuffer_alloc(fh)) {
- res = -ENOMEM;
- return res;
- }
- } else if (fh->map_mode == ZORAN_MAP_MODE_JPG_REC ||
- fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
- /* we need to calculate size ourselves now */
- if (req->count < 4)
- req->count = 4;
- if (req->count > jpg_nbufs)
- req->count = jpg_nbufs;
-
- /* The next mmap will map the MJPEG buffers */
- map_mode_jpg(fh, req->type == V4L2_BUF_TYPE_VIDEO_OUTPUT);
- fh->buffers.num_buffers = req->count;
- zr->buffer_size = zoran_v4l2_calc_bufsize(&zr->jpg_settings);
-
- if (jpg_fbuffer_alloc(fh)) {
- res = -ENOMEM;
- return res;
- }
- } else {
- pci_err(zr->pci_dev, "VIDIOC_REQBUFS - unknown type %d\n", req->type);
- res = -EINVAL;
- return res;
- }
- return res;
-}
-
-static int zoran_querybuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
- struct zoran_fh *fh = __fh;
-
- return zoran_v4l2_buffer_status(fh, buf, buf->index);
-}
-
-static int zoran_qbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
- int res = 0, codec_mode, buf_type;
-
- switch (fh->map_mode) {
- case ZORAN_MAP_MODE_RAW:
- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- pci_err(zr->pci_dev, "VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
- buf->type, fh->map_mode);
- res = -EINVAL;
- return res;
- }
-
- res = zoran_v4l_queue_frame(fh, buf->index);
- if (res)
- return res;
- if (!zr->v4l_memgrab_active && fh->buffers.active == ZORAN_LOCKED)
- zr36057_set_memgrab(zr, 1);
- break;
-
- case ZORAN_MAP_MODE_JPG_REC:
- case ZORAN_MAP_MODE_JPG_PLAY:
- if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY) {
- buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- codec_mode = BUZ_MODE_MOTION_DECOMPRESS;
- } else {
- buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- codec_mode = BUZ_MODE_MOTION_COMPRESS;
- }
-
- if (buf->type != buf_type) {
- pci_err(zr->pci_dev, "VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
- buf->type, fh->map_mode);
- res = -EINVAL;
- return res;
- }
-
- res = zoran_jpg_queue_frame(fh, buf->index, codec_mode);
- if (res != 0)
- return res;
- if (zr->codec_mode == BUZ_MODE_IDLE &&
- fh->buffers.active == ZORAN_LOCKED)
- zr36057_enable_jpg(zr, codec_mode);
-
- break;
-
- default:
- pci_err(zr->pci_dev, "VIDIOC_QBUF - unsupported type %d\n", buf->type);
- res = -EINVAL;
- break;
- }
- return res;
-}
-
-static int zoran_dqbuf(struct file *file, void *__fh, struct v4l2_buffer *buf)
-{
- struct zoran_fh *fh = __fh;
- struct zoran *zr = fh->zr;
- int res = 0, buf_type, num = -1; /* compiler borks here (?) */
-
- switch (fh->map_mode) {
- case ZORAN_MAP_MODE_RAW:
- if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
- pci_err(zr->pci_dev, "VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
- buf->type, fh->map_mode);
- res = -EINVAL;
- return res;
- }
-
- num = zr->v4l_pend[zr->v4l_sync_tail & V4L_MASK_FRAME];
- if (file->f_flags & O_NONBLOCK &&
- zr->v4l_buffers.buffer[num].state != BUZ_STATE_DONE) {
- res = -EAGAIN;
- return res;
- }
- res = v4l_sync(fh, num);
- if (res)
- return res;
- zr->v4l_sync_tail++;
- res = zoran_v4l2_buffer_status(fh, buf, num);
- break;
-
- case ZORAN_MAP_MODE_JPG_REC:
- case ZORAN_MAP_MODE_JPG_PLAY:
- {
- struct zoran_sync bs;
-
- if (fh->map_mode == ZORAN_MAP_MODE_JPG_PLAY)
- buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
- else
- buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
- if (buf->type != buf_type) {
- pci_err(zr->pci_dev, "VIDIOC_QBUF - invalid buf->type=%d for map_mode=%d\n",
- buf->type, fh->map_mode);
- res = -EINVAL;
- return res;
- }
-
- num = zr->jpg_pend[zr->jpg_que_tail & BUZ_MASK_FRAME];
-
- if (file->f_flags & O_NONBLOCK &&
- zr->jpg_buffers.buffer[num].state !=