From aebaf60c074d36d2e764cae9337b33e137a9b335 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 21:18:22 +0100 Subject: [PATCH 1/6] facetimehd: change fthd_channel_ringbuf_send() error handling In the current implementation it returns -1 on error, an offset value otherwise. Change it to return a negative error value, and add a pointer to an u32 for receiving the entry offset as an extra argument. This makes the ugly (u32)-1 return code comparision obsolete, and we can return a more detailed error code like EAGAIN if all ringbuffer slots are busy. --- fthd_drv.c | 29 ++++++++++++++++++++++------- fthd_isp.c | 6 ++++-- fthd_ringbuf.c | 15 +++++++++++---- fthd_ringbuf.h | 4 ++-- fthd_v4l2.c | 11 ++++++----- 5 files changed, 45 insertions(+), 20 deletions(-) diff --git a/fthd_drv.c b/fthd_drv.c index 0acf8cd..510ed33 100644 --- a/fthd_drv.c +++ b/fthd_drv.c @@ -104,6 +104,7 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv, { u32 request_size, response_size, address; struct isp_mem_obj *obj; + int ret; request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE); response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE); @@ -114,7 +115,9 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv, FTHD_S2_MEMCPY_FROMIO(&obj, address - 64, sizeof(obj)); isp_mem_destroy(obj); - fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0); + ret = fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0, NULL); + if (ret) + pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); } else { if (!request_size) return; @@ -126,7 +129,10 @@ static void sharedmalloc_handler(struct fthd_private *dev_priv, response_size >> 24,response_size >> 16, response_size >> 8, response_size); FTHD_S2_MEMCPY_TOIO(obj->offset, &obj, sizeof(obj)); - fthd_channel_ringbuf_send(dev_priv, chan, obj->offset + 64, 0, 0); + ret = fthd_channel_ringbuf_send(dev_priv, chan, obj->offset + 64, 0, 0, NULL); + if (ret) + pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); + } } @@ -157,7 +163,7 @@ static void buf_t2h_handler(struct fthd_private *dev_priv, u32 entry) { u32 request_size, response_size, address; - + int ret; request_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_REQUEST_SIZE); response_size = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_RESPONSE_SIZE); address = FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS); @@ -167,15 +173,21 @@ static void buf_t2h_handler(struct fthd_private *dev_priv, fthd_buffer_return_handler(dev_priv, address & ~3, request_size); - fthd_channel_ringbuf_send(dev_priv, chan, (response_size & 0x10000000) ? address : 0, - 0, 0x80000000); + ret = fthd_channel_ringbuf_send(dev_priv, chan, (response_size & 0x10000000) ? address : 0, + 0, 0x80000000, NULL); + if (ret) + pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); + } static void io_t2h_handler(struct fthd_private *dev_priv, struct fw_channel *chan, u32 entry) { - fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0); + int ret = fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0, NULL); + if (ret) + pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); + } static void buf_h2t_handler(struct fthd_private *dev_priv, @@ -188,6 +200,7 @@ static void buf_h2t_handler(struct fthd_private *dev_priv, static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *chan) { u32 entry; + int ret; while((entry = fthd_channel_ringbuf_receive(dev_priv, chan)) != (u32)-1) { pr_debug("channel %s: message available, address %08x\n", chan->name, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS)); @@ -195,7 +208,9 @@ static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *ch sharedmalloc_handler(dev_priv, chan, entry); } else if (chan == dev_priv->channel_terminal) { terminal_handler(dev_priv, chan, entry); - fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0); + ret = fthd_channel_ringbuf_send(dev_priv, chan, 0, 0, 0, NULL); + if (ret) + pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); } else if (chan == dev_priv->channel_buf_t2h) { buf_t2h_handler(dev_priv, chan, entry); } else if (chan == dev_priv->channel_io) { diff --git a/fthd_isp.c b/fthd_isp.c index 6b0ff32..fece39e 100644 --- a/fthd_isp.c +++ b/fthd_isp.c @@ -296,8 +296,10 @@ static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds comman if (request_len) FTHD_S2_MEMCPY_TOIO(request->offset + sizeof(struct isp_cmd_hdr), buf, request_len); - entry = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_io, - request->offset, request_len + 8, (response_len ? *response_len : 0) + 8); + ret = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_io, + request->offset, request_len + 8, (response_len ? *response_len : 0) + 8, &entry); + if (ret) + goto out; if (entry == (u32)-1) { ret = -EIO; diff --git a/fthd_ringbuf.c b/fthd_ringbuf.c index 5617041..f77de0c 100644 --- a/fthd_ringbuf.c +++ b/fthd_ringbuf.c @@ -76,8 +76,8 @@ void fthd_channel_ringbuf_init(struct fthd_private *dev_priv, struct fw_channel } } -u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan, - u32 data_offset, u32 request_size, u32 response_size) +int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan, + u32 data_offset, u32 request_size, u32 response_size, u32 *entryp) { u32 entry; @@ -88,12 +88,17 @@ u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel * if (chan->tx_lock) { spin_unlock_irq(&chan->lock); - return (u32)-1; + return -EBUSY; } if (chan->type != FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size) chan->ringbuf.idx = 0; + if (!(FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0)) { + spin_unlock_irq(&chan->lock); + return -EAGAIN; + } + chan->tx_lock = 1; chan->rx_lock = 0; @@ -107,7 +112,9 @@ u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel * spin_lock_irq(&dev_priv->io_lock); FTHD_ISP_REG_WRITE(0x10 << chan->source, ISP_REG_41020); spin_unlock_irq(&dev_priv->io_lock); - return entry; + if (entryp) + *entryp = entry; + return 0; } u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, diff --git a/fthd_ringbuf.h b/fthd_ringbuf.h index 06783fa..ffe0625 100644 --- a/fthd_ringbuf.h +++ b/fthd_ringbuf.h @@ -42,8 +42,8 @@ struct fthd_private; extern void fthd_channel_ringbuf_dump(struct fthd_private *dev_priv, struct fw_channel *chan); extern void fthd_channel_ringbuf_init(struct fthd_private *dev_priv, struct fw_channel *chan); extern u32 fthd_channel_ringbuf_get_entry(struct fthd_private *, struct fw_channel *); -extern u32 fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan, - u32 data_offset, u32 request_size, u32 response_size); +extern int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel *chan, + u32 data_offset, u32 request_size, u32 response_size, u32 *entry); extern u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, struct fw_channel *chan); diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 4c5077a..5050a1d 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -126,15 +126,16 @@ static void fthd_buffer_cleanup(struct vb2_buffer *vb) static int fthd_send_h2t_buffer(struct fthd_private *dev_priv, struct h2t_buf_ctx *ctx) { u32 entry; + int ret; pr_debug("sending buffer %p size %ld, ctx %p\n", ctx->vb, sizeof(ctx->dma_desc_list), ctx); FTHD_S2_MEMCPY_TOIO(ctx->dma_desc_obj->offset, &ctx->dma_desc_list, sizeof(ctx->dma_desc_list)); - entry = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_buf_h2t, - ctx->dma_desc_obj->offset, 0x180, 0x30000000); + ret = fthd_channel_ringbuf_send(dev_priv, dev_priv->channel_buf_h2t, + ctx->dma_desc_obj->offset, 0x180, 0x30000000, &entry); - if (entry == (u32)-1) { - pr_debug("send failed\n"); - return -EIO; + if (ret) { + pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); + return ret; } if (wait_event_interruptible_timeout(ctx->wq, ctx->done, HZ) <= 0) { From 3574901c31c5e6149bf170e313d78711f8629406 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 22:21:37 +0100 Subject: [PATCH 2/6] facetimehd: add missing linefeeds in pr_debug Signed-off-by: Sven Schnelle --- fthd_drv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fthd_drv.c b/fthd_drv.c index 510ed33..4a6b7e6 100644 --- a/fthd_drv.c +++ b/fthd_drv.c @@ -80,13 +80,13 @@ static int fthd_pci_reserve_mem(struct fthd_private *dev_priv) dev_priv->isp_io = ioremap_nocache(start, len); dev_priv->isp_io_len = len; - pr_debug("Allocated S2 regs (BAR %d). %u bytes at 0x%p", + pr_debug("Allocated S2 regs (BAR %d). %u bytes at 0x%p\n", FTHD_PCI_S2_IO, dev_priv->s2_io_len, dev_priv->s2_io); - pr_debug("Allocated S2 mem (BAR %d). %u bytes at 0x%p", + pr_debug("Allocated S2 mem (BAR %d). %u bytes at 0x%p\n", FTHD_PCI_S2_MEM, dev_priv->s2_mem_len, dev_priv->s2_mem); - pr_debug("Allocated ISP regs (BAR %d). %u bytes at 0x%p", + pr_debug("Allocated ISP regs (BAR %d). %u bytes at 0x%p\n", FTHD_PCI_ISP_IO, dev_priv->isp_io_len, dev_priv->isp_io); return 0; From ca8c5584e07a5ca2702ef6be79ba2e5be0769f2e Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 22:59:44 +0100 Subject: [PATCH 3/6] facetimehd: add channel waitqueue add a per channel waitqueue to be able to have more than one ringbuffer entry in flight. Signed-off-by: Sven Schnelle --- fthd_drv.c | 27 +++++++++++++++------------ fthd_drv.h | 8 ++------ fthd_isp.c | 12 +++--------- fthd_ringbuf.c | 26 +++++++++++++------------- fthd_ringbuf.h | 1 + fthd_v4l2.c | 24 +----------------------- 6 files changed, 35 insertions(+), 63 deletions(-) diff --git a/fthd_drv.c b/fthd_drv.c index 4a6b7e6..f47517b 100644 --- a/fthd_drv.c +++ b/fthd_drv.c @@ -190,18 +190,26 @@ static void io_t2h_handler(struct fthd_private *dev_priv, } -static void buf_h2t_handler(struct fthd_private *dev_priv, - struct fw_channel *chan, - u32 entry) -{ - fthd_buffer_queued_handler(dev_priv, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & ~3); -} - static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *chan) { u32 entry; int ret; + if (chan == dev_priv->channel_io) { + pr_debug("IO channel ready\n"); + wake_up_interruptible(&chan->wq); + return; + } + + if (chan == dev_priv->channel_buf_h2t) { + pr_debug("H2T channel ready\n"); + wake_up_interruptible(&chan->wq); + return; + } + + if (chan == dev_priv->channel_debug) + return; + while((entry = fthd_channel_ringbuf_receive(dev_priv, chan)) != (u32)-1) { pr_debug("channel %s: message available, address %08x\n", chan->name, FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS)); if (chan == dev_priv->channel_shared_malloc) { @@ -213,12 +221,8 @@ static void fthd_handle_irq(struct fthd_private *dev_priv, struct fw_channel *ch pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); } else if (chan == dev_priv->channel_buf_t2h) { buf_t2h_handler(dev_priv, chan, entry); - } else if (chan == dev_priv->channel_io) { - wake_up_interruptible(&dev_priv->cmd_wq); } else if (chan == dev_priv->channel_io_t2h) { io_t2h_handler(dev_priv, chan, entry); - } else if (chan == dev_priv->channel_buf_h2t) { - buf_h2t_handler(dev_priv, chan, entry); } } } @@ -456,7 +460,6 @@ static int fthd_pci_probe(struct pci_dev *pdev, mutex_init(&dev_priv->vb2_queue_lock); mutex_init(&dev_priv->ioctl_lock); - init_waitqueue_head(&dev_priv->cmd_wq); INIT_LIST_HEAD(&dev_priv->buffer_queue); INIT_WORK(&dev_priv->irq_work, fthd_irq_work); diff --git a/fthd_drv.h b/fthd_drv.h index f967cf1..41050c2 100644 --- a/fthd_drv.h +++ b/fthd_drv.h @@ -56,11 +56,10 @@ struct fw_channel { u32 size; u32 source; u32 type; - int tx_lock; - int rx_lock; struct fthd_ringbuf ringbuf; spinlock_t lock; - + /* waitqueue for signaling completion */ + wait_queue_head_t wq; char *name; }; @@ -75,9 +74,6 @@ struct fthd_private { /* lock for synchronizing with irq/workqueue */ spinlock_t io_lock; - /* waitqueue for signaling command completion */ - wait_queue_head_t cmd_wq; - /* Mapped PCI resources */ void __iomem *s2_io; u32 s2_io_len; diff --git a/fthd_isp.c b/fthd_isp.c index fece39e..6af25cb 100644 --- a/fthd_isp.c +++ b/fthd_isp.c @@ -236,11 +236,8 @@ static int isp_fill_channel_info(struct fthd_private *dev_priv, int offset, int chan->source = info.source; chan->size = info.size; chan->offset = info.offset; - if (chan->type == FW_CHAN_TYPE_OUT) - chan->rx_lock = 1; - if (chan->type == FW_CHAN_TYPE_IN) - chan->tx_lock = 1; spin_lock_init(&chan->lock); + init_waitqueue_head(&chan->wq); } dev_priv->channel_terminal = isp_get_chan_index(dev_priv, "TERMINAL"); @@ -312,13 +309,10 @@ static int fthd_isp_cmd(struct fthd_private *dev_priv, enum fthd_isp_cmds comman goto out; } - if (wait_event_interruptible_timeout(dev_priv->cmd_wq, - FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1, HZ) <= 0) { - dev_err(&dev_priv->pdev->dev, "timeout wait for command %d\n", cmd.opcode); - fthd_channel_ringbuf_dump(dev_priv, dev_priv->channel_io); + ret = fthd_channel_wait_ready(dev_priv, dev_priv->channel_io, entry, 2000); + if (ret) { if (response_len) *response_len = 0; - ret = -ETIMEDOUT; goto out; } diff --git a/fthd_ringbuf.c b/fthd_ringbuf.c index f77de0c..6097dc2 100644 --- a/fthd_ringbuf.c +++ b/fthd_ringbuf.c @@ -86,12 +86,7 @@ int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel * spin_lock_irq(&chan->lock); entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx); - if (chan->tx_lock) { - spin_unlock_irq(&chan->lock); - return -EBUSY; - } - - if (chan->type != FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size) + if (++chan->ringbuf.idx >= chan->size) chan->ringbuf.idx = 0; if (!(FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0)) { @@ -99,9 +94,6 @@ int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_channel * return -EAGAIN; } - chan->tx_lock = 1; - chan->rx_lock = 0; - FTHD_S2_MEM_WRITE(request_size, entry + FTHD_RINGBUF_REQUEST_SIZE); FTHD_S2_MEM_WRITE(response_size, entry + FTHD_RINGBUF_RESPONSE_SIZE); wmb(); @@ -123,8 +115,6 @@ u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, u32 entry, ret = (u32)-1; spin_lock_irq(&chan->lock); - if (chan->rx_lock) - goto out; entry = get_entry_addr(dev_priv, chan, chan->ringbuf.idx); @@ -137,9 +127,19 @@ u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, if (chan->type == FW_CHAN_TYPE_OUT && ++chan->ringbuf.idx >= chan->size) chan->ringbuf.idx = 0; - chan->rx_lock = 1; - chan->tx_lock = 0; out: spin_unlock_irq(&chan->lock); return ret; } + +int fthd_channel_wait_ready(struct fthd_private *dev_priv, struct fw_channel *chan, u32 entry, int timeout) +{ + if (wait_event_interruptible_timeout(chan->wq, + (FTHD_S2_MEM_READ(entry + FTHD_RINGBUF_ADDRESS_FLAGS) & 1) ^ (chan->type != 0), + msecs_to_jiffies(timeout)) <= 0) { + dev_err(&dev_priv->pdev->dev, "%s: timeout\n", chan->name); + fthd_channel_ringbuf_dump(dev_priv, chan); + return -ETIMEDOUT; + } + return 0; +} diff --git a/fthd_ringbuf.h b/fthd_ringbuf.h index ffe0625..3b75610 100644 --- a/fthd_ringbuf.h +++ b/fthd_ringbuf.h @@ -48,4 +48,5 @@ extern int fthd_channel_ringbuf_send(struct fthd_private *dev_priv, struct fw_ch extern u32 fthd_channel_ringbuf_receive(struct fthd_private *dev_priv, struct fw_channel *chan); +extern int fthd_channel_wait_ready(struct fthd_private *dev_priv, struct fw_channel *chan, u32 entry, int timeout); #endif diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 5050a1d..f7c909e 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -137,29 +137,7 @@ static int fthd_send_h2t_buffer(struct fthd_private *dev_priv, struct h2t_buf_ct pr_err("%s: fthd_channel_ringbuf_send: %d\n", __FUNCTION__, ret); return ret; } - - if (wait_event_interruptible_timeout(ctx->wq, ctx->done, HZ) <= 0) { - dev_err(&dev_priv->pdev->dev, "timeout wait for buffer %p\n", ctx->vb); - return -ETIMEDOUT; - } - ctx->done = 0; - return 0; -} - -void fthd_buffer_queued_handler(struct fthd_private *dev_priv, u32 offset) -{ - - struct dma_descriptor_list list; - struct h2t_buf_ctx *ctx; - - - FTHD_S2_MEMCPY_FROMIO(&list, offset, sizeof(list)); - - ctx = (struct h2t_buf_ctx *)list.desc[0].tag; - pr_debug("vb %p, ctx = %p\n", ctx->vb, ctx); - memcpy(&ctx->dma_desc_list, &list, sizeof(ctx->dma_desc_list)); - ctx->done = 1; - wake_up_interruptible(&ctx->wq); + return fthd_channel_wait_ready(dev_priv, dev_priv->channel_buf_h2t, entry, 2000); } static void fthd_buffer_queue(struct vb2_buffer *vb) From c0e9fbb6e6583df3d4a35657ad8defd08c060784 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 23:01:19 +0100 Subject: [PATCH 4/6] facetimehd: return error if channel list is empty Signed-off-by: Sven Schnelle --- fthd_isp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fthd_isp.c b/fthd_isp.c index 6af25cb..35545c6 100644 --- a/fthd_isp.c +++ b/fthd_isp.c @@ -209,13 +209,14 @@ static int isp_fill_channel_info(struct fthd_private *dev_priv, int offset, int int i; if (!num_channels) - return 0; + return -EINVAL; - dev_priv->num_channels = num_channels; dev_priv->channels = kzalloc(num_channels * sizeof(struct fw_channel *), GFP_KERNEL); if (!dev_priv->channels) goto out; + dev_priv->num_channels = num_channels; + for(i = 0; i < num_channels; i++) { FTHD_S2_MEMCPY_FROMIO(&info, offset + i * 256, sizeof(info)); From 4758d7a8485dba300b8798fcb069eb0e45cd0f02 Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 23:02:23 +0100 Subject: [PATCH 5/6] facetimehd: set framesize type to stepwise --- fthd_v4l2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fthd_v4l2.c b/fthd_v4l2.c index f7c909e..02180f9 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -520,7 +520,7 @@ static int fthd_v4l2_ioctl_enum_framesizes(struct file *filp, void *priv, if (sizes->index) return -EINVAL; - sizes->type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + sizes->type = V4L2_FRMSIZE_TYPE_STEPWISE; sizes->stepwise.min_width = 320; sizes->stepwise.max_width = 2560; sizes->stepwise.min_height = 240; From 6bbe3712f88fde7648790db88c41338e4729050b Mon Sep 17 00:00:00 2001 From: Sven Schnelle Date: Sat, 28 Nov 2015 23:09:40 +0100 Subject: [PATCH 6/6] facetimehd: fix enum_frameintervals() Signed-off-by: Sven Schnelle --- fthd_v4l2.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/fthd_v4l2.c b/fthd_v4l2.c index 02180f9..9e6c10c 100644 --- a/fthd_v4l2.c +++ b/fthd_v4l2.c @@ -33,6 +33,11 @@ #include "fthd_ringbuf.h" #include "fthd_buffer.h" +#define FTHD_MAX_WIDTH 2560 +#define FTHD_MAX_HEIGHT 1600 +#define FTHD_MIN_WIDTH 320 +#define FTHD_MIN_HEIGHT 240 + #define FTHD_FMT(_desc, _x, _y, _sizeimage, _planes, _pixfmt) \ { \ .fmt.width = (_x), \ @@ -521,10 +526,10 @@ static int fthd_v4l2_ioctl_enum_framesizes(struct file *filp, void *priv, return -EINVAL; sizes->type = V4L2_FRMSIZE_TYPE_STEPWISE; - sizes->stepwise.min_width = 320; - sizes->stepwise.max_width = 2560; - sizes->stepwise.min_height = 240; - sizes->stepwise.max_height = 1600; + sizes->stepwise.min_width = FTHD_MIN_WIDTH; + sizes->stepwise.max_width = FTHD_MAX_WIDTH; + sizes->stepwise.min_height = FTHD_MIN_HEIGHT; + sizes->stepwise.max_height = FTHD_MAX_HEIGHT; sizes->stepwise.step_width = 8; sizes->stepwise.step_height = 1; return 0; @@ -543,13 +548,19 @@ static int fthd_v4l2_ioctl_enum_frameintervals(struct file *filp, void *priv, interval->pixel_format != V4L2_PIX_FMT_NV16) return -EINVAL; + if (interval->width & 7 + || interval->width > FTHD_MAX_WIDTH + || interval->height > FTHD_MAX_HEIGHT) + return -EINVAL; + interval->type = V4L2_FRMIVAL_TYPE_STEPWISE; + interval->stepwise.step.numerator = 1; + interval->stepwise.step.denominator = 1000; interval->stepwise.min.numerator = 33; interval->stepwise.min.denominator = 1000; interval->stepwise.max.numerator = 500; interval->stepwise.max.denominator = 1000; - - return -ENODEV; + return 0; } static struct v4l2_ioctl_ops fthd_ioctl_ops = {