msm: rotator: add downscale support in rotator
Rotator is capable of performing 1/2, 1/4 and 1/8 down scaling. Add
downscale_ratio parameter to provide support for this feature.
CRs-Fixed: 315874
Change-Id: I57dc3456ccc9bec2a125750b3e9909ffcbaf45f6
Signed-off-by: Adrian Salido-Moreno <adrianm@codeaurora.org>
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index edf5c27..d6fb937 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -82,6 +82,7 @@
#define MAX_SESSIONS 16
#define INVALID_SESSION -1
#define VERSION_KEY_MASK 0xFFFFFF00
+#define MAX_DOWNSCALE_RATIO 3
struct tile_parm {
unsigned int width; /* tile's width */
@@ -428,7 +429,9 @@
}
iowrite32((1 << 18) | /* chroma sampling 1=H2V1 */
(ROTATIONS_TO_BITMASK(info->rotations) << 9) |
- 1 << 8, /* ROT_EN */
+ 1 << 8 | /* ROT_EN */
+ info->downscale_ratio << 2 | /* downscale v ratio */
+ info->downscale_ratio, /* downscale h ratio */
MSM_ROTATOR_SUB_BLOCK_CFG);
iowrite32(0 << 29 | /* frame format 0 = linear */
(use_imem ? 0 : 1) << 22 | /* tile size */
@@ -528,7 +531,9 @@
}
iowrite32((3 << 18) | /* chroma sampling 3=4:2:0 */
(ROTATIONS_TO_BITMASK(info->rotations) << 9) |
- 1 << 8, /* ROT_EN */
+ 1 << 8 | /* ROT_EN */
+ 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 */
@@ -579,7 +584,9 @@
MSM_ROTATOR_OUT_PACK_PATTERN1);
iowrite32((1 << 18) | /* chroma sampling 1=H2V1 */
(ROTATIONS_TO_BITMASK(info->rotations) << 9) |
- 1 << 8, /* ROT_EN */
+ 1 << 8 | /* ROT_EN */
+ info->downscale_ratio << 2 | /* downscale v ratio */
+ info->downscale_ratio, /* downscale h ratio */
MSM_ROTATOR_SUB_BLOCK_CFG);
iowrite32(0 << 29 | /* frame format 0 = linear */
(use_imem ? 0 : 1) << 22 | /* tile size */
@@ -624,7 +631,9 @@
iowrite32(info->dst.width * bpp, MSM_ROTATOR_OUT_YSTRIDE1);
iowrite32((0 << 18) | /* chroma sampling 0=rgb */
(ROTATIONS_TO_BITMASK(info->rotations) << 9) |
- 1 << 8, /* ROT_EN */
+ 1 << 8 | /* ROT_EN */
+ info->downscale_ratio << 2 | /* downscale v ratio */
+ info->downscale_ratio, /* downscale h ratio */
MSM_ROTATOR_SUB_BLOCK_CFG);
switch (info->src.format) {
case MDP_RGB_565:
@@ -1068,24 +1077,31 @@
if (copy_from_user(&info, (void __user *)arg, sizeof(info)))
return -EFAULT;
- if (info.rotations & MDP_ROT_90) {
- dst_w = info.src_rect.h;
- dst_h = info.src_rect.w;
- } else {
- dst_w = info.src_rect.w;
- dst_h = info.src_rect.h;
- }
-
if ((info.rotations > MSM_ROTATOR_MAX_ROT) ||
(info.src.height > MSM_ROTATOR_MAX_H) ||
(info.src.width > MSM_ROTATOR_MAX_W) ||
(info.dst.height > MSM_ROTATOR_MAX_H) ||
(info.dst.width > MSM_ROTATOR_MAX_W) ||
- checkoffset(info.src_rect.x, info.src_rect.w, info.src.width) ||
+ (info.downscale_ratio > MAX_DOWNSCALE_RATIO)) {
+ pr_err("%s: Invalid parameters\n", __func__);
+ return -EINVAL;
+ }
+
+ if (info.rotations & MDP_ROT_90) {
+ dst_w = info.src_rect.h >> info.downscale_ratio;
+ dst_h = info.src_rect.w >> info.downscale_ratio;
+ } else {
+ dst_w = info.src_rect.w >> info.downscale_ratio;
+ dst_h = info.src_rect.h >> info.downscale_ratio;
+ }
+
+ if (checkoffset(info.src_rect.x, info.src_rect.w, info.src.width) ||
checkoffset(info.src_rect.y, info.src_rect.h, info.src.height) ||
checkoffset(info.dst_x, dst_w, info.dst.width) ||
- checkoffset(info.dst_y, dst_h, info.dst.height))
- return -EINVAL;
+ checkoffset(info.dst_y, dst_h, info.dst.height)) {
+ pr_err("%s: Invalid src or dst rect\n", __func__);
+ return -ERANGE;
+ }
switch (info.src.format) {
case MDP_RGB_565: