aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSylwester Nawrocki <s.nawrocki@samsung.com>2010-12-27 12:47:32 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-03-21 19:31:39 -0400
commitac75934cc644051dc1b33b234448ea4a0990f31f (patch)
treedc50b556438386f3d8b08836c5e41fb7cb7dda68
parentd9160afd31565e44ebbd909b283baad8c9a3c224 (diff)
[media] s5p-fimc: Enable simultaneous rotation and flipping
Map all (0, 90, 180, 270) deg counterclockwise rotation and horizontal and vertical flip controls to (0, 90) deg rotation, horizontal and vertical flip transformations available in the device. Signed-off-by: Sylwester Nawrocki <s.nawrocki@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/s5p-fimc/fimc-core.c9
-rw-r--r--drivers/media/video/s5p-fimc/fimc-reg.c74
2 files changed, 31 insertions, 52 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c
index 9ebb92530053..b8d59f44a088 100644
--- a/drivers/media/video/s5p-fimc/fimc-core.c
+++ b/drivers/media/video/s5p-fimc/fimc-core.c
@@ -1055,13 +1055,6 @@ int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
1055 struct fimc_dev *fimc = ctx->fimc_dev; 1055 struct fimc_dev *fimc = ctx->fimc_dev;
1056 unsigned long flags; 1056 unsigned long flags;
1057 1057
1058 if (ctx->rotation != 0 &&
1059 (ctrl->id == V4L2_CID_HFLIP || ctrl->id == V4L2_CID_VFLIP)) {
1060 v4l2_err(&fimc->m2m.v4l2_dev,
1061 "Simultaneous flip and rotation is not supported\n");
1062 return -EINVAL;
1063 }
1064
1065 spin_lock_irqsave(&ctx->slock, flags); 1058 spin_lock_irqsave(&ctx->slock, flags);
1066 1059
1067 switch (ctrl->id) { 1060 switch (ctrl->id) {
@@ -1102,7 +1095,7 @@ int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl)
1102} 1095}
1103 1096
1104static int fimc_m2m_s_ctrl(struct file *file, void *priv, 1097static int fimc_m2m_s_ctrl(struct file *file, void *priv,
1105 struct v4l2_control *ctrl) 1098 struct v4l2_control *ctrl)
1106{ 1099{
1107 struct fimc_ctx *ctx = priv; 1100 struct fimc_ctx *ctx = priv;
1108 int ret = 0; 1101 int ret = 0;
diff --git a/drivers/media/video/s5p-fimc/fimc-reg.c b/drivers/media/video/s5p-fimc/fimc-reg.c
index c4703b5800c4..c14c8316ea13 100644
--- a/drivers/media/video/s5p-fimc/fimc-reg.c
+++ b/drivers/media/video/s5p-fimc/fimc-reg.c
@@ -37,11 +37,11 @@ void fimc_hw_reset(struct fimc_dev *dev)
37 writel(cfg, dev->regs + S5P_CIGCTRL); 37 writel(cfg, dev->regs + S5P_CIGCTRL);
38} 38}
39 39
40static u32 fimc_hw_get_in_flip(u32 ctx_flip) 40static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
41{ 41{
42 u32 flip = S5P_MSCTRL_FLIP_NORMAL; 42 u32 flip = S5P_MSCTRL_FLIP_NORMAL;
43 43
44 switch (ctx_flip) { 44 switch (ctx->flip) {
45 case FLIP_X_AXIS: 45 case FLIP_X_AXIS:
46 flip = S5P_MSCTRL_FLIP_X_MIRROR; 46 flip = S5P_MSCTRL_FLIP_X_MIRROR;
47 break; 47 break;
@@ -51,16 +51,20 @@ static u32 fimc_hw_get_in_flip(u32 ctx_flip)
51 case FLIP_XY_AXIS: 51 case FLIP_XY_AXIS:
52 flip = S5P_MSCTRL_FLIP_180; 52 flip = S5P_MSCTRL_FLIP_180;
53 break; 53 break;
54 default:
55 break;
54 } 56 }
57 if (ctx->rotation <= 90)
58 return flip;
55 59
56 return flip; 60 return (flip ^ S5P_MSCTRL_FLIP_180) & S5P_MSCTRL_FLIP_180;
57} 61}
58 62
59static u32 fimc_hw_get_target_flip(u32 ctx_flip) 63static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
60{ 64{
61 u32 flip = S5P_CITRGFMT_FLIP_NORMAL; 65 u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
62 66
63 switch (ctx_flip) { 67 switch (ctx->flip) {
64 case FLIP_X_AXIS: 68 case FLIP_X_AXIS:
65 flip = S5P_CITRGFMT_FLIP_X_MIRROR; 69 flip = S5P_CITRGFMT_FLIP_X_MIRROR;
66 break; 70 break;
@@ -70,11 +74,13 @@ static u32 fimc_hw_get_target_flip(u32 ctx_flip)
70 case FLIP_XY_AXIS: 74 case FLIP_XY_AXIS:
71 flip = S5P_CITRGFMT_FLIP_180; 75 flip = S5P_CITRGFMT_FLIP_180;
72 break; 76 break;
73 case FLIP_NONE: 77 default:
74 break; 78 break;
75
76 } 79 }
77 return flip; 80 if (ctx->rotation <= 90)
81 return flip;
82
83 return (flip ^ S5P_CITRGFMT_FLIP_180) & S5P_CITRGFMT_FLIP_180;
78} 84}
79 85
80void fimc_hw_set_rotation(struct fimc_ctx *ctx) 86void fimc_hw_set_rotation(struct fimc_ctx *ctx)
@@ -84,10 +90,7 @@ void fimc_hw_set_rotation(struct fimc_ctx *ctx)
84 90
85 cfg = readl(dev->regs + S5P_CITRGFMT); 91 cfg = readl(dev->regs + S5P_CITRGFMT);
86 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 | 92 cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 |
87 S5P_CITRGFMT_FLIP_180); 93 S5P_CITRGFMT_FLIP_180);
88
89 flip = readl(dev->regs + S5P_MSCTRL);
90 flip &= ~S5P_MSCTRL_FLIP_MASK;
91 94
92 /* 95 /*
93 * The input and output rotator cannot work simultaneously. 96 * The input and output rotator cannot work simultaneously.
@@ -95,26 +98,22 @@ void fimc_hw_set_rotation(struct fimc_ctx *ctx)
95 * in direct fifo output mode. 98 * in direct fifo output mode.
96 */ 99 */
97 if (ctx->rotation == 90 || ctx->rotation == 270) { 100 if (ctx->rotation == 90 || ctx->rotation == 270) {
98 if (ctx->out_path == FIMC_LCDFIFO) {
99 cfg |= S5P_CITRGFMT_INROT90;
100 if (ctx->rotation == 270)
101 flip |= S5P_MSCTRL_FLIP_180;
102 } else {
103 cfg |= S5P_CITRGFMT_OUTROT90;
104 if (ctx->rotation == 270)
105 cfg |= S5P_CITRGFMT_FLIP_180;
106 }
107 } else if (ctx->rotation == 180) {
108 if (ctx->out_path == FIMC_LCDFIFO) 101 if (ctx->out_path == FIMC_LCDFIFO)
109 flip |= S5P_MSCTRL_FLIP_180; 102 cfg |= S5P_CITRGFMT_INROT90;
110 else 103 else
111 cfg |= S5P_CITRGFMT_FLIP_180; 104 cfg |= S5P_CITRGFMT_OUTROT90;
112 } 105 }
113 if (ctx->rotation == 180 || ctx->rotation == 270)
114 writel(flip, dev->regs + S5P_MSCTRL);
115 106
116 cfg |= fimc_hw_get_target_flip(ctx->flip); 107 if (ctx->out_path == FIMC_DMA) {
117 writel(cfg, dev->regs + S5P_CITRGFMT); 108 cfg |= fimc_hw_get_target_flip(ctx);
109 writel(cfg, dev->regs + S5P_CITRGFMT);
110 } else {
111 /* LCD FIFO path */
112 flip = readl(dev->regs + S5P_MSCTRL);
113 flip &= ~S5P_MSCTRL_FLIP_MASK;
114 flip |= fimc_hw_get_in_flip(ctx);
115 writel(flip, dev->regs + S5P_MSCTRL);
116 }
118} 117}
119 118
120void fimc_hw_set_target_format(struct fimc_ctx *ctx) 119void fimc_hw_set_target_format(struct fimc_ctx *ctx)
@@ -131,18 +130,13 @@ void fimc_hw_set_target_format(struct fimc_ctx *ctx)
131 S5P_CITRGFMT_VSIZE_MASK); 130 S5P_CITRGFMT_VSIZE_MASK);
132 131
133 switch (frame->fmt->color) { 132 switch (frame->fmt->color) {
134 case S5P_FIMC_RGB565: 133 case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
135 case S5P_FIMC_RGB666:
136 case S5P_FIMC_RGB888:
137 cfg |= S5P_CITRGFMT_RGB; 134 cfg |= S5P_CITRGFMT_RGB;
138 break; 135 break;
139 case S5P_FIMC_YCBCR420: 136 case S5P_FIMC_YCBCR420:
140 cfg |= S5P_CITRGFMT_YCBCR420; 137 cfg |= S5P_CITRGFMT_YCBCR420;
141 break; 138 break;
142 case S5P_FIMC_YCBYCR422: 139 case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422:
143 case S5P_FIMC_YCRYCB422:
144 case S5P_FIMC_CBYCRY422:
145 case S5P_FIMC_CRYCBY422:
146 if (frame->fmt->colplanes == 1) 140 if (frame->fmt->colplanes == 1)
147 cfg |= S5P_CITRGFMT_YCBCR422_1P; 141 cfg |= S5P_CITRGFMT_YCBCR422_1P;
148 else 142 else
@@ -410,8 +404,7 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
410 404
411 /* Set the input DMA to process single frame only. */ 405 /* Set the input DMA to process single frame only. */
412 cfg = readl(dev->regs + S5P_MSCTRL); 406 cfg = readl(dev->regs + S5P_MSCTRL);
413 cfg &= ~(S5P_MSCTRL_FLIP_MASK 407 cfg &= ~(S5P_MSCTRL_INFORMAT_MASK
414 | S5P_MSCTRL_INFORMAT_MASK
415 | S5P_MSCTRL_IN_BURST_COUNT_MASK 408 | S5P_MSCTRL_IN_BURST_COUNT_MASK
416 | S5P_MSCTRL_INPUT_MASK 409 | S5P_MSCTRL_INPUT_MASK
417 | S5P_MSCTRL_C_INT_IN_MASK 410 | S5P_MSCTRL_C_INT_IN_MASK
@@ -450,13 +443,6 @@ void fimc_hw_set_in_dma(struct fimc_ctx *ctx)
450 break; 443 break;
451 } 444 }
452 445
453 /*
454 * Input DMA flip mode (and rotation).
455 * Do not allow simultaneous rotation and flipping.
456 */
457 if (!ctx->rotation && ctx->out_path == FIMC_LCDFIFO)
458 cfg |= fimc_hw_get_in_flip(ctx->flip);
459
460 writel(cfg, dev->regs + S5P_MSCTRL); 446 writel(cfg, dev->regs + S5P_MSCTRL);
461 447
462 /* Input/output DMA linear/tiled mode. */ 448 /* Input/output DMA linear/tiled mode. */