msm: rotator: Enable support for 2-pass fast YUV mode
Add support for 2-pass rotator operation for downscaling
and 90 degree rotation when rotator operates in fast YUV
mode. 2-pass is supported for 420 H2V2 formats.
Change-Id: Ib8ce802a5a8aabe10c88422e3b8d82708c5b05d4
Signed-off-by: Padmanabhan Komanduru <pkomandu@codeaurora.org>
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index d6a871d..305033b 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -155,6 +155,8 @@
struct msm_rotator_img_info img_info;
struct msm_rotator_fd_info fd_info;
int fast_yuv_enable;
+ int enable_2pass;
+ u32 mem_hid;
};
struct msm_rotator_commit_info {
@@ -179,6 +181,7 @@
int session_index;
struct sync_fence *acq_fen;
int fast_yuv_en;
+ int enable_2pass;
};
struct msm_rotator_dev {
@@ -222,6 +225,9 @@
atomic_t commit_q_r;
atomic_t commit_q_w;
atomic_t commit_q_cnt;
+ struct rot_buf_type *y_rot_buf;
+ struct rot_buf_type *chroma_rot_buf;
+ struct rot_buf_type *chroma2_rot_buf;
};
#define COMPONENT_5BITS 1
@@ -248,6 +254,129 @@
{"smmu_iface_clk"}
};
+u32 rotator_allocate_2pass_buf(struct rot_buf_type *rot_buf, int s_ndx)
+{
+ ion_phys_addr_t addr, read_addr = 0;
+ size_t buffer_size;
+ unsigned long len;
+
+ if (!rot_buf) {
+ pr_err("Rot_buf NULL pointer %s %i", __func__, __LINE__);
+ return 0;
+ }
+
+ if (rot_buf->write_addr || !IS_ERR_OR_NULL(rot_buf->ihdl))
+ return 0;
+
+ buffer_size = roundup(1920 * 1088, SZ_4K);
+
+ if (!IS_ERR_OR_NULL(mrd->client)) {
+ pr_info("%s:%d ion based allocation\n",
+ __func__, __LINE__);
+ rot_buf->ihdl = ion_alloc(mrd->client, buffer_size, SZ_4K,
+ mrd->rot_session[s_ndx]->mem_hid, 0);
+ if (!IS_ERR_OR_NULL(rot_buf->ihdl)) {
+ if (rot_iommu_split_domain) {
+ if (ion_map_iommu(mrd->client, rot_buf->ihdl,
+ ROTATOR_SRC_DOMAIN, GEN_POOL, SZ_4K,
+ 0, &read_addr, &len, 0, 0)) {
+ pr_err("ion_map_iommu() read failed\n");
+ return -ENOMEM;
+ }
+ if (mrd->rot_session[s_ndx]->mem_hid &
+ ION_SECURE) {
+ if (ion_phys(mrd->client, rot_buf->ihdl,
+ &addr, (size_t *)&len)) {
+ pr_err(
+ "%s:%d: ion_phys map failed\n",
+ __func__, __LINE__);
+ return -ENOMEM;
+ }
+ } else {
+ if (ion_map_iommu(mrd->client,
+ rot_buf->ihdl, ROTATOR_DST_DOMAIN,
+ GEN_POOL, SZ_4K, 0, &addr, &len,
+ 0, 0)) {
+ pr_err("ion_map_iommu() failed\n");
+ return -ENOMEM;
+ }
+ }
+ } else {
+ if (ion_map_iommu(mrd->client, rot_buf->ihdl,
+ ROTATOR_SRC_DOMAIN, GEN_POOL, SZ_4K,
+ 0, &addr, &len, 0, 0)) {
+ pr_err("ion_map_iommu() write failed\n");
+ return -ENOMEM;
+ }
+ }
+ } else {
+ pr_err("%s:%d: ion_alloc failed\n", __func__,
+ __LINE__);
+ return -ENOMEM;
+ }
+ } else {
+ addr = allocate_contiguous_memory_nomap(buffer_size,
+ mrd->rot_session[s_ndx]->mem_hid, 4);
+ }
+ if (addr) {
+ pr_info("allocating %d bytes at write=%x, read=%x for 2-pass\n",
+ buffer_size, (u32) addr, (u32) read_addr);
+ rot_buf->write_addr = addr;
+
+ if (read_addr)
+ rot_buf->read_addr = read_addr;
+ else
+ rot_buf->read_addr = rot_buf->write_addr;
+
+ return 0;
+ } else {
+ pr_err("%s cannot allocate memory for rotator 2-pass!\n",
+ __func__);
+ return -ENOMEM;
+ }
+}
+
+void rotator_free_2pass_buf(struct rot_buf_type *rot_buf, int s_ndx)
+{
+
+ if (!rot_buf) {
+ pr_err("Rot_buf NULL pointer %s %i", __func__, __LINE__);
+ return;
+ }
+
+ if (!rot_buf->write_addr)
+ return;
+
+ if (!IS_ERR_OR_NULL(mrd->client)) {
+ if (!IS_ERR_OR_NULL(rot_buf->ihdl)) {
+ if (rot_iommu_split_domain) {
+ if (!(mrd->rot_session[s_ndx]->mem_hid &
+ ION_SECURE))
+ ion_unmap_iommu(mrd->client,
+ rot_buf->ihdl, ROTATOR_DST_DOMAIN,
+ GEN_POOL);
+ ion_unmap_iommu(mrd->client, rot_buf->ihdl,
+ ROTATOR_SRC_DOMAIN, GEN_POOL);
+ } else {
+ ion_unmap_iommu(mrd->client, rot_buf->ihdl,
+ ROTATOR_SRC_DOMAIN, GEN_POOL);
+ }
+ ion_free(mrd->client, rot_buf->ihdl);
+ rot_buf->ihdl = NULL;
+ pr_info("%s:%d Free rotator 2pass memory",
+ __func__, __LINE__);
+ }
+ } else {
+ if (rot_buf->write_addr) {
+ free_contiguous_memory_by_paddr(rot_buf->write_addr);
+ pr_debug("%s:%d Free rotator 2pass pmem\n", __func__,
+ __LINE__);
+ }
+ }
+ rot_buf->write_addr = 0;
+ rot_buf->read_addr = 0;
+}
+
int msm_rotator_iommu_map_buf(int mem_id, int domain,
unsigned long *start, unsigned long *len,
struct ion_handle **pihdl, unsigned int secure)
@@ -1007,7 +1136,7 @@
MSM_ROTATOR_OUT_PACK_PATTERN1);
}
- iowrite32((3 << 18) | /* chroma sampling 3=4:2:0 */
+ iowrite32((3 << 18) | /* chroma sampling 3=4:2:0 */
(ROTATIONS_TO_BITMASK(info->rotations) << 9) |
1 << 8 | /* ROT_EN */
fast_yuv_en << 4 | /*fast YUV*/
@@ -1018,6 +1147,307 @@
iowrite32((is_tile ? 2 : 0) << 29 | /* frame format */
(use_imem ? 0 : 1) << 22 | /* tile size */
(in_chroma2_paddr ? 1 : 2) << 19 | /* fetch planes */
+ 0 << 18 | /* unpack align */
+ 1 << 17 | /* unpack tight */
+ 1 << 13 | /* unpack count 0=1 component */
+ 0 << 9 | /* src Bpp 0=1 byte ... */
+ 0 << 8 | /* has alpha */
+ 0 << 6 | /* alpha bits 3=8bits */
+ 3 << 4 | /* R/Cr bits 1=5 2=6 3=8 */
+ 3 << 2 | /* B/Cb bits 1=5 2=6 3=8 */
+ 3 << 0, /* G/Y bits 1=5 2=6 3=8 */
+ MSM_ROTATOR_SRC_FORMAT);
+ }
+ return 0;
+}
+
+static int msm_rotator_ycxcx_h2v2_2pass(struct msm_rotator_img_info *info,
+ unsigned int in_paddr,
+ unsigned int out_paddr,
+ unsigned int use_imem,
+ int new_session,
+ unsigned int in_chroma_paddr,
+ unsigned int out_chroma_paddr,
+ unsigned int in_chroma2_paddr,
+ unsigned int out_chroma2_paddr,
+ int fast_yuv_en,
+ int enable_2pass,
+ int session_index)
+{
+ uint32_t pass2_src_format, pass1_dst_format, dst_format;
+ int is_tile = 0, post_pass1_buf_is_planar = 0;
+ unsigned int status;
+ int post_pass1_ystride = info->src_rect.w >> info->downscale_ratio;
+ int post_pass1_height = info->src_rect.h >> info->downscale_ratio;
+
+ /* DST format = SRC format for non-tiled SRC formats
+ * when fast YUV is enabled. For TILED formats,
+ * DST format of MDP_Y_CRCB_H2V2_TILE = MDP_Y_CRCB_H2V2
+ * DST format of MDP_Y_CBCR_H2V2_TILE = MDP_Y_CBCR_H2V2
+ */
+ switch (info->src.format) {
+ case MDP_Y_CRCB_H2V2_TILE:
+ is_tile = 1;
+ dst_format = MDP_Y_CRCB_H2V2;
+ pass1_dst_format = MDP_Y_CRCB_H2V2;
+ pass2_src_format = pass1_dst_format;
+ break;
+ case MDP_Y_CR_CB_H2V2:
+ case MDP_Y_CR_CB_GH2V2:
+ case MDP_Y_CB_CR_H2V2:
+ post_pass1_buf_is_planar = 1;
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V2:
+ dst_format = info->src.format;
+ pass1_dst_format = info->src.format;
+ pass2_src_format = pass1_dst_format;
+ break;
+ case MDP_Y_CBCR_H2V2_TILE:
+ is_tile = 1;
+ dst_format = MDP_Y_CBCR_H2V2;
+ pass1_dst_format = info->src.format;
+ pass2_src_format = pass1_dst_format;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (info->dst.format != dst_format)
+ return -EINVAL;
+
+ /* Beginning of Pass-1 */
+ /* rotator expects YCbCr for planar input format */
+ if ((info->src.format == MDP_Y_CR_CB_H2V2 ||
+ info->src.format == MDP_Y_CR_CB_GH2V2) &&
+ rotator_hw_revision < ROTATOR_REVISION_V2)
+ swap(in_chroma_paddr, in_chroma2_paddr);
+
+ iowrite32(in_paddr, MSM_ROTATOR_SRCP0_ADDR);
+ iowrite32(in_chroma_paddr, MSM_ROTATOR_SRCP1_ADDR);
+ iowrite32(in_chroma2_paddr, MSM_ROTATOR_SRCP2_ADDR);
+
+ if (new_session) {
+ if (in_chroma2_paddr) {
+ if (info->src.format == MDP_Y_CR_CB_GH2V2) {
+ iowrite32(ALIGN(info->src.width, 16) |
+ ALIGN((info->src.width / 2), 16) << 16,
+ MSM_ROTATOR_SRC_YSTRIDE1);
+ iowrite32(ALIGN((info->src.width / 2), 16),
+ MSM_ROTATOR_SRC_YSTRIDE2);
+ } else {
+ iowrite32(info->src.width |
+ (info->src.width / 2) << 16,
+ MSM_ROTATOR_SRC_YSTRIDE1);
+ iowrite32((info->src.width / 2),
+ MSM_ROTATOR_SRC_YSTRIDE2);
+ }
+ } else {
+ iowrite32(info->src.width |
+ info->src.width << 16,
+ MSM_ROTATOR_SRC_YSTRIDE1);
+ }
+ }
+
+ pr_debug("src_rect.w=%i src_rect.h=%i src_rect.x=%i src_rect.y=%i",
+ info->src_rect.w, info->src_rect.h, info->src_rect.x,
+ info->src_rect.y);
+ pr_debug("src.width=%i src.height=%i src_format=%i",
+ info->src.width, info->src.height, info->src.format);
+ pr_debug("dst_width=%i dst_height=%i dst.x=%i dst.y=%i",
+ info->dst.width, info->dst.height, info->dst_x, info->dst_y);
+ pr_debug("post_pass1_ystride=%i post_pass1_height=%i downscale=%i",
+ post_pass1_ystride, post_pass1_height, info->downscale_ratio);
+
+ rotator_allocate_2pass_buf(mrd->y_rot_buf, session_index);
+ rotator_allocate_2pass_buf(mrd->chroma_rot_buf, session_index);
+ if (post_pass1_buf_is_planar)
+ rotator_allocate_2pass_buf(mrd->chroma2_rot_buf, session_index);
+
+ iowrite32(mrd->y_rot_buf->write_addr, MSM_ROTATOR_OUTP0_ADDR);
+ iowrite32(mrd->chroma_rot_buf->write_addr, MSM_ROTATOR_OUTP1_ADDR);
+ if (post_pass1_buf_is_planar)
+ iowrite32(mrd->chroma2_rot_buf->write_addr,
+ MSM_ROTATOR_OUTP2_ADDR);
+
+ if (post_pass1_buf_is_planar) {
+ if (pass1_dst_format == MDP_Y_CR_CB_GH2V2) {
+ iowrite32(ALIGN(post_pass1_ystride, 16) |
+ ALIGN((post_pass1_ystride / 2), 16) << 16,
+ MSM_ROTATOR_OUT_YSTRIDE1);
+ iowrite32(ALIGN((post_pass1_ystride / 2), 16),
+ MSM_ROTATOR_OUT_YSTRIDE2);
+ } else {
+ iowrite32(post_pass1_ystride |
+ post_pass1_ystride / 2 << 16,
+ MSM_ROTATOR_OUT_YSTRIDE1);
+ iowrite32(post_pass1_ystride / 2,
+ MSM_ROTATOR_OUT_YSTRIDE2);
+ }
+ } else {
+ iowrite32(post_pass1_ystride |
+ post_pass1_ystride << 16,
+ MSM_ROTATOR_OUT_YSTRIDE1);
+ }
+
+ if (pass1_dst_format == MDP_Y_CBCR_H2V2 ||
+ pass1_dst_format == MDP_Y_CB_CR_H2V2) {
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
+ MSM_ROTATOR_SRC_UNPACK_PATTERN1);
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
+ MSM_ROTATOR_OUT_PACK_PATTERN1);
+ } else {
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+ MSM_ROTATOR_SRC_UNPACK_PATTERN1);
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+ MSM_ROTATOR_OUT_PACK_PATTERN1);
+ }
+
+ iowrite32((3 << 18) | /* chroma sampling 3=4:2:0 */
+ 0 << 9 | /* Pass-1 No Rotation */
+ 1 << 8 | /* ROT_EN */
+ fast_yuv_en << 4 | /*fast YUV*/
+ info->downscale_ratio << 2 | /* downscale v ratio */
+ info->downscale_ratio, /* downscale h ratio */
+ MSM_ROTATOR_SUB_BLOCK_CFG);
+
+ iowrite32((is_tile ? 2 : 0) << 29 | /* frame format */
+ (use_imem ? 0 : 1) << 22 | /* tile size */
+ (in_chroma2_paddr ? 1 : 2) << 19 | /* fetch planes */
+ 0 << 18 | /* unpack align */
+ 1 << 17 | /* unpack tight */
+ 1 << 13 | /* unpack count 0=1 component */
+ 0 << 9 | /* src Bpp 0=1 byte ... */
+ 0 << 8 | /* has alpha */
+ 0 << 6 | /* alpha bits 3=8bits */
+ 3 << 4 | /* R/Cr bits 1=5 2=6 3=8 */
+ 3 << 2 | /* B/Cb bits 1=5 2=6 3=8 */
+ 3 << 0, /* G/Y bits 1=5 2=6 3=8 */
+ MSM_ROTATOR_SRC_FORMAT);
+
+ iowrite32(3, MSM_ROTATOR_INTR_ENABLE);
+
+ msm_rotator_dev->processing = 1;
+ iowrite32(0x1, MSM_ROTATOR_START);
+ mutex_unlock(&msm_rotator_dev->rotator_lock);
+ /* End of Pass-1 */
+ wait_event(msm_rotator_dev->wq,
+ (msm_rotator_dev->processing == 0));
+ /* Beginning of Pass-2 */
+ mutex_lock(&msm_rotator_dev->rotator_lock);
+ status = (unsigned char)ioread32(MSM_ROTATOR_INTR_STATUS);
+ if ((status & 0x03) != 0x01) {
+ pr_err("%s(): AXI Bus Error, issuing SW_RESET\n",
+ __func__);
+ iowrite32(0x1, MSM_ROTATOR_SW_RESET);
+ }
+ iowrite32(0, MSM_ROTATOR_INTR_ENABLE);
+ iowrite32(3, MSM_ROTATOR_INTR_CLEAR);
+
+ if (use_imem)
+ iowrite32(0x42, MSM_ROTATOR_MAX_BURST_SIZE);
+
+ iowrite32(((post_pass1_height & 0x1fff)
+ << 16) |
+ (post_pass1_ystride & 0x1fff),
+ MSM_ROTATOR_SRC_SIZE);
+ iowrite32(0 << 16 | 0,
+ MSM_ROTATOR_SRC_XY);
+ iowrite32(((post_pass1_height & 0x1fff)
+ << 16) |
+ (post_pass1_ystride & 0x1fff),
+ MSM_ROTATOR_SRC_IMAGE_SIZE);
+
+ /* rotator expects YCbCr for planar input format */
+ if ((pass2_src_format == MDP_Y_CR_CB_H2V2 ||
+ pass2_src_format == MDP_Y_CR_CB_GH2V2) &&
+ rotator_hw_revision < ROTATOR_REVISION_V2)
+ swap(mrd->chroma_rot_buf->read_addr,
+ mrd->chroma2_rot_buf->read_addr);
+
+ iowrite32(mrd->y_rot_buf->read_addr, MSM_ROTATOR_SRCP0_ADDR);
+ iowrite32(mrd->chroma_rot_buf->read_addr,
+ MSM_ROTATOR_SRCP1_ADDR);
+ if (mrd->chroma2_rot_buf->read_addr)
+ iowrite32(mrd->chroma2_rot_buf->read_addr,
+ MSM_ROTATOR_SRCP2_ADDR);
+
+ if (post_pass1_buf_is_planar) {
+ if (pass2_src_format == MDP_Y_CR_CB_GH2V2) {
+ iowrite32(ALIGN(post_pass1_ystride, 16) |
+ ALIGN((post_pass1_ystride / 2), 16) << 16,
+ MSM_ROTATOR_SRC_YSTRIDE1);
+ iowrite32(ALIGN((post_pass1_ystride / 2), 16),
+ MSM_ROTATOR_SRC_YSTRIDE2);
+ } else {
+ iowrite32(post_pass1_ystride |
+ (post_pass1_ystride / 2) << 16,
+ MSM_ROTATOR_SRC_YSTRIDE1);
+ iowrite32((post_pass1_ystride / 2),
+ MSM_ROTATOR_SRC_YSTRIDE2);
+ }
+ } else {
+ iowrite32(post_pass1_ystride |
+ post_pass1_ystride << 16,
+ MSM_ROTATOR_SRC_YSTRIDE1);
+ }
+
+ iowrite32(out_paddr +
+ ((info->dst_y * info->dst.width) + info->dst_x),
+ MSM_ROTATOR_OUTP0_ADDR);
+ iowrite32(out_chroma_paddr +
+ (((info->dst_y * info->dst.width)/2) + info->dst_x),
+ MSM_ROTATOR_OUTP1_ADDR);
+ if (out_chroma2_paddr)
+ iowrite32(out_chroma2_paddr +
+ (((info->dst_y * info->dst.width)/2) + info->dst_x),
+ MSM_ROTATOR_OUTP2_ADDR);
+
+
+ if (new_session) {
+ if (out_chroma2_paddr) {
+ if (info->dst.format == MDP_Y_CR_CB_GH2V2) {
+ iowrite32(ALIGN(info->dst.width, 16) |
+ ALIGN((info->dst.width / 2), 16) << 16,
+ MSM_ROTATOR_OUT_YSTRIDE1);
+ iowrite32(ALIGN((info->dst.width / 2), 16),
+ MSM_ROTATOR_OUT_YSTRIDE2);
+ } else {
+ iowrite32(info->dst.width |
+ info->dst.width/2 << 16,
+ MSM_ROTATOR_OUT_YSTRIDE1);
+ iowrite32(info->dst.width/2,
+ MSM_ROTATOR_OUT_YSTRIDE2);
+ }
+ } else {
+ iowrite32(info->dst.width |
+ info->dst.width << 16,
+ MSM_ROTATOR_OUT_YSTRIDE1);
+ }
+
+ if (dst_format == MDP_Y_CBCR_H2V2 ||
+ dst_format == MDP_Y_CB_CR_H2V2) {
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
+ MSM_ROTATOR_SRC_UNPACK_PATTERN1);
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8),
+ MSM_ROTATOR_OUT_PACK_PATTERN1);
+ } else {
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+ MSM_ROTATOR_SRC_UNPACK_PATTERN1);
+ iowrite32(GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8),
+ MSM_ROTATOR_OUT_PACK_PATTERN1);
+ }
+
+ iowrite32((3 << 18) | /* chroma sampling 3=4:2:0 */
+ (ROTATIONS_TO_BITMASK(info->rotations) << 9) |
+ 1 << 8 | /* ROT_EN */
+ fast_yuv_en << 4 | /*fast YUV*/
+ 0 << 2 | /* No downscale in Pass-2 */
+ 0, /* No downscale in Pass-2 */
+ MSM_ROTATOR_SUB_BLOCK_CFG);
+
+ iowrite32(0 << 29 |
+ /* Output of Pass-1 will always be non-tiled */
+ (use_imem ? 0 : 1) << 22 | /* tile size */
+ (in_chroma2_paddr ? 1 : 2) << 19 | /* fetch planes */
0 << 18 | /* unpack align */
1 << 17 | /* unpack tight */
1 << 13 | /* unpack count 0=1 component */
@@ -1497,6 +1927,7 @@
commit_info->session_index = s;
commit_info->acq_fen = msm_rotator_dev->sync_info[s].acq_fen;
commit_info->fast_yuv_en = mrd->rot_session[s]->fast_yuv_enable;
+ commit_info->enable_2pass = mrd->rot_session[s]->enable_2pass;
mutex_unlock(&msm_rotator_dev->rotator_lock);
return 0;
@@ -1616,7 +2047,8 @@
case MDP_Y_CR_CB_GH2V2:
case MDP_Y_CRCB_H2V2_TILE:
case MDP_Y_CBCR_H2V2_TILE:
- rc = msm_rotator_ycxcx_h2v2(img_info,
+ if (!commit_info->enable_2pass)
+ rc = msm_rotator_ycxcx_h2v2(img_info,
in_paddr, out_paddr, use_imem,
msm_rotator_dev->last_session_idx
!= s,
@@ -1625,6 +2057,18 @@
in_chroma2_paddr,
out_chroma2_paddr,
commit_info->fast_yuv_en);
+ else
+ rc = msm_rotator_ycxcx_h2v2_2pass(img_info,
+ in_paddr, out_paddr, use_imem,
+ msm_rotator_dev->last_session_idx
+ != s,
+ in_chroma_paddr,
+ out_chroma_paddr,
+ in_chroma2_paddr,
+ out_chroma2_paddr,
+ commit_info->fast_yuv_en,
+ commit_info->enable_2pass,
+ s);
break;
case MDP_Y_CBCR_H2V1:
case MDP_Y_CRCB_H2V1:
@@ -1913,7 +2357,7 @@
int first_free_idx = INVALID_SESSION;
unsigned int dst_w, dst_h;
unsigned int is_planar420 = 0;
- int fast_yuv_en = 0;
+ int fast_yuv_en = 0, enable_2pass = 0;
struct rot_sync_info *sync_info;
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
@@ -1954,9 +2398,7 @@
case MDP_Y_CRCB_H2V2:
case MDP_Y_CRCB_H2V2_TILE:
case MDP_Y_CBCR_H2V2_TILE:
- if (rotator_hw_revision >= ROTATOR_REVISION_V2 &&
- !(info.downscale_ratio &&
- (info.rotations & MDP_ROT_90)))
+ if (rotator_hw_revision >= ROTATOR_REVISION_V2) {
fast_yuv_en = !fast_yuv_invalid_size_checker(
info.rotations,
info.src.width,
@@ -1965,6 +2407,10 @@
dst_h,
dst_w,
is_planar420);
+ if (fast_yuv_en && info.downscale_ratio &&
+ (info.rotations & MDP_ROT_90))
+ enable_2pass = 1;
+ }
break;
default:
fast_yuv_en = 0;
@@ -2030,6 +2476,7 @@
rot_session->img_info = info;
rot_session->fd_info = *fd_info;
rot_session->fast_yuv_enable = fast_yuv_en;
+ rot_session->enable_2pass = enable_2pass;
if (msm_rotator_dev->last_session_idx == s)
msm_rotator_dev->last_session_idx =
@@ -2060,6 +2507,18 @@
rot_session->img_info = info;
rot_session->fd_info = *fd_info;
rot_session->fast_yuv_enable = fast_yuv_en;
+ rot_session->enable_2pass = enable_2pass;
+
+ if (!IS_ERR_OR_NULL(mrd->client)) {
+ if (rot_session->img_info.secure) {
+ rot_session->mem_hid &= ~BIT(ION_IOMMU_HEAP_ID);
+ rot_session->mem_hid |= ION_SECURE;
+ } else {
+ rot_session->mem_hid |= BIT(ION_IOMMU_HEAP_ID);
+ rot_session->mem_hid &= ~ION_SECURE;
+ }
+ }
+
s = first_free_idx;
} else if (s == MAX_SESSIONS) {
dev_dbg(msm_rotator_dev->device, "%s: all sessions in use\n",
@@ -2115,6 +2574,11 @@
INVALID_SESSION;
msm_rotator_signal_timeline(s);
msm_rotator_release_acq_fence(s);
+ if (msm_rotator_dev->rot_session[s]->enable_2pass) {
+ rotator_free_2pass_buf(mrd->y_rot_buf, s);
+ rotator_free_2pass_buf(mrd->chroma_rot_buf, s);
+ rotator_free_2pass_buf(mrd->chroma2_rot_buf, s);
+ }
kfree(msm_rotator_dev->rot_session[s]);
msm_rotator_dev->rot_session[s] = NULL;
break;
@@ -2283,6 +2747,14 @@
msm_rotator_dev->core_clk = NULL;
msm_rotator_dev->pclk = NULL;
+ mrd->y_rot_buf = kmalloc(sizeof(struct rot_buf_type), GFP_KERNEL);
+ mrd->chroma_rot_buf = kmalloc(sizeof(struct rot_buf_type), GFP_KERNEL);
+ mrd->chroma2_rot_buf = kmalloc(sizeof(struct rot_buf_type), GFP_KERNEL);
+
+ memset((void *)mrd->y_rot_buf, 0, sizeof(struct rot_buf_type));
+ memset((void *)mrd->chroma_rot_buf, 0, sizeof(struct rot_buf_type));
+ memset((void *)mrd->chroma2_rot_buf, 0, sizeof(struct rot_buf_type));
+
#ifdef CONFIG_MSM_BUS_SCALING
if (!msm_rotator_dev->bus_client_handle && pdata &&
pdata->bus_scale_table) {
diff --git a/include/linux/msm_rotator.h b/include/linux/msm_rotator.h
index 6a8d286..bb4aec0 100644
--- a/include/linux/msm_rotator.h
+++ b/include/linux/msm_rotator.h
@@ -30,6 +30,12 @@
int rel_fen_fd;
};
+struct rot_buf_type {
+ struct ion_handle *ihdl;
+ uint32_t write_addr;
+ uint32_t read_addr;
+};
+
struct msm_rotator_img_info {
unsigned int session_id;
struct msmfb_img src;