diff options
author | Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com> | 2011-08-26 20:41:41 +0530 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@stericsson.com> | 2011-09-19 16:00:18 +0200 |
commit | af67808803975d8d61def779f8eac971fe1c915e (patch) | |
tree | 83bcad5697d47af14e69584035ec4a593b0d6abd | |
parent | be6bef0765a85c9ed462076a19c192d836faaa9c (diff) |
b2r2:Migrate driver to kernel 3.0
Migrate the following b2r2 driver patches to kernel3.0
dbc424d b2r2: Add optimized path for VUY(A)888(8) 24/32-bit formats
2142b2d b2r2: Add VUY(A)888(8) 24/32-bit formats
797c68c [b2r2] Fix QA tools warning in b2r2_node_split.c
ST-Ericsson ID: 352334
ST-Ericsson Linux next: NA
ST-Ericsson FOSS-OUT ID: NA
Change-Id: I5f3160a9568ad17eb05eae0b7b8adba146153ea9
Signed-off-by: Naveen Kumar Gaddipati <naveen.gaddipati@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29563
-rw-r--r-- | drivers/video/b2r2/b2r2_blt_main.c | 112 | ||||
-rw-r--r-- | drivers/video/b2r2/b2r2_generic.c | 147 | ||||
-rw-r--r-- | drivers/video/b2r2/b2r2_hw.h | 24 | ||||
-rw-r--r-- | drivers/video/b2r2/b2r2_input_validation.c | 5 | ||||
-rw-r--r-- | drivers/video/b2r2/b2r2_node_split.c | 123 | ||||
-rw-r--r-- | drivers/video/b2r2/b2r2_utils.c | 12 | ||||
-rw-r--r-- | include/video/b2r2_blt.h | 6 |
7 files changed, 341 insertions, 88 deletions
diff --git a/drivers/video/b2r2/b2r2_blt_main.c b/drivers/video/b2r2/b2r2_blt_main.c index a2b21f4a2c1..097d2854a83 100644 --- a/drivers/video/b2r2/b2r2_blt_main.c +++ b/drivers/video/b2r2/b2r2_blt_main.c @@ -339,7 +339,7 @@ static int b2r2_blt_release(struct inode *inode, struct file *filp) job = b2r2_core_job_find_first_with_tag((int) instance); while (job) { b2r2_core_job_cancel(job); - /* This release matches addref in b2r2_core_job_find... */ + /* Matches addref in b2r2_core_job_find... */ b2r2_core_job_release(job, __func__); job = b2r2_core_job_find_first_with_tag((int) instance); } @@ -483,8 +483,8 @@ static long b2r2_blt_ioctl(struct file *file, b2r2_log_info("b2r2_blt=%d Going generic.\n", ret); request_gen = kmalloc(sizeof(*request_gen), GFP_KERNEL); if (!request_gen) { - b2r2_log_err( - "%s: Failed to alloc mem for request_gen\n", __func__); + b2r2_log_err("%s: Failed to alloc mem for " + "request_gen\n", __func__); return -ENOMEM; } @@ -513,19 +513,27 @@ static long b2r2_blt_ioctl(struct file *file, * make a copy that the HW can use. */ if ((request_gen->user_req.flags & - B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) != 0) { - request_gen->clut = dma_alloc_coherent(b2r2_blt_device(), - CLUT_SIZE, &(request_gen->clut_phys_addr), + B2R2_BLT_FLAG_CLUT_COLOR_CORRECTION) + != 0) { + request_gen->clut = + dma_alloc_coherent(b2r2_blt_device(), + CLUT_SIZE, + &(request_gen->clut_phys_addr), GFP_DMA | GFP_KERNEL); if (request_gen->clut == NULL) { - b2r2_log_err("%s CLUT allocation failed.\n", __func__); + b2r2_log_err("%s CLUT allocation " + "failed.\n", __func__); kfree(request_gen); return -ENOMEM; } - if (copy_from_user(request_gen->clut, request_gen->user_req.clut, CLUT_SIZE)) { - b2r2_log_err("%s: CLUT copy_from_user failed\n", __func__); - dma_free_coherent(b2r2_blt_device(), CLUT_SIZE, request_gen->clut, + if (copy_from_user(request_gen->clut, + request_gen->user_req.clut, + CLUT_SIZE)) { + b2r2_log_err("%s: CLUT copy_from_user " + "failed\n", __func__); + dma_free_coherent(b2r2_blt_device(), + CLUT_SIZE, request_gen->clut, request_gen->clut_phys_addr); request_gen->clut = NULL; request_gen->clut_phys_addr = 0; @@ -537,7 +545,8 @@ static long b2r2_blt_ioctl(struct file *file, request_gen->profile = is_profiler_registered_approx(); ret = b2r2_generic_blt(instance, request_gen); - b2r2_log_info("\nb2r2_generic_blt=%d Generic done.\n", ret); + b2r2_log_info("\nb2r2_generic_blt=%d Generic done.\n", + ret); } #endif /* CONFIG_B2R2_GENERIC_FALLBACK */ @@ -1339,9 +1348,8 @@ static void tile_job_callback_gen(struct b2r2_core_job *job) #ifdef CONFIG_DEBUG_FS /* Notify if a tile job is cancelled */ - if (job->job_state == B2R2_CORE_JOB_CANCELED) { + if (job->job_state == B2R2_CORE_JOB_CANCELED) b2r2_log_info("%s: Tile job cancelled:\n", __func__); - } #endif /* Local addref / release within this func */ @@ -1832,19 +1840,24 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, x = -dst_rect->x; for (; x < dst_rect->width && - x + dst_rect->x < dst_img_width; x += tmp_buf_width) { + x + dst_rect->x < dst_img_width; + x += tmp_buf_width) { /* * Tile jobs are freed by the supplied release function * when ref_count on a tile_job reaches zero. */ - struct b2r2_core_job *tile_job = kmalloc(sizeof(*tile_job), GFP_KERNEL); + struct b2r2_core_job *tile_job = + kmalloc(sizeof(*tile_job), GFP_KERNEL); if (tile_job == NULL) { /* - * Skip this tile. Do not abort, just hope for better luck - * with rest of the tiles. Memory might become available. + * Skip this tile. Do not abort, + * just hope for better luck + * with rest of the tiles. + * Memory might become available. */ b2r2_log_info("%s: Failed to alloc job. " - "Skipping tile at (x, y)=(%d, %d)\n", __func__, x, y); + "Skipping tile at (x, y)=(%d, %d)\n", + __func__, x, y); continue; } tile_job->tag = request->job.tag; @@ -1865,7 +1878,8 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, * Only a part of the tile can be written. * Limit imposed by buffer size. */ - dst_rect_tile.width = dst_img_width - (x + dst_rect->x); + dst_rect_tile.width = + dst_img_width - (x + dst_rect->x); } else if (x + tmp_buf_width > dst_rect->width) { /* * Only a part of the tile can be written. @@ -1877,10 +1891,12 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, dst_rect_tile.width = tmp_buf_width; } /* - * Where applicable, calculate area in src buffer that is needed - * to generate the specified part of destination rectangle. + * Where applicable, calculate area in src buffer + * that is needed to generate the specified part + * of destination rectangle. */ - b2r2_generic_set_areas(request, request->first_node, &dst_rect_tile); + b2r2_generic_set_areas(request, + request->first_node, &dst_rect_tile); /* Submit the job */ b2r2_log_info("%s: Submitting job\n", __func__); @@ -1940,7 +1956,8 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, x + dst_rect->x < dst_img_width; x += tmp_buf_width) { struct b2r2_core_job *tile_job = NULL; if (x + tmp_buf_width < dst_rect->width && - x + dst_rect->x + tmp_buf_width < dst_img_width) { + x + dst_rect->x + tmp_buf_width < + dst_img_width) { /* * Tile jobs are freed by the supplied release function * when ref_count on a tile_job reaches zero. @@ -1987,26 +2004,29 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, } /* * y is now the last row. Either because the whole dst_rect - * has been processed, or because the last row that will be written - * to dst_img has been reached. Limits imposed in the same way - * as for width. + * has been processed, or because the last row that will be + * written to dst_img has been reached. Limits imposed in + * the same way as for width. */ dst_rect_tile.y = y; if (y + dst_rect->y + tmp_buf_height > dst_img_height) - dst_rect_tile.height = dst_img_height - (y + dst_rect->y); + dst_rect_tile.height = + dst_img_height - (y + dst_rect->y); else if (y + tmp_buf_height > dst_rect->height) dst_rect_tile.height = dst_rect->height - y; else dst_rect_tile.height = tmp_buf_height; - b2r2_generic_set_areas(request, request->first_node, &dst_rect_tile); + b2r2_generic_set_areas(request, + request->first_node, &dst_rect_tile); b2r2_log_info("%s: Submitting job\n", __func__); inc_stat(&stat_n_in_blt_add); mutex_lock(&instance->lock); if (x + tmp_buf_width < dst_rect->width && - x + dst_rect->x + tmp_buf_width < dst_img_width) { + x + dst_rect->x + tmp_buf_width < + dst_img_width) { request_id = b2r2_core_job_add(tile_job); } else { /* @@ -2036,7 +2056,8 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, inc_stat(&stat_n_in_blt_wait); if (x + tmp_buf_width < dst_rect->width && - x + dst_rect->x + tmp_buf_width < dst_img_width) { + x + dst_rect->x + tmp_buf_width < + dst_img_width) { ret = b2r2_core_job_wait(tile_job); } else { /* @@ -2056,8 +2077,10 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, "%s: Synchronous wait done\n", __func__); if (x + tmp_buf_width < dst_rect->width && - x + dst_rect->x + tmp_buf_width < dst_img_width) - nsec_active_in_b2r2 += tile_job->nsec_active_in_hw; + x + dst_rect->x + tmp_buf_width < + dst_img_width) + nsec_active_in_b2r2 += + tile_job->nsec_active_in_hw; else nsec_active_in_b2r2 += request->job.nsec_active_in_hw; @@ -2069,7 +2092,8 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, * when the last tile is processed. */ if (x + tmp_buf_width < dst_rect->width && - x + dst_rect->x + tmp_buf_width < dst_img_width) { + x + dst_rect->x + tmp_buf_width < + dst_img_width) { b2r2_core_job_release(tile_job, __func__); } else { b2r2_core_job_release(&request->job, __func__); @@ -2100,7 +2124,8 @@ static int b2r2_generic_blt(struct b2r2_blt_instance *instance, if (request->profile) { request->nsec_active_in_cpu = - (s32)((u32)task_sched_runtime(current) - thread_runtime_at_start); + (s32)((u32)task_sched_runtime(current) - + thread_runtime_at_start); request->total_time_nsec = (s32)(b2r2_get_curr_nsec() - request->start_time_nsec); request->job.nsec_active_in_hw = nsec_active_in_b2r2; @@ -2433,7 +2458,8 @@ static int resolve_buf(struct b2r2_blt_img *img, if (file == NULL) return -EINVAL; #ifdef CONFIG_FB - if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) { + if (MAJOR(file->f_dentry->d_inode->i_rdev) == + FB_MAJOR) { /* * This is a frame buffer device, find fb_info * (OK to do it like this, no locking???) @@ -2503,7 +2529,8 @@ static int resolve_buf(struct b2r2_blt_img *img, * @resolved_buf: Gathered info (physical address etc.) about buffer * @is_dst: true if the buffer is a destination buffer, false if the buffer is a * source buffer. - * @rect: rectangle in the image buffer that should be synced. NULL the buffer is a source mask. + * @rect: rectangle in the image buffer that should be synced. + * NULL if the buffer is a source mask. * @img_width: width of the complete image buffer * @fmt: buffer format */ @@ -2554,11 +2581,15 @@ static void sync_buf(struct b2r2_blt_img *img, (img->fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMIPLANAR_MB_STE)) { sa.start = (unsigned long)resolved->virtual_address; - sa.end = (unsigned long)resolved->virtual_address + img->buf.len; + sa.end = (unsigned long)resolved->virtual_address + + img->buf.len; start_phys = resolved->physical_address; end_phys = resolved->physical_address + img->buf.len; } else { - /* buffer is not a src_mask so make use of rect when clean & flush caches*/ + /* + * buffer is not a src_mask so make use of rect when + * clean & flush caches + */ u32 bpp; /* Bits per pixel */ u32 pitch; @@ -2573,11 +2604,13 @@ static void sync_buf(struct b2r2_blt_img *img, case B2R2_BLT_FMT_24_BIT_RGB888: /* Fall through */ case B2R2_BLT_FMT_24_BIT_ARGB8565: /* Fall through */ case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: bpp = 24; break; case B2R2_BLT_FMT_32_BIT_ARGB8888: /* Fall through */ case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Fall through */ case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: bpp = 32; break; default: @@ -2930,7 +2963,8 @@ static int debugfs_b2r2_blt_request_read(struct file *filp, char __user *buf, goto out; } - dev_size = sprintf_req(&debugfs_latest_request, Buf, sizeof(char) * 4096); + dev_size = sprintf_req(&debugfs_latest_request, Buf, + sizeof(char) * 4096); /* No more to read if offset != 0 */ if (*f_pos > dev_size) diff --git a/drivers/video/b2r2/b2r2_generic.c b/drivers/video/b2r2/b2r2_generic.c index 738e11bf4ba..5941e39be91 100644 --- a/drivers/video/b2r2/b2r2_generic.c +++ b/drivers/video/b2r2/b2r2_generic.c @@ -180,11 +180,13 @@ static inline enum b2r2_native_fmt to_native_fmt(enum b2r2_blt_fmt fmt) return B2R2_NATIVE_ARGB8565; case B2R2_BLT_FMT_24_BIT_RGB888: return B2R2_NATIVE_RGB888; + case B2R2_BLT_FMT_24_BIT_VUY888: case B2R2_BLT_FMT_24_BIT_YUV888: return B2R2_NATIVE_YCBCR888; case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Not actually supported by HW */ case B2R2_BLT_FMT_32_BIT_ARGB8888: return B2R2_NATIVE_ARGB8888; + case B2R2_BLT_FMT_32_BIT_VUYA8888: /* fall through */ case B2R2_BLT_FMT_32_BIT_AYUV8888: return B2R2_NATIVE_AYCBCR8888; case B2R2_BLT_FMT_CB_Y_CR_Y: @@ -220,6 +222,7 @@ static inline enum b2r2_ty get_alpha_range(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_32_BIT_ARGB8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_8_BIT_A8: case B2R2_BLT_FMT_32_BIT_ABGR8888: return B2R2_TY_ALPHA_RANGE_255; /* 0 - 255 */ @@ -250,15 +253,15 @@ static unsigned int get_pitch(enum b2r2_blt_fmt format, u32 width) case B2R2_BLT_FMT_16_BIT_ARGB4444: return width * 2; break; - case B2R2_BLT_FMT_24_BIT_RGB888: /* all 24 bits/pixel RGB formats */ + case B2R2_BLT_FMT_24_BIT_RGB888: /* all 24 bits/pixel raster formats */ case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: return width * 3; break; - case B2R2_BLT_FMT_32_BIT_ARGB8888: /* all 32 bits/pixel RGB formats */ + case B2R2_BLT_FMT_32_BIT_ARGB8888: /* all 32 bits/pixel formats */ case B2R2_BLT_FMT_32_BIT_ABGR8888: - return width * 4; - break; + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: return width * 4; break; @@ -532,6 +535,8 @@ static void setup_fill_input_stage(const struct b2r2_blt_request *req, case B2R2_BLT_FMT_CB_Y_CR_Y: case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_YUV420_PACKED_PLANAR: case B2R2_BLT_FMT_YUV422_PACKED_PLANAR: case B2R2_BLT_FMT_YVU420_PACKED_PLANAR: @@ -607,6 +612,8 @@ static void setup_fill_input_stage(const struct b2r2_blt_request *req, switch (dst_img->fmt) { case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED; node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX; @@ -618,6 +625,27 @@ static void setup_fill_input_stage(const struct b2r2_blt_request *req, B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO; node->node.GROUP15.B2R2_VMX3 = B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO; + /* + * Re-arrange the color components from + * VUY(A) to (A)YUV + */ + if (dst_img->fmt == + B2R2_BLT_FMT_24_BIT_VUY888) { + u32 Y = src_color & 0xff; + u32 U = src_color & 0xff00; + u32 V = src_color & 0xff0000; + src_color = (Y << 16) | U | (V >> 16); + } else if (dst_img->fmt == + B2R2_BLT_FMT_32_BIT_VUYA8888) { + u32 A = src_color & 0xff; + u32 Y = src_color & 0xff00; + u32 U = src_color & 0xff0000; + u32 V = src_color & 0xff000000; + src_color = (A << 24) | + (Y << 8) | + (U >> 8) | + (V >> 24); + } break; case B2R2_BLT_FMT_Y_CB_Y_CR: /* @@ -703,6 +731,7 @@ static void setup_input_stage(const struct b2r2_blt_request *req, /* horizontal and vertical scan order for out_buf */ enum b2r2_ty dst_hso = B2R2_TY_HSO_LEFT_TO_RIGHT; enum b2r2_ty dst_vso = B2R2_TY_VSO_TOP_TO_BOTTOM; + u32 endianness = 0; u32 fctl = 0; u32 rsf = 0; u32 rzi = 0; @@ -838,9 +867,13 @@ static void setup_input_stage(const struct b2r2_blt_request *req, break; case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: /* * Set up IVMX. - * Color components are laid out in memory as V, U, Y, (A) + * For B2R2_BLT_FMT_32_BIT_YUV888 and + * B2R2_BLT_FMT_32_BIT_AYUV8888 + * the color components are laid out in memory as V, U, Y, (A) * with V at the first byte (due to little endian addressing). * B2R2 expects them to be as U, Y, V, (A) * with U at the first byte. @@ -855,6 +888,14 @@ static void setup_input_stage(const struct b2r2_blt_request *req, B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO; node->node.GROUP15.B2R2_VMX3 = B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO; + + /* + * Re-arrange color components from VUY(A) to (A)YUV + * for input VMX to work on them further. + */ + if (src_img->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + src_img->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + endianness = B2R2_TY_ENDIAN_BIG_NOT_LITTLE; break; case B2R2_BLT_FMT_YUV420_PACKED_PLANAR: case B2R2_BLT_FMT_YUV422_PACKED_PLANAR: @@ -1161,7 +1202,8 @@ static void setup_input_stage(const struct b2r2_blt_request *req, to_native_fmt(src_img->fmt) | get_alpha_range(src_img->fmt) | B2R2_TY_HSO_LEFT_TO_RIGHT | - B2R2_TY_VSO_TOP_TO_BOTTOM; + B2R2_TY_VSO_TOP_TO_BOTTOM | + endianness; node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_2_FETCH_FROM_MEM; node->node.GROUP0.B2R2_CIC |= B2R2_CIC_SOURCE_2; @@ -1240,6 +1282,7 @@ static void setup_dst_read_stage(const struct b2r2_blt_request *req, const struct b2r2_blt_img *dst_img = &(req->user_req.dst_img); u32 fctl = 0; u32 rsf = 0; + u32 endianness = 0; bool yuv_semi_planar = dst_img->fmt == B2R2_BLT_FMT_YUV420_PACKED_SEMI_PLANAR || dst_img->fmt == B2R2_BLT_FMT_YUV422_PACKED_SEMI_PLANAR || @@ -1278,36 +1321,59 @@ static void setup_dst_read_stage(const struct b2r2_blt_request *req, node->node.GROUP15.B2R2_VMX3 = B2R2_VMX3_RGB_TO_BGR; break; case B2R2_BLT_FMT_Y_CB_Y_CR: + /* Set up IVMX */ + node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED; + node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX; + /* + * Setup input VMX to convert YVU to RGB 601 VIDEO + * Chroma components are swapped + * so it is YVU and not YUV. + */ + node->node.GROUP15.B2R2_VMX0 = B2R2_VMX0_YVU_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX1 = B2R2_VMX1_YVU_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX2 = B2R2_VMX2_YVU_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX3 = B2R2_VMX3_YVU_TO_RGB_601_VIDEO; + break; case B2R2_BLT_FMT_CB_Y_CR_Y: + /* Set up IVMX */ + node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED; + node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX; + node->node.GROUP15.B2R2_VMX0 = B2R2_VMX0_YUV_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX1 = B2R2_VMX1_YUV_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX2 = B2R2_VMX2_YUV_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX3 = B2R2_VMX3_YUV_TO_RGB_601_VIDEO; + break; case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: - /* Set up IVMX */ + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: + /* + * Set up IVMX. + * For B2R2_BLT_FMT_32_BIT_YUV888 and + * B2R2_BLT_FMT_32_BIT_AYUV8888 + * the color components are laid out in memory as V, U, Y, (A) + * with V at the first byte (due to little endian addressing). + * B2R2 expects them to be as U, Y, V, (A) + * with U at the first byte. + */ node->node.GROUP0.B2R2_INS |= B2R2_INS_IVMX_ENABLED; node->node.GROUP0.B2R2_CIC |= B2R2_CIC_IVMX; - if (dst_img->fmt == B2R2_BLT_FMT_Y_CB_Y_CR) { - /* - * Setup input VMX to convert YVU to RGB 601 VIDEO - * Chroma components are swapped - * so it is YVU and not YUV. - */ - node->node.GROUP15.B2R2_VMX0 = - B2R2_VMX0_YVU_TO_RGB_601_VIDEO; - node->node.GROUP15.B2R2_VMX1 = - B2R2_VMX1_YVU_TO_RGB_601_VIDEO; - node->node.GROUP15.B2R2_VMX2 = - B2R2_VMX2_YVU_TO_RGB_601_VIDEO; - node->node.GROUP15.B2R2_VMX3 = - B2R2_VMX3_YVU_TO_RGB_601_VIDEO; - } else { - node->node.GROUP15.B2R2_VMX0 = - B2R2_VMX0_YUV_TO_RGB_601_VIDEO; - node->node.GROUP15.B2R2_VMX1 = - B2R2_VMX1_YUV_TO_RGB_601_VIDEO; - node->node.GROUP15.B2R2_VMX2 = - B2R2_VMX2_YUV_TO_RGB_601_VIDEO; - node->node.GROUP15.B2R2_VMX3 = - B2R2_VMX3_YUV_TO_RGB_601_VIDEO; - } + node->node.GROUP15.B2R2_VMX0 = + B2R2_VMX0_BLT_YUV888_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX1 = + B2R2_VMX1_BLT_YUV888_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX2 = + B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO; + node->node.GROUP15.B2R2_VMX3 = + B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO; + + /* + * Re-arrange color components from VUY(A) to (A)YUV + * for input VMX to work on them further. + */ + if (dst_img->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + dst_img->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + endianness = B2R2_TY_ENDIAN_BIG_NOT_LITTLE; break; case B2R2_BLT_FMT_YUV420_PACKED_PLANAR: case B2R2_BLT_FMT_YUV422_PACKED_PLANAR: @@ -1536,7 +1602,8 @@ static void setup_dst_read_stage(const struct b2r2_blt_request *req, to_native_fmt(dst_img->fmt) | get_alpha_range(dst_img->fmt) | B2R2_TY_HSO_LEFT_TO_RIGHT | - B2R2_TY_VSO_TOP_TO_BOTTOM; + B2R2_TY_VSO_TOP_TO_BOTTOM | + endianness; node->node.GROUP0.B2R2_INS |= B2R2_INS_SOURCE_2_FETCH_FROM_MEM; @@ -1689,6 +1756,7 @@ static void setup_writeback_stage(const struct b2r2_blt_request *req, u32 dst_dither = 0; u32 dst_pitch = 0; + u32 endianness = 0; b2r2_log_info("%s ENTRY\n", __func__); @@ -2057,7 +2125,9 @@ static void setup_writeback_stage(const struct b2r2_blt_request *req, B2R2_VMX3_RGB_TO_YVU_601_VIDEO; break; case B2R2_BLT_FMT_24_BIT_YUV888: /* fall through */ - case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_AYUV8888: /* fall through */ + case B2R2_BLT_FMT_24_BIT_VUY888: /* fall through */ + case B2R2_BLT_FMT_32_BIT_VUYA8888: node->node.GROUP0.B2R2_INS |= B2R2_INS_OVMX_ENABLED; node->node.GROUP0.B2R2_CIC |= B2R2_CIC_OVMX; node->node.GROUP16.B2R2_VMX0 = @@ -2068,6 +2138,14 @@ static void setup_writeback_stage(const struct b2r2_blt_request *req, B2R2_VMX2_RGB_TO_BLT_YUV888_601_VIDEO; node->node.GROUP16.B2R2_VMX3 = B2R2_VMX3_RGB_TO_BLT_YUV888_601_VIDEO; + + /* + * Re-arrange color components from (A)YUV to VUY(A) + * when bytes are stored in memory. + */ + if (dst_fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + dst_fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + endianness = B2R2_TY_ENDIAN_BIG_NOT_LITTLE; break; default: break; @@ -2080,7 +2158,8 @@ static void setup_writeback_stage(const struct b2r2_blt_request *req, get_alpha_range(dst_img->fmt) | B2R2_TY_HSO_LEFT_TO_RIGHT | B2R2_TY_VSO_TOP_TO_BOTTOM | - dst_dither; + dst_dither | + endianness; node->node.GROUP0.B2R2_ACK = B2R2_ACK_MODE_BYPASS_S2_S3; node->node.GROUP0.B2R2_INS |= diff --git a/drivers/video/b2r2/b2r2_hw.h b/drivers/video/b2r2/b2r2_hw.h index 0dd5f758eb5..d492168913a 100644 --- a/drivers/video/b2r2/b2r2_hw.h +++ b/drivers/video/b2r2/b2r2_hw.h @@ -680,4 +680,28 @@ enum b2r2_plug_page_size { #define B2R2_VMX2_BLT_YUV888_TO_RGB_601_VIDEO 0x2006f000 #define B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO 0x34f21322 +/* VMX register values for YUV to BLT_YUV888 conversion */ +#define B2R2_VMX0_YUV_TO_BLT_YUV888 0x00040000 +#define B2R2_VMX1_YUV_TO_BLT_YUV888 0x00000100 +#define B2R2_VMX2_YUV_TO_BLT_YUV888 0x20000000 +#define B2R2_VMX3_YUV_TO_BLT_YUV888 0x00000000 + +/* VMX register values for BLT_YUV888 to YUV conversion */ +#define B2R2_VMX0_BLT_YUV888_TO_YUV 0x00000100 +#define B2R2_VMX1_BLT_YUV888_TO_YUV 0x20000000 +#define B2R2_VMX2_BLT_YUV888_TO_YUV 0x00040000 +#define B2R2_VMX3_BLT_YUV888_TO_YUV 0x00000000 + +/* VMX register values for YVU to BLT_YUV888 conversion */ +#define B2R2_VMX0_YVU_TO_BLT_YUV888 0x00040000 +#define B2R2_VMX1_YVU_TO_BLT_YUV888 0x20000000 +#define B2R2_VMX2_YVU_TO_BLT_YUV888 0x00000100 +#define B2R2_VMX3_YVU_TO_BLT_YUV888 0x00000000 + +/* VMX register values for BLT_YUV888 to YVU conversion */ +#define B2R2_VMX0_BLT_YUV888_TO_YVU 0x00040000 +#define B2R2_VMX1_BLT_YUV888_TO_YVU 0x20000000 +#define B2R2_VMX2_BLT_YUV888_TO_YVU 0x00000100 +#define B2R2_VMX3_BLT_YUV888_TO_YVU 0x00000000 + #endif /* B2R2_HW_H__ */ diff --git a/drivers/video/b2r2/b2r2_input_validation.c b/drivers/video/b2r2/b2r2_input_validation.c index 2604d8f77e0..0de714f1161 100644 --- a/drivers/video/b2r2/b2r2_input_validation.c +++ b/drivers/video/b2r2/b2r2_input_validation.c @@ -70,6 +70,8 @@ static bool is_valid_format(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_32_BIT_ABGR8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: case B2R2_BLT_FMT_YUV444_PACKED_PLANAR: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: return true; default: @@ -105,9 +107,11 @@ static bool is_valid_pitch_for_fmt(u32 pitch, s32 width, enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_RGB888: case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: case B2R2_BLT_FMT_32_BIT_ARGB8888: case B2R2_BLT_FMT_32_BIT_ABGR8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: if (!b2r2_is_aligned(pitch, 4)) return false; @@ -127,6 +131,7 @@ static bool is_aligned_width_for_fmt(s32 width, enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_RGB888: case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: if (!b2r2_is_aligned(width, 4)) return false; diff --git a/drivers/video/b2r2/b2r2_node_split.c b/drivers/video/b2r2/b2r2_node_split.c index 90674e0e540..5aa62be8b4b 100644 --- a/drivers/video/b2r2/b2r2_node_split.c +++ b/drivers/video/b2r2/b2r2_node_split.c @@ -67,6 +67,33 @@ static const u32 vmx_blt_yuv888_to_rgb[] = { B2R2_VMX3_BLT_YUV888_TO_RGB_601_VIDEO, }; +static const u32 vmx_yuv_to_blt_yuv888[] = { + B2R2_VMX0_YUV_TO_BLT_YUV888, + B2R2_VMX1_YUV_TO_BLT_YUV888, + B2R2_VMX2_YUV_TO_BLT_YUV888, + B2R2_VMX3_YUV_TO_BLT_YUV888, +}; + +static const u32 vmx_blt_yuv888_to_yuv[] = { + B2R2_VMX0_BLT_YUV888_TO_YUV, + B2R2_VMX1_BLT_YUV888_TO_YUV, + B2R2_VMX2_BLT_YUV888_TO_YUV, + B2R2_VMX3_BLT_YUV888_TO_YUV, +}; + +static const u32 vmx_yvu_to_blt_yuv888[] = { + B2R2_VMX0_YVU_TO_BLT_YUV888, + B2R2_VMX1_YVU_TO_BLT_YUV888, + B2R2_VMX2_YVU_TO_BLT_YUV888, + B2R2_VMX3_YVU_TO_BLT_YUV888, +}; + +static const u32 vmx_blt_yuv888_to_yvu[] = { + B2R2_VMX0_BLT_YUV888_TO_YVU, + B2R2_VMX1_BLT_YUV888_TO_YVU, + B2R2_VMX2_BLT_YUV888_TO_YVU, + B2R2_VMX3_BLT_YUV888_TO_YVU, +}; static const u32 vmx_yvu_to_rgb[] = { B2R2_VMX0_YVU_TO_RGB_601_VIDEO, B2R2_VMX1_YVU_TO_RGB_601_VIDEO, @@ -270,6 +297,8 @@ int b2r2_node_split_analyze(const struct b2r2_blt_request *req, switch (req->user_req.src_img.fmt) { case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: if (!is_rgb_fmt(req->user_req.dst_img.fmt)) { ret = -ENOSYS; goto unsupported; @@ -283,6 +312,8 @@ int b2r2_node_split_analyze(const struct b2r2_blt_request *req, switch (req->user_req.dst_img.fmt) { case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: if (!is_rgb_fmt(req->user_req.src_img.fmt)) { ret = -ENOSYS; goto unsupported; @@ -692,7 +723,14 @@ static int analyze_fmt_conv(struct b2r2_node_split_buf *src, if (is_yvu_fmt(dst->fmt)) *vmx = &vmx_rgb_to_yvu[0]; else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 || - dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) + dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 || + dst->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + dst->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + /* + * (A)YUV/VUY(A) formats differ only in component + * order. This is handled by the endianness bit + * in B2R2_STY/TTY registers when src/target are set. + */ *vmx = &vmx_rgb_to_blt_yuv888[0]; else if (is_yuv_fmt(dst->fmt)) *vmx = &vmx_rgb_to_yuv[0]; @@ -704,29 +742,48 @@ static int analyze_fmt_conv(struct b2r2_node_split_buf *src, else if (is_bgr_fmt(dst->fmt)) *vmx = &vmx_yvu_to_bgr[0]; else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 || - dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) - BUG_ON(1); + dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 || + dst->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + dst->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + *vmx = &vmx_yvu_to_blt_yuv888[0]; else if (is_yuv_fmt(dst->fmt) && !is_yvu_fmt(dst->fmt)) *vmx = &vmx_yvu_to_yuv[0]; } else if (src->fmt == B2R2_BLT_FMT_24_BIT_YUV888 || - src->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) { - if (is_rgb_fmt(dst->fmt)) + src->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 || + src->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + src->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) { + /* + * (A)YUV/VUY(A) formats differ only in component + * order. This is handled by the endianness bit + * in B2R2_STY/TTY registers when src/target are set. + */ + if (is_rgb_fmt(dst->fmt)) { *vmx = &vmx_blt_yuv888_to_rgb[0]; - else - /* - * not supported, b2r2_node_split_analyze() - * should have returned ENOSYS. - */ - BUG_ON(1); + } else if (is_yvu_fmt(dst->fmt)) { + *vmx = &vmx_blt_yuv888_to_yvu[0]; + } else if (is_yuv_fmt(dst->fmt)) { + switch (dst->fmt) { + case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: /* do nothing */ + break; + default: + *vmx = &vmx_blt_yuv888_to_yuv[0]; + break; + } + } } else if (is_yuv_fmt(src->fmt)) { if (is_rgb_fmt(dst->fmt)) *vmx = &vmx_yuv_to_rgb[0]; else if (is_bgr_fmt(dst->fmt)) *vmx = &vmx_yuv_to_bgr[0]; else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 || - dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) - BUG_ON(1); + dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 || + dst->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + dst->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + *vmx = &vmx_yuv_to_blt_yuv888[0]; else if (is_yvu_fmt(dst->fmt)) *vmx = &vmx_yvu_to_yuv[0]; } else if (is_bgr_fmt(src->fmt)) { @@ -735,7 +792,9 @@ static int analyze_fmt_conv(struct b2r2_node_split_buf *src, else if (is_yvu_fmt(dst->fmt)) *vmx = &vmx_bgr_to_yvu[0]; else if (dst->fmt == B2R2_BLT_FMT_24_BIT_YUV888 || - dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) + dst->fmt == B2R2_BLT_FMT_32_BIT_AYUV8888 || + dst->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + dst->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) BUG_ON(1); else if (is_yuv_fmt(dst->fmt)) *vmx = &vmx_bgr_to_yuv[0]; @@ -778,7 +837,8 @@ static int analyze_color_fill(struct b2r2_node_split_job *this, if ((!this->blend) && ((this->flags & B2R2_BLT_FLAG_SOURCE_FILL_RAW) || (this->dst.fmt == B2R2_BLT_FMT_32_BIT_ARGB8888) || (this->dst.fmt == B2R2_BLT_FMT_32_BIT_ABGR8888) || - (this->dst.fmt == B2R2_BLT_FMT_32_BIT_AYUV8888))) { + (this->dst.fmt == B2R2_BLT_FMT_32_BIT_AYUV8888) || + (this->dst.fmt == B2R2_BLT_FMT_32_BIT_VUYA8888))) { this->type = B2R2_DIRECT_FILL; /* The color format will be the same as the dst fmt */ @@ -2707,6 +2767,7 @@ static enum b2r2_ty get_alpha_range(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_32_BIT_ARGB8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_8_BIT_A8: case B2R2_BLT_FMT_32_BIT_ABGR8888: return B2R2_TY_ALPHA_RANGE_255; /* 0 - 255 */ @@ -2725,6 +2786,8 @@ static u8 get_alpha(enum b2r2_blt_fmt fmt, u32 pixel) case B2R2_BLT_FMT_32_BIT_ABGR8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: return (pixel >> 24) & 0xff; + case B2R2_BLT_FMT_32_BIT_VUYA8888: + return pixel & 0xff; case B2R2_BLT_FMT_24_BIT_ARGB8565: return (pixel & 0xfff) >> 16; case B2R2_BLT_FMT_16_BIT_ARGB4444: @@ -2754,6 +2817,10 @@ static u32 set_alpha(enum b2r2_blt_fmt fmt, u8 alpha, u32 color) color &= 0x00ffffff; alpha_mask = alpha << 24; break; + case B2R2_BLT_FMT_32_BIT_VUYA8888: + color &= 0xffffff00; + alpha_mask = alpha; + break; case B2R2_BLT_FMT_24_BIT_ARGB8565: color &= 0x00ffff; alpha_mask = alpha << 16; @@ -2793,6 +2860,7 @@ static bool fmt_has_alpha(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_32_BIT_ABGR8888: case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_1_BIT_A1: case B2R2_BLT_FMT_8_BIT_A8: return true; @@ -2837,6 +2905,8 @@ static bool is_yuv_fmt(enum b2r2_blt_fmt fmt) switch (fmt) { case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_Y_CB_Y_CR: case B2R2_BLT_FMT_CB_Y_CR_Y: case B2R2_BLT_FMT_YUV420_PACKED_PLANAR: @@ -2942,6 +3012,8 @@ static bool is_yuv444_fmt(enum b2r2_blt_fmt fmt) switch (fmt) { case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_YUV444_PACKED_PLANAR: return true; default: @@ -2988,11 +3060,13 @@ static int fmt_byte_pitch(enum b2r2_blt_fmt fmt, u32 width) case B2R2_BLT_FMT_24_BIT_RGB888: /* Fall through */ case B2R2_BLT_FMT_24_BIT_ARGB8565: /* Fall through */ case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: return width * 3; case B2R2_BLT_FMT_32_BIT_ARGB8888: /* Fall through */ case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Fall through */ case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: return width << 2; default: @@ -3026,11 +3100,13 @@ static enum b2r2_native_fmt to_native_fmt(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_RGB888: return B2R2_NATIVE_RGB888; case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: /* Not actually supported by HW */ return B2R2_NATIVE_YCBCR888; case B2R2_BLT_FMT_32_BIT_ABGR8888: /* Not actually supported by HW */ case B2R2_BLT_FMT_32_BIT_ARGB8888: return B2R2_NATIVE_ARGB8888; case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: /* Not actually supported by HW */ return B2R2_NATIVE_AYCBCR8888; case B2R2_BLT_FMT_CB_Y_CR_Y: return B2R2_NATIVE_YCBCR422R; @@ -3125,6 +3201,8 @@ static enum b2r2_fmt_type get_fmt_type(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_1_BIT_A1: case B2R2_BLT_FMT_8_BIT_A8: return B2R2_FMT_TYPE_RASTER; @@ -3256,6 +3334,11 @@ static void set_target(struct b2r2_node *node, u32 addr, node->node.GROUP1.B2R2_TTY = buf->pitch | to_native_fmt(buf->fmt) | buf->alpha_range | buf->chroma_selection | buf->hso | buf->vso | buf->dither | buf->plane_selection; + + if (buf->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + buf->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + node->node.GROUP1.B2R2_TTY |= B2R2_TY_ENDIAN_BIG_NOT_LITTLE; + node->node.GROUP1.B2R2_TSZ = ((buf->win.width & 0xfff) << B2R2_SZ_WIDTH_SHIFT) | ((buf->win.height & 0xfff) << B2R2_SZ_HEIGHT_SHIFT); @@ -3306,6 +3389,11 @@ static void set_src(struct b2r2_src_config *src, u32 addr, src->B2R2_SBA = addr; src->B2R2_STY = buf->pitch | to_native_fmt(buf->fmt) | buf->alpha_range | buf->hso | buf->vso; + + if (buf->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + buf->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + src->B2R2_STY |= B2R2_TY_ENDIAN_BIG_NOT_LITTLE; + src->B2R2_SSZ = ((buf->win.width & 0xfff) << B2R2_SZ_WIDTH_SHIFT) | ((buf->win.height & 0xfff) << B2R2_SZ_HEIGHT_SHIFT); src->B2R2_SXY = ((buf->win.x & 0xffff) << B2R2_XY_X_SHIFT) | @@ -3330,6 +3418,11 @@ static void set_src_1(struct b2r2_node *node, u32 addr, node->node.GROUP3.B2R2_SBA = addr; node->node.GROUP3.B2R2_STY = buf->pitch | to_native_fmt(buf->fmt) | buf->alpha_range | buf->hso | buf->vso; + + if (buf->fmt == B2R2_BLT_FMT_24_BIT_VUY888 || + buf->fmt == B2R2_BLT_FMT_32_BIT_VUYA8888) + node->node.GROUP3.B2R2_STY |= B2R2_TY_ENDIAN_BIG_NOT_LITTLE; + node->node.GROUP3.B2R2_SXY = ((buf->win.x & 0xffff) << B2R2_XY_X_SHIFT) | ((buf->win.y & 0xffff) << B2R2_XY_Y_SHIFT); diff --git a/drivers/video/b2r2/b2r2_utils.c b/drivers/video/b2r2/b2r2_utils.c index 44ea06e51fd..ad0e7a42fa1 100644 --- a/drivers/video/b2r2/b2r2_utils.c +++ b/drivers/video/b2r2/b2r2_utils.c @@ -101,12 +101,14 @@ int b2r2_get_fmt_bpp(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_RGB888: case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: case B2R2_BLT_FMT_YUV444_PACKED_PLANAR: return 24; case B2R2_BLT_FMT_32_BIT_ARGB8888: case B2R2_BLT_FMT_32_BIT_ABGR8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: return 32; default: @@ -134,6 +136,8 @@ int b2r2_get_fmt_y_bpp(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_YUV444_PACKED_PLANAR: case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: return 8; default: @@ -155,9 +159,11 @@ bool b2r2_is_single_plane_fmt(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_RGB888: case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: case B2R2_BLT_FMT_32_BIT_ARGB8888: case B2R2_BLT_FMT_32_BIT_ABGR8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_Y_CB_Y_CR: case B2R2_BLT_FMT_CB_Y_CR_Y: return true; @@ -178,9 +184,11 @@ bool b2r2_is_independent_pixel_fmt(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_24_BIT_RGB888: case B2R2_BLT_FMT_24_BIT_ARGB8565: case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_24_BIT_VUY888: case B2R2_BLT_FMT_32_BIT_ARGB8888: case B2R2_BLT_FMT_32_BIT_ABGR8888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: case B2R2_BLT_FMT_YUV444_PACKED_PLANAR: return true; @@ -196,6 +204,8 @@ bool b2r2_is_ycbcri_fmt(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_CB_Y_CR_Y: case B2R2_BLT_FMT_24_BIT_YUV888: case B2R2_BLT_FMT_32_BIT_AYUV8888: + case B2R2_BLT_FMT_24_BIT_VUY888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: return true; default: @@ -270,6 +280,8 @@ bool b2r2_is_ycbcr444_fmt(enum b2r2_blt_fmt fmt) case B2R2_BLT_FMT_YUV444_PACKED_PLANAR: case B2R2_BLT_FMT_32_BIT_AYUV8888: case B2R2_BLT_FMT_24_BIT_YUV888: + case B2R2_BLT_FMT_32_BIT_VUYA8888: + case B2R2_BLT_FMT_24_BIT_VUY888: return true; default: diff --git a/include/video/b2r2_blt.h b/include/video/b2r2_blt.h index 1cf5f661598..a992155f0da 100644 --- a/include/video/b2r2_blt.h +++ b/include/video/b2r2_blt.h @@ -127,6 +127,10 @@ struct b2r2_blt_rect { * The buffer shall contain a plane of Y, V, and U data in this order. * (Same as B2R2_BLT_FMT_YUV422_PACKED_PLANAR except that chroma * order is swapped.) + * @B2R2_BLT_FMT_24_BIT_VUY888: 24 bits per pixel VUY format with colors + * stored as V 23:16, U 15:8, and Y 7:0. + * @B2R2_BLT_FMT_32_BIT_VUYA8888: 32 bits per pixel VUYA format with colors + * stored as V 31:24, U 23:16, Y 15:8, and Alpha 7:0. */ enum b2r2_blt_fmt { B2R2_BLT_FMT_UNUSED = 0, @@ -155,6 +159,8 @@ enum b2r2_blt_fmt { B2R2_BLT_FMT_YVU422_PACKED_SEMI_PLANAR = 0x7F00000A, B2R2_BLT_FMT_YVU420_PACKED_PLANAR = 0x7F00000B, B2R2_BLT_FMT_YVU422_PACKED_PLANAR = 0x7F00000C, + B2R2_BLT_FMT_24_BIT_VUY888 = 0x7F00000D, + B2R2_BLT_FMT_32_BIT_VUYA8888 = 0x7F00000E, }; /** |