aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/platform/ti-vpe
diff options
context:
space:
mode:
authorArchit Taneja <archit@ti.com>2013-12-03 06:51:13 -0500
committerMauro Carvalho Chehab <m.chehab@samsung.com>2013-12-10 13:49:48 -0500
commita51cd8f5d0a21ccc8d313a9992293ab2541b40a8 (patch)
tree1c0b27151a708233adea082fdc5f137770cd9339 /drivers/media/platform/ti-vpe
parentfe104a9b61ac8856e7973058b71f33224a7d5ed7 (diff)
[media] v4l: ti-vpe: make sure VPDMA line stride constraints are met
When VPDMA fetches or writes to an image buffer, the line stride must be a multiple of 16 bytes. If it isn't, VPDMA HW will write/fetch until the next 16 byte boundry. This causes VPE to work incorrectly for source or destination widths which don't satisfy the above alignment requirement. In order to prevent this, we now make sure that when we set pix format for the input and output buffers, the VPE source and destination image line strides are 16 byte aligned. Also, the motion vector buffers for the de-interlacer are allocated in such a way that it ensures the same alignment. Signed-off-by: Archit Taneja <archit@ti.com> Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/platform/ti-vpe')
-rw-r--r--drivers/media/platform/ti-vpe/vpdma.c4
-rw-r--r--drivers/media/platform/ti-vpe/vpdma.h5
-rw-r--r--drivers/media/platform/ti-vpe/vpe.c53
3 files changed, 46 insertions, 16 deletions
diff --git a/drivers/media/platform/ti-vpe/vpdma.c b/drivers/media/platform/ti-vpe/vpdma.c
index af0a5ffcaa98..f97253f6699f 100644
--- a/drivers/media/platform/ti-vpe/vpdma.c
+++ b/drivers/media/platform/ti-vpe/vpdma.c
@@ -602,7 +602,7 @@ void vpdma_add_out_dtd(struct vpdma_desc_list *list, struct v4l2_rect *c_rect,
602 if (fmt->data_type == DATA_TYPE_C420) 602 if (fmt->data_type == DATA_TYPE_C420)
603 depth = 8; 603 depth = 8;
604 604
605 stride = (depth * c_rect->width) >> 3; 605 stride = ALIGN((depth * c_rect->width) >> 3, VPDMA_STRIDE_ALIGN);
606 dma_addr += (c_rect->left * depth) >> 3; 606 dma_addr += (c_rect->left * depth) >> 3;
607 607
608 dtd = list->next; 608 dtd = list->next;
@@ -655,7 +655,7 @@ void vpdma_add_in_dtd(struct vpdma_desc_list *list, int frame_width,
655 depth = 8; 655 depth = 8;
656 } 656 }
657 657
658 stride = (depth * c_rect->width) >> 3; 658 stride = ALIGN((depth * c_rect->width) >> 3, VPDMA_STRIDE_ALIGN);
659 dma_addr += (c_rect->left * depth) >> 3; 659 dma_addr += (c_rect->left * depth) >> 3;
660 660
661 dtd = list->next; 661 dtd = list->next;
diff --git a/drivers/media/platform/ti-vpe/vpdma.h b/drivers/media/platform/ti-vpe/vpdma.h
index eaa2a71a5db9..62dd14305e81 100644
--- a/drivers/media/platform/ti-vpe/vpdma.h
+++ b/drivers/media/platform/ti-vpe/vpdma.h
@@ -45,7 +45,10 @@ struct vpdma_data_format {
45}; 45};
46 46
47#define VPDMA_DESC_ALIGN 16 /* 16-byte descriptor alignment */ 47#define VPDMA_DESC_ALIGN 16 /* 16-byte descriptor alignment */
48 48#define VPDMA_STRIDE_ALIGN 16 /*
49 * line stride of source and dest
50 * buffers should be 16 byte aligned
51 */
49#define VPDMA_DTD_DESC_SIZE 32 /* 8 words */ 52#define VPDMA_DTD_DESC_SIZE 32 /* 8 words */
50#define VPDMA_CFD_CTD_DESC_SIZE 16 /* 4 words */ 53#define VPDMA_CFD_CTD_DESC_SIZE 16 /* 4 words */
51 54
diff --git a/drivers/media/platform/ti-vpe/vpe.c b/drivers/media/platform/ti-vpe/vpe.c
index f949ef57a54c..669777052a16 100644
--- a/drivers/media/platform/ti-vpe/vpe.c
+++ b/drivers/media/platform/ti-vpe/vpe.c
@@ -30,6 +30,7 @@
30#include <linux/sched.h> 30#include <linux/sched.h>
31#include <linux/slab.h> 31#include <linux/slab.h>
32#include <linux/videodev2.h> 32#include <linux/videodev2.h>
33#include <linux/log2.h>
33 34
34#include <media/v4l2-common.h> 35#include <media/v4l2-common.h>
35#include <media/v4l2-ctrls.h> 36#include <media/v4l2-ctrls.h>
@@ -54,10 +55,6 @@
54/* required alignments */ 55/* required alignments */
55#define S_ALIGN 0 /* multiple of 1 */ 56#define S_ALIGN 0 /* multiple of 1 */
56#define H_ALIGN 1 /* multiple of 2 */ 57#define H_ALIGN 1 /* multiple of 2 */
57#define W_ALIGN 1 /* multiple of 2 */
58
59/* multiple of 128 bits, line stride, 16 bytes */
60#define L_ALIGN 4
61 58
62/* flags that indicate a format can be used for capture/output */ 59/* flags that indicate a format can be used for capture/output */
63#define VPE_FMT_TYPE_CAPTURE (1 << 0) 60#define VPE_FMT_TYPE_CAPTURE (1 << 0)
@@ -780,12 +777,21 @@ static int set_srcdst_params(struct vpe_ctx *ctx)
780 777
781 if ((s_q_data->flags & Q_DATA_INTERLACED) && 778 if ((s_q_data->flags & Q_DATA_INTERLACED) &&
782 !(d_q_data->flags & Q_DATA_INTERLACED)) { 779 !(d_q_data->flags & Q_DATA_INTERLACED)) {
780 int bytes_per_line;
783 const struct vpdma_data_format *mv = 781 const struct vpdma_data_format *mv =
784 &vpdma_misc_fmts[VPDMA_DATA_FMT_MV]; 782 &vpdma_misc_fmts[VPDMA_DATA_FMT_MV];
785 783
786 ctx->deinterlacing = 1; 784 ctx->deinterlacing = 1;
787 mv_buf_size = 785 /*
788 (s_q_data->width * s_q_data->height * mv->depth) >> 3; 786 * we make sure that the source image has a 16 byte aligned
787 * stride, we need to do the same for the motion vector buffer
788 * by aligning it's stride to the next 16 byte boundry. this
789 * extra space will not be used by the de-interlacer, but will
790 * ensure that vpdma operates correctly
791 */
792 bytes_per_line = ALIGN((s_q_data->width * mv->depth) >> 3,
793 VPDMA_STRIDE_ALIGN);
794 mv_buf_size = bytes_per_line * s_q_data->height;
789 } else { 795 } else {
790 ctx->deinterlacing = 0; 796 ctx->deinterlacing = 0;
791 mv_buf_size = 0; 797 mv_buf_size = 0;
@@ -1352,7 +1358,8 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f,
1352{ 1358{
1353 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp; 1359 struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
1354 struct v4l2_plane_pix_format *plane_fmt; 1360 struct v4l2_plane_pix_format *plane_fmt;
1355 int i; 1361 unsigned int w_align;
1362 int i, depth, depth_bytes;
1356 1363
1357 if (!fmt || !(fmt->types & type)) { 1364 if (!fmt || !(fmt->types & type)) {
1358 vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n", 1365 vpe_err(ctx->dev, "Fourcc format (0x%08x) invalid.\n",
@@ -1363,7 +1370,31 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f,
1363 if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE) 1370 if (pix->field != V4L2_FIELD_NONE && pix->field != V4L2_FIELD_ALTERNATE)
1364 pix->field = V4L2_FIELD_NONE; 1371 pix->field = V4L2_FIELD_NONE;
1365 1372
1366 v4l_bound_align_image(&pix->width, MIN_W, MAX_W, W_ALIGN, 1373 depth = fmt->vpdma_fmt[VPE_LUMA]->depth;
1374
1375 /*
1376 * the line stride should 16 byte aligned for VPDMA to work, based on
1377 * the bytes per pixel, figure out how much the width should be aligned
1378 * to make sure line stride is 16 byte aligned
1379 */
1380 depth_bytes = depth >> 3;
1381
1382 if (depth_bytes == 3)
1383 /*
1384 * if bpp is 3(as in some RGB formats), the pixel width doesn't
1385 * really help in ensuring line stride is 16 byte aligned
1386 */
1387 w_align = 4;
1388 else
1389 /*
1390 * for the remainder bpp(4, 2 and 1), the pixel width alignment
1391 * can ensure a line stride alignment of 16 bytes. For example,
1392 * if bpp is 2, then the line stride can be 16 byte aligned if
1393 * the width is 8 byte aligned
1394 */
1395 w_align = order_base_2(VPDMA_DESC_ALIGN / depth_bytes);
1396
1397 v4l_bound_align_image(&pix->width, MIN_W, MAX_W, w_align,
1367 &pix->height, MIN_H, MAX_H, H_ALIGN, 1398 &pix->height, MIN_H, MAX_H, H_ALIGN,
1368 S_ALIGN); 1399 S_ALIGN);
1369 1400
@@ -1383,15 +1414,11 @@ static int __vpe_try_fmt(struct vpe_ctx *ctx, struct v4l2_format *f,
1383 } 1414 }
1384 1415
1385 for (i = 0; i < pix->num_planes; i++) { 1416 for (i = 0; i < pix->num_planes; i++) {
1386 int depth;
1387
1388 plane_fmt = &pix->plane_fmt[i]; 1417 plane_fmt = &pix->plane_fmt[i];
1389 depth = fmt->vpdma_fmt[i]->depth; 1418 depth = fmt->vpdma_fmt[i]->depth;
1390 1419
1391 if (i == VPE_LUMA) 1420 if (i == VPE_LUMA)
1392 plane_fmt->bytesperline = 1421 plane_fmt->bytesperline = (pix->width * depth) >> 3;
1393 round_up((pix->width * depth) >> 3,
1394 1 << L_ALIGN);
1395 else 1422 else
1396 plane_fmt->bytesperline = pix->width; 1423 plane_fmt->bytesperline = pix->width;
1397 1424