diff options
author | Sylwester Nawrocki <s.nawrocki@samsung.com> | 2010-12-27 12:47:32 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-03-21 19:31:39 -0400 |
commit | ac75934cc644051dc1b33b234448ea4a0990f31f (patch) | |
tree | dc50b556438386f3d8b08836c5e41fb7cb7dda68 | |
parent | d9160afd31565e44ebbd909b283baad8c9a3c224 (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.c | 9 | ||||
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-reg.c | 74 |
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 | ||
1104 | static int fimc_m2m_s_ctrl(struct file *file, void *priv, | 1097 | static 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 | ||
40 | static u32 fimc_hw_get_in_flip(u32 ctx_flip) | 40 | static 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 | ||
59 | static u32 fimc_hw_get_target_flip(u32 ctx_flip) | 63 | static 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 | ||
80 | void fimc_hw_set_rotation(struct fimc_ctx *ctx) | 86 | void 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 | ||
120 | void fimc_hw_set_target_format(struct fimc_ctx *ctx) | 119 | void 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. */ |