v4l: ti-vpe: Some VPE fixes and enhancements
cover v4l: ti-vpe: Some VPE fixes and enhancements
This patch set mainly consists of minor fixes for the VPE driver. These fixes ensure the following:
- The VPE module can be inserted and removed successively.
- Make sure that smaller resolutions like qcif work correctly.
- Prevent race condition between firmware loading and an open call to the v4l2 device.
- Prevent the possibility of output m2m queue not having sufficient 'ready' buffers.
- Some VPDMA data descriptor fields weren't understood correctly before. They are now used correctly.
The rest of the patches add some minor features like DMA buf support and cropping.
Reference branch:
[email protected]:boddob/linux.git vpe_for_315
Archit Taneja (7):
v4l: ti-vpe: Make sure in job_ready that we have the needed number of
dst_bufs
v4l: ti-vpe: register video device only when firmware is loaded
v4l: ti-vpe: Use video_device_release_empty
v4l: ti-vpe: Allow DMABUF buffer type support
v4l: ti-vpe: Allow usage of smaller images
v4l: ti-vpe: Fix some params in VPE data descriptors
v4l: ti-vpe: Add crop support in VPE driver
drivers/media/platform/ti-vpe/vpdma.c | 58 ++++++++--- drivers/media/platform/ti-vpe/vpdma.h | 16 +-- drivers/media/platform/ti-vpe/vpe.c | 180 +++++++++++++++++++++++++++------- 3 files changed, 198 insertions(+), 56 deletions(-)
Signature · 1 line
1.8.3.2
PATCH 1/7 v4l: ti-vpe: Make sure in job_ready that we have the needed number of dst_bufs
VPE has a ctrl parameter which decides how many mem to mem transactions the active job from the job queue can perform.
The driver's job_ready() made sure that the number of ready source buffers are sufficient for the job to execute successfully. But it didn't make sure if there are sufficient ready destination buffers in the capture queue for the VPE output.
If the time taken by VPE to process a single frame is really slow, then it's possible that we don't need to imply such a restriction on the dst queue, but really fast transactions(small resolution, no de-interlacing) may cause us to hit the condition where we don't have any free buffers for the VPE to write on.
Add the extra check in job_ready() to make sure we have the sufficient amount of destination buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +3 -0
@@ -887,6 +887,9 @@ static int job_ready(void *priv)if (v4l2_m2m_num_src_bufs_ready (ctx->m2m_ctx) < needed)return 0 ; +if (v4l2_m2m_num_dst_bufs_ready (ctx->m2m_ctx) < needed) +return 0 ; +return 1 ; }
Signature · 1 line
1.8.3.2
PATCH 2/7 v4l: ti-vpe: register video device only when firmware is loaded
In reply to Archit Tanejavpe fops(vpe_open in particular) should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.
Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when it returns.
We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through vpdma_create().
The ready field in vpdma_data is no longer needed since we always have firmware loaded before the device is registered.
A minor problem with this approach is that if the video_register_device fails(which doesn't really happen), the vpe platform device would be registered. however, there won't be any v4l2 device corresponding to it.
--- drivers/media/platform/ti-vpe/vpdma.c | 8 +++-- drivers/media/platform/ti-vpe/vpdma.h | 7 +++-- drivers/media/platform/ti-vpe/vpe.c | 55 ++++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 29 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +5 -3
@@ -781,7 +781,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context)/* already initialized */ if (read_field_reg (vpdma,VPDMA_LIST_ATTR ,VPDMA_LIST_RDY_MASK ,VPDMA_LIST_RDY_SHFT )) { - vpdma->ready = true; + vpdma->cb (vpdma->pdev);return ; }
@@ -811,7 +811,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context) goto free_buf; } - vpdma->ready = true; + vpdma->cb (vpdma->pdev); free_buf:vpdma_unmap_desc_buf (vpdma, &fw_dma_buf);
@@ -839,7 +839,8 @@ static int vpdma_load_firmware(struct vpdma_data *vpdma)return 0 ; } -struct vpdma_data *vpdma_create (struct platform_device *pdev) +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev)) {struct resource *res;struct vpdma_data *vpdma;
@@ -854,6 +855,7 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev) } vpdma->pdev = pdev; + vpdma->cb = cb; res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"vpdma" );if (res ==NULL ) {
drivers/media/platform/ti-vpe/vpdma.h +4 -3
@@ -35,8 +35,8 @@ struct vpdma_data {struct platform_device *pdev; -/* tells whether vpdma firmware is loaded or not */ -bool ready; +/* callback to VPE driver when the firmware is loaded */ +void (*cb)(struct platform_device *pdev); };enum vpdma_data_format_type {
@@ -208,6 +208,7 @@ void vpdma_set_frame_start_event(struct vpdma_data *vpdma,void vpdma_dump_regs (struct vpdma_data *vpdma);/* initialize vpdma, passed with VPE's platform device pointer */ -struct vpdma_data *vpdma_create (struct platform_device *pdev); +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev));#endif
drivers/media/platform/ti-vpe/vpe.c +32 -23
81 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH 3/7 v4l: ti-vpe: Use video_device_release_empty
In reply to Archit TanejaThe video_device struct is currently embedded in the driver data struct vpe_dev. A vpe_dev instance is allocated by the driver, and the memory for the vfd is a part of this struct.
The v4l2 core, however, manages the removal of the vfd region, through the video_device's .release() op, which currently is the helper video_device_release. This causes memory corruption, and leads to issues when we try to re-insert the vpe module.
Use the video_device_release_empty helper function instead
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +1 -1
@@ -1998,7 +1998,7 @@ static struct video_device vpe_videodev = { .fops = &vpe_fops, .ioctl_ops = &vpe_ioctl_ops, .minor = -1, - .release = video_device_release, + .release = video_device_release_empty, .vfl_dir = VFL_DIR_M2M, };
Signature · 1 line
1.8.3.2
PATCH 4/7 v4l: ti-vpe: Allow DMABUF buffer type support
In reply to Archit TanejaFor OMAP and DRA7x, we generally allocate video and graphics buffers through omapdrm since the corresponding omap-gem driver provides DMM-Tiler backed contiguous buffers. omapdrm is a dma-buf exporter. These buffers are used by other drivers in the video pipeline.
Add VB2_DMABUF flag to the io_modes of the vb2 output and capture queues. This allows the driver to import dma shared buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -1768,7 +1768,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (src_vq,0 ,sizeof (*src_vq)); src_vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ; - src_vq->io_modes =VB2_MMAP ; + src_vq->io_modes =VB2_MMAP |VB2_DMABUF ; src_vq->drv_priv = ctx; src_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); src_vq->ops = &vpe_qops;
@@ -1781,7 +1781,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (dst_vq,0 ,sizeof (*dst_vq)); dst_vq->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ; - dst_vq->io_modes =VB2_MMAP ; + dst_vq->io_modes =VB2_MMAP |VB2_DMABUF ; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); dst_vq->ops = &vpe_qops;
Signature · 1 line
1.8.3.2
PATCH 5/7 v4l: ti-vpe: Allow usage of smaller images
In reply to Archit TanejaThe minimum width and height for VPE input/output was kept as 128 pixels. VPE doesn't have a constraint on the image height, it requires the image width to be atleast 16 bytes.
Change the minimum supported dimensions to 32x32. This allows us to de-interlace qcif content. A smaller image size than 32x32 didn't make much sense, so stopped at this.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -49,8 +49,8 @@#define VPE_MODULE_NAME "vpe"/* minimum and maximum frame sizes */ -#define MIN_W 128 -#define MIN_H 128 +#define MIN_W 32 +#define MIN_H 32#define MAX_W 1920#define MAX_H 1080
Signature · 1 line
1.8.3.2
RE: [PATCH 5/7] v4l: ti-vpe: Allow usage of smaller images
Hi Archit,
Quoted 6 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Monday, March 03, 2014 8:33 AMThe minimum width and height for VPE input/output was kept as 128 pixels. VPE doesn't have a constraint on the image height, it requires the image width to be atleast 16 bytes.
"16 bytes" - shouldn't it be pixels? (also "at least" :) ) I can correct it when applying the patch if the above is the case.
Quoted 5 lines
Change the minimum supported dimensions to 32x32. This allows us to de- interlace qcif content. A smaller image size than 32x32 didn't make much sense, so stopped at this.
Signed-off-by Archit Taneja <[email protected]>
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Quoted 22 lines
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/media/platform/ti-vpe/vpe.c +2
-3@@ -49,8 +49,8 @@#define VPE_MODULE_NAME "vpe"/* minimum and maximum frame sizes */ -#define MIN_W 128 -#define MIN_H 128 +#define MIN_W 32 +#define MIN_H 32#define MAX_W 1920#define MAX_H 1080 --1.8.3.2
Re: [PATCH 5/7] v4l: ti-vpe: Allow usage of smaller images
Hi,
Quoted 11 lines · Kamil Debski
Hi Archit,
Quoted 6 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Monday, March 03, 2014 8:33 AMThe minimum width and height for VPE input/output was kept as 128 pixels. VPE doesn't have a constraint on the image height, it requires the image width to be atleast 16 bytes.
"16 bytes" - shouldn't it be pixels? (also "at least" :) ) I can correct it when applying the patch if the above is the case.
VPDMA IP requires the line stride of the input/output images to be at least 16 bytes in total.
This can safely result in a minimum width of 16 pixels(NV12 has the least bpp with 1 byte per pixel). But we don't really have any need to support such small image resolutions. So I picked up 32x32 as the minimum size, and tested VPE with that.
Thanks,
Archit
PATCH 6/7 v4l: ti-vpe: Fix some params in VPE data descriptors
In reply to Archit TanejaSome parameters of the VPE descriptors were understood incorrectly. They are now fixed. The fixes are explained as follows:
- When adding an inbound data descriptor to the VPDMA descriptor list, we intend to use c_rect as the cropped region fetched by VPDMA. Therefore, c_rect->width shouldn't be used to calculate the line stride, the original image width should be used for that. We add a 'width' argument which gives the buffer width in memory.
- frame_width and frame_height describe the complete width and height of the client to which the channel is connected. If there are multiple channels fetching data and providing to the same client, the above 2 arguments should be the width and height of the region covered by all the channels. In the case where there is only one channel providing pixel data to the client (like in VPE), frame_width and frame_height should be the cropped width and cropped height respectively. The calculation of these params is done in the vpe driver now.
- start_h and start_v is also used in the case of multiple channels to describe where each channel should start filling pixel data. We don't use this in VPE, and pass 0s to the vpdma_add_in_dtd() helper.
- Some minor changes are made to the vpdma_add_out_dtd() helper. The c_rect param is removed since cropping isn't possible for outbound data, and 'width' is added to calculate the line stride.
--- drivers/media/platform/ti-vpe/vpdma.c | 50 ++++++++++++++++++++++++++--------- drivers/media/platform/ti-vpe/vpdma.h | 9 ++++--- drivers/media/platform/ti-vpe/vpe.c | 16 +++++++---- 3 files changed, 53 insertions(+), 22 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +37 -13
@@ -614,8 +614,15 @@ static void dump_dtd(struct vpdma_dtd *dtd)/* * append an outbound data transfer descriptor to the given descriptor list, * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* flags: VPDMA flags to configure some descriptor fileds */ -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags) {
@@ -633,8 +640,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, fmt->data_type == DATA_TYPE_C420) depth =8 ; - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -664,31 +670,48 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,/* * append an inbound data transfer descriptor to the given descriptor list, * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory(not the cropped width) +* @c_rect: crop params of input image +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* field: top or bottom field info of the input image +* flags: VPDMA flags to configure some descriptor fileds +* frame_width/height: the complete width/height of the image presented to the +* client (this makes sense when multiple channels are +* connected to the same client, forming a larger frame) +* start_h, start_v: position where the given channel starts providing pixel +* data to the client (makes sense when multiple channels +* contribute to the client) */ -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags) +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v) {int priority =0 ;int notify =1 ;int depth = fmt->depth;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int stride; -int height = c_rect->height;struct vpdma_dtd *dtd; channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && fmt->data_type ==DATA_TYPE_C420 ) { - height >>=1 ; - frame_height >>=1 ; + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -701,13 +724,14 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, !!(flags &VPDMA_DATA_ODD_LINE_SKIP ), stride); - dtd->xfer_length_height =dtd_xfer_length_height (c_rect->width, height); + dtd->xfer_length_height =dtd_xfer_length_height (rect.width, + rect.height); dtd->start_addr = (u32 ) dma_addr; dtd->pkt_ctl =dtd_pkt_ctl (!!(flags &VPDMA_DATA_MODE_TILED ),DTD_DIR_IN , channel, priority, next_chan); dtd->frame_width_height =dtd_frame_width_height (frame_width, frame_height); - dtd->start_h_v =dtd_start_h_v (c_rect->left, c_rect->top); + dtd->start_h_v =dtd_start_h_v (start_h, start_v); dtd->client_attr0 =0 ; dtd->client_attr1 =0 ;
drivers/media/platform/ti-vpe/vpdma.h +5 -4
@@ -186,13 +186,14 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, struct vpdma_buf *adb);void vpdma_add_sync_on_channel_ctd (struct vpdma_desc_list *list,enum vpdma_channel chan); -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags); -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags); +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v);/* vpdma list interrupt management */ void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
drivers/media/platform/ti-vpe/vpe.c +11 -5
@@ -986,7 +986,6 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->dst_vb; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = !ctx->src_mv_buf_selector;
@@ -1015,7 +1014,7 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_out_dtd (&ctx->desc_list, c_rect, vpdma_fmt, dma_addr, +vpdma_add_out_dtd (&ctx->desc_list, q_data->width, vpdma_fmt, dma_addr, p_data->channel, flags); }
@@ -1024,11 +1023,11 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = ctx->src_mv_buf_selector;int field = vb->v4l2_buf.field ==V4L2_FIELD_BOTTOM ; +int frame_width, frame_height;dma_addr_t dma_addr;u32 flags =0 ;
@@ -1055,8 +1054,15 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_in_dtd (&ctx->desc_list, q_data->width, q_data->height, - c_rect, vpdma_fmt, dma_addr, p_data->channel, field, flags); + frame_width = q_data->c_rect.width; + frame_height = q_data->c_rect.height; + +if (p_data->vb_part && fmt->fourcc ==V4L2_PIX_FMT_NV12 ) + frame_height /=2 ; + +vpdma_add_in_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, field, flags, frame_width, + frame_height,0 ,0 ); }/*
Signature · 1 line
1.8.3.2
PATCH 7/7 v4l: ti-vpe: Add crop support in VPE driver
In reply to Archit TanejaAdd crop ioctl ops. For VPE, cropping only makes sense with the input to VPE, or the V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE buffer type.
For the CAPTURE type, a S_CROP ioctl results in setting the crop region as the whole image itself, hence making crop dimensions same as the pix dimensions.
Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change, set_srcdst_params() is called for this purpose.
Some standard crop parameter checks are done in __vpe_try_crop().
--- drivers/media/platform/ti-vpe/vpe.c | 96 +++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +96 -0
@@ -1585,6 +1585,98 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_crop (struct vpe_ctx *ctx,struct v4l2_crop *cr) +{ +struct vpe_q_data *q_data; + + q_data =get_q_data (ctx, cr->type); +if (!q_data) +return -EINVAL ; + +/* we don't support crop on capture plane */ +if (cr->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) { + cr->c.top = cr->c.left =0 ; + cr->c.width = q_data->width; + cr->c.height = q_data->height; +return 0 ; + } + +if (cr->c.top <0 || cr->c.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + cr->c.top = cr->c.left =0 ; + } + +v4l_bound_align_image (&cr->c.width,MIN_W , q_data->width,1 , + &cr->c.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (cr->c.left + cr->c.width > q_data->width) + cr->c.left = q_data->width - cr->c.width; +if (cr->c.top + cr->c.height > q_data->height) + cr->c.top = q_data->height - cr->c.height; + +return 0 ; +} + +static int vpe_cropcap (struct file *file,void *priv,struct v4l2_cropcap *cr) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + + q_data =get_q_data (ctx, cr->type); +if (!q_data) +return -EINVAL ; + + cr->bounds.left =0 ; + cr->bounds.top =0 ; + cr->bounds.width = q_data->width; + cr->bounds.height = q_data->height; + cr->defrect = cr->bounds; + +return 0 ; +} + +static int vpe_g_crop (struct file *file,void *fh,struct v4l2_crop *cr) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + + q_data =get_q_data (ctx, cr->type); +if (!q_data) +return -EINVAL ; + + cr->c = q_data->c_rect; + +return 0 ; +} + +static int vpe_s_crop (struct file *file,void *priv, +const struct v4l2_crop *crop) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +struct v4l2_crop cr = *crop; +int ret; + + ret =__vpe_try_crop (ctx, &cr); +if (ret) +return ret; + + q_data =get_q_data (ctx, cr.type); + +if ((q_data->c_rect.left == cr.c.left) && + (q_data->c_rect.top == cr.c.top) && + (q_data->c_rect.width == cr.c.width) && + (q_data->c_rect.height == cr.c.height)) { +vpe_dbg (ctx->dev,"requested crop values are already set\n" ); +return 0 ; + } + + q_data->c_rect = cr.c; + +return set_srcdst_params (ctx); +} +static int vpe_reqbufs (struct file *file,void *priv,struct v4l2_requestbuffers *reqbufs) {
@@ -1672,6 +1764,10 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, + .vidioc_cropcap = vpe_cropcap, + .vidioc_g_crop = vpe_g_crop, + .vidioc_s_crop = vpe_s_crop, + .vidioc_reqbufs = vpe_reqbufs, .vidioc_querybuf = vpe_querybuf,
Signature · 1 line
1.8.3.2
Re: [PATCH 7/7] v4l: ti-vpe: Add crop support in VPE driver
Hi Archit!
Quoted 11 lines · Archit Taneja
Add crop ioctl ops. For VPE, cropping only makes sense with the input to VPE, or the
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANEbuffer type.For the CAPTURE type, a
S_CROPioctl results in setting the crop region as the whole image itself, hence making crop dimensions same as the pix dimensions.Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Some standard crop parameter checks are done in
__vpe_try_crop().
Please use the selection ops instead: if you implement cropping with those then you'll support both the selection API and the old cropping API will be implemented by the v4l2 core using the selection ops. Two for the price of one...
Regards,
Hans
Quoted 121 lines
Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpe.c | 96 +++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+)drivers/media/platform/ti-vpe/vpe.c +96
-0@@ -1585,6 +1585,98 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_crop (struct vpe_ctx *ctx,struct v4l2_crop *cr) +{ +struct vpe_q_data *q_data; + + q_data =get_q_data (ctx, cr->type); +if (!q_data) +return -EINVAL ; + +/* we don't support crop on capture plane */ +if (cr->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ) { + cr->c.top = cr->c.left =0 ; + cr->c.width = q_data->width; + cr->c.height = q_data->height; +return 0 ; + } + +if (cr->c.top <0 || cr->c.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + cr->c.top = cr->c.left =0 ; + } + +v4l_bound_align_image (&cr->c.width,MIN_W , q_data->width,1 , + &cr->c.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (cr->c.left + cr->c.width > q_data->width) + cr->c.left = q_data->width - cr->c.width; +if (cr->c.top + cr->c.height > q_data->height) + cr->c.top = q_data->height - cr->c.height; + +return 0 ; +} + +static int vpe_cropcap (struct file *file,void *priv,struct v4l2_cropcap *cr) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + + q_data =get_q_data (ctx, cr->type); +if (!q_data) +return -EINVAL ; + + cr->bounds.left =0 ; + cr->bounds.top =0 ; + cr->bounds.width = q_data->width; + cr->bounds.height = q_data->height; + cr->defrect = cr->bounds; + +return 0 ; +} + +static int vpe_g_crop (struct file *file,void *fh,struct v4l2_crop *cr) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + + q_data =get_q_data (ctx, cr->type); +if (!q_data) +return -EINVAL ; + + cr->c = q_data->c_rect; + +return 0 ; +} + +static int vpe_s_crop (struct file *file,void *priv, +const struct v4l2_crop *crop) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +struct v4l2_crop cr = *crop; +int ret; + + ret =__vpe_try_crop (ctx, &cr); +if (ret) +return ret; + + q_data =get_q_data (ctx, cr.type); + +if ((q_data->c_rect.left == cr.c.left) && + (q_data->c_rect.top == cr.c.top) && + (q_data->c_rect.width == cr.c.width) && + (q_data->c_rect.height == cr.c.height)) { +vpe_dbg (ctx->dev,"requested crop values are already set\n" ); +return 0 ; + } + + q_data->c_rect = cr.c; + +return set_srcdst_params (ctx); +} +static int vpe_reqbufs (struct file *file,void *priv,struct v4l2_requestbuffers *reqbufs) {@@ -1672,6 +1764,10 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, + .vidioc_cropcap = vpe_cropcap, + .vidioc_g_crop = vpe_g_crop, + .vidioc_s_crop = vpe_s_crop, + .vidioc_reqbufs = vpe_reqbufs, .vidioc_querybuf = vpe_querybuf,
Re: [PATCH 7/7] v4l: ti-vpe: Add crop support in VPE driver
Hi,
Quoted 13 lines · Hans Verkuil
Hi Archit!
Quoted 10 lines · Archit Taneja
Add crop ioctl ops. For VPE, cropping only makes sense with the input to VPE, or the
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANEbuffer type.For the CAPTURE type, a
S_CROPioctl results in setting the crop region as the whole image itself, hence making crop dimensions same as the pix dimensions.Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.
Quoted 5 lines
Quoted 1 line
Some standard crop parameter checks are done in
__vpe_try_crop().Please use the selection ops instead: if you implement cropping with those then you'll support both the selection API and the old cropping API will be implemented by the v4l2 core using the selection ops. Two for the price of one...
<snip>
Thanks for the feedback. I'll use selection ops here.
Archit
RE: [PATCH 7/7] v4l: ti-vpe: Add crop support in VPE driver
Hi Archit,
Quoted 26 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Monday, March 03, 2014 9:26 AMHi,
Quoted 4 lines · Hans Verkuil
Hi Archit!
Quoted 1 line · Archit Taneja
Add crop ioctl ops. For VPE, cropping only makes sense with the
input
Quoted 4 lines
Quoted 4 lines
to VPE, or the
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANEbuffer type.For the CAPTURE type, a
S_CROPioctl results in setting the crop region as the whole image itself, hence making crop dimensions sameas the pix dimensions.
Quoted 10 lines
Quoted 6 lines
Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Some standard crop parameter checks are done in
__vpe_try_crop().Please use the selection ops instead: if you implement cropping with those then you'll support both the selection API and the old cropping API will be implemented by the v4l2 core using the selection ops. Two
Quoted 7 lines
for the price of one...
<snip>
Thanks for the feedback. I'll use selection ops here.
From your reply I understand that you will send a v2 of these patches,
right?
If so, please correct the typos I mentioned in the patch 5/7.
Also, it is quite late for v3.15. I did already send a pull request to Mauro,
However I have one patch pending. Could you tell me when are you planning to post v2 of these patches? I want to decide whether should I wait for your patchset or should I send the second pull request with the pending patch as soon as possible.
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Re: [PATCH 7/7] v4l: ti-vpe: Add crop support in VPE driver
Hi,
Quoted 38 lines · Kamil Debski
Hi Archit,
Quoted 23 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Monday, March 03, 2014 9:26 AMHi,
Quoted 4 lines · Hans Verkuil
Hi Archit!
Quoted 1 line · Archit Taneja
Add crop ioctl ops. For VPE, cropping only makes sense with the
input
Quoted 4 lines
Quoted 4 lines
to VPE, or the
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANEbuffer type.For the CAPTURE type, a
S_CROPioctl results in setting the crop region as the whole image itself, hence making crop dimensions sameas the pix dimensions.
Quoted 7 lines
Quoted 6 lines
Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Some standard crop parameter checks are done in
__vpe_try_crop().Quoted 8 lines
Quoted 3 lines
Please use the selection ops instead: if you implement cropping with those then you'll support both the selection API and the old cropping API will be implemented by the v4l2 core using the selection ops. Two
for the price of one...
<snip>
Thanks for the feedback. I'll use selection ops here.
From your reply I understand that you will send a v2 of these patches,
right?
If so, please correct the typos I mentioned in the patch 5/7.
Quoted 6 lines
Also, it is quite late for v3.15. I did already send a pull request to Mauro,
However I have one patch pending. Could you tell me when are you planning to post v2 of these patches? I want to decide whether should I wait for your patchset or should I send the second pull request with the pending patch as soon as possible.
I'll post a v2 of this set by tomorrow(India time). I have worked on a patch which converts it to selection ioctls, but I need to test it, and get some comments on whether I have implemented the selection ops correctly.
Thanks,
Archit
Re: [PATCH 7/7] v4l: ti-vpe: Add crop support in VPE driver
In reply to Hans VerkuilHi Hans,
Quoted 13 lines · Hans Verkuil
Hi Archit!
Quoted 10 lines · Archit Taneja
Add crop ioctl ops. For VPE, cropping only makes sense with the input to VPE, or the
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANEbuffer type.For the CAPTURE type, a
S_CROPioctl results in setting the crop region as the whole image itself, hence making crop dimensions same as the pix dimensions.Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.
Quoted 5 lines
Quoted 1 line
Some standard crop parameter checks are done in
__vpe_try_crop().Please use the selection ops instead: if you implement cropping with those then you'll support both the selection API and the old cropping API will be implemented by the v4l2 core using the selection ops. Two for the price of one...
When using selection API, I was finding issues using the older cropping API. The v4l_s_crop() ioctl func assumes that "crop means compose for output devices". However, for a m2m device. It probably makes sense to provide the following configuration:
for V4L2_BUF_TYPE_VIDEO_OUTPUT (input to the mem to mem HW), use CROP target(to crop the input buffer)
and, for V4L2_BUF_TYPE_VIDEO_CAPTURE(output of the mem to mem HW), use COMPOSE target(to place the HW output into a larger region)
Don't you think forcing OUTPUT devices to 'COMPOSE' for older cropping API is a bit limiting?
Thanks,
Archit
Re: [PATCH 7/7] v4l: ti-vpe: Add crop support in VPE driver
Quoted 28 lines · Archit Taneja
Hi Hans,
Quoted 13 lines · Hans Verkuil
Hi Archit!
Quoted 10 lines · Archit Taneja
Add crop ioctl ops. For VPE, cropping only makes sense with the input to VPE, or the
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANEbuffer type.For the CAPTURE type, a
S_CROPioctl results in setting the crop region as the whole image itself, hence making crop dimensions same as the pix dimensions.Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Quoted 5 lines
Quoted 1 line
Some standard crop parameter checks are done in
__vpe_try_crop().Please use the selection ops instead: if you implement cropping with those then you'll support both the selection API and the old cropping API will be implemented by the v4l2 core using the selection ops. Two for the price of one...
When using selection API, I was finding issues using the older cropping API. The
v4l_s_crop()ioctl func assumes that "crop means compose for output devices". However, for a m2m device. It probably makes sense to provide the following configuration:
Quoted 8 lines
for
V4L2_BUF_TYPE_VIDEO_OUTPUT(input to the mem to mem HW), use CROP target(to crop the input buffer)and, for
V4L2_BUF_TYPE_VIDEO_CAPTURE(output of the mem to mem HW), use COMPOSE target(to place the HW output into a larger region)Don't you think forcing OUTPUT devices to 'COMPOSE' for older cropping API is a bit limiting?
Yes, and that's why the selection API was created to work around that limitation :-)
The old cropping API was insufficiently flexible for modern devices, so we came up with this replacement.
Another reason why you have to implement the selection API: it's the only way to implement your functionality.
Regards,
Hans
Re: [PATCH 7/7] v4l: ti-vpe: Add crop support in VPE driver
Hi,
Quoted 38 lines · Hans Verkuil
Quoted 28 lines · Archit Taneja
Hi Hans,
Quoted 13 lines · Hans Verkuil
Hi Archit!
Quoted 10 lines · Archit Taneja
Add crop ioctl ops. For VPE, cropping only makes sense with the input to VPE, or the
V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANEbuffer type.For the CAPTURE type, a
S_CROPioctl results in setting the crop region as the whole image itself, hence making crop dimensions same as the pix dimensions.Setting the crop successfully should result in re-configuration of those registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Quoted 5 lines
Quoted 1 line
Some standard crop parameter checks are done in
__vpe_try_crop().Please use the selection ops instead: if you implement cropping with those then you'll support both the selection API and the old cropping API will be implemented by the v4l2 core using the selection ops. Two for the price of one...
When using selection API, I was finding issues using the older cropping API. The
v4l_s_crop()ioctl func assumes that "crop means compose for output devices". However, for a m2m device. It probably makes sense to provide the following configuration:Quoted 8 lines
for
V4L2_BUF_TYPE_VIDEO_OUTPUT(input to the mem to mem HW), use CROP target(to crop the input buffer)and, for
V4L2_BUF_TYPE_VIDEO_CAPTURE(output of the mem to mem HW), use COMPOSE target(to place the HW output into a larger region)Don't you think forcing OUTPUT devices to 'COMPOSE' for older cropping API is a bit limiting?
Quoted 8 lines
Yes, and that's why the selection API was created to work around that limitation :-)
The old cropping API was insufficiently flexible for modern devices, so we came up with this replacement.
Another reason why you have to implement the selection API: it's the only way to implement your functionality.
Okay, I'll go ahead with the selection API then :)
Archit
v2 cover v4l: ti-vpe: Some VPE fixes and enhancements
In reply to Archit TanejaThis patch set mainly consists of minor fixes for the VPE driver. These fixes ensure the following:
- The VPE module can be inserted and removed successively.
- Make sure that smaller resolutions like qcif work correctly.
- Prevent race condition between firmware loading and an open call to the v4l2 device.
- Prevent the possibility of output m2m queue not having sufficient 'ready' buffers.
- Some VPDMA data descriptor fields weren't understood correctly before. They are now used correctly.
The rest of the patches add some minor features like DMA buf support and cropping/composing.
Reference branch:
[email protected]:boddob/linux.git vpe_for_315
Changes in v2:
- selection API used instead of older cropping API.
- Typo fix.
- Some changes in patch 6/7 to support composing on the capture side of VPE.
Archit Taneja (7):
v4l: ti-vpe: Make sure in job_ready that we have the needed number of
dst_bufs
v4l: ti-vpe: register video device only when firmware is loaded
v4l: ti-vpe: Use video_device_release_empty
v4l: ti-vpe: Allow DMABUF buffer type support
v4l: ti-vpe: Allow usage of smaller images
v4l: ti-vpe: Fix some params in VPE data descriptors
v4l: ti-vpe: Add selection API in VPE driver
drivers/media/platform/ti-vpe/vpdma.c | 68 +++++++--- drivers/media/platform/ti-vpe/vpdma.h | 17 +-- drivers/media/platform/ti-vpe/vpe.c | 228 +++++++++++++++++++++++++++++----- 3 files changed, 255 insertions(+), 58 deletions(-)
Signature · 1 line
1.8.3.2
PATCH v2 1/7 v4l: ti-vpe: Make sure in job_ready that we have the needed number of dst_bufs
VPE has a ctrl parameter which decides how many mem to mem transactions the active job from the job queue can perform.
The driver's job_ready() made sure that the number of ready source buffers are sufficient for the job to execute successfully. But it didn't make sure if there are sufficient ready destination buffers in the capture queue for the VPE output.
If the time taken by VPE to process a single frame is really slow, then it's possible that we don't need to imply such a restriction on the dst queue, but really fast transactions(small resolution, no de-interlacing) may cause us to hit the condition where we don't have any free buffers for the VPE to write on.
Add the extra check in job_ready() to make sure we have the sufficient amount of destination buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +3 -0
@@ -887,6 +887,9 @@ static int job_ready(void *priv)if (v4l2_m2m_num_src_bufs_ready (ctx->m2m_ctx) < needed)return 0 ; +if (v4l2_m2m_num_dst_bufs_ready (ctx->m2m_ctx) < needed) +return 0 ; +return 1 ; }
Signature · 1 line
1.8.3.2
PATCH v2 2/7 v4l: ti-vpe: register video device only when firmware is loaded
In reply to Archit Tanejavpe fops(vpe_open in particular) should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.
Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when it returns.
We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through vpdma_create().
The ready field in vpdma_data is no longer needed since we always have firmware loaded before the device is registered.
A minor problem with this approach is that if the video_register_device fails(which doesn't really happen), the vpe platform device would be registered. however, there won't be any v4l2 device corresponding to it.
--- drivers/media/platform/ti-vpe/vpdma.c | 8 +++-- drivers/media/platform/ti-vpe/vpdma.h | 7 +++-- drivers/media/platform/ti-vpe/vpe.c | 55 ++++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 29 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +5 -3
@@ -781,7 +781,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context)/* already initialized */ if (read_field_reg (vpdma,VPDMA_LIST_ATTR ,VPDMA_LIST_RDY_MASK ,VPDMA_LIST_RDY_SHFT )) { - vpdma->ready = true; + vpdma->cb (vpdma->pdev);return ; }
@@ -811,7 +811,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context) goto free_buf; } - vpdma->ready = true; + vpdma->cb (vpdma->pdev); free_buf:vpdma_unmap_desc_buf (vpdma, &fw_dma_buf);
@@ -839,7 +839,8 @@ static int vpdma_load_firmware(struct vpdma_data *vpdma)return 0 ; } -struct vpdma_data *vpdma_create (struct platform_device *pdev) +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev)) {struct resource *res;struct vpdma_data *vpdma;
@@ -854,6 +855,7 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev) } vpdma->pdev = pdev; + vpdma->cb = cb; res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"vpdma" );if (res ==NULL ) {
drivers/media/platform/ti-vpe/vpdma.h +4 -3
@@ -35,8 +35,8 @@ struct vpdma_data {struct platform_device *pdev; -/* tells whether vpdma firmware is loaded or not */ -bool ready; +/* callback to VPE driver when the firmware is loaded */ +void (*cb)(struct platform_device *pdev); };enum vpdma_data_format_type {
@@ -208,6 +208,7 @@ void vpdma_set_frame_start_event(struct vpdma_data *vpdma,void vpdma_dump_regs (struct vpdma_data *vpdma);/* initialize vpdma, passed with VPE's platform device pointer */ -struct vpdma_data *vpdma_create (struct platform_device *pdev); +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev));#endif
drivers/media/platform/ti-vpe/vpe.c +32 -23
81 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH v2 3/7 v4l: ti-vpe: Use video_device_release_empty
In reply to Archit TanejaThe video_device struct is currently embedded in the driver data struct vpe_dev. A vpe_dev instance is allocated by the driver, and the memory for the vfd is a part of this struct.
The v4l2 core, however, manages the removal of the vfd region, through the video_device's .release() op, which currently is the helper video_device_release. This causes memory corruption, and leads to issues when we try to re-insert the vpe module.
Use the video_device_release_empty helper function instead
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +1 -1
@@ -1998,7 +1998,7 @@ static struct video_device vpe_videodev = { .fops = &vpe_fops, .ioctl_ops = &vpe_ioctl_ops, .minor = -1, - .release = video_device_release, + .release = video_device_release_empty, .vfl_dir = VFL_DIR_M2M, };
Signature · 1 line
1.8.3.2
PATCH v2 4/7 v4l: ti-vpe: Allow DMABUF buffer type support
In reply to Archit TanejaFor OMAP and DRA7x, we generally allocate video and graphics buffers through omapdrm since the corresponding omap-gem driver provides DMM-Tiler backed contiguous buffers. omapdrm is a dma-buf exporter. These buffers are used by other drivers in the video pipeline.
Add VB2_DMABUF flag to the io_modes of the vb2 output and capture queues. This allows the driver to import dma shared buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -1768,7 +1768,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (src_vq,0 ,sizeof (*src_vq)); src_vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ; - src_vq->io_modes =VB2_MMAP ; + src_vq->io_modes =VB2_MMAP |VB2_DMABUF ; src_vq->drv_priv = ctx; src_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); src_vq->ops = &vpe_qops;
@@ -1781,7 +1781,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (dst_vq,0 ,sizeof (*dst_vq)); dst_vq->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ; - dst_vq->io_modes =VB2_MMAP ; + dst_vq->io_modes =VB2_MMAP |VB2_DMABUF ; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); dst_vq->ops = &vpe_qops;
Signature · 1 line
1.8.3.2
PATCH v2 5/7 v4l: ti-vpe: Allow usage of smaller images
In reply to Archit TanejaThe minimum width and height for VPE input/output was kept as 128 pixels. VPE doesn't have a constraint on the image height, it requires the image width to be at least 16 bytes.
Change the minimum supported dimensions to 32x32. This allows us to de-interlace qcif content. A smaller image size than 32x32 didn't make much sense, so stopped at this.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -49,8 +49,8 @@#define VPE_MODULE_NAME "vpe"/* minimum and maximum frame sizes */ -#define MIN_W 128 -#define MIN_H 128 +#define MIN_W 32 +#define MIN_H 32#define MAX_W 1920#define MAX_H 1080
Signature · 1 line
1.8.3.2
PATCH v2 6/7 v4l: ti-vpe: Fix some params in VPE data descriptors
In reply to Archit TanejaSome parameters of the VPE descriptors were understood incorrectly. They are now fixed. The fixes are explained as follows:
- When adding an inbound data descriptor to the VPDMA descriptor list, we intend to use c_rect as the cropped region fetched by VPDMA. Therefore, c_rect->width shouldn't be used to calculate the line stride, the original image width should be used for that. We add a 'width' argument which gives the buffer width in memory.
- frame_width and frame_height describe the complete width and height of the client to which the channel is connected. If there are multiple channels fetching data and providing to the same client, the above 2 arguments should be the width and height of the region covered by all the channels. In the case where there is only one channel providing pixel data to the client (like in VPE), frame_width and frame_height should be the cropped width and cropped height respectively. The calculation of these params is done in the vpe driver now.
- start_h and start_v is also used in the case of multiple channels to describe where each channel should start filling pixel data. We don't use this in VPE, and pass 0s to the vpdma_add_in_dtd() helper.
- Some minor changes are made to the vpdma_add_out_dtd() helper. The c_rect param is used for specifying the 'composition' target, and 'width' is added to calculate the line stride.
--- drivers/media/platform/ti-vpe/vpdma.c | 60 +++++++++++++++++++++++++++-------- drivers/media/platform/ti-vpe/vpdma.h | 10 +++--- drivers/media/platform/ti-vpe/vpe.c | 18 +++++++---- 3 files changed, 64 insertions(+), 24 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +46 -14
@@ -614,8 +614,17 @@ static void dump_dtd(struct vpdma_dtd *dtd)/* * append an outbound data transfer descriptor to the given descriptor list, * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory +* @c_rect: compose params of output image +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* flags: VPDMA flags to configure some descriptor fileds */ -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags) {
@@ -623,6 +632,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,int field =0 ;int notify =1 ;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int depth = fmt->depth;int stride;struct vpdma_dtd *dtd;
@@ -630,11 +640,15 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && - fmt->data_type ==DATA_TYPE_C420 ) + fmt->data_type ==DATA_TYPE_C420 ) { + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; + } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -664,31 +678,48 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,/* * append an inbound data transfer descriptor to the given descriptor list, * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory(not the cropped width) +* @c_rect: crop params of input image +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* field: top or bottom field info of the input image +* flags: VPDMA flags to configure some descriptor fileds +* frame_width/height: the complete width/height of the image presented to the +* client (this makes sense when multiple channels are +* connected to the same client, forming a larger frame) +* start_h, start_v: position where the given channel starts providing pixel +* data to the client (makes sense when multiple channels +* contribute to the client) */ -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags) +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v) {int priority =0 ;int notify =1 ;int depth = fmt->depth;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int stride; -int height = c_rect->height;struct vpdma_dtd *dtd; channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && fmt->data_type ==DATA_TYPE_C420 ) { - height >>=1 ; - frame_height >>=1 ; + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -701,13 +732,14 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, !!(flags &VPDMA_DATA_ODD_LINE_SKIP ), stride); - dtd->xfer_length_height =dtd_xfer_length_height (c_rect->width, height); + dtd->xfer_length_height =dtd_xfer_length_height (rect.width, + rect.height); dtd->start_addr = (u32 ) dma_addr; dtd->pkt_ctl =dtd_pkt_ctl (!!(flags &VPDMA_DATA_MODE_TILED ),DTD_DIR_IN , channel, priority, next_chan); dtd->frame_width_height =dtd_frame_width_height (frame_width, frame_height); - dtd->start_h_v =dtd_start_h_v (c_rect->left, c_rect->top); + dtd->start_h_v =dtd_start_h_v (start_h, start_v); dtd->client_attr0 =0 ; dtd->client_attr1 =0 ;
drivers/media/platform/ti-vpe/vpdma.h +6 -4
@@ -186,13 +186,15 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, struct vpdma_buf *adb);void vpdma_add_sync_on_channel_ctd (struct vpdma_desc_list *list,enum vpdma_channel chan); -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags); -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags); +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v);/* vpdma list interrupt management */ void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
drivers/media/platform/ti-vpe/vpe.c +12 -6
@@ -986,7 +986,6 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->dst_vb; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = !ctx->src_mv_buf_selector;
@@ -1015,8 +1014,8 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_out_dtd (&ctx->desc_list, c_rect, vpdma_fmt, dma_addr, - p_data->channel, flags); +vpdma_add_out_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, flags); }static void add_in_dtd (struct vpe_ctx *ctx,int port)
@@ -1024,11 +1023,11 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = ctx->src_mv_buf_selector;int field = vb->v4l2_buf.field ==V4L2_FIELD_BOTTOM ; +int frame_width, frame_height;dma_addr_t dma_addr;u32 flags =0 ;
@@ -1055,8 +1054,15 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_in_dtd (&ctx->desc_list, q_data->width, q_data->height, - c_rect, vpdma_fmt, dma_addr, p_data->channel, field, flags); + frame_width = q_data->c_rect.width; + frame_height = q_data->c_rect.height; + +if (p_data->vb_part && fmt->fourcc ==V4L2_PIX_FMT_NV12 ) + frame_height /=2 ; + +vpdma_add_in_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, field, flags, frame_width, + frame_height,0 ,0 ); }/*
Signature · 1 line
1.8.3.2
PATCH v2 7/7 v4l: ti-vpe: Add selection API in VPE driver
In reply to Archit TanejaAdd selection ioctl ops. For VPE, cropping makes sense only for the input to VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers) and composing makes sense only for the output of VPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).
For the CAPTURE type, V4L2_SEL_TGT_COMPOSE results in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type, V4L2_SEL_TGT_CROP results in selecting a rectangle region within the source buffer.
Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change, set_srcdst_params() is called for this purpose.
--- drivers/media/platform/ti-vpe/vpe.c | 142 ++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +142 -0
@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :return &ctx->q_data[Q_DATA_DST ];default :BUG ();
@@ -1585,6 +1587,143 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE : +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +/* +* COMPOSE target is only valid for capture buffer type, for +* output buffer type, assign existing crop parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) { +break ; + }else { + s->r = q_data->c_rect; +return 0 ; + } + +case V4L2_SEL_TGT_CROP : +case V4L2_SEL_TGT_CROP_DEFAULT : +case V4L2_SEL_TGT_CROP_BOUNDS : +/* +* CROP target is only valid for output buffer type, for capture +* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) { +break ; + }else { + s->r = q_data->c_rect; +return 0 ; + } +default : +return -EINVAL ; + } + +if (s->r.top <0 || s->r.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + s->r.top = s->r.left =0 ; + } + +v4l_bound_align_image (&s->r.width,MIN_W , q_data->width,1 , + &s->r.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (s->r.left + s->r.width > q_data->width) + s->r.left = q_data->width - s->r.width; +if (s->r.top + s->r.height > q_data->height) + s->r.top = q_data->height - s->r.height; + +return 0 ; +} + +static int vpe_g_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +/* return width and height from S_FMT of the respective buffer type */ +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +case V4L2_SEL_TGT_CROP_BOUNDS : +case V4L2_SEL_TGT_CROP_DEFAULT : + s->r.left =0 ; + s->r.top =0 ; + s->r.width = q_data->width; + s->r.height = q_data->height; +return 0 ; + +/* +* CROP target holds for the output buffer type, and COMPOSE target +* holds for the capture buffer type. We still return the c_rect params +* for both the target types. +*/ +case V4L2_SEL_TGT_COMPOSE : +case V4L2_SEL_TGT_CROP : + s->r.left = q_data->c_rect.left; + s->r.top = q_data->c_rect.top; + s->r.width = q_data->c_rect.width; + s->r.height = q_data->c_rect.height; +return 0 ; + } + +return -EINVAL ; +} + + +static int vpe_s_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +struct v4l2_selection sel = *s; +int ret; + + ret =__vpe_try_selection (ctx, &sel); +if (ret) +return ret; + + q_data =get_q_data (ctx, sel.type); +if (!q_data) +return -EINVAL ; + +if ((q_data->c_rect.left == sel.r.left) && + (q_data->c_rect.top == sel.r.top) && + (q_data->c_rect.width == sel.r.width) && + (q_data->c_rect.height == sel.r.height)) { +vpe_dbg (ctx->dev, +"requested crop/compose values are already set\n" ); +return 0 ; + } + + q_data->c_rect = sel.r; + +return set_srcdst_params (ctx); +} +static int vpe_reqbufs (struct file *file,void *priv,struct v4l2_requestbuffers *reqbufs) {
@@ -1672,6 +1811,9 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, + .vidioc_g_selection = vpe_g_selection, + .vidioc_s_selection = vpe_s_selection, + .vidioc_reqbufs = vpe_reqbufs, .vidioc_querybuf = vpe_querybuf,
Signature · 1 line
1.8.3.2
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Hi Archit,
Quoted 22 lines · Archit Taneja
Add selection ioctl ops. For VPE, cropping makes sense only for the input to
VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers)and composing makes sense only for the output ofVPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).For the CAPTURE type,
V4L2_SEL_TGT_COMPOSEresults in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type,V4L2_SEL_TGT_CROPresults in selecting a rectangle region within the source buffer.Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpe.c | 142 ++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+)drivers/media/platform/ti-vpe/vpe.c +0
-0
drivers/media/platform/ti-vpe/vpe.c static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, · line 416
Quoted 7 lines
drivers/media/platform/ti-vpe/vpe.c +2
-0@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :
I noticed that the querycap implementation is wrong. It reports V4L2_CAP_VIDEO_M2M instead of V4L2_CAP_VIDEO_M2M_MPLANE.
This driver is using the multiplanar formats, so the M2M_MPLANE cap should be set.
This should be a separate patch.
BTW, did you test the driver with the v4l2-compliance tool? The latest version
(http://git.linuxtv.org/v4l-utils.git) has m2m support.
However, if you want to test streaming (the -s option), then you will probably need to base your kernel on this tree:
http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/vb2-part1
That branch contains a pile of fixes for vb2 and without that v4l2-compliance -s will fail a number of tests.
Quoted 21 lines
drivers/media/platform/ti-vpe/vpe.c +14
-0return &ctx->q_data[Q_DATA_DST ];default :BUG ();@@ -1585,6 +1587,143 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE :
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1613
Quoted 10 lines
drivers/media/platform/ti-vpe/vpe.c +10
-0+case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +/* +* COMPOSE target is only valid for capture buffer type, for +* output buffer type, assign existing crop parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) { +break ; + }else {
No need for the 'else' keywork here.
Quoted 5 lines
drivers/media/platform/ti-vpe/vpe.c +5
-0+ s->r = q_data->c_rect; +return 0 ; + } + +case V4L2_SEL_TGT_CROP :
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1628
Quoted 10 lines
drivers/media/platform/ti-vpe/vpe.c +10
-0+case V4L2_SEL_TGT_CROP_DEFAULT : +case V4L2_SEL_TGT_CROP_BOUNDS : +/* +* CROP target is only valid for output buffer type, for capture +* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) { +break ; + }else {
Ditto.
Quoted 103 lines
drivers/media/platform/ti-vpe/vpe.c +98
-0+ s->r = q_data->c_rect; +return 0 ; + } +default : +return -EINVAL ; + } + +if (s->r.top <0 || s->r.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + s->r.top = s->r.left =0 ; + } + +v4l_bound_align_image (&s->r.width,MIN_W , q_data->width,1 , + &s->r.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (s->r.left + s->r.width > q_data->width) + s->r.left = q_data->width - s->r.width; +if (s->r.top + s->r.height > q_data->height) + s->r.top = q_data->height - s->r.height; + +return 0 ; +} + +static int vpe_g_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +/* return width and height from S_FMT of the respective buffer type */ +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +case V4L2_SEL_TGT_CROP_BOUNDS : +case V4L2_SEL_TGT_CROP_DEFAULT : + s->r.left =0 ; + s->r.top =0 ; + s->r.width = q_data->width; + s->r.height = q_data->height; +return 0 ; + +/* +* CROP target holds for the output buffer type, and COMPOSE target +* holds for the capture buffer type. We still return the c_rect params +* for both the target types. +*/ +case V4L2_SEL_TGT_COMPOSE : +case V4L2_SEL_TGT_CROP : + s->r.left = q_data->c_rect.left; + s->r.top = q_data->c_rect.top; + s->r.width = q_data->c_rect.width; + s->r.height = q_data->c_rect.height; +return 0 ; + } + +return -EINVAL ; +} + + +static int vpe_s_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +struct v4l2_selection sel = *s; +int ret; + + ret =__vpe_try_selection (ctx, &sel); +if (ret) +return ret; + + q_data =get_q_data (ctx, sel.type); +if (!q_data) +return -EINVAL ; + +if ((q_data->c_rect.left == sel.r.left) && + (q_data->c_rect.top == sel.r.top) && + (q_data->c_rect.width == sel.r.width) && + (q_data->c_rect.height == sel.r.height)) { +vpe_dbg (ctx->dev, +"requested crop/compose values are already set\n" ); +return 0 ; + } + + q_data->c_rect = sel.r; + +return set_srcdst_params (ctx); +} +static int vpe_reqbufs (struct file *file,void *priv,struct v4l2_requestbuffers *reqbufs) {
drivers/media/platform/ti-vpe/vpe.c static const struct v4l2_ioctl_ops vpe_ioctl_ops = { · line 1819
Quoted 9 lines
drivers/media/platform/ti-vpe/vpe.c +3
-0@@ -1672,6 +1811,9 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, + .vidioc_g_selection = vpe_g_selection, + .vidioc_s_selection = vpe_s_selection, + .vidioc_reqbufs = vpe_reqbufs, .vidioc_querybuf = vpe_querybuf,
Regards,
Hans
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Hi,
Quoted 36 lines · Hans Verkuil
Hi Archit,
Quoted 22 lines · Archit Taneja
Add selection ioctl ops. For VPE, cropping makes sense only for the input to
VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers)and composing makes sense only for the output ofVPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).For the CAPTURE type,
V4L2_SEL_TGT_COMPOSEresults in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type,V4L2_SEL_TGT_CROPresults in selecting a rectangle region within the source buffer.Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpe.c | 142 ++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+)drivers/media/platform/ti-vpe/vpe.c +0
-0drivers/media/platform/ti-vpe/vpe.c static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, · line 416
Quoted 7 lines
drivers/media/platform/ti-vpe/vpe.c +2
-0@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :I noticed that the querycap implementation is wrong. It reports
V4L2_CAP_VIDEO_M2Minstead ofV4L2_CAP_VIDEO_M2M_MPLANE.
Quoted 4 lines
This driver is using the multiplanar formats, so the
M2M_MPLANEcap should be set.This should be a separate patch.
Thanks for pointing this out, I'll make a patch for that.
Quoted 4 lines
BTW, did you test the driver with the v4l2-compliance tool? The latest version
(http://git.linuxtv.org/v4l-utils.git) has m2m support.
I haven't tested it with this yet.
Quoted 4 lines
However, if you want to test streaming (the -s option), then you will probably need to base your kernel on this tree:
http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/vb2-part1
I can give it a try. It'll probably take a bit more time to try this out. I'll need to port some minor DRA7x stuff.
Kamil,
Do you think you have some more time for the m2m pull request?
Quoted 47 lines
That branch contains a pile of fixes for vb2 and without that v4l2-compliance -s will fail a number of tests.
Quoted 21 lines
drivers/media/platform/ti-vpe/vpe.c +14
-0return &ctx->q_data[Q_DATA_DST ];default :BUG ();@@ -1585,6 +1587,143 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE :drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1613
Quoted 10 lines
drivers/media/platform/ti-vpe/vpe.c +10
-0+case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +/* +* COMPOSE target is only valid for capture buffer type, for +* output buffer type, assign existing crop parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) { +break ; + }else {No need for the 'else' keywork here.
Quoted 9 lines
drivers/media/platform/ti-vpe/vpe.c +9
-0+ s->r = q_data->c_rect; +return 0 ; + } + +case V4L2_SEL_TGT_CROP : +case V4L2_SEL_TGT_CROP_DEFAULT : +case V4L2_SEL_TGT_CROP_BOUNDS : +/* +* CROP target is only valid for output buffer type, for capture
Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1628
Quoted 6 lines
drivers/media/platform/ti-vpe/vpe.c +6
-0+* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) { +break ; + }else {Ditto.
Thanks. I'll fix these.
I had a minor question about the selection API:
Are the V4L2_SET_TGT_CROP/COMPOSE_DEFAULT and the corresponding 'BOUNDS' targets supposed to be used with VIDIOC_S_SELECTION? If so, what's the expect behaviour?
Thanks,
Archit
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Quoted 5 lines · Archit Taneja
I had a minor question about the selection API:
Are the V4L2_SET_TGT_CROP/COMPOSE_DEFAULT and the corresponding 'BOUNDS' targets supposed to be used with
VIDIOC_S_SELECTION? If so, what's the expect behaviour?
No, those are read only in practice. So only used with G_SELECTION, never with S_SELECTION.
Regards,
Hans
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Hi Hans,
Quoted 9 lines · Hans Verkuil
Quoted 5 lines · Archit Taneja
I had a minor question about the selection API:
Are the V4L2_SET_TGT_CROP/COMPOSE_DEFAULT and the corresponding 'BOUNDS' targets supposed to be used with
VIDIOC_S_SELECTION? If so, what's the expect behaviour?No, those are read only in practice. So only used with
G_SELECTION, never withS_SELECTION.
<snip>
I tried the v4l2-compliance thing. It's awesome! And a bit annoying too when it comes to fixing little things needed for compliance :). But it's required, and I hope to fix these eventually.
After a few small fixes in the driver, I get the results as below. I am debugging the cause of try_fmt and s_fmt failures. I'm not sure why the streaming test fails with MMAP, the logs of my driver show that a successful mem2mem transaction happened.
I tried this on the 'vb2-part1' branch as you suggested.
Do you think I can go ahead with posting the v3 patch set for 3.15, and work on fixing the compliance issue for the -rc fixes?
Thanks,
Archit
# ./utils/v4l2-compliance/v4l2-compliance -v --streaming=10
root@localhost:~/source_trees/v4l-utils# Driver Info:
Driver name : vpe
Card type : vpe
Bus info : platform:vpe
Driver version: 3.14.0
Capabilities : 0x84004000
Video Memory-to-Memory Multiplanar
Streaming
Device Capabilities
Device Caps : 0x04004000
Video Memory-to-Memory Multiplanar
StreamingCompliance test for device /dev/video0 (not using libv4l2):
Required ioctls:
test VIDIOC_QUERYCAP: OK
Allow for multiple opens:
test second video open: OK
test VIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OK
Debug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported) test VIDIOC_LOG_STATUS: OK (Not Supported)
Input ioctls:
test VIDIOC_G/S_TUNER: OK (Not Supported) test VIDIOC_G/S_FREQUENCY: OK (Not Supported) test VIDIOC_S_HW_FREQ_SEEK: OK (Not Supported) test VIDIOC_ENUMAUDIO: OK (Not Supported) test VIDIOC_G/S/ENUMINPUT: OK (Not Supported) test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0
Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported) test VIDIOC_G/S_FREQUENCY: OK (Not Supported) test VIDIOC_ENUMAUDOUT: OK (Not Supported) test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported) test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0
Control ioctls:
info: checking v4l2_queryctrl of control 'User
Controls' (0x00980001)
info: checking v4l2_queryctrl of control 'Buffers Per
Transaction' (0x00981950)
info: checking v4l2_queryctrl of control 'Buffers Per
Transaction' (0x08000000)
test VIDIOC_QUERYCTRL/MENU: OK
info: checking control 'User Controls' (0x00980001)
info: checking control 'Buffers Per Transaction'
(0x00981950)
test VIDIOC_G/S_CTRL: OK
info: checking extended control 'User Controls'
(0x00980001)
info: checking extended control 'Buffers Per
Transaction' (0x00981950)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
info: checking control event 'User Controls' (0x00980001)
info: checking control event 'Buffers Per Transaction'
(0x00981950)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 1 Private Controls: 1
Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported) test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported) test VIDIOC_DV_TIMINGS_CAP: OK (Not Supported)
Format ioctls:
info: found 8 formats for buftype 9
info: found 4 formats for buftype 10
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK test VIDIOC_G/S_PARM: OK (Not Supported)
test VIDIOC_G_FBUF: OK (Not Supported)
test VIDIOC_G_FMT: OK
fail: v4l2-test-formats.cpp(614): Video Capture
Multiplanar: TRY_FMT(G_FMT) != G_FMT
test VIDIOC_TRY_FMT: FAIL
warn: v4l2-test-formats.cpp(834): S_FMT cannot handle
an invalid pixelformat.
warn: v4l2-test-formats.cpp(835): This may or may not
be a problem. For more information see:
warn: v4l2-test-formats.cpp(836): http://www.mail-archive.com/[email protected]/msg56550.html fail: v4l2-test-formats.cpp(420): pix_mp.reserved not zeroed fail: v4l2-test-formats.cpp(851): Video Capture
Multiplanar is valid, but no S_FMT was implemented
test VIDIOC_S_FMT: FAIL
test VIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)
Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported) test VIDIOC_G_ENC_INDEX: OK (Not Supported) test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Buffer ioctls:
info: test buftype Video Capture Multiplanar
warn: v4l2-test-buffers.cpp(403): VIDIOC_CREATE_BUFS
not supported
info: test buftype Video Output Multiplanar
warn: v4l2-test-buffers.cpp(403): VIDIOC_CREATE_BUFS
not supported
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
test VIDIOC_EXPBUF: OK (Not Supported)
test read/write: OK (Not Supported)
Video Capture Multiplanar (polling):
Buffer: 0 Sequence: 0 Field: Top Timestamp: 113.178208s
fail: v4l2-test-buffers.cpp(222): buf.field !=
cur_fmt.fmt.pix.field
fail: v4l2-test-buffers.cpp(630): checkQueryBuf(node,
buf, bufs.type, bufs.memory, buf.index, Dequeued, last_seq)
fail: v4l2-test-buffers.cpp(1038): captureBufs(node, bufs, m2m_bufs, frame_count, true)
test MMAP: FAIL
test USERPTR: OK (Not Supported)
test DMABUF: Cannot test, specify --expbuf-device
Total: 40, Succeeded: 37, Failed: 3, Warnings: 5
[1]+ Exit 1 ./utils/v4l2-compliance/v4l2-compliance -v --streaming=10
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Quoted 24 lines · Archit Taneja
Hi Hans,
Quoted 9 lines · Hans Verkuil
Quoted 5 lines · Archit Taneja
I had a minor question about the selection API:
Are the V4L2_SET_TGT_CROP/COMPOSE_DEFAULT and the corresponding 'BOUNDS' targets supposed to be used with
VIDIOC_S_SELECTION? If so, what's the expect behaviour?No, those are read only in practice. So only used with
G_SELECTION, never withS_SELECTION.<snip>
I tried the v4l2-compliance thing. It's awesome! And a bit annoying too when it comes to fixing little things needed for compliance :). But it's required, and I hope to fix these eventually.
After a few small fixes in the driver, I get the results as below. I am debugging the cause of
try_fmtands_fmtfailures. I'm not sure why the streaming test fails with MMAP, the logs of my driver show that a successful mem2mem transaction happened.
Quoted 4 lines
I tried this on the 'vb2-part1' branch as you suggested.
Do you think I can go ahead with posting the v3 patch set for 3.15, and work on fixing the compliance issue for the -rc fixes?
It's fine to upstream this in staging, but while not all compliance errors are fixed it can't go to drivers/media. I'm tightening the screws on that since v4l2-compliance is getting to be such a powerful tool for ensuring the driver complies.
Quoted 92 lines
Thanks,
Archit# ./utils/v4l2-compliance/v4l2-compliance -v --streaming=10 root@localhost:~/source_trees/v4l-utils# Driver Info: Driver name : vpe Card type : vpe Bus info : platform:vpe Driver version: 3.14.0 Capabilities : 0x84004000 Video Memory-to-Memory Multiplanar Streaming Device Capabilities Device Caps : 0x04004000 Video Memory-to-Memory Multiplanar StreamingCompliance test for device
/dev/video0(not using libv4l2):Required ioctls:
testVIDIOC_QUERYCAP: OKAllow for multiple opens:
test second video open: OK
testVIDIOC_QUERYCAP: OK
test VIDIOC_G/S_PRIORITY: OKDebug ioctls:
test VIDIOC_DBG_G/S_REGISTER: OK (Not Supported) testVIDIOC_LOG_STATUS: OK (Not Supported)Input ioctls:
test VIDIOC_G/S_TUNER: OK (Not Supported) test VIDIOC_G/S_FREQUENCY: OK (Not Supported) testVIDIOC_S_HW_FREQ_SEEK: OK (Not Supported) testVIDIOC_ENUMAUDIO: OK (Not Supported) test VIDIOC_G/S/ENUMINPUT: OK (Not Supported) test VIDIOC_G/S_AUDIO: OK (Not Supported)
Inputs: 0 Audio Inputs: 0 Tuners: 0Output ioctls:
test VIDIOC_G/S_MODULATOR: OK (Not Supported) test VIDIOC_G/S_FREQUENCY: OK (Not Supported) testVIDIOC_ENUMAUDOUT: OK (Not Supported) test VIDIOC_G/S/ENUMOUTPUT: OK (Not Supported) test VIDIOC_G/S_AUDOUT: OK (Not Supported)
Outputs: 0 Audio Outputs: 0 Modulators: 0Control ioctls:
info: checkingv4l2_queryctrlof control 'User
Controls' (0x00980001)
info: checkingv4l2_queryctrlof control 'Buffers Per
Transaction' (0x00981950)
info: checkingv4l2_queryctrlof control 'Buffers Per
Transaction' (0x08000000)
test VIDIOC_QUERYCTRL/MENU: OK
info: checking control 'User Controls' (0x00980001)
info: checking control 'Buffers Per Transaction'
(0x00981950)
test VIDIOC_G/S_CTRL: OK
info: checking extended control 'User Controls'
(0x00980001)
info: checking extended control 'Buffers Per
Transaction' (0x00981950)
test VIDIOC_G/S/TRY_EXT_CTRLS: OK
info: checking control event 'User Controls' (0x00980001)
info: checking control event 'Buffers Per Transaction'
(0x00981950)
test VIDIOC_(UN)SUBSCRIBE_EVENT/DQEVENT: OK
test VIDIOC_G/S_JPEGCOMP: OK (Not Supported)
Standard Controls: 1 Private Controls: 1Input/Output configuration ioctls:
test VIDIOC_ENUM/G/S/QUERY_STD: OK (Not Supported) test VIDIOC_ENUM/G/S/QUERY_DV_TIMINGS: OK (Not Supported) testVIDIOC_DV_TIMINGS_CAP: OK (Not Supported)Format ioctls:
info: found 8 formats for buftype 9
info: found 4 formats for buftype 10
test VIDIOC_ENUM_FMT/FRAMESIZES/FRAMEINTERVALS: OK test VIDIOC_G/S_PARM: OK (Not Supported)
testVIDIOC_G_FBUF: OK (Not Supported)
testVIDIOC_G_FMT: OK
fail: v4l2-test-formats.cpp(614): Video Capture
Multiplanar:TRY_FMT(G_FMT)!=G_FMT
testVIDIOC_TRY_FMT: FAIL
warn: v4l2-test-formats.cpp(834):S_FMTcannot handle
an invalid pixelformat.
warn: v4l2-test-formats.cpp(835): This may or may not
be a problem. For more information see:
Quoted 4 lines
warn: v4l2-test-formats.cpp(836): http://www.mail-archive.com/[email protected]/msg56550.html fail: v4l2-test-formats.cpp(420): pix_mp.reserved notzeroed
This is easy enough to fix.
Quoted 2 lines
fail: v4l2-test-formats.cpp(851): Video CaptureMultiplanar is valid, but no
S_FMTwas implemented
For the FMT things: run with -T: that gives nice traces. You can also set the debug flag: echo 2 >/sys/class/video4linux/video0/debug to see all ioctls in more detail.
Quoted 8 lines
test
VIDIOC_S_FMT: FAIL
testVIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported) testVIDIOC_G_ENC_INDEX: OK (Not Supported) test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)
Quoted 14 lines
Buffer ioctls:
info: test buftype Video Capture Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
info: test buftype Video Output Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
testVIDIOC_EXPBUF: OK (Not Supported)
test read/write: OK (Not Supported)
Video Capture Multiplanar (polling):
Buffer: 0 Sequence: 0 Field: Top Timestamp: 113.178208s
fail: v4l2-test-buffers.cpp(222): buf.field !=
cur_fmt.fmt.pix.field
Definitely needs to be fixed, you probably just don't set the field at all.
Quoted 8 lines
fail: v4l2-test-buffers.cpp(630): checkQueryBuf(node, buf, bufs.type, bufs.memory, buf.index, Dequeued, last_seq) fail: v4l2-test-buffers.cpp(1038): captureBufs(node,bufs,
m2m_bufs,frame_count, true)
test MMAP: FAIL
test USERPTR: OK (Not Supported)
test DMABUF: Cannot test, specify --expbuf-device
Quoted 4 lines
Total: 40, Succeeded: 37, Failed: 3, Warnings: 5
[1]+ Exit 1 ./utils/v4l2-compliance/v4l2-compliance -v
--streaming=10
Regards,
Hans
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Hi,
Quoted 9 lines · Hans Verkuil
Quoted 3 lines
Do you think I can go ahead with posting the v3 patch set for 3.15, and work on fixing the compliance issue for the -rc fixes?
It's fine to upstream this in staging, but while not all compliance errors are fixed it can't go to
drivers/media. I'm tightening the screws on that since v4l2-compliance is getting to be such a powerful tool for ensuring the driver complies.
But the vpe driver is already in drivers/media. How do I push these patches if the vpe drivers is not in staging?
<snip>
Quoted 11 lines
Quoted 10 lines
Multiplanar:
TRY_FMT(G_FMT)!=G_FMT
testVIDIOC_TRY_FMT: FAIL
warn: v4l2-test-formats.cpp(834):S_FMTcannot handle
an invalid pixelformat.
warn: v4l2-test-formats.cpp(835): This may or may not
be a problem. For more information see:warn: v4l2-test-formats.cpp(836): http://www.mail-archive.com/[email protected]/msg56550.html fail: v4l2-test-formats.cpp(420): pix_mp.reserved notzeroed
Quoted 8 lines
This is easy enough to fix.
Quoted 2 lines
fail: v4l2-test-formats.cpp(851): Video CaptureMultiplanar is valid, but no
S_FMTwas implementedFor the FMT things: run with -T: that gives nice traces. You can also set the debug flag: echo 2 >/sys/class/video4linux/video0/debug to see all ioctls in more detail.
Thanks for the tip, will try this.
Quoted 24 lines
Quoted 9 lines
test
VIDIOC_S_FMT: FAIL
testVIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported) testVIDIOC_G_ENC_INDEX: OK (Not Supported) test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)Quoted 14 lines
Buffer ioctls:
info: test buftype Video Capture Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
info: test buftype Video Output Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
testVIDIOC_EXPBUF: OK (Not Supported)
test read/write: OK (Not Supported)
Video Capture Multiplanar (polling):
Buffer: 0 Sequence: 0 Field: Top Timestamp: 113.178208s
fail: v4l2-test-buffers.cpp(222): buf.field !=
cur_fmt.fmt.pix.field
Quoted 1 line
Definitely needs to be fixed, you probably just don't set the field at all.
The VPE output is always progressive. But yes, I should still set the field parameter to something.
Thanks,
Archit
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Quoted 7 lines · Archit Taneja
Hi,
Quoted 4 lines · Hans Verkuil
Quoted 3 lines
Do you think I can go ahead with posting the v3 patch set for 3.15, and work on fixing the compliance issue for the -rc fixes?
Quoted 8 lines
Quoted 5 lines
It's fine to upstream this in staging, but while not all compliance errors are fixed it can't go to
drivers/media. I'm tightening the screws on that since v4l2-compliance is getting to be such a powerful tool for ensuring the driver complies.But the vpe driver is already in
drivers/media. How do I push these patches if the vpe drivers is not in staging?
Oops, sorry. I got confused with Benoit's AM437x ti-vpfe patch :-)
Disregard what I said, it's OK to upstream it. But if you could just spend some hours fixing the problems, that would really be best.
Quoted 49 lines
<snip>
Quoted 11 lines
Quoted 10 lines
Multiplanar:
TRY_FMT(G_FMT)!=G_FMT
testVIDIOC_TRY_FMT: FAIL
warn: v4l2-test-formats.cpp(834):S_FMTcannot handle
an invalid pixelformat.
warn: v4l2-test-formats.cpp(835): This may or may not
be a problem. For more information see:warn: v4l2-test-formats.cpp(836): http://www.mail-archive.com/[email protected]/msg56550.html fail: v4l2-test-formats.cpp(420): pix_mp.reserved notzeroed
Quoted 8 lines
This is easy enough to fix.
Quoted 2 lines
fail: v4l2-test-formats.cpp(851): Video CaptureMultiplanar is valid, but no
S_FMTwas implementedFor the FMT things: run with -T: that gives nice traces. You can also set the debug flag: echo 2 >/sys/class/video4linux/video0/debug to see all ioctls in more detail.
Thanks for the tip, will try this.
Quoted 24 lines
Quoted 23 lines
test
VIDIOC_S_FMT: FAIL
testVIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported) testVIDIOC_G_ENC_INDEX: OK (Not Supported) test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)Buffer ioctls:
info: test buftype Video Capture Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
info: test buftype Video Output Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
testVIDIOC_EXPBUF: OK (Not Supported)
test read/write: OK (Not Supported)
Video Capture Multiplanar (polling):
Buffer: 0 Sequence: 0 Field: Top Timestamp: 113.178208s
fail: v4l2-test-buffers.cpp(222): buf.field !=
cur_fmt.fmt.pix.field
Quoted 4 lines
Quoted 1 line
Definitely needs to be fixed, you probably just don't set the field at all.
The VPE output is always progressive. But yes, I should still set the field parameter to something.
V4L2_FIELD_NONE is the correct field setting for that.
Regards,
Hans
Quoted 9 lines
Thanks,
Archit--
To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Quoted 14 lines · Hans Verkuil
Quoted 13 lines · Archit Taneja
Hi,
Quoted 9 lines · Hans Verkuil
Quoted 3 lines
Do you think I can go ahead with posting the v3 patch set for 3.15, and work on fixing the compliance issue for the -rc fixes?
It's fine to upstream this in staging, but while not all compliance errors are fixed it can't go to
drivers/media. I'm tightening the screws on that since v4l2-compliance is getting to be such a powerful tool for ensuring the driver complies.
Quoted 7 lines
Quoted 2 lines
But the vpe driver is already in
drivers/media. How do I push these patches if the vpe drivers is not in staging?Oops, sorry. I got confused with Benoit's AM437x ti-vpfe patch :-)
Disregard what I said, it's OK to upstream it. But if you could just spend some hours fixing the problems, that would really be best.
Sure, I'll try to fix these issues and then post a v3.
Quoted 50 lines
Quoted 50 lines
<snip>
Quoted 11 lines
Quoted 10 lines
Multiplanar:
TRY_FMT(G_FMT)!=G_FMT
testVIDIOC_TRY_FMT: FAIL
warn: v4l2-test-formats.cpp(834):S_FMTcannot handle
an invalid pixelformat.
warn: v4l2-test-formats.cpp(835): This may or may not
be a problem. For more information see:warn: v4l2-test-formats.cpp(836): http://www.mail-archive.com/[email protected]/msg56550.html fail: v4l2-test-formats.cpp(420): pix_mp.reserved notzeroed
Quoted 8 lines
This is easy enough to fix.
Quoted 2 lines
fail: v4l2-test-formats.cpp(851): Video CaptureMultiplanar is valid, but no
S_FMTwas implementedFor the FMT things: run with -T: that gives nice traces. You can also set the debug flag: echo 2 >/sys/class/video4linux/video0/debug to see all ioctls in more detail.
Thanks for the tip, will try this.
Quoted 24 lines
Quoted 23 lines
test
VIDIOC_S_FMT: FAIL
testVIDIOC_G_SLICED_VBI_CAP: OK (Not Supported)Codec ioctls:
test VIDIOC_(TRY_)ENCODER_CMD: OK (Not Supported) testVIDIOC_G_ENC_INDEX: OK (Not Supported) test VIDIOC_(TRY_)DECODER_CMD: OK (Not Supported)Buffer ioctls:
info: test buftype Video Capture Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
info: test buftype Video Output Multiplanar
warn: v4l2-test-buffers.cpp(403):VIDIOC_CREATE_BUFS
not supported
test VIDIOC_REQBUFS/CREATE_BUFS/QUERYBUF: OK
testVIDIOC_EXPBUF: OK (Not Supported)
test read/write: OK (Not Supported)
Video Capture Multiplanar (polling):
Buffer: 0 Sequence: 0 Field: Top Timestamp: 113.178208s
fail: v4l2-test-buffers.cpp(222): buf.field !=
cur_fmt.fmt.pix.field
Quoted 6 lines
Quoted 4 lines
Quoted 1 line
Definitely needs to be fixed, you probably just don't set the field at all.
The VPE output is always progressive. But yes, I should still set the field parameter to something.
V4L2_FIELD_NONEis the correct field setting for that.
I checked the driver, it isn't setting it to V4L2_FIELD_NONE. Will fix this.
Archit
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Hi Hans,
Quoted 9 lines · Archit Taneja
Quoted 6 lines · Hans Verkuil
On 03/07/2014 02:22 PM, Archit Taneja wrote:
Disregard what I said, it's OK to upstream it. But if you could just spend
some hours fixing the problems, that would really be best.Sure, I'll try to fix these issues and then post a v3.
I fixed most of the compliance errors. There were some things I needed to change in .utils/v4l2-compliance/v4l2-test-buffers.cpp'. I added those with some questions in the comments:
utils/v4l2-compliance/v4l2-test-buffers.cpp +18 -4
@@ -219,7 +219,13 @@ static int checkQueryBuf(struct node *node, const struct v4l2_buffer &buf, fail_on_test(!(buf.flags & (V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR))); if (node->is_video) { fail_on_test(buf.field == V4L2_FIELD_ALTERNATE); - fail_on_test(buf.field == V4L2_FIELD_ANY); + /* + * the OUTPUT buffers are queued with V4L2_FIELD_ANY + * field type by the application. Is it the driver's + * job to change this to NONE in buf_prepare? + */ + + /* fail_on_test(buf.field == V4L2_FIELD_ANY); */ if (cur_fmt.fmt.pix.field == V4L2_FIELD_ALTERNATE) { fail_on_test(buf.field != V4L2_FIELD_BOTTOM && buf.field != V4L2_FIELD_TOP);
@@ -651,9 +657,17 @@ static int captureBufs(struct node *node, const struct v4l2_requestbuffers &bufs } else if (node->is_m2m && timestamp == V4L2_BUF_FLAG_TIMESTAMP_COPY) { fail_on_test(buffer_info.find(buf.timestamp) == buffer_info.end()); struct v4l2_buffer &orig_buf = buffer_info[buf.timestamp]; - fail_on_test(buf.field != orig_buf.field); - fail_on_test((buf.flags & valid_output_flags) != - (orig_buf.flags & valid_output_flags)); + /* same issue as as in checkQueryBuf */ + /* fail_on_test(buf.field != orig_buf.field); */ + + /* + * the queued buffers are filled with flags like + * V4L2_BUF_FLAG_KEYFRAME, these are lost when + * the captured buffers are dequed. How do we + * fix this? + */ + /*fail_on_test((buf.flags & valid_output_flags) != + (orig_buf.flags & valid_output_flags)); */ if (buf.flags & V4L2_BUF_FLAG_TIMECODE) fail_on_test(memcmp(&buf.timecode, &orig_buf.timecode, sizeof(buf.timecode)));
Thanks,
Archit
Re: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
Quoted 23 lines · Archit Taneja
Hi Hans,
Quoted 9 lines · Archit Taneja
Quoted 6 lines · Hans Verkuil
On 03/07/2014 02:22 PM, Archit Taneja wrote:
Disregard what I said, it's OK to upstream it. But if you could just spend
some hours fixing the problems, that would really be best.Sure, I'll try to fix these issues and then post a v3.
I fixed most of the compliance errors. There were some things I needed to change in .utils/v4l2-compliance/v4l2-test-buffers.cpp'. I added those with some questions in the comments:
utils/v4l2-compliance/v4l2-test-buffers.cpp +0
-0
utils/v4l2-compliance/v4l2-test-buffers.cpp static int checkQueryBuf(struct node *node, const · line 226
Quoted 9 lines
utils/v4l2-compliance/v4l2-test-buffers.cpp +4
-1@@ -219,7 +219,13 @@ static int checkQueryBuf(struct node *node, const struct v4l2_buffer &buf, fail_on_test(!(buf.flags & (V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR))); if (node->is_video) { fail_on_test(buf.field == V4L2_FIELD_ALTERNATE); - fail_on_test(buf.field == V4L2_FIELD_ANY); + /* + * the OUTPUT buffers are queued with V4L2_FIELD_ANY + * field type by the application. Is it the driver's + * job to change this to NONE in buf_prepare?
Yes, it is. Applications may pass in FIELD_ANY, but the driver must never return it, it should always be replaced by what the driver actually uses.
Quoted 12 lines
utils/v4l2-compliance/v4l2-test-buffers.cpp +3
-0+ */ + + /* fail_on_test(buf.field == V4L2_FIELD_ANY); */ if (cur_fmt.fmt.pix.field == V4L2_FIELD_ALTERNATE) { fail_on_test(buf.field != V4L2_FIELD_BOTTOM &&buf.field != V4L2_FIELD_TOP);utils/v4l2-compliance/v4l2-test-buffers.cpp +0
-0@@ -651,9 +657,17 @@ static int captureBufs(struct node *node, conststruct
v4l2_requestbuffers&bufs
} else if (node->is_m2m&& timestamp ==V4L2_BUF_FLAG_TIMESTAMP_COPY) {
fail_on_test(buffer_info.find(buf.timestamp) == buffer_info.end()); structv4l2_buffer&orig_buf= buffer_info[buf.timestamp];utils/v4l2-compliance/v4l2-test-buffers.cpp +0
-1- fail_on_test(buf.field != orig_buf.field);
utils/v4l2-compliance/v4l2-test-buffers.cpp static int captureBufs(struct node *node, const struct v4l2_requestbuffers &bufs · line 667
Quoted 10 lines
utils/v4l2-compliance/v4l2-test-buffers.cpp +8
-2- fail_on_test((buf.flags & valid_output_flags) != - (orig_buf.flags & valid_output_flags)); + /* same issue as as in checkQueryBuf */ + /* fail_on_test(buf.field != orig_buf.field); */ + + /* + * the queued buffers are filled with flags like + * V4L2_BUF_FLAG_KEYFRAME, these are lost when + * the captured buffers are dequed. How do we + * fix this?
Well, the driver has to copy them :-)
Note that v4l2-compliance assumes that there is a 1 to 1 mapping between buffers coming into the codec and buffers coming out of the codec. If that's not the case, then copying such flags does not make any sense. On the other hand, in that case using V4L2_BUF_FLAG_TIMESTAMP_COPY probably makes no sense either.
Regards,
Hans
Quoted 11 lines
utils/v4l2-compliance/v4l2-test-buffers.cpp +3
-0+ */ + /*fail_on_test((buf.flags & valid_output_flags) != + (orig_buf.flags & valid_output_flags)); */ if (buf.flags & V4L2_BUF_FLAG_TIMECODE) fail_on_test(memcmp(&buf.timecode, &orig_buf.timecode, sizeof(buf.timecode)));Thanks,
Archit
RE: [PATCH v2 7/7] v4l: ti-vpe: Add selection API in VPE driver
In reply to Archit TanejaHi Archit,
Quoted 71 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Tuesday, March 04, 2014 12:25 PMHi,
Quoted 6 lines · Hans Verkuil
Hi Archit,
Quoted 3 lines · Archit Taneja
Add selection ioctl ops. For VPE, cropping makes sense only for the input to
VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers)and composing makes sense only for the output of VPE(orV4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).
Quoted 2 lines
Quoted 2 lines
For the CAPTURE type,
V4L2_SEL_TGT_COMPOSEresults in VPE writingthe
Quoted 1 line
Quoted 1 line
output in a rectangle within the capture buffer. For the OUTPUT
type,
Quoted 1 line
Quoted 1 line
V4L2_SEL_TGT_CROPresults in selecting a rectangle region within thesource buffer.
Quoted 4 lines
Quoted 4 lines
Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called forthis purpose.
Quoted 4 lines
Quoted 4 lines
Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpe.c | 142++++++++++++++++++++++++++++++++++++
Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static struct vpe_q_data *get_q_data(struct
Quoted 8 lines
1 file changed, 142 insertions(+)drivers/media/platform/ti-vpe/vpe.c +0
-0@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct
vpe_ctx*ctx,Quoted 11 lines
drivers/media/platform/ti-vpe/vpe.c static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, · line 416
Quoted 7 lines
drivers/media/platform/ti-vpe/vpe.c +2
-0{switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :I noticed that the querycap implementation is wrong. It reports
V4L2_CAP_VIDEO_M2Minstead ofV4L2_CAP_VIDEO_M2M_MPLANE.Quoted 4 lines
This driver is using the multiplanar formats, so the
M2M_MPLANEcap should be set.This should be a separate patch.
Thanks for pointing this out, I'll make a patch for that.
Quoted 2 lines
BTW, did you test the driver with the v4l2-compliance tool? The
latest
Quoted 3 lines
version
(http://git.linuxtv.org/v4l-utils.git) has m2m support.I haven't tested it with this yet.
Quoted 4 lines
However, if you want to test streaming (the -s option), then you will probably need to base your kernel on this tree:
http://git.linuxtv.org/hverkuil/media_tree.git/shortlog/refs/heads/vb2
Quoted 8 lines
Quoted 1 line
-part1
I can give it a try. It'll probably take a bit more time to try this out. I'll need to port some minor DRA7x stuff.
Kamil,
Do you think you have some more time for the m2m pull request?
Yes, I would like to send the final pull request at the beginning of the coming week.
Quoted 65 lines
Quoted 8 lines
That branch contains a pile of fixes for vb2 and without that v4l2-compliance -s will fail a number of tests.
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void
Quoted 4 lines
drivers/media/platform/ti-vpe/vpe.c +0
-0return &ctx->q_data[Q_DATA_DST ];default :BUG ();@@ -1585,6 +1587,143 @@ static int vpe_s_fmt(struct file *file, void*priv, struct
v4l2_format*f)Quoted 13 lines
Quoted 13 lines
drivers/media/platform/ti-vpe/vpe.c +10
-0return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct +v4l2_selection *s) { +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data)Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c +8
-0+return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE : +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +/* +* COMPOSE target is only valid for capture buffer type, for
Quoted 1 line
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void · line 1608
Quoted 1 line
drivers/media/platform/ti-vpe/vpe.c +1
-0+* output buffer type, assign existing crop parameters to the
Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1613
Quoted 5 lines
drivers/media/platform/ti-vpe/vpe.c +5
-0+* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) { +break ; + }else {No need for the 'else' keywork here.
Quoted 9 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
Quoted 9 lines
drivers/media/platform/ti-vpe/vpe.c +9
-0+ s->r = q_data->c_rect; +return 0 ; + } + +case V4L2_SEL_TGT_CROP : +case V4L2_SEL_TGT_CROP_DEFAULT : +case V4L2_SEL_TGT_CROP_BOUNDS : +/* +* CROP target is only valid for output buffer type, for capture
Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1628
Quoted 6 lines
drivers/media/platform/ti-vpe/vpe.c +6
-0+* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) { +break ; + }else {Ditto.
Thanks. I'll fix these.
I had a minor question about the selection API:
Quoted 7 lines
Are the V4L2_SET_TGT_CROP/COMPOSE_DEFAULT and the corresponding 'BOUNDS'
targets supposed to be used withVIDIOC_S_SELECTION? If so, what's the expect behaviour?Thanks,
Archit
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
v3 cover v4l: ti-vpe: Some VPE fixes and enhancements
In reply to Archit TanejaThis patch set mainly consists of minor fixes for the VPE driver. These fixes ensure the following:
- The VPE module can be inserted and removed successively.
- Make sure that smaller resolutions like qcif work correctly.
- Prevent race condition between firmware loading and an open call to the v4l2 device.
- Prevent the possibility of output m2m queue not having sufficient 'ready' buffers.
- Some VPDMA data descriptor fields weren't understood correctly before. They are now used correctly.
The rest of the patches add some minor features like DMA buf support and cropping/composing.
Reference branch:
[email protected]:boddob/linux.git vpe_for_315
Changes in v3:
- improvements in selection API patch.
- querycap fixes for v4l2 compliance.
- v4l2_buffer 'field' and flags' fixes for compliance.
- fixes in try_fmt vpe_open for compliance.
- rename a IOMEM resource for better DT compatibility.
Changes in v2:
- selection API used instead of older cropping API.
- Typo fix.
- Some changes in patch 6/7 to support composing on the capture side of VPE.
Archit Taneja (14):
v4l: ti-vpe: Make sure in job_ready that we have the needed number of
dst_bufs
v4l: ti-vpe: register video device only when firmware is loaded
v4l: ti-vpe: Use video_device_release_empty
v4l: ti-vpe: Allow DMABUF buffer type support
v4l: ti-vpe: Allow usage of smaller images
v4l: ti-vpe: Fix some params in VPE data descriptors
v4l: ti-vpe: Add selection API in VPE driver
v4l: ti-vpe: Rename csc memory resource name
v4l: ti-vpe: report correct capabilities in querycap
v4l: ti-vpe: Use correct bus_info name for the device in querycap
v4l: ti-vpe: Fix initial configuration queue data
v4l: ti-vpe: zero out reserved fields in try_fmt
v4l: ti-vpe: Set correct field parameter for output and capture
buffers
v4l: ti-vpe: retain v4l2_buffer flags for captured buffers
drivers/media/platform/ti-vpe/csc.c | 2 +- drivers/media/platform/ti-vpe/vpdma.c | 68 ++++++--- drivers/media/platform/ti-vpe/vpdma.h | 17 ++- drivers/media/platform/ti-vpe/vpe.c | 263 ++++++++++++++++++++++++++++------ 4 files changed, 281 insertions(+), 69 deletions(-)
Signature · 1 line
1.8.3.2
PATCH v3 1/14 v4l: ti-vpe: Make sure in job_ready that we have the needed number of dst_bufs
VPE has a ctrl parameter which decides how many mem to mem transactions the active job from the job queue can perform.
The driver's job_ready() made sure that the number of ready source buffers are sufficient for the job to execute successfully. But it didn't make sure if there are sufficient ready destination buffers in the capture queue for the VPE output.
If the time taken by VPE to process a single frame is really slow, then it's possible that we don't need to imply such a restriction on the dst queue, but really fast transactions(small resolution, no de-interlacing) may cause us to hit the condition where we don't have any free buffers for the VPE to write on.
Add the extra check in job_ready() to make sure we have the sufficient amount of destination buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +3 -0
@@ -887,6 +887,9 @@ static int job_ready(void *priv)if (v4l2_m2m_num_src_bufs_ready (ctx->m2m_ctx) < needed)return 0 ; +if (v4l2_m2m_num_dst_bufs_ready (ctx->m2m_ctx) < needed) +return 0 ; +return 1 ; }
Signature · 1 line
1.8.3.2
RE: [PATCH v3 01/14] v4l: ti-vpe: Make sure in job_ready that we have the needed number of dst_bufs
Hi,
Quoted 17 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Tuesday, March 11, 2014 9:34 AMVPE has a ctrl parameter which decides how many mem to mem transactions the active job from the job queue can perform.
The driver's
job_ready()made sure that the number of ready source buffers are sufficient for the job to execute successfully. But it didn't make sure if there are sufficient ready destination buffers in the capture queue for the VPE output.If the time taken by VPE to process a single frame is really slow, then it's possible that we don't need to imply such a restriction on the dst queue, but really fast
transactions(small resolution, no de-interlacing)may cause us to hit the condition where we don't have any free buffers for the VPE to write on.
Quoted 4 lines
Add the extra check in
job_ready()to make sure we have the sufficient amount of destination buffers.Signed-off-by Archit Taneja <[email protected]>
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Quoted 21 lines
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)drivers/media/platform/ti-vpe/vpe.c +3
-1@@ -887,6 +887,9 @@ static int job_ready(void *priv)if (v4l2_m2m_num_src_bufs_ready (ctx->m2m_ctx) < needed)return 0 ; +if (v4l2_m2m_num_dst_bufs_ready (ctx->m2m_ctx) < needed) +return 0 ; +return 1 ; } --1.8.3.2
PATCH v3 2/14 v4l: ti-vpe: register video device only when firmware is loaded
In reply to Archit Tanejavpe fops(vpe_open in particular) should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.
Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when it returns.
We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through vpdma_create().
The ready field in vpdma_data is no longer needed since we always have firmware loaded before the device is registered.
A minor problem with this approach is that if the video_register_device fails(which doesn't really happen), the vpe platform device would be registered. however, there won't be any v4l2 device corresponding to it.
--- drivers/media/platform/ti-vpe/vpdma.c | 8 +++-- drivers/media/platform/ti-vpe/vpdma.h | 7 +++-- drivers/media/platform/ti-vpe/vpe.c | 55 ++++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 29 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +5 -3
@@ -781,7 +781,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context)/* already initialized */ if (read_field_reg (vpdma,VPDMA_LIST_ATTR ,VPDMA_LIST_RDY_MASK ,VPDMA_LIST_RDY_SHFT )) { - vpdma->ready = true; + vpdma->cb (vpdma->pdev);return ; }
@@ -811,7 +811,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context) goto free_buf; } - vpdma->ready = true; + vpdma->cb (vpdma->pdev); free_buf:vpdma_unmap_desc_buf (vpdma, &fw_dma_buf);
@@ -839,7 +839,8 @@ static int vpdma_load_firmware(struct vpdma_data *vpdma)return 0 ; } -struct vpdma_data *vpdma_create (struct platform_device *pdev) +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev)) {struct resource *res;struct vpdma_data *vpdma;
@@ -854,6 +855,7 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev) } vpdma->pdev = pdev; + vpdma->cb = cb; res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"vpdma" );if (res ==NULL ) {
drivers/media/platform/ti-vpe/vpdma.h +4 -3
@@ -35,8 +35,8 @@ struct vpdma_data {struct platform_device *pdev; -/* tells whether vpdma firmware is loaded or not */ -bool ready; +/* callback to VPE driver when the firmware is loaded */ +void (*cb)(struct platform_device *pdev); };enum vpdma_data_format_type {
@@ -208,6 +208,7 @@ void vpdma_set_frame_start_event(struct vpdma_data *vpdma,void vpdma_dump_regs (struct vpdma_data *vpdma);/* initialize vpdma, passed with VPE's platform device pointer */ -struct vpdma_data *vpdma_create (struct platform_device *pdev); +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev));#endif
drivers/media/platform/ti-vpe/vpe.c +32 -23
81 lines not on this page · raw message
Signature · 1 line
1.8.3.2
RE: [PATCH v3 02/14] v4l: ti-vpe: register video device only when firmware is loaded
Hi Archit,
Quoted 16 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Tuesday, March 11, 2014 9:34 AMvpe
fops(vpe_open in particular)should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls
request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when it returns.We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through
vpdma_create().
Quoted 7 lines
The ready field in
vpdma_datais no longer needed since we always have firmware loaded before the device is registered.A minor problem with this approach is that if the
video_register_devicefails(which doesn't really happen), the vpe platform device would be registered.
however, there won't be any v4l2 device corresponding to it.
Could you explain to me one thing. request_firmware cannot be used in probe, thus you are using request_firmware_nowait. Why cannot the firmware be
loaded on open with a regular request_firmware that is waiting?
This patch seems to swap one problem for another. The possibility that open fails (because firmware is not yet loaded) is swapped for a vague possibility
that video_register_device.
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Quoted 168 lines
Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpdma.c | 8 +++-- drivers/media/platform/ti-vpe/vpdma.h | 7 +++-- drivers/media/platform/ti-vpe/vpe.c | 55 ++++++++++++++++++++------- -------- 3 files changed, 41 insertions(+), 29 deletions(-)drivers/media/platform/ti-vpe/vpdma.c +2
-2@@ -781,7 +781,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context)/* already initialized */ if (read_field_reg (vpdma,VPDMA_LIST_ATTR ,VPDMA_LIST_RDY_MASK ,VPDMA_LIST_RDY_SHFT )) { - vpdma->ready = true; + vpdma->cb (vpdma->pdev);return ; }@@ -811,7 +811,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context) goto free_buf; } - vpdma->ready = true; + vpdma->cb (vpdma->pdev); free_buf:
vpdma_unmap_desc_buf(vpdma, &fw_dma_buf); @@ -839,7 +839,8 @@
static intvpdma_load_firmware(struct vpdma_data *vpdma)drivers/media/platform/ti-vpe/vpdma.c +3
-1return 0 ; } -struct vpdma_data *vpdma_create (struct platform_device *pdev) +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev)) {struct resource *res;struct vpdma_data *vpdma;@@ -854,6 +855,7 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev) } vpdma->pdev = pdev; + vpdma->cb = cb; res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"vpdma" );drivers/media/platform/ti-vpe/vpdma.c +0
-0if (res ==NULL ) {drivers/media/platform/ti-vpe/vpdma.h +4
-2@@ -35,8 +35,8 @@ struct vpdma_data {struct platform_device *pdev; -/* tells whether vpdma firmware is loaded or not */ -bool ready; +/* callback to VPE driver when the firmware is loaded */ +void (*cb)(struct platform_device *pdev); };enum vpdma_data_format_type {@@ -208,6 +208,7 @@ void vpdma_set_frame_start_event(struct vpdma_data *vpdma, void vpdma_dump_regs(struct vpdma_data *vpdma);/* initialize vpdma, passed with VPE's platform device pointer */ - struct vpdma_data *vpdma_create(struct platform_device *pdev); +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev));#endif drivers/media/platform/ti-vpe/vpe.c +30
-6@@ -1817,11 +1817,6 @@ static int vpe_open(struct file *file)vpe_dbg (dev,"vpe_open\n" ); -if (!dev->vpdma->ready) { -vpe_err (dev,"vpdma firmware not loaded\n" ); -return -ENODEV ; - } - ctx =kzalloc (sizeof (*ctx),GFP_KERNEL );if (!ctx)return -ENOMEM ;@@ -2039,10 +2034,40 @@ static void vpe_runtime_put(struct platform_device *pdev) WARN_ON(r < 0 && r != -ENOSYS); } +static void vpe_fw_cb (struct platform_device *pdev) { +struct vpe_dev *dev =platform_get_drvdata (pdev); +struct video_device *vfd; +int ret; + + vfd = &dev->vfd; + *vfd = vpe_videodev; + vfd->lock = &dev->dev_mutex; + vfd->v4l2_dev = &dev->v4l2_dev; + + ret =video_register_device (vfd,VFL_TYPE_GRABBER ,0 ); +if (ret) { +vpe_err (dev,"Failed to register video device\n" ); + +vpe_set_clock_enable (dev,0 ); +vpe_runtime_put (pdev); +pm_runtime_disable (&pdev->dev); +v4l2_m2m_release (dev->m2m_dev); +vb2_dma_contig_cleanup_ctx (dev->alloc_ctx); +v4l2_device_unregister (&dev->v4l2_dev); + +return ; + } + +video_set_drvdata (vfd, dev); +snprintf (vfd->name,sizeof (vfd->name),"%s" , vpe_videodev.name); +dev_info (dev->v4l2_dev.dev,"Device registered as /dev/video%d\n" , + vfd->num); +} +static int vpe_probe (struct platform_device *pdev) {struct vpe_dev *dev; -struct video_device *vfd;int ret, irq, func; dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL); @@ -2123,28 +2148,12 @@ static int
vpe_probe(struct platform_device *pdev)drivers/media/platform/ti-vpe/vpe.c +1
-18goto runtime_put; } - dev->vpdma =vpdma_create (pdev); + dev->vpdma =vpdma_create (pdev, vpe_fw_cb);if (IS_ERR (dev->vpdma)) { ret =PTR_ERR (dev->vpdma); goto runtime_put; } - vfd = &dev->vfd; - *vfd = vpe_videodev; - vfd->lock = &dev->dev_mutex; - vfd->v4l2_dev = &dev->v4l2_dev; - - ret =video_register_device (vfd,VFL_TYPE_GRABBER ,0 ); -if (ret) { -vpe_err (dev,"Failed to register video device\n" ); - goto runtime_put; - } - -video_set_drvdata (vfd, dev); -snprintf (vfd->name,sizeof (vfd->name),"%s" , vpe_videodev.name); -dev_info (dev->v4l2_dev.dev,"Device registered as /dev/video%d\n" , - vfd->num); -return 0 ; runtime_put: --1.8.3.2
Re: [PATCH v3 02/14] v4l: ti-vpe: register video device only when firmware is loaded
Hi Kamil,
Quoted 26 lines · Kamil Debski
Hi Archit,
Quoted 16 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Tuesday, March 11, 2014 9:34 AMvpe
fops(vpe_open in particular)should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls
request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when it returns.We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through
vpdma_create().Quoted 7 lines
The ready field in
vpdma_datais no longer needed since we always have firmware loaded before the device is registered.A minor problem with this approach is that if the
video_register_devicefails(which doesn't really happen), the vpe platform device would be registered.
however, there won't be any v4l2 device corresponding to it.
Quoted 4 lines
Could you explain to me one thing.
request_firmwarecannot be used in probe, thus you are usingrequest_firmware_nowait. Why cannot the firmware be
loaded on open with a regularrequest_firmwarethat is waiting?
I totally agree with you here. Placing the firmware in open() would probably make more sense.
The reason I didn't place it in open() is because I didn't want to release firmware in a corresponding close(), and be in a situation where the firmware is loaded multiple times in the driver's lifetime.
There are some reasons for doing this. First, it will require more testing with respect to whether the firmware is loaded correctly successive times :), the second is that loading firmware might probably take a bit of time, and we don't want to make applications too slow(I haven't measured the time taken, so I don't have a strong case for this either)
Quoted 5 lines
This patch seems to swap one problem for another. The possibility that open fails (because firmware is not yet loaded) is swapped for a vague possibility
thatvideo_register_device.
The driver will work fine in most cases even without this patch(apart from the possibility mentioned as above).
We could discard this patch from this series, and I can work on a patch which moves firmware loading to the vpe_open() call, and hence solving the issue in the right manner. Does that sound fine?
Thanks,
Archit
RE: [PATCH v3 02/14] v4l: ti-vpe: register video device only when firmware is loaded
Hi,
Quoted 38 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Thursday, March 13, 2014 1:09 PMHi Kamil,
Quoted 13 lines · Kamil Debski
Hi Archit,
Quoted 11 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Tuesday, March 11, 2014 9:34 AMvpe
fops(vpe_open in particular)should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls
request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when itreturns.
Quoted 13 lines
Quoted 5 lines
We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through
vpdma_create().Quoted 7 lines
The ready field in
vpdma_datais no longer needed since we always have firmware loaded before the device is registered.A minor problem with this approach is that if the
video_register_devicefails(which doesn't really happen), the vpe platform device would be registered.
however, there won't be any v4l2 device corresponding to it.Quoted 4 lines
Could you explain to me one thing.
request_firmwarecannot be used in probe, thus you are usingrequest_firmware_nowait. Why cannot the firmware be loaded on open with a regularrequest_firmwarethat is waiting?
Quoted 6 lines
I totally agree with you here. Placing the firmware in
open()would probably make more sense.The reason I didn't place it in
open()is because I didn't want to release firmware in a correspondingclose(), and be in a situation where the firmware is loaded multiple times in the driver's lifetime.
Would it be possible to load firmware in open and release it in remove? I know that this would disturb the symmetry between open-release and probe-remove. But this could work.
Quoted 12 lines
There are some reasons for doing this. First, it will require more testing with respect to whether the firmware is loaded correctly successive times :), the second is that loading firmware might probably take a bit of time, and we don't want to make applications too
slow(I haven't measured the time taken, so I don't have a strong case for this either)Quoted 2 lines
This patch seems to swap one problem for another. The possibility
that
Quoted 1 line
open fails (because firmware is not yet loaded) is swapped for a
vague
Quoted 8 lines
Quoted 1 line
possibility that
video_register_device.The driver will work fine in most cases even without this patch(apart from the possibility mentioned as above).
We could discard this patch from this series, and I can work on a patch which moves firmware loading to the
vpe_open()call, and hence solving the issue in the right manner. Does that sound fine?
I agree, this should be a good solution.
Quoted 3 lines
Thanks,
Archit
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Re: [PATCH v3 02/14] v4l: ti-vpe: register video device only when firmware is loaded
Hi,
Quoted 43 lines · Kamil Debski
Hi,
Quoted 41 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Thursday, March 13, 2014 1:09 PMHi Kamil,
Quoted 13 lines · Kamil Debski
Hi Archit,
Quoted 11 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Tuesday, March 11, 2014 9:34 AMvpe
fops(vpe_open in particular)should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls
request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when itreturns.
Quoted 13 lines
Quoted 5 lines
We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through
vpdma_create().Quoted 7 lines
The ready field in
vpdma_datais no longer needed since we always have firmware loaded before the device is registered.A minor problem with this approach is that if the
video_register_devicefails(which doesn't really happen), the vpe platform device would be registered.
however, there won't be any v4l2 device corresponding to it.Quoted 4 lines
Could you explain to me one thing.
request_firmwarecannot be used in probe, thus you are usingrequest_firmware_nowait. Why cannot the firmware be loaded on open with a regularrequest_firmwarethat is waiting?I totally agree with you here. Placing the firmware in
open()would probably make more sense.
Quoted 7 lines
Quoted 3 lines
The reason I didn't place it in
open()is because I didn't want to release firmware in a correspondingclose(), and be in a situation where the firmware is loaded multiple times in the driver's lifetime.Would it be possible to load firmware in open and release it in remove? I know that this would disturb the symmetry between open-release and probe-remove. But this could work.
That might work.
Currently, the driver doesn't do any clock management, it just enables the clocks in probe, and disables them in remove. I need to check how the firmware is dependent on clocks. We could make a better decision about where to release the firmware with that information.
Archit
PATCH v3 3/14 v4l: ti-vpe: Use video_device_release_empty
In reply to Archit TanejaThe video_device struct is currently embedded in the driver data struct vpe_dev. A vpe_dev instance is allocated by the driver, and the memory for the vfd is a part of this struct.
The v4l2 core, however, manages the removal of the vfd region, through the video_device's .release() op, which currently is the helper video_device_release. This causes memory corruption, and leads to issues when we try to re-insert the vpe module.
Use the video_device_release_empty helper function instead
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +1 -1
@@ -2000,7 +2000,7 @@ static struct video_device vpe_videodev = { .fops = &vpe_fops, .ioctl_ops = &vpe_ioctl_ops, .minor = -1, - .release = video_device_release, + .release = video_device_release_empty, .vfl_dir = VFL_DIR_M2M, };
Signature · 1 line
1.8.3.2
Re: [PATCH v3 03/14] v4l: ti-vpe: Use video_device_release_empty
Quoted 4 lines · Archit Taneja
The
video_devicestruct is currently embedded in the driver data structvpe_dev. Avpe_devinstance is allocated by the driver, and the memory for the vfd is a part of this struct.
Quoted 8 lines
The v4l2 core, however, manages the removal of the vfd region, through the video_device's .release() op, which currently is the helper
video_device_release. This causes memory corruption, and leads to issues when we try to re-insert the vpe module.Use the
video_device_release_emptyhelper function insteadSigned-off-by Archit Taneja <[email protected]>
Quoted 18 lines
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/media/platform/ti-vpe/vpe.c +1
-1@@ -2000,7 +2000,7 @@ static struct video_device vpe_videodev = { .fops = &vpe_fops, .ioctl_ops = &vpe_ioctl_ops, .minor = -1, - .release = video_device_release, + .release = video_device_release_empty, .vfl_dir = VFL_DIR_M2M, };
PATCH v3 4/14 v4l: ti-vpe: Allow DMABUF buffer type support
In reply to Archit TanejaFor OMAP and DRA7x, we generally allocate video and graphics buffers through omapdrm since the corresponding omap-gem driver provides DMM-Tiler backed contiguous buffers. omapdrm is a dma-buf exporter. These buffers are used by other drivers in the video pipeline.
Add VB2_DMABUF flag to the io_modes of the vb2 output and capture queues. This allows the driver to import dma shared buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -1770,7 +1770,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (src_vq,0 ,sizeof (*src_vq)); src_vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ; - src_vq->io_modes =VB2_MMAP ; + src_vq->io_modes =VB2_MMAP |VB2_DMABUF ; src_vq->drv_priv = ctx; src_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); src_vq->ops = &vpe_qops;
@@ -1783,7 +1783,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (dst_vq,0 ,sizeof (*dst_vq)); dst_vq->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ; - dst_vq->io_modes =VB2_MMAP ; + dst_vq->io_modes =VB2_MMAP |VB2_DMABUF ; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); dst_vq->ops = &vpe_qops;
Signature · 1 line
1.8.3.2
Re: [PATCH v3 04/14] v4l: ti-vpe: Allow DMABUF buffer type support
Quoted 9 lines · Archit Taneja
For OMAP and DRA7x, we generally allocate video and graphics buffers through omapdrm since the corresponding omap-gem driver provides DMM-Tiler backed contiguous buffers. omapdrm is a dma-buf exporter. These buffers are used by other drivers in the video pipeline.
Add
VB2_DMABUFflag to theio_modesof the vb2 output and capture queues. This allows the driver to import dma shared buffers.Signed-off-by Archit Taneja <[email protected]>
Quoted 27 lines
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/media/platform/ti-vpe/vpe.c +2
-2@@ -1770,7 +1770,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (src_vq,0 ,sizeof (*src_vq)); src_vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ; - src_vq->io_modes =VB2_MMAP ; + src_vq->io_modes =VB2_MMAP |VB2_DMABUF ; src_vq->drv_priv = ctx; src_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); src_vq->ops = &vpe_qops;@@ -1783,7 +1783,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (dst_vq,0 ,sizeof (*dst_vq)); dst_vq->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ; - dst_vq->io_modes =VB2_MMAP ; + dst_vq->io_modes =VB2_MMAP |VB2_DMABUF ; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); dst_vq->ops = &vpe_qops;
PATCH v3 5/14 v4l: ti-vpe: Allow usage of smaller images
In reply to Archit TanejaThe minimum width and height for VPE input/output was kept as 128 pixels. VPE doesn't have a constraint on the image height, it requires the image width to be at least 16 bytes.
Change the minimum supported dimensions to 32x32. This allows us to de-interlace qcif content. A smaller image size than 32x32 didn't make much sense, so stopped at this.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -49,8 +49,8 @@#define VPE_MODULE_NAME "vpe"/* minimum and maximum frame sizes */ -#define MIN_W 128 -#define MIN_H 128 +#define MIN_W 32 +#define MIN_H 32#define MAX_W 1920#define MAX_H 1080
Signature · 1 line
1.8.3.2
Re: [PATCH v3 05/14] v4l: ti-vpe: Allow usage of smaller images
Quoted 9 lines · Archit Taneja
The minimum width and height for VPE input/output was kept as 128 pixels. VPE doesn't have a constraint on the image height, it requires the image width to be at least 16 bytes.
Change the minimum supported dimensions to 32x32. This allows us to de-interlace qcif content. A smaller image size than 32x32 didn't make much sense, so stopped at this.
Signed-off-by Archit Taneja <[email protected]>
Quoted 20 lines
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)drivers/media/platform/ti-vpe/vpe.c +2
-2@@ -49,8 +49,8 @@#define VPE_MODULE_NAME "vpe"/* minimum and maximum frame sizes */ -#define MIN_W 128 -#define MIN_H 128 +#define MIN_W 32 +#define MIN_H 32#define MAX_W 1920#define MAX_H 1080
PATCH v3 6/14 v4l: ti-vpe: Fix some params in VPE data descriptors
In reply to Archit TanejaSome parameters of the VPE descriptors were understood incorrectly. They are now fixed. The fixes are explained as follows:
- When adding an inbound data descriptor to the VPDMA descriptor list, we intend to use c_rect as the cropped region fetched by VPDMA. Therefore, c_rect->width shouldn't be used to calculate the line stride, the original image width should be used for that. We add a 'width' argument which gives the buffer width in memory.
- frame_width and frame_height describe the complete width and height of the client to which the channel is connected. If there are multiple channels fetching data and providing to the same client, the above 2 arguments should be the width and height of the region covered by all the channels. In the case where there is only one channel providing pixel data to the client (like in VPE), frame_width and frame_height should be the cropped width and cropped height respectively. The calculation of these params is done in the vpe driver now.
- start_h and start_v is also used in the case of multiple channels to describe where each channel should start filling pixel data. We don't use this in VPE, and pass 0s to the vpdma_add_in_dtd() helper.
- Some minor changes are made to the vpdma_add_out_dtd() helper. The c_rect param is used for specifying the 'composition' target, and 'width' is added to calculate the line stride.
--- drivers/media/platform/ti-vpe/vpdma.c | 60 +++++++++++++++++++++++++++-------- drivers/media/platform/ti-vpe/vpdma.h | 10 +++--- drivers/media/platform/ti-vpe/vpe.c | 18 +++++++---- 3 files changed, 64 insertions(+), 24 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +46 -14
@@ -614,8 +614,17 @@ static void dump_dtd(struct vpdma_dtd *dtd)/* * append an outbound data transfer descriptor to the given descriptor list, * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory +* @c_rect: compose params of output image +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* flags: VPDMA flags to configure some descriptor fileds */ -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags) {
@@ -623,6 +632,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,int field =0 ;int notify =1 ;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int depth = fmt->depth;int stride;struct vpdma_dtd *dtd;
@@ -630,11 +640,15 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && - fmt->data_type ==DATA_TYPE_C420 ) + fmt->data_type ==DATA_TYPE_C420 ) { + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; + } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -664,31 +678,48 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,/* * append an inbound data transfer descriptor to the given descriptor list, * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory(not the cropped width) +* @c_rect: crop params of input image +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* field: top or bottom field info of the input image +* flags: VPDMA flags to configure some descriptor fileds +* frame_width/height: the complete width/height of the image presented to the +* client (this makes sense when multiple channels are +* connected to the same client, forming a larger frame) +* start_h, start_v: position where the given channel starts providing pixel +* data to the client (makes sense when multiple channels +* contribute to the client) */ -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags) +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v) {int priority =0 ;int notify =1 ;int depth = fmt->depth;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int stride; -int height = c_rect->height;struct vpdma_dtd *dtd; channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && fmt->data_type ==DATA_TYPE_C420 ) { - height >>=1 ; - frame_height >>=1 ; + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -701,13 +732,14 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, !!(flags &VPDMA_DATA_ODD_LINE_SKIP ), stride); - dtd->xfer_length_height =dtd_xfer_length_height (c_rect->width, height); + dtd->xfer_length_height =dtd_xfer_length_height (rect.width, + rect.height); dtd->start_addr = (u32 ) dma_addr; dtd->pkt_ctl =dtd_pkt_ctl (!!(flags &VPDMA_DATA_MODE_TILED ),DTD_DIR_IN , channel, priority, next_chan); dtd->frame_width_height =dtd_frame_width_height (frame_width, frame_height); - dtd->start_h_v =dtd_start_h_v (c_rect->left, c_rect->top); + dtd->start_h_v =dtd_start_h_v (start_h, start_v); dtd->client_attr0 =0 ; dtd->client_attr1 =0 ;
drivers/media/platform/ti-vpe/vpdma.h +6 -4
@@ -186,13 +186,15 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, struct vpdma_buf *adb);void vpdma_add_sync_on_channel_ctd (struct vpdma_desc_list *list,enum vpdma_channel chan); -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags); -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags); +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v);/* vpdma list interrupt management */ void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
drivers/media/platform/ti-vpe/vpe.c +12 -6
@@ -986,7 +986,6 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->dst_vb; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = !ctx->src_mv_buf_selector;
@@ -1015,8 +1014,8 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_out_dtd (&ctx->desc_list, c_rect, vpdma_fmt, dma_addr, - p_data->channel, flags); +vpdma_add_out_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, flags); }static void add_in_dtd (struct vpe_ctx *ctx,int port)
@@ -1024,11 +1023,11 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = ctx->src_mv_buf_selector;int field = vb->v4l2_buf.field ==V4L2_FIELD_BOTTOM ; +int frame_width, frame_height;dma_addr_t dma_addr;u32 flags =0 ;
@@ -1055,8 +1054,15 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_in_dtd (&ctx->desc_list, q_data->width, q_data->height, - c_rect, vpdma_fmt, dma_addr, p_data->channel, field, flags); + frame_width = q_data->c_rect.width; + frame_height = q_data->c_rect.height; + +if (p_data->vb_part && fmt->fourcc ==V4L2_PIX_FMT_NV12 ) + frame_height /=2 ; + +vpdma_add_in_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, field, flags, frame_width, + frame_height,0 ,0 ); }/*
Signature · 1 line
1.8.3.2
PATCH v3 7/14 v4l: ti-vpe: Add selection API in VPE driver
In reply to Archit TanejaAdd selection ioctl ops. For VPE, cropping makes sense only for the input to VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers) and composing makes sense only for the output of VPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).
For the CAPTURE type, V4L2_SEL_TGT_COMPOSE results in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type, V4L2_SEL_TGT_CROP results in selecting a rectangle region within the source buffer.
Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change, set_srcdst_params() is called for this purpose.
--- drivers/media/platform/ti-vpe/vpe.c | 141 ++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +141 -0
@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :return &ctx->q_data[Q_DATA_DST ];default :BUG ();
@@ -1587,6 +1589,142 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE : +/* +* COMPOSE target is only valid for capture buffer type, for +* output buffer type, assign existing crop parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) +break ; + + s->r = q_data->c_rect; +return 0 ; + +case V4L2_SEL_TGT_CROP : +/* +* CROP target is only valid for output buffer type, for capture +* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) +break ; + + s->r = q_data->c_rect; +return 0 ; + +/* +* bound and default crop/compose targets are invalid targets to +* try/set +*/ +default : +return -EINVAL ; + } + +if (s->r.top <0 || s->r.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + s->r.top = s->r.left =0 ; + } + +v4l_bound_align_image (&s->r.width,MIN_W , q_data->width,1 , + &s->r.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (s->r.left + s->r.width > q_data->width) + s->r.left = q_data->width - s->r.width; +if (s->r.top + s->r.height > q_data->height) + s->r.top = q_data->height - s->r.height; + +return 0 ; +} + +static int vpe_g_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +/* return width and height from S_FMT of the respective buffer type */ +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +case V4L2_SEL_TGT_CROP_BOUNDS : +case V4L2_SEL_TGT_CROP_DEFAULT : + s->r.left =0 ; + s->r.top =0 ; + s->r.width = q_data->width; + s->r.height = q_data->height; +return 0 ; + +/* +* CROP target holds for the output buffer type, and COMPOSE target +* holds for the capture buffer type. We still return the c_rect params +* for both the target types. +*/ +case V4L2_SEL_TGT_COMPOSE : +case V4L2_SEL_TGT_CROP : + s->r.left = q_data->c_rect.left; + s->r.top = q_data->c_rect.top; + s->r.width = q_data->c_rect.width; + s->r.height = q_data->c_rect.height; +return 0 ; + } + +return -EINVAL ; +} + + +static int vpe_s_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +struct v4l2_selection sel = *s; +int ret; + + ret =__vpe_try_selection (ctx, &sel); +if (ret) +return ret; + + q_data =get_q_data (ctx, sel.type); +if (!q_data) +return -EINVAL ; + +if ((q_data->c_rect.left == sel.r.left) && + (q_data->c_rect.top == sel.r.top) && + (q_data->c_rect.width == sel.r.width) && + (q_data->c_rect.height == sel.r.height)) { +vpe_dbg (ctx->dev, +"requested crop/compose values are already set\n" ); +return 0 ; + } + + q_data->c_rect = sel.r; + +return set_srcdst_params (ctx); +} +static int vpe_reqbufs (struct file *file,void *priv,struct v4l2_requestbuffers *reqbufs) {
@@ -1674,6 +1812,9 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, + .vidioc_g_selection = vpe_g_selection, + .vidioc_s_selection = vpe_s_selection, + .vidioc_reqbufs = vpe_reqbufs, .vidioc_querybuf = vpe_querybuf,
Signature · 1 line
1.8.3.2
Re: [PATCH v3 07/14] v4l: ti-vpe: Add selection API in VPE driver
Hi Archit,
A few small comments below...
Quoted 47 lines · Archit Taneja
Add selection ioctl ops. For VPE, cropping makes sense only for the input to
VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers)and composing makes sense only for the output ofVPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).For the CAPTURE type,
V4L2_SEL_TGT_COMPOSEresults in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type,V4L2_SEL_TGT_CROPresults in selecting a rectangle region within the source buffer.Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpe.c | 141 ++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+)drivers/media/platform/ti-vpe/vpe.c +13
-0@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :return &ctx->q_data[Q_DATA_DST ];default :BUG ();@@ -1587,6 +1589,142 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ;
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1612
Quoted 10 lines
drivers/media/platform/ti-vpe/vpe.c +10
-0+ +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE : +/* +* COMPOSE target is only valid for capture buffer type, for +* output buffer type, assign existing crop parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) +break ;
Shouldn't this return -EINVAL?
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1624
Quoted 12 lines
drivers/media/platform/ti-vpe/vpe.c +12
-0+ + s->r = q_data->c_rect; +return 0 ; + +case V4L2_SEL_TGT_CROP : +/* +* CROP target is only valid for output buffer type, for capture +* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) +break ;
Ditto.
Quoted 43 lines
drivers/media/platform/ti-vpe/vpe.c +43
-0+ + s->r = q_data->c_rect; +return 0 ; + +/* +* bound and default crop/compose targets are invalid targets to +* try/set +*/ +default : +return -EINVAL ; + } + +if (s->r.top <0 || s->r.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + s->r.top = s->r.left =0 ; + } + +v4l_bound_align_image (&s->r.width,MIN_W , q_data->width,1 , + &s->r.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (s->r.left + s->r.width > q_data->width) + s->r.left = q_data->width - s->r.width; +if (s->r.top + s->r.height > q_data->height) + s->r.top = q_data->height - s->r.height; + +return 0 ; +} + +static int vpe_g_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; +
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1677
Quoted 10 lines
drivers/media/platform/ti-vpe/vpe.c +10
-0+switch (s->target) { +/* return width and height from S_FMT of the respective buffer type */ +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +case V4L2_SEL_TGT_CROP_BOUNDS : +case V4L2_SEL_TGT_CROP_DEFAULT : + s->r.left =0 ; + s->r.top =0 ; + s->r.width = q_data->width; + s->r.height = q_data->height;
The crop targets only make sense for type OUTPUT and the compose only for type CAPTURE. Add some checks for that.
Quoted 64 lines
drivers/media/platform/ti-vpe/vpe.c +53
-0+return 0 ; + +/* +* CROP target holds for the output buffer type, and COMPOSE target +* holds for the capture buffer type. We still return the c_rect params +* for both the target types. +*/ +case V4L2_SEL_TGT_COMPOSE : +case V4L2_SEL_TGT_CROP : + s->r.left = q_data->c_rect.left; + s->r.top = q_data->c_rect.top; + s->r.width = q_data->c_rect.width; + s->r.height = q_data->c_rect.height; +return 0 ; + } + +return -EINVAL ; +} + + +static int vpe_s_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +struct v4l2_selection sel = *s; +int ret; + + ret =__vpe_try_selection (ctx, &sel); +if (ret) +return ret; + + q_data =get_q_data (ctx, sel.type); +if (!q_data) +return -EINVAL ; + +if ((q_data->c_rect.left == sel.r.left) && + (q_data->c_rect.top == sel.r.top) && + (q_data->c_rect.width == sel.r.width) && + (q_data->c_rect.height == sel.r.height)) { +vpe_dbg (ctx->dev, +"requested crop/compose values are already set\n" ); +return 0 ; + } + + q_data->c_rect = sel.r; + +return set_srcdst_params (ctx); +} +static int vpe_reqbufs (struct file *file,void *priv,struct v4l2_requestbuffers *reqbufs) {@@ -1674,6 +1812,9 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, + .vidioc_g_selection = vpe_g_selection, + .vidioc_s_selection = vpe_s_selection, + .vidioc_reqbufs = vpe_reqbufs, .vidioc_querybuf = vpe_querybuf,
Re: [PATCH v3 07/14] v4l: ti-vpe: Add selection API in VPE driver
Quoted 56 lines · Hans Verkuil
Hi Archit,
A few small comments below...
Quoted 51 lines · Archit Taneja
Add selection ioctl ops. For VPE, cropping makes sense only for the input to
VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers)and composing makes sense only for the output ofVPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).For the CAPTURE type,
V4L2_SEL_TGT_COMPOSEresults in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type,V4L2_SEL_TGT_CROPresults in selecting a rectangle region within the source buffer.Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpe.c | 141 ++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+)drivers/media/platform/ti-vpe/vpe.c +17
-0@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :return &ctx->q_data[Q_DATA_DST ];default :BUG ();@@ -1587,6 +1589,142 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE : +/*
Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1612
Quoted 6 lines
drivers/media/platform/ti-vpe/vpe.c +6
-0+* COMPOSE target is only valid for capture buffer type, for +* output buffer type, assign existing crop parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) +break ;Shouldn't this return
-EINVAL?
compose only makes sense for CAPTURE. So, it breaks and performs the calculations after the switch statement.
Quoted 4 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1615
Quoted 4 lines
drivers/media/platform/ti-vpe/vpe.c +3
-0+ + s->r = q_data->c_rect; +return 0 ;
The above 2 lines are called for if we try to set compose for OUTPUT. I don't return an error here, just keep the size as the original rect size, and return 0.
I'll replace these 2 lines with 'return -EINVAL;'
Quoted 60 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1624
Quoted 9 lines
drivers/media/platform/ti-vpe/vpe.c +9
-0+ +case V4L2_SEL_TGT_CROP : +/* +* CROP target is only valid for output buffer type, for capture +* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) +break ;Ditto.
Quoted 48 lines
drivers/media/platform/ti-vpe/vpe.c +48
-0+ + s->r = q_data->c_rect; +return 0 ; + +/* +* bound and default crop/compose targets are invalid targets to +* try/set +*/ +default : +return -EINVAL ; + } + +if (s->r.top <0 || s->r.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + s->r.top = s->r.left =0 ; + } + +v4l_bound_align_image (&s->r.width,MIN_W , q_data->width,1 , + &s->r.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (s->r.left + s->r.width > q_data->width) + s->r.left = q_data->width - s->r.width; +if (s->r.top + s->r.height > q_data->height) + s->r.top = q_data->height - s->r.height; + +return 0 ; +} + +static int vpe_g_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +/* return width and height from S_FMT of the respective buffer type */ +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +case V4L2_SEL_TGT_CROP_BOUNDS :
Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1677
Quoted 5 lines
drivers/media/platform/ti-vpe/vpe.c +5
-0+case V4L2_SEL_TGT_CROP_DEFAULT : + s->r.left =0 ; + s->r.top =0 ; + s->r.width = q_data->width; + s->r.height = q_data->height;The crop targets only make sense for type OUTPUT and the compose only for type CAPTURE. Add some checks for that.
I return the image size for G_FMT irrespective of what combination of crop/compose CAPTURE/OUTPUT it is. I suppose it is better to return an error if the user tries to configure a wrong combination.
Thanks,
Archit
Re: [PATCH v3 07/14] v4l: ti-vpe: Add selection API in VPE driver
Quoted 66 lines · Archit Taneja
Quoted 56 lines · Hans Verkuil
Hi Archit,
A few small comments below...
Quoted 51 lines · Archit Taneja
Add selection ioctl ops. For VPE, cropping makes sense only for the input to
VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers)and composing makes sense only for the output ofVPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).For the CAPTURE type,
V4L2_SEL_TGT_COMPOSEresults in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type,V4L2_SEL_TGT_CROPresults in selecting a rectangle region within the source buffer.Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change,
set_srcdst_params()is called for this purpose.Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/vpe.c | 141 ++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+)drivers/media/platform/ti-vpe/vpe.c +17
-0@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :return &ctx->q_data[Q_DATA_DST ];default :BUG ();@@ -1587,6 +1589,142 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE : +/* Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1612
Quoted 6 lines
drivers/media/platform/ti-vpe/vpe.c +6
-0+* COMPOSE target is only valid for capture buffer type, for +* output buffer type, assign existing crop parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) +break ;Shouldn't this return
-EINVAL?
Quoted 1 line
compose only makes sense for CAPTURE. So, it breaks and performs the calculations after the switch statement.
It's so easy to get confused here.
Quoted 9 lines
Quoted 5 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1615
Quoted 5 lines
drivers/media/platform/ti-vpe/vpe.c +3
-0+ + s->r = q_data->c_rect; +return 0 ;The above 2 lines are called for if we try to set compose for OUTPUT. I don't return an error here, just keep the size as the original rect size, and return 0.
I'll replace these 2 lines with 'return
-EINVAL;'
Yes, that makes more sense.
Quoted 70 lines
Quoted 61 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1624
Quoted 10 lines
drivers/media/platform/ti-vpe/vpe.c +9
-0+ +case V4L2_SEL_TGT_CROP : +/* +* CROP target is only valid for output buffer type, for capture +* buffer type, assign existing compose parameters to the +* selection rectangle +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) +break ;Ditto.
Quoted 48 lines
drivers/media/platform/ti-vpe/vpe.c +48
-0+ + s->r = q_data->c_rect; +return 0 ; + +/* +* bound and default crop/compose targets are invalid targets to +* try/set +*/ +default : +return -EINVAL ; + } + +if (s->r.top <0 || s->r.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + s->r.top = s->r.left =0 ; + } + +v4l_bound_align_image (&s->r.width,MIN_W , q_data->width,1 , + &s->r.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (s->r.left + s->r.width > q_data->width) + s->r.left = q_data->width - s->r.width; +if (s->r.top + s->r.height > q_data->height) + s->r.top = q_data->height - s->r.height; + +return 0 ; +} + +static int vpe_g_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +/* return width and height from S_FMT of the respective buffer type */ +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +case V4L2_SEL_TGT_CROP_BOUNDS :Quoted 8 lines
drivers/media/platform/ti-vpe/vpe.c static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f) · line 1677
Quoted 5 lines
drivers/media/platform/ti-vpe/vpe.c +5
-0+case V4L2_SEL_TGT_CROP_DEFAULT : + s->r.left =0 ; + s->r.top =0 ; + s->r.width = q_data->width; + s->r.height = q_data->height;The crop targets only make sense for type OUTPUT and the compose only for type CAPTURE. Add some checks for that.
Quoted 3 lines
I return the image size for
G_FMTirrespective of what combination of crop/compose CAPTURE/OUTPUT it is. I suppose it is better to return an error if the user tries to configure a wrong combination.
Yes. If for no other reason that I plan on adding crop/compose/scaling support to v4l2-compliance soon, and this will probably be one of the tests.
Quoted 8 lines
Thanks,
ArchitSignature · 3 lines
To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3 07/14] v4l: ti-vpe: Add selection API in VPE driver
Quoted 7 lines · Hans Verkuil
Quoted 6 lines · Archit Taneja
Quoted 5 lines · Hans Verkuil
Hi Archit,
A few small comments below...
On 03/11/14 09:33, Archit Taneja wrote:
<snip>
Quoted 2 lines
Yes. If for no other reason that I plan on adding crop/compose/scaling support to v4l2-compliance soon, and this will probably be one of the tests.
Thanks, will update. Thanks for reviewing of the series.
Archit
Quoted 10 lines
Quoted 9 lines
Thanks,
Archit--
To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v3 8/14 v4l: ti-vpe: Rename csc memory resource name
In reply to Archit TanejaRename the memory block resource "vpe_csc" to "csc" since it also exists within the VIP IP block. This would make the name more generic, and both VPE and VIP DT nodes in the future can use it.
--- drivers/media/platform/ti-vpe/csc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/csc.c +1 -1
@@ -180,7 +180,7 @@ struct csc_data *csc_create(struct platform_device *pdev) csc->pdev = pdev; csc->res =platform_get_resource_byname (pdev,IORESOURCE_MEM , -"vpe_csc" ); +"csc" );if (csc->res ==NULL ) {dev_err (&pdev->dev,"missing platform resources data\n" );return ERR_PTR (-ENODEV );
Signature · 1 line
1.8.3.2
PATCH v3 9/14 v4l: ti-vpe: report correct capabilities in querycap
In reply to Archit Tanejaquerycap currently returns V4L2_CAP_VIDEO_M2M as a capability, this should be V4L2_CAP_VIDEO_M2M_MPLANE instead, as the driver supports multiplanar formats.
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +1 -1
@@ -1347,7 +1347,7 @@ static int vpe_querycap(struct file *file, void *priv,strncpy (cap->driver,VPE_MODULE_NAME ,sizeof (cap->driver) -1 );strncpy (cap->card,VPE_MODULE_NAME ,sizeof (cap->card) -1 );strlcpy (cap->bus_info,VPE_MODULE_NAME ,sizeof (cap->bus_info)); - cap->device_caps =V4L2_CAP_VIDEO_M2M |V4L2_CAP_STREAMING ; + cap->device_caps =V4L2_CAP_VIDEO_M2M_MPLANE |V4L2_CAP_STREAMING ; cap->capabilities = cap->device_caps |V4L2_CAP_DEVICE_CAPS ;return 0 ; }
Signature · 1 line
1.8.3.2
Re: [PATCH v3 09/14] v4l: ti-vpe: report correct capabilities in querycap
Quoted 4 lines · Archit Taneja
querycap currently returns
V4L2_CAP_VIDEO_M2Mas a capability, this should beV4L2_CAP_VIDEO_M2M_MPLANEinstead, as the driver supports multiplanar formats.Signed-off-by Archit Taneja <[email protected]>
Quoted 18 lines
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/media/platform/ti-vpe/vpe.c +1
-1@@ -1347,7 +1347,7 @@ static int vpe_querycap(struct file *file, void *priv,strncpy (cap->driver,VPE_MODULE_NAME ,sizeof (cap->driver) -1 );strncpy (cap->card,VPE_MODULE_NAME ,sizeof (cap->card) -1 );strlcpy (cap->bus_info,VPE_MODULE_NAME ,sizeof (cap->bus_info)); - cap->device_caps =V4L2_CAP_VIDEO_M2M |V4L2_CAP_STREAMING ; + cap->device_caps =V4L2_CAP_VIDEO_M2M_MPLANE |V4L2_CAP_STREAMING ; cap->capabilities = cap->device_caps |V4L2_CAP_DEVICE_CAPS ;return 0 ; }
PATCH v3 10/14 v4l: ti-vpe: Use correct bus_info name for the device in querycap
In reply to Archit TanejaThe bus_info parameter in v4l2_capabilities expects a 'platform_' prefix. This wasn't done in the driver and hence was breaking compliance. Update the bus_info parameter accordingly.
--- drivers/media/platform/ti-vpe/vpe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +2 -1
@@ -1346,7 +1346,8 @@ static int vpe_querycap(struct file *file, void *priv, {strncpy (cap->driver,VPE_MODULE_NAME ,sizeof (cap->driver) -1 );strncpy (cap->card,VPE_MODULE_NAME ,sizeof (cap->card) -1 ); -strlcpy (cap->bus_info,VPE_MODULE_NAME ,sizeof (cap->bus_info)); +snprintf (cap->bus_info,sizeof (cap->bus_info),"platform:%s" , +VPE_MODULE_NAME ); cap->device_caps =V4L2_CAP_VIDEO_M2M_MPLANE |V4L2_CAP_STREAMING ; cap->capabilities = cap->device_caps |V4L2_CAP_DEVICE_CAPS ;return 0 ;
Signature · 1 line
1.8.3.2
Re: [PATCH v3 10/14] v4l: ti-vpe: Use correct bus_info name for the device in querycap
Quoted 5 lines · Archit Taneja
The
bus_infoparameter inv4l2_capabilitiesexpects a 'platform_' prefix. This wasn't done in the driver and hence was breaking compliance. Update thebus_infoparameter accordingly.Signed-off-by Archit Taneja <[email protected]>
Quoted 19 lines
--- drivers/media/platform/ti-vpe/vpe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/media/platform/ti-vpe/vpe.c +2
-1@@ -1346,7 +1346,8 @@ static int vpe_querycap(struct file *file, void *priv, {strncpy (cap->driver,VPE_MODULE_NAME ,sizeof (cap->driver) -1 );strncpy (cap->card,VPE_MODULE_NAME ,sizeof (cap->card) -1 ); -strlcpy (cap->bus_info,VPE_MODULE_NAME ,sizeof (cap->bus_info)); +snprintf (cap->bus_info,sizeof (cap->bus_info),"platform:%s" , +VPE_MODULE_NAME ); cap->device_caps =V4L2_CAP_VIDEO_M2M_MPLANE |V4L2_CAP_STREAMING ; cap->capabilities = cap->device_caps |V4L2_CAP_DEVICE_CAPS ;return 0 ;
PATCH v3 11/14 v4l: ti-vpe: Fix initial configuration queue data
In reply to Archit TanejaThe vpe output and capture queues are initially configured to default values in vpe_open(). A G_FMT before any S_FMTs will result in these values being populated.
The colorspace and bytesperline parameter of this initial configuration are incorrect. This breaks compliance when as we get 'TRY_FMT(G_FMT) != G_FMT'.
Fix the initial queue configuration such that it wouldn't need to be fixed by try_fmt.
--- drivers/media/platform/ti-vpe/vpe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +4 -2
@@ -2012,9 +2012,11 @@ static int vpe_open(struct file *file) s_q_data->fmt = &vpe_formats[2 ]; s_q_data->width =1920 ; s_q_data->height =1080 ; - s_q_data->sizeimage[VPE_LUMA ] = (s_q_data->width * s_q_data->height * + s_q_data->bytesperline[VPE_LUMA ] = (s_q_data->width * s_q_data->fmt->vpdma_fmt[VPE_LUMA ]->depth) >>3 ; - s_q_data->colorspace =V4L2_COLORSPACE_SMPTE170M ; + s_q_data->sizeimage[VPE_LUMA ] = (s_q_data->bytesperline[VPE_LUMA ] * + s_q_data->height); + s_q_data->colorspace =V4L2_COLORSPACE_REC709 ; s_q_data->field =V4L2_FIELD_NONE ; s_q_data->c_rect.left =0 ; s_q_data->c_rect.top =0 ;
Signature · 1 line
1.8.3.2
Re: [PATCH v3 11/14] v4l: ti-vpe: Fix initial configuration queue data
Quoted 11 lines · Archit Taneja
The vpe output and capture queues are initially configured to default values in
vpe_open(). AG_FMTbefore anyS_FMTswill result in these values being populated.The colorspace and bytesperline parameter of this initial configuration are incorrect. This breaks compliance when as we get '
TRY_FMT(G_FMT)!=G_FMT'.Fix the initial queue configuration such that it wouldn't need to be fixed by
try_fmt.Signed-off-by Archit Taneja <[email protected]>
Quoted 23 lines
--- drivers/media/platform/ti-vpe/vpe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)drivers/media/platform/ti-vpe/vpe.c +4
-2@@ -2012,9 +2012,11 @@ static int vpe_open(struct file *file) s_q_data->fmt = &vpe_formats[2 ]; s_q_data->width =1920 ; s_q_data->height =1080 ; - s_q_data->sizeimage[VPE_LUMA ] = (s_q_data->width * s_q_data->height * + s_q_data->bytesperline[VPE_LUMA ] = (s_q_data->width * s_q_data->fmt->vpdma_fmt[VPE_LUMA ]->depth) >>3 ; - s_q_data->colorspace =V4L2_COLORSPACE_SMPTE170M ; + s_q_data->sizeimage[VPE_LUMA ] = (s_q_data->bytesperline[VPE_LUMA ] * + s_q_data->height); + s_q_data->colorspace =V4L2_COLORSPACE_REC709 ; s_q_data->field =V4L2_FIELD_NONE ; s_q_data->c_rect.left =0 ; s_q_data->c_rect.top =0 ;
PATCH v3 12/14 v4l: ti-vpe: zero out reserved fields in try_fmt
In reply to Archit TanejaZero out the reserved formats in v4l2_pix_format_mplane and v4l2_plane_pix_format members of the returned v4l2_format pointer when passed through TRY_FMT ioctl.
This ensures that the user doesn't interpret the non-zero fields as some data passed by the driver, and ensures compliance.
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +3 -0
@@ -1488,6 +1488,7 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, } } +memset (pix->reserved,0 ,sizeof (pix->reserved));for (i =0 ; i < pix->num_planes; i++) { plane_fmt = &pix->plane_fmt[i]; depth = fmt->vpdma_fmt[i]->depth;
@@ -1499,6 +1500,8 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, plane_fmt->sizeimage = (pix->height * pix->width * depth) >>3 ; + +memset (plane_fmt->reserved,0 ,sizeof (plane_fmt->reserved)); }return 0 ;
Signature · 1 line
1.8.3.2
Re: [PATCH v3 12/14] v4l: ti-vpe: zero out reserved fields in try_fmt
Quoted 8 lines · Archit Taneja
Zero out the reserved formats in
v4l2_pix_format_mplaneandv4l2_plane_pix_formatmembers of the returnedv4l2_formatpointer when passed throughTRY_FMTioctl.This ensures that the user doesn't interpret the non-zero fields as some data passed by the driver, and ensures compliance.
Signed-off-by Archit Taneja <[email protected]>
Quoted 26 lines
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)drivers/media/platform/ti-vpe/vpe.c +3
-0@@ -1488,6 +1488,7 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, } } +memset (pix->reserved,0 ,sizeof (pix->reserved));for (i =0 ; i < pix->num_planes; i++) { plane_fmt = &pix->plane_fmt[i]; depth = fmt->vpdma_fmt[i]->depth;@@ -1499,6 +1500,8 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, plane_fmt->sizeimage = (pix->height * pix->width * depth) >>3 ; + +memset (plane_fmt->reserved,0 ,sizeof (plane_fmt->reserved)); }return 0 ;
PATCH v3 13/14 v4l: ti-vpe: Set correct field parameter for output and capture buffers
In reply to Archit TanejaThe vpe driver wasn't setting the correct field parameter for dequed CAPTURE type buffers for the case where the captured output is progressive.
Set the field to V4L2_FIELD_NONE for the completed destination buffers when the captured output is progressive.
For OUTPUT type buffers, a queued buffer's field is forced to V4L2_FIELD_NONE if the pixel format(configured through s_fmt for the buffer type V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE specifies) the field type isn't interlaced. If the pixel format specified was V4L2_FIELD_ALTERNATE, and the queued buffer's field isn't V4L2_FIELD_TOP or V4L2_FIELD_BOTTOM, the vb2 buf_prepare op returns an error.
This ensures compliance, and that the dequeued output and captured buffers contain the field type that the driver used internally.
--- drivers/media/platform/ti-vpe/vpe.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +12 -1
@@ -1296,10 +1296,10 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) d_buf->timecode = s_buf->timecode; } d_buf->sequence = ctx->sequence; - d_buf->field = ctx->field; d_q_data = &ctx->q_data[Q_DATA_DST ];if (d_q_data->flags &Q_DATA_INTERLACED ) { + d_buf->field = ctx->field;if (ctx->field ==V4L2_FIELD_BOTTOM ) { ctx->sequence++; ctx->field =V4L2_FIELD_TOP ;
@@ -1308,6 +1308,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) ctx->field =V4L2_FIELD_BOTTOM ; } }else { + d_buf->field =V4L2_FIELD_NONE ; ctx->sequence++; }
@@ -1871,6 +1872,16 @@ static int vpe_buf_prepare(struct vb2_buffer *vb) q_data =get_q_data (ctx, vb->vb2_queue->type); num_planes = q_data->fmt->coplanar ?2 :1 ; +if (vb->vb2_queue->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) { +if (!(q_data->flags &Q_DATA_INTERLACED )) { + vb->v4l2_buf.field =V4L2_FIELD_NONE ; + }else { +if (vb->v4l2_buf.field !=V4L2_FIELD_TOP || + vb->v4l2_buf.field !=V4L2_FIELD_BOTTOM ) +return -EINVAL ; + } + } +for (i =0 ; i < num_planes; i++) {if (vb2_plane_size (vb, i) < q_data->sizeimage[i]) { vpe_err(ctx->dev,
Signature · 1 line
1.8.3.2
Re: [PATCH v3 13/14] v4l: ti-vpe: Set correct field parameter for output and capture buffers
Quoted 13 lines · Archit Taneja
The vpe driver wasn't setting the correct field parameter for dequed CAPTURE type buffers for the case where the captured output is progressive.
Set the field to
V4L2_FIELD_NONEfor the completed destination buffers when the captured output is progressive.For OUTPUT type buffers, a queued buffer's field is forced to
V4L2_FIELD_NONEif the pixelformat(configured through s_fmt for the buffer type V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE specifies)the field type isn't interlaced. If the pixel format specified wasV4L2_FIELD_ALTERNATE, and the queued buffer's field isn'tV4L2_FIELD_TOPorV4L2_FIELD_BOTTOM, the vb2buf_prepareop returns an error.
Quoted 4 lines
This ensures compliance, and that the dequeued output and captured buffers contain the field type that the driver used internally.
Signed-off-by Archit Taneja <[email protected]>
Quoted 46 lines
--- drivers/media/platform/ti-vpe/vpe.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)drivers/media/platform/ti-vpe/vpe.c +12
-1@@ -1296,10 +1296,10 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) d_buf->timecode = s_buf->timecode; } d_buf->sequence = ctx->sequence; - d_buf->field = ctx->field; d_q_data = &ctx->q_data[Q_DATA_DST ];if (d_q_data->flags &Q_DATA_INTERLACED ) { + d_buf->field = ctx->field;if (ctx->field ==V4L2_FIELD_BOTTOM ) { ctx->sequence++; ctx->field =V4L2_FIELD_TOP ;@@ -1308,6 +1308,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) ctx->field =V4L2_FIELD_BOTTOM ; } }else { + d_buf->field =V4L2_FIELD_NONE ; ctx->sequence++; }@@ -1871,6 +1872,16 @@ static int vpe_buf_prepare(struct vb2_buffer *vb) q_data =get_q_data (ctx, vb->vb2_queue->type); num_planes = q_data->fmt->coplanar ?2 :1 ; +if (vb->vb2_queue->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) { +if (!(q_data->flags &Q_DATA_INTERLACED )) { + vb->v4l2_buf.field =V4L2_FIELD_NONE ; + }else { +if (vb->v4l2_buf.field !=V4L2_FIELD_TOP || + vb->v4l2_buf.field !=V4L2_FIELD_BOTTOM ) +return -EINVAL ; + } + } +for (i =0 ; i < num_planes; i++) {if (vb2_plane_size (vb, i) < q_data->sizeimage[i]) { vpe_err(ctx->dev,
PATCH v3 14/14 v4l: ti-vpe: retain v4l2_buffer flags for captured buffers
In reply to Archit TanejaThe dequed CAPTURE_MPLANE type buffers don't contain the flags that the originally queued OUTPUT_MPLANE type buffers have. This breaks compliance.
Copy the source v4l2_buffer flags to the destination v4l2_buffer flags before they are dequed.
--- drivers/media/platform/ti-vpe/vpe.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +4 -5
@@ -1288,13 +1288,12 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) s_buf = &s_vb->v4l2_buf; d_buf = &d_vb->v4l2_buf; + d_buf->flags = s_buf->flags; + d_buf->timestamp = s_buf->timestamp; - d_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK ; - d_buf->flags |= s_buf->flags &V4L2_BUF_FLAG_TSTAMP_SRC_MASK ; -if (s_buf->flags &V4L2_BUF_FLAG_TIMECODE ) { - d_buf->flags |=V4L2_BUF_FLAG_TIMECODE ; +if (s_buf->flags &V4L2_BUF_FLAG_TIMECODE ) d_buf->timecode = s_buf->timecode; - } + d_buf->sequence = ctx->sequence; d_q_data = &ctx->q_data[Q_DATA_DST ];
Signature · 1 line
1.8.3.2
Re: [PATCH v3 14/14] v4l: ti-vpe: retain v4l2_buffer flags for captured buffers
Quoted 7 lines · Archit Taneja
The dequed
CAPTURE_MPLANEtype buffers don't contain the flags that the originally queuedOUTPUT_MPLANEtype buffers have. This breaks compliance.Copy the source
v4l2_bufferflags to the destinationv4l2_bufferflags before they are dequed.Signed-off-by Archit Taneja <[email protected]>
Quoted 27 lines
--- drivers/media/platform/ti-vpe/vpe.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)drivers/media/platform/ti-vpe/vpe.c +4
-5@@ -1288,13 +1288,12 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) s_buf = &s_vb->v4l2_buf; d_buf = &d_vb->v4l2_buf; + d_buf->flags = s_buf->flags; + d_buf->timestamp = s_buf->timestamp; - d_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK ; - d_buf->flags |= s_buf->flags &V4L2_BUF_FLAG_TSTAMP_SRC_MASK ; -if (s_buf->flags &V4L2_BUF_FLAG_TIMECODE ) { - d_buf->flags |=V4L2_BUF_FLAG_TIMECODE ; +if (s_buf->flags &V4L2_BUF_FLAG_TIMECODE ) d_buf->timecode = s_buf->timecode; - } + d_buf->sequence = ctx->sequence; d_q_data = &ctx->q_data[Q_DATA_DST ];
v4 cover v4l: ti-vpe: Some VPE fixes and enhancements
In reply to Archit TanejaThis patch set mainly consists of minor fixes for the VPE driver. These fixes ensure the following:
- The VPE module can be inserted and removed successively.
- Make sure that smaller resolutions like qcif work correctly.
- Prevent race condition between firmware loading and an open call to the v4l2 device.
- Prevent the possibility of output m2m queue not having sufficient 'ready' buffers.
- Some VPDMA data descriptor fields weren't understood correctly before. They are now used correctly.
The rest of the patches add some minor features like DMA buf support and cropping/composing.
Reference branch:
[email protected]:boddob/linux.git vpe_for_315
Changes in v4:
- More legible code for selection API
- Stricter checking for target type vs crop type in g_selection
- Minor fix in patch 13/14, there was a logical bug in buf_prepare when checking validity of top and bottom fields.
Changes in v3:
- improvements in selection API patch.
- querycap fixes for v4l2 compliance.
- v4l2_buffer 'field' and flags' fixes for compliance.
- fixes in try_fmt vpe_open for compliance.
- rename a IOMEM resource for better DT compatibility.
Changes in v2:
- selection API used instead of older cropping API.
- Typo fix.
- Some changes in patch 6/7 to support composing on the capture side of VPE.
Archit Taneja (14):
v4l: ti-vpe: Make sure in job_ready that we have the needed number of
dst_bufs
v4l: ti-vpe: register video device only when firmware is loaded
v4l: ti-vpe: Use video_device_release_empty
v4l: ti-vpe: Allow DMABUF buffer type support
v4l: ti-vpe: Allow usage of smaller images
v4l: ti-vpe: Fix some params in VPE data descriptors
v4l: ti-vpe: Add selection API in VPE driver
v4l: ti-vpe: Rename csc memory resource name
v4l: ti-vpe: report correct capabilities in querycap
v4l: ti-vpe: Use correct bus_info name for the device in querycap
v4l: ti-vpe: Fix initial configuration queue data
v4l: ti-vpe: zero out reserved fields in try_fmt
v4l: ti-vpe: Set correct field parameter for output and capture
buffers
v4l: ti-vpe: retain v4l2_buffer flags for captured buffers
drivers/media/platform/ti-vpe/csc.c | 2 +- drivers/media/platform/ti-vpe/vpdma.c | 68 ++++++--- drivers/media/platform/ti-vpe/vpdma.h | 17 ++- drivers/media/platform/ti-vpe/vpe.c | 272 ++++++++++++++++++++++++++++------ 4 files changed, 290 insertions(+), 69 deletions(-)
Signature · 1 line
1.8.3.2
PATCH v4 1/14 v4l: ti-vpe: Make sure in job_ready that we have the needed number of dst_bufs
VPE has a ctrl parameter which decides how many mem to mem transactions the active job from the job queue can perform.
The driver's job_ready() made sure that the number of ready source buffers are sufficient for the job to execute successfully. But it didn't make sure if there are sufficient ready destination buffers in the capture queue for the VPE output.
If the time taken by VPE to process a single frame is really slow, then it's possible that we don't need to imply such a restriction on the dst queue, but really fast transactions(small resolution, no de-interlacing) may cause us to hit the condition where we don't have any free buffers for the VPE to write on.
Add the extra check in job_ready() to make sure we have the sufficient amount of destination buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +3 -0
@@ -887,6 +887,9 @@ static int job_ready(void *priv)if (v4l2_m2m_num_src_bufs_ready (ctx->m2m_ctx) < needed)return 0 ; +if (v4l2_m2m_num_dst_bufs_ready (ctx->m2m_ctx) < needed) +return 0 ; +return 1 ; }
Signature · 1 line
1.8.3.2
RE: [PATCH v4 01/14] v4l: ti-vpe: Make sure in job_ready that we have the needed number of dst_bufs
Quoted 17 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Thursday, March 13, 2014 12:44 PMVPE has a ctrl parameter which decides how many mem to mem transactions the active job from the job queue can perform.
The driver's
job_ready()made sure that the number of ready source buffers are sufficient for the job to execute successfully. But it didn't make sure if there are sufficient ready destination buffers in the capture queue for the VPE output.If the time taken by VPE to process a single frame is really slow, then it's possible that we don't need to imply such a restriction on the dst queue, but really fast
transactions(small resolution, no de-interlacing)may cause us to hit the condition where we don't have any free buffers for the VPE to write on.
Quoted 4 lines
Add the extra check in
job_ready()to make sure we have the sufficient amount of destination buffers.Signed-off-by Archit Taneja <[email protected]>
Quoted 21 lines
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)drivers/media/platform/ti-vpe/vpe.c +3
-1@@ -887,6 +887,9 @@ static int job_ready(void *priv)if (v4l2_m2m_num_src_bufs_ready (ctx->m2m_ctx) < needed)return 0 ; +if (v4l2_m2m_num_dst_bufs_ready (ctx->m2m_ctx) < needed) +return 0 ; +return 1 ; } --1.8.3.2
PATCH v4 2/14 v4l: ti-vpe: register video device only when firmware is loaded
In reply to Archit Tanejavpe fops(vpe_open in particular) should be called only when VPDMA firmware is loaded. File operations on the video device are possible the moment it is registered.
Currently, we register the video device for VPE at driver probe, after calling a vpdma helper to initialize VPDMA and load firmware. This function is non-blocking(it calls request_firmware_nowait()), and doesn't ensure that the firmware is actually loaded when it returns.
We remove the device registration from vpe probe, and move it to a callback provided by the vpe driver to the vpdma library, through vpdma_create().
The ready field in vpdma_data is no longer needed since we always have firmware loaded before the device is registered.
A minor problem with this approach is that if the video_register_device fails(which doesn't really happen), the vpe platform device would be registered. however, there won't be any v4l2 device corresponding to it.
--- drivers/media/platform/ti-vpe/vpdma.c | 8 +++-- drivers/media/platform/ti-vpe/vpdma.h | 7 +++-- drivers/media/platform/ti-vpe/vpe.c | 55 ++++++++++++++++++++--------------- 3 files changed, 41 insertions(+), 29 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +5 -3
@@ -781,7 +781,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context)/* already initialized */ if (read_field_reg (vpdma,VPDMA_LIST_ATTR ,VPDMA_LIST_RDY_MASK ,VPDMA_LIST_RDY_SHFT )) { - vpdma->ready = true; + vpdma->cb (vpdma->pdev);return ; }
@@ -811,7 +811,7 @@ static void vpdma_firmware_cb(const struct firmware *f, void *context) goto free_buf; } - vpdma->ready = true; + vpdma->cb (vpdma->pdev); free_buf:vpdma_unmap_desc_buf (vpdma, &fw_dma_buf);
@@ -839,7 +839,8 @@ static int vpdma_load_firmware(struct vpdma_data *vpdma)return 0 ; } -struct vpdma_data *vpdma_create (struct platform_device *pdev) +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev)) {struct resource *res;struct vpdma_data *vpdma;
@@ -854,6 +855,7 @@ struct vpdma_data *vpdma_create(struct platform_device *pdev) } vpdma->pdev = pdev; + vpdma->cb = cb; res =platform_get_resource_byname (pdev,IORESOURCE_MEM ,"vpdma" );if (res ==NULL ) {
drivers/media/platform/ti-vpe/vpdma.h +4 -3
@@ -35,8 +35,8 @@ struct vpdma_data {struct platform_device *pdev; -/* tells whether vpdma firmware is loaded or not */ -bool ready; +/* callback to VPE driver when the firmware is loaded */ +void (*cb)(struct platform_device *pdev); };enum vpdma_data_format_type {
@@ -208,6 +208,7 @@ void vpdma_set_frame_start_event(struct vpdma_data *vpdma,void vpdma_dump_regs (struct vpdma_data *vpdma);/* initialize vpdma, passed with VPE's platform device pointer */ -struct vpdma_data *vpdma_create (struct platform_device *pdev); +struct vpdma_data *vpdma_create (struct platform_device *pdev, +void (*cb)(struct platform_device *pdev));#endif
drivers/media/platform/ti-vpe/vpe.c +32 -23
81 lines not on this page · raw message
Signature · 1 line
1.8.3.2
PATCH v4 3/14 v4l: ti-vpe: Use video_device_release_empty
In reply to Archit TanejaThe video_device struct is currently embedded in the driver data struct vpe_dev. A vpe_dev instance is allocated by the driver, and the memory for the vfd is a part of this struct.
The v4l2 core, however, manages the removal of the vfd region, through the video_device's .release() op, which currently is the helper video_device_release. This causes memory corruption, and leads to issues when we try to re-insert the vpe module.
Use the video_device_release_empty helper function instead.
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +1 -1
@@ -2000,7 +2000,7 @@ static struct video_device vpe_videodev = { .fops = &vpe_fops, .ioctl_ops = &vpe_ioctl_ops, .minor = -1, - .release = video_device_release, + .release = video_device_release_empty, .vfl_dir = VFL_DIR_M2M, };
Signature · 1 line
1.8.3.2
PATCH v4 4/14 v4l: ti-vpe: Allow DMABUF buffer type support
In reply to Archit TanejaFor OMAP and DRA7x, we generally allocate video and graphics buffers through omapdrm since the corresponding omap-gem driver provides DMM-Tiler backed contiguous buffers. omapdrm is a dma-buf exporter. These buffers are used by other drivers in the video pipeline.
Add VB2_DMABUF flag to the io_modes of the vb2 output and capture queues. This allows the driver to import dma shared buffers.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -1770,7 +1770,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (src_vq,0 ,sizeof (*src_vq)); src_vq->type =V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ; - src_vq->io_modes =VB2_MMAP ; + src_vq->io_modes =VB2_MMAP |VB2_DMABUF ; src_vq->drv_priv = ctx; src_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); src_vq->ops = &vpe_qops;
@@ -1783,7 +1783,7 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,memset (dst_vq,0 ,sizeof (*dst_vq)); dst_vq->type =V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE ; - dst_vq->io_modes =VB2_MMAP ; + dst_vq->io_modes =VB2_MMAP |VB2_DMABUF ; dst_vq->drv_priv = ctx; dst_vq->buf_struct_size =sizeof (struct v4l2_m2m_buffer ); dst_vq->ops = &vpe_qops;
Signature · 1 line
1.8.3.2
PATCH v4 5/14 v4l: ti-vpe: Allow usage of smaller images
In reply to Archit TanejaThe minimum width and height for VPE input/output was kept as 128 pixels. VPE doesn't have a constraint on the image height, it requires the image width to be at least 16 bytes.
Change the minimum supported dimensions to 32x32. This allows us to de-interlace qcif content. A smaller image size than 32x32 didn't make much sense, so stopped at this.
--- drivers/media/platform/ti-vpe/vpe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +2 -2
@@ -49,8 +49,8 @@#define VPE_MODULE_NAME "vpe"/* minimum and maximum frame sizes */ -#define MIN_W 128 -#define MIN_H 128 +#define MIN_W 32 +#define MIN_H 32#define MAX_W 1920#define MAX_H 1080
Signature · 1 line
1.8.3.2
PATCH v4 6/14 v4l: ti-vpe: Fix some params in VPE data descriptors
In reply to Archit TanejaSome parameters of the VPE descriptors were understood incorrectly. They are now fixed. The fixes are explained as follows:
- When adding an inbound data descriptor to the VPDMA descriptor list, we intend to use c_rect as the cropped region fetched by VPDMA. Therefore, c_rect->width shouldn't be used to calculate the line stride, the original image width should be used for that. We add a 'width' argument which gives the buffer width in memory.
- frame_width and frame_height describe the complete width and height of the client to which the channel is connected. If there are multiple channels fetching data and providing to the same client, the above 2 arguments should be the width and height of the region covered by all the channels. In the case where there is only one channel providing pixel data to the client (like in VPE), frame_width and frame_height should be the cropped width and cropped height respectively. The calculation of these params is done in the vpe driver now.
- start_h and start_v is also used in the case of multiple channels to describe where each channel should start filling pixel data. We don't use this in VPE, and pass 0s to the vpdma_add_in_dtd() helper.
- Some minor changes are made to the vpdma_add_out_dtd() helper. The c_rect param is used for specifying the 'composition' target, and 'width' is added to calculate the line stride.
--- drivers/media/platform/ti-vpe/vpdma.c | 60 +++++++++++++++++++++++++++-------- drivers/media/platform/ti-vpe/vpdma.h | 10 +++--- drivers/media/platform/ti-vpe/vpe.c | 18 +++++++---- 3 files changed, 64 insertions(+), 24 deletions(-)
drivers/media/platform/ti-vpe/vpdma.c +46 -14
@@ -614,8 +614,17 @@ static void dump_dtd(struct vpdma_dtd *dtd)/* * append an outbound data transfer descriptor to the given descriptor list, * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory +* @c_rect: compose params of output image +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* flags: VPDMA flags to configure some descriptor fileds */ -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags) {
@@ -623,6 +632,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,int field =0 ;int notify =1 ;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int depth = fmt->depth;int stride;struct vpdma_dtd *dtd;
@@ -630,11 +640,15 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && - fmt->data_type ==DATA_TYPE_C420 ) + fmt->data_type ==DATA_TYPE_C420 ) { + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; + } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -664,31 +678,48 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,/* * append an inbound data transfer descriptor to the given descriptor list, * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel +* +* @list: vpdma desc list to which we add this decriptor +* @width: width of the image in pixels in memory(not the cropped width) +* @c_rect: crop params of input image +* @fmt: vpdma data format of the buffer +* dma_addr: dma address as seen by VPDMA +* chan: VPDMA channel +* field: top or bottom field info of the input image +* flags: VPDMA flags to configure some descriptor fileds +* frame_width/height: the complete width/height of the image presented to the +* client (this makes sense when multiple channels are +* connected to the same client, forming a larger frame) +* start_h, start_v: position where the given channel starts providing pixel +* data to the client (makes sense when multiple channels +* contribute to the client) */ -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags) +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v) {int priority =0 ;int notify =1 ;int depth = fmt->depth;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int stride; -int height = c_rect->height;struct vpdma_dtd *dtd; channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && fmt->data_type ==DATA_TYPE_C420 ) { - height >>=1 ; - frame_height >>=1 ; + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
@@ -701,13 +732,14 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, !!(flags &VPDMA_DATA_ODD_LINE_SKIP ), stride); - dtd->xfer_length_height =dtd_xfer_length_height (c_rect->width, height); + dtd->xfer_length_height =dtd_xfer_length_height (rect.width, + rect.height); dtd->start_addr = (u32 ) dma_addr; dtd->pkt_ctl =dtd_pkt_ctl (!!(flags &VPDMA_DATA_MODE_TILED ),DTD_DIR_IN , channel, priority, next_chan); dtd->frame_width_height =dtd_frame_width_height (frame_width, frame_height); - dtd->start_h_v =dtd_start_h_v (c_rect->left, c_rect->top); + dtd->start_h_v =dtd_start_h_v (start_h, start_v); dtd->client_attr0 =0 ; dtd->client_attr1 =0 ;
drivers/media/platform/ti-vpe/vpdma.h +6 -4
@@ -186,13 +186,15 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, struct vpdma_buf *adb);void vpdma_add_sync_on_channel_ctd (struct vpdma_desc_list *list,enum vpdma_channel chan); -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags); -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags); +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v);/* vpdma list interrupt management */ void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
drivers/media/platform/ti-vpe/vpe.c +12 -6
@@ -986,7 +986,6 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->dst_vb; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = !ctx->src_mv_buf_selector;
@@ -1015,8 +1014,8 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_out_dtd (&ctx->desc_list, c_rect, vpdma_fmt, dma_addr, - p_data->channel, flags); +vpdma_add_out_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, flags); }static void add_in_dtd (struct vpe_ctx *ctx,int port)
@@ -1024,11 +1023,11 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = ctx->src_mv_buf_selector;int field = vb->v4l2_buf.field ==V4L2_FIELD_BOTTOM ; +int frame_width, frame_height;dma_addr_t dma_addr;u32 flags =0 ;
@@ -1055,8 +1054,15 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_in_dtd (&ctx->desc_list, q_data->width, q_data->height, - c_rect, vpdma_fmt, dma_addr, p_data->channel, field, flags); + frame_width = q_data->c_rect.width; + frame_height = q_data->c_rect.height; + +if (p_data->vb_part && fmt->fourcc ==V4L2_PIX_FMT_NV12 ) + frame_height /=2 ; + +vpdma_add_in_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, field, flags, frame_width, + frame_height,0 ,0 ); }/*
Signature · 1 line
1.8.3.2
RE: [PATCH v4 06/14] v4l: ti-vpe: Fix some params in VPE data descriptors
Hi,
Quoted 42 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Thursday, March 13, 2014 12:44 PM
To: [email protected]; [email protected]
Cc: [email protected]; [email protected]; Archit Taneja
Subject: [PATCH v4 06/14] v4l: ti-vpe: Fix some params in VPE data descriptorsSome parameters of the VPE descriptors were understood incorrectly. They are now fixed. The fixes are explained as follows:
- When adding an inbound data descriptor to the VPDMA descriptor list, we intend
to usec_rectas the cropped region fetched by VPDMA. Therefore,c_rect->width
shouldn't be used to calculate the line stride, the original image
width
should be used for that. We add a 'width' argument which gives the
buffer
width in memory.-
frame_widthandframe_heightdescribe the complete width and height of the
client to which the channel is connected. If there are multiple
channels
fetching data and providing to the same client, the above 2 arguments
should
be the width and height of the region covered by all the channels. In
the case
where there is only one channel providing pixel data to the client (like in VPE),frame_widthandframe_heightshould be the cropped
width and
cropped height respectively. The calculation of these params is done
in the
vpe driver now.-
start_handstart_vis also used in the case of multiple channels to describe
where each channel should start filling pixel data. We don't use this
in VPE,
and pass 0s to thevpdma_add_in_dtd()helper.
Quoted 5 lines
- Some minor changes are made to the
vpdma_add_out_dtd()helper. Thec_rect
param is used for specifying the 'composition' target, and 'width'
is added
to calculate the line stride.
This patch looks ok. Passes checkpatch and compiles. I can't say much more as I have limited knowledge of the internals of VPE and don't have the hardware.
Quoted 1 line
Signed-off-by Archit Taneja <[email protected]>
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Quoted 76 lines
--- drivers/media/platform/ti-vpe/vpdma.c | 60 +++++++++++++++++++++++++++-------- drivers/media/platform/ti-vpe/vpdma.h | 10 +++--- drivers/media/platform/ti-vpe/vpe.c | 18 +++++++---- 3 files changed, 64 insertions(+), 24 deletions(-)drivers/media/platform/ti-vpe/vpdma.c +0
-0@@ -614,8 +614,17 @@ static void dump_dtd(struct vpdma_dtd *dtd)/* * append an outbound data transfer descriptor to the given descriptor list, * this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel
+ *
+ * @list: vpdma desc list to which we add this decriptor
+ * @width: width of the image in pixels in memory
+ * @c_rect: compose params of output image
+ * @fmt: vpdma data format of the buffer
+ *dma_addr: dma address as seen by VPDMA
+ * chan: VPDMA channel
+ * flags: VPDMA flags to configure some descriptor fileds */
-void vpdma_add_out_dtd(structvpdma_desc_list*list, structv4l2_rect*c_rect,drivers/media/platform/ti-vpe/vpdma.c +3
-0+void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags) {@@ -623,6 +632,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list,struct v4l2_rect *c_rect, int field = 0;int notify =1 ;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int depth = fmt->depth;int stride;drivers/media/platform/ti-vpe/vpdma.c +7
-3struct vpdma_dtd *dtd;@@ -630,11 +640,15 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect, channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && - fmt->data_type ==DATA_TYPE_C420 ) + fmt->data_type ==DATA_TYPE_C420 ) { + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; + } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;drivers/media/platform/ti-vpe/vpdma.c +0
-0WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));@@ -664,31 +678,48 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,/* * append an inbound data transfer descriptor to the given descriptor list, * this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel
+ *
+ * @list: vpdma desc list to which we add this decriptor
+ * @width: width of the image in pixels in memory(not the cropped
+ width)
+ * @c_rect: crop params of input image
+ * @fmt: vpdma data format of the buffer
Quoted 8 lines
+ *
dma_addr: dma address as seen by VPDMA
+ * chan: VPDMA channel
+ * field: top or bottom field info of the input image
+ * flags: VPDMA flags to configure some descriptor fileds
+ * frame_width/height: the complete width/height of the image presented to the
+ * client (this makes sense when multiple channels are
+ * connected to the same client, forming a larger
frame)
Quoted 45 lines
+ *
start_h,start_v: position where the given channel starts providing pixel
+ * data to the client (makes sense when multiple
channels
+ * contribute to the client)
*/drivers/media/platform/ti-vpe/vpdma.c +3
-3-void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags) + enum vpdma_channel chan, int field, u32 flags, int
frame_width,drivers/media/platform/ti-vpe/vpdma.c +7
-5+ int frame_height, int start_h, int start_v) { int priority = 0;int notify =1 ;int depth = fmt->depth;int channel, next_chan; +struct v4l2_rect rect = *c_rect;int stride; -int height = c_rect->height;struct vpdma_dtd *dtd; channel = next_chan = chan_info[chan].num;if (fmt->type ==VPDMA_DATA_FMT_TYPE_YUV && fmt->data_type ==DATA_TYPE_C420 ) { - height >>=1 ; - frame_height >>=1 ; + rect.height >>=1 ; + rect.top >>=1 ; depth =8 ; } - stride =ALIGN ((depth * c_rect->width) >>3 ,VPDMA_STRIDE_ALIGN ); - dma_addr += (c_rect->left * depth) >>3 ; + stride =ALIGN ((depth * width) >>3 ,VPDMA_STRIDE_ALIGN ); + + dma_addr += rect.top * stride + (rect.left * depth >>3 ); dtd = list->next;WARN_ON ((void *)(dtd +1 ) > (list->buf.addr + list->buf.size));
drivers/media/platform/ti-vpe/vpdma.c void vpdma_add_in_dtd(struct vpdma_desc_list · line 733
Quoted 2 lines
drivers/media/platform/ti-vpe/vpdma.c +0
-0@@ -701,13 +732,14 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width, !!(flags &
VPDMA_DATA_ODD_LINE_SKIP),
Quoted 104 lines
drivers/media/platform/ti-vpe/vpdma.c +3
-2stride); - dtd->xfer_length_height =dtd_xfer_length_height (c_rect->width, height); + dtd->xfer_length_height =dtd_xfer_length_height (rect.width, + rect.height); dtd->start_addr = (u32 ) dma_addr; dtd->pkt_ctl =dtd_pkt_ctl (!!(flags &VPDMA_DATA_MODE_TILED ),DTD_DIR_IN , channel, priority, next_chan); dtd->frame_width_height =dtd_frame_width_height (frame_width, frame_height); - dtd->start_h_v =dtd_start_h_v (c_rect->left, c_rect->top); + dtd->start_h_v =dtd_start_h_v (start_h, start_v); dtd->client_attr0 =0 ;drivers/media/platform/ti-vpe/vpdma.c +0
-0dtd->client_attr1 =0 ;drivers/media/platform/ti-vpe/vpdma.h +6
-4@@ -186,13 +186,15 @@ void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client, struct vpdma_buf *adb);void vpdma_add_sync_on_channel_ctd (struct vpdma_desc_list *list,enum vpdma_channel chan); -void vpdma_add_out_dtd (struct vpdma_desc_list *list,struct v4l2_rect *c_rect, +void vpdma_add_out_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr,enum vpdma_channel chan,u32 flags); -void vpdma_add_in_dtd (struct vpdma_desc_list *list,int frame_width, -int frame_height,struct v4l2_rect *c_rect, +void vpdma_add_in_dtd (struct vpdma_desc_list *list,int width, +const struct v4l2_rect *c_rect,const struct vpdma_data_format *fmt,dma_addr_t dma_addr, -enum vpdma_channel chan,int field,u32 flags); +enum vpdma_channel chan,int field,u32 flags,int frame_width, +int frame_height,int start_h,int start_v);/* vpdma list interrupt management */
void vpdma_enable_list_complete_irq(structvpdma_data*vpdma, intlist_num, diff --gita/drivers/media/platform/ti-vpe/vpe.cb/drivers/media/platform/ti-vpe/vpe.c
index dbdc338..ece9b96 100644drivers/media/platform/ti-vpe/vpe.c +0
-1@@ -986,7 +986,6 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port)struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_DST ];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->dst_vb; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;drivers/media/platform/ti-vpe/vpe.c +14
-5int mv_buf_selector = !ctx->src_mv_buf_selector; @@ -1015,8 +1014,8 @@ static void add_out_dtd(struct vpe_ctx *ctx, int port) if (q_data->flags & Q_DATA_MODE_TILED) flags |= VPDMA_DATA_MODE_TILED; -vpdma_add_out_dtd (&ctx->desc_list, c_rect, vpdma_fmt, dma_addr, - p_data->channel, flags); +vpdma_add_out_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, flags); } static void add_in_dtd(struct vpe_ctx *ctx, int port) @@ -1024,11 +1023,11 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port) struct vpe_q_data *q_data = &ctx->q_data[Q_DATA_SRC];const struct vpe_port_data *p_data = &port_data[port];struct vb2_buffer *vb = ctx->src_vbs[p_data->vb_index]; -struct v4l2_rect *c_rect = &q_data->c_rect;struct vpe_fmt *fmt = q_data->fmt;const struct vpdma_data_format *vpdma_fmt;int mv_buf_selector = ctx->src_mv_buf_selector;int field = vb->v4l2_buf.field ==V4L2_FIELD_BOTTOM ; +int frame_width, frame_height;dma_addr_t dma_addr;u32 flags =0 ;@@ -1055,8 +1054,15 @@ static void add_in_dtd(struct vpe_ctx *ctx, int port)if (q_data->flags &Q_DATA_MODE_TILED ) flags |=VPDMA_DATA_MODE_TILED ; -vpdma_add_in_dtd (&ctx->desc_list, q_data->width, q_data->height, - c_rect, vpdma_fmt, dma_addr, p_data->channel, field, flags); + frame_width = q_data->c_rect.width; + frame_height = q_data->c_rect.height; + +if (p_data->vb_part && fmt->fourcc ==V4L2_PIX_FMT_NV12 ) + frame_height /=2 ; + +vpdma_add_in_dtd (&ctx->desc_list, q_data->width, &q_data->c_rect, + vpdma_fmt, dma_addr, p_data->channel, field, flags, frame_width, + frame_height,0 ,0 ); }/*
--
1.8.3.2
PATCH v4 7/14 v4l: ti-vpe: Add selection API in VPE driver
In reply to Archit TanejaAdd selection ioctl ops. For VPE, cropping makes sense only for the input to VPE(or V4L2_BUF_TYPE_VIDEO_OUTPUT/MPLANE buffers) and composing makes sense only for the output of VPE(or V4L2_BUF_TYPE_VIDEO_CAPTURE/MPLANE buffers).
For the CAPTURE type, V4L2_SEL_TGT_COMPOSE results in VPE writing the output in a rectangle within the capture buffer. For the OUTPUT type, V4L2_SEL_TGT_CROP results in selecting a rectangle region within the source buffer.
Setting the crop/compose rectangles should successfully result in re-configuration of registers which are affected when either source or destination dimensions change, set_srcdst_params() is called for this purpose.
--- drivers/media/platform/ti-vpe/vpe.c | 150 ++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +150 -0
@@ -410,8 +410,10 @@ static struct vpe_q_data *get_q_data(struct vpe_ctx *ctx, {switch (type) {case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE : +case V4L2_BUF_TYPE_VIDEO_OUTPUT :return &ctx->q_data[Q_DATA_SRC ];case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE : +case V4L2_BUF_TYPE_VIDEO_CAPTURE :return &ctx->q_data[Q_DATA_DST ];default :BUG ();
@@ -1587,6 +1589,151 @@ static int vpe_s_fmt(struct file *file, void *priv, struct v4l2_format *f)return set_srcdst_params (ctx); } +static int __vpe_try_selection (struct vpe_ctx *ctx,struct v4l2_selection *s) +{ +struct vpe_q_data *q_data; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE : +/* +* COMPOSE target is only valid for capture buffer type, return +* error for output buffer type +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) +return -EINVAL ; +break ; +case V4L2_SEL_TGT_CROP : +/* +* CROP target is only valid for output buffer type, return +* error for capture buffer type +*/ +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) +return -EINVAL ; +break ; +/* +* bound and default crop/compose targets are invalid targets to +* try/set +*/ +default : +return -EINVAL ; + } + +if (s->r.top <0 || s->r.left <0 ) { +vpe_err (ctx->dev,"negative values for top and left\n" ); + s->r.top = s->r.left =0 ; + } + +v4l_bound_align_image (&s->r.width,MIN_W , q_data->width,1 , + &s->r.height,MIN_H , q_data->height,H_ALIGN ,S_ALIGN ); + +/* adjust left/top if cropping rectangle is out of bounds */ +if (s->r.left + s->r.width > q_data->width) + s->r.left = q_data->width - s->r.width; +if (s->r.top + s->r.height > q_data->height) + s->r.top = q_data->height - s->r.height; + +return 0 ; +} + +static int vpe_g_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +bool use_c_rect = false; + +if ((s->type !=V4L2_BUF_TYPE_VIDEO_CAPTURE ) && + (s->type !=V4L2_BUF_TYPE_VIDEO_OUTPUT )) +return -EINVAL ; + + q_data =get_q_data (ctx, s->type); +if (!q_data) +return -EINVAL ; + +switch (s->target) { +case V4L2_SEL_TGT_COMPOSE_DEFAULT : +case V4L2_SEL_TGT_COMPOSE_BOUNDS : +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) +return -EINVAL ; +break ; +case V4L2_SEL_TGT_CROP_BOUNDS : +case V4L2_SEL_TGT_CROP_DEFAULT : +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) +return -EINVAL ; +break ; +case V4L2_SEL_TGT_COMPOSE : +if (s->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT ) +return -EINVAL ; + use_c_rect = true; +break ; +case V4L2_SEL_TGT_CROP : +if (s->type ==V4L2_BUF_TYPE_VIDEO_CAPTURE ) +return -EINVAL ; + use_c_rect = true; +break ; +default : +return -EINVAL ; + } + +if (use_c_rect) { +/* +* for CROP/COMPOSE target type, return c_rect params from the +* respective buffer type +*/ + s->r = q_data->c_rect; + }else { +/* +* for DEFAULT/BOUNDS target type, return width and height from +* S_FMT of the respective buffer type +*/ + s->r.left =0 ; + s->r.top =0 ; + s->r.width = q_data->width; + s->r.height = q_data->height; + } + +return 0 ; +} + + +static int vpe_s_selection (struct file *file,void *fh, +struct v4l2_selection *s) +{ +struct vpe_ctx *ctx =file2ctx (file); +struct vpe_q_data *q_data; +struct v4l2_selection sel = *s; +int ret; + + ret =__vpe_try_selection (ctx, &sel); +if (ret) +return ret; + + q_data =get_q_data (ctx, sel.type); +if (!q_data) +return -EINVAL ; + +if ((q_data->c_rect.left == sel.r.left) && + (q_data->c_rect.top == sel.r.top) && + (q_data->c_rect.width == sel.r.width) && + (q_data->c_rect.height == sel.r.height)) { +vpe_dbg (ctx->dev, +"requested crop/compose values are already set\n" ); +return 0 ; + } + + q_data->c_rect = sel.r; + +return set_srcdst_params (ctx); +} +static int vpe_reqbufs (struct file *file,void *priv,struct v4l2_requestbuffers *reqbufs) {
@@ -1674,6 +1821,9 @@ static const struct v4l2_ioctl_ops vpe_ioctl_ops = { .vidioc_try_fmt_vid_out_mplane = vpe_try_fmt, .vidioc_s_fmt_vid_out_mplane = vpe_s_fmt, + .vidioc_g_selection = vpe_g_selection, + .vidioc_s_selection = vpe_s_selection, + .vidioc_reqbufs = vpe_reqbufs, .vidioc_querybuf = vpe_querybuf,
Signature · 1 line
1.8.3.2
PATCH v4 8/14 v4l: ti-vpe: Rename csc memory resource name
In reply to Archit TanejaRename the memory block resource "vpe_csc" to "csc" since it also exists within the VIP IP block. This would make the name more generic, and both VPE and VIP DT nodes in the future can use it.
--- drivers/media/platform/ti-vpe/csc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/csc.c +1 -1
@@ -180,7 +180,7 @@ struct csc_data *csc_create(struct platform_device *pdev) csc->pdev = pdev; csc->res =platform_get_resource_byname (pdev,IORESOURCE_MEM , -"vpe_csc" ); +"csc" );if (csc->res ==NULL ) {dev_err (&pdev->dev,"missing platform resources data\n" );return ERR_PTR (-ENODEV );
Signature · 1 line
1.8.3.2
RE: [PATCH v4 08/14] v4l: ti-vpe: Rename csc memory resource name
Hi,
Quoted 6 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Thursday, March 13, 2014 12:44 PMRename the memory block resource "
vpe_csc" to "csc" since it also exists within the VIP IP block. This would make the name more generic, and both VPE and VIP DT nodes in the future can use it.
I understand that this is not yet used in any public dts files. Right?
Best wishes,
Signature · 2 lines
Kamil Debski Samsung R&D Institute Poland
Quoted 23 lines
Signed-off-by Archit Taneja <[email protected]>--- drivers/media/platform/ti-vpe/csc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)drivers/media/platform/ti-vpe/csc.c +1
-1@@ -180,7 +180,7 @@ struct csc_data *csc_create(struct platform_device *pdev) csc->pdev = pdev; csc->res =platform_get_resource_byname (pdev,IORESOURCE_MEM , -"vpe_csc" ); +"csc" );if (csc->res ==NULL ) {dev_err (&pdev->dev,"missing platform resources data\n" );return
ERR_PTR(-ENODEV);
--
1.8.3.2
Re: [PATCH v4 08/14] v4l: ti-vpe: Rename csc memory resource name
Hi Kamil,
Quoted 5 lines · Kamil Debski
Hi,
Quoted 3 lines
From: Archit Taneja [mailto:[email protected]]
Sent: Thursday, March 13, 2014 12:44 PM
Quoted 8 lines
Quoted 3 lines
Rename the memory block resource "
vpe_csc" to "csc" since it also exists within the VIP IP block. This would make the name more generic, and both VPE and VIP DT nodes in the future can use it.I understand that this is not yet used in any public dts files. Right?
Best wishes,
Yes, a VPE DT node doesn't exist in any public dts files yet. So it's safe to change the name.
It should eventually come in dra7.dtsi. There is a dependency on a crossbar IP module, which provides us with an IRQ line for VPE going to the GIC. Once that is merged, I can add the VPE DT node.
Thanks,
Archit
PATCH v4 9/14 v4l: ti-vpe: report correct capabilities in querycap
In reply to Archit Tanejaquerycap currently returns V4L2_CAP_VIDEO_M2M as a capability, this should be V4L2_CAP_VIDEO_M2M_MPLANE instead, as the driver supports multiplanar formats.
--- drivers/media/platform/ti-vpe/vpe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +1 -1
@@ -1347,7 +1347,7 @@ static int vpe_querycap(struct file *file, void *priv,strncpy (cap->driver,VPE_MODULE_NAME ,sizeof (cap->driver) -1 );strncpy (cap->card,VPE_MODULE_NAME ,sizeof (cap->card) -1 );strlcpy (cap->bus_info,VPE_MODULE_NAME ,sizeof (cap->bus_info)); - cap->device_caps =V4L2_CAP_VIDEO_M2M |V4L2_CAP_STREAMING ; + cap->device_caps =V4L2_CAP_VIDEO_M2M_MPLANE |V4L2_CAP_STREAMING ; cap->capabilities = cap->device_caps |V4L2_CAP_DEVICE_CAPS ;return 0 ; }
Signature · 1 line
1.8.3.2
PATCH v4 10/14 v4l: ti-vpe: Use correct bus_info name for the device in querycap
In reply to Archit TanejaThe bus_info parameter in v4l2_capabilities expects a 'platform_' prefix. This wasn't done in the driver and hence was breaking compliance. Update the bus_info parameter accordingly.
--- drivers/media/platform/ti-vpe/vpe.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +2 -1
@@ -1346,7 +1346,8 @@ static int vpe_querycap(struct file *file, void *priv, {strncpy (cap->driver,VPE_MODULE_NAME ,sizeof (cap->driver) -1 );strncpy (cap->card,VPE_MODULE_NAME ,sizeof (cap->card) -1 ); -strlcpy (cap->bus_info,VPE_MODULE_NAME ,sizeof (cap->bus_info)); +snprintf (cap->bus_info,sizeof (cap->bus_info),"platform:%s" , +VPE_MODULE_NAME ); cap->device_caps =V4L2_CAP_VIDEO_M2M_MPLANE |V4L2_CAP_STREAMING ; cap->capabilities = cap->device_caps |V4L2_CAP_DEVICE_CAPS ;return 0 ;
Signature · 1 line
1.8.3.2
PATCH v4 11/14 v4l: ti-vpe: Fix initial configuration queue data
In reply to Archit TanejaThe vpe output and capture queues are initially configured to default values in vpe_open(). A G_FMT before any S_FMTs will result in these values being populated.
The colorspace and bytesperline parameter of this initial configuration are incorrect. This breaks compliance when as we get 'TRY_FMT(G_FMT) != G_FMT'.
Fix the initial queue configuration such that it wouldn't need to be fixed by try_fmt.
--- drivers/media/platform/ti-vpe/vpe.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +4 -2
@@ -2021,9 +2021,11 @@ static int vpe_open(struct file *file) s_q_data->fmt = &vpe_formats[2 ]; s_q_data->width =1920 ; s_q_data->height =1080 ; - s_q_data->sizeimage[VPE_LUMA ] = (s_q_data->width * s_q_data->height * + s_q_data->bytesperline[VPE_LUMA ] = (s_q_data->width * s_q_data->fmt->vpdma_fmt[VPE_LUMA ]->depth) >>3 ; - s_q_data->colorspace =V4L2_COLORSPACE_SMPTE170M ; + s_q_data->sizeimage[VPE_LUMA ] = (s_q_data->bytesperline[VPE_LUMA ] * + s_q_data->height); + s_q_data->colorspace =V4L2_COLORSPACE_REC709 ; s_q_data->field =V4L2_FIELD_NONE ; s_q_data->c_rect.left =0 ; s_q_data->c_rect.top =0 ;
Signature · 1 line
1.8.3.2
PATCH v4 12/14 v4l: ti-vpe: zero out reserved fields in try_fmt
In reply to Archit TanejaZero out the reserved formats in v4l2_pix_format_mplane and v4l2_plane_pix_format members of the returned v4l2_format pointer when passed through TRY_FMT ioctl.
This ensures that the user doesn't interpret the non-zero fields as some data passed by the driver, and ensures compliance.
--- drivers/media/platform/ti-vpe/vpe.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/media/platform/ti-vpe/vpe.c +3 -0
@@ -1488,6 +1488,7 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, } } +memset (pix->reserved,0 ,sizeof (pix->reserved));for (i =0 ; i < pix->num_planes; i++) { plane_fmt = &pix->plane_fmt[i]; depth = fmt->vpdma_fmt[i]->depth;
@@ -1499,6 +1500,8 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f, plane_fmt->sizeimage = (pix->height * pix->width * depth) >>3 ; + +memset (plane_fmt->reserved,0 ,sizeof (plane_fmt->reserved)); }return 0 ;
Signature · 1 line
1.8.3.2
PATCH v4 13/14 v4l: ti-vpe: Set correct field parameter for output and capture buffers
In reply to Archit TanejaThe vpe driver wasn't setting the correct field parameter for dequed CAPTURE type buffers for the case where the captured output is progressive.
Set the field to V4L2_FIELD_NONE for the completed destination buffers when the captured output is progressive.
For OUTPUT type buffers, a queued buffer's field is forced to V4L2_FIELD_NONE if the pixel format(configured through s_fmt for the buffer type V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE specifies) the field type isn't interlaced. If the pixel format specified was V4L2_FIELD_ALTERNATE, and the queued buffer's field isn't V4L2_FIELD_TOP or V4L2_FIELD_BOTTOM, the vb2 buf_prepare op returns an error.
This ensures compliance, and that the dequeued output and captured buffers contain the field type that the driver used internally.
--- drivers/media/platform/ti-vpe/vpe.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/media/platform/ti-vpe/vpe.c +12 -1
@@ -1296,10 +1296,10 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) d_buf->timecode = s_buf->timecode; } d_buf->sequence = ctx->sequence; - d_buf->field = ctx->field; d_q_data = &ctx->q_data[Q_DATA_DST ];if (d_q_data->flags &Q_DATA_INTERLACED ) { + d_buf->field = ctx->field;if (ctx->field ==V4L2_FIELD_BOTTOM ) { ctx->sequence++; ctx->field =V4L2_FIELD_TOP ;
@@ -1308,6 +1308,7 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) ctx->field =V4L2_FIELD_BOTTOM ; } }else { + d_buf->field =V4L2_FIELD_NONE ; ctx->sequence++; }
@@ -1880,6 +1881,16 @@ static int vpe_buf_prepare(struct vb2_buffer *vb) q_data =get_q_data (ctx, vb->vb2_queue->type); num_planes = q_data->fmt->coplanar ?2 :1 ; +if (vb->vb2_queue->type ==V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE ) { +if (!(q_data->flags &Q_DATA_INTERLACED )) { + vb->v4l2_buf.field =V4L2_FIELD_NONE ; + }else { +if (vb->v4l2_buf.field !=V4L2_FIELD_TOP && + vb->v4l2_buf.field !=V4L2_FIELD_BOTTOM ) +return -EINVAL ; + } + } +for (i =0 ; i < num_planes; i++) {if (vb2_plane_size (vb, i) < q_data->sizeimage[i]) { vpe_err(ctx->dev,
Signature · 1 line
1.8.3.2
PATCH v4 14/14 v4l: ti-vpe: retain v4l2_buffer flags for captured buffers
In reply to Archit TanejaThe dequed CAPTURE_MPLANE type buffers don't contain the flags that the originally queued OUTPUT_MPLANE type buffers have. This breaks compliance.
Copy the source v4l2_buffer flags to the destination v4l2_buffer flags before they are dequed.
--- drivers/media/platform/ti-vpe/vpe.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/media/platform/ti-vpe/vpe.c +4 -5
@@ -1288,13 +1288,12 @@ static irqreturn_t vpe_irq(int irq_vpe, void *data) s_buf = &s_vb->v4l2_buf; d_buf = &d_vb->v4l2_buf; + d_buf->flags = s_buf->flags; + d_buf->timestamp = s_buf->timestamp; - d_buf->flags &= ~V4L2_BUF_FLAG_TSTAMP_SRC_MASK ; - d_buf->flags |= s_buf->flags &V4L2_BUF_FLAG_TSTAMP_SRC_MASK ; -if (s_buf->flags &V4L2_BUF_FLAG_TIMECODE ) { - d_buf->flags |=V4L2_BUF_FLAG_TIMECODE ; +if (s_buf->flags &V4L2_BUF_FLAG_TIMECODE ) d_buf->timecode = s_buf->timecode; - } + d_buf->sequence = ctx->sequence; d_q_data = &ctx->q_data[Q_DATA_DST ];
Signature · 1 line
1.8.3.2