diff options
Diffstat (limited to 'drivers/media/video/s5p-fimc/fimc-core.c')
-rw-r--r-- | drivers/media/video/s5p-fimc/fimc-core.c | 59 |
1 files changed, 40 insertions, 19 deletions
diff --git a/drivers/media/video/s5p-fimc/fimc-core.c b/drivers/media/video/s5p-fimc/fimc-core.c index 09bfac45ea32..560cd21dae28 100644 --- a/drivers/media/video/s5p-fimc/fimc-core.c +++ b/drivers/media/video/s5p-fimc/fimc-core.c | |||
@@ -200,24 +200,21 @@ static struct v4l2_queryctrl *get_ctrl(int id) | |||
200 | return NULL; | 200 | return NULL; |
201 | } | 201 | } |
202 | 202 | ||
203 | int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f) | 203 | int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot) |
204 | { | 204 | { |
205 | if (r->width > f->width) { | 205 | int tx, ty; |
206 | if (f->width > (r->width * SCALER_MAX_HRATIO)) | ||
207 | return -EINVAL; | ||
208 | } else { | ||
209 | if ((f->width * SCALER_MAX_HRATIO) < r->width) | ||
210 | return -EINVAL; | ||
211 | } | ||
212 | 206 | ||
213 | if (r->height > f->height) { | 207 | if (rot == 90 || rot == 270) { |
214 | if (f->height > (r->height * SCALER_MAX_VRATIO)) | 208 | ty = dw; |
215 | return -EINVAL; | 209 | tx = dh; |
216 | } else { | 210 | } else { |
217 | if ((f->height * SCALER_MAX_VRATIO) < r->height) | 211 | tx = dw; |
218 | return -EINVAL; | 212 | ty = dh; |
219 | } | 213 | } |
220 | 214 | ||
215 | if ((sw >= SCALER_MAX_HRATIO * tx) || (sh >= SCALER_MAX_VRATIO * ty)) | ||
216 | return -EINVAL; | ||
217 | |||
221 | return 0; | 218 | return 0; |
222 | } | 219 | } |
223 | 220 | ||
@@ -1065,6 +1062,7 @@ int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl) | |||
1065 | struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; | 1062 | struct samsung_fimc_variant *variant = ctx->fimc_dev->variant; |
1066 | struct fimc_dev *fimc = ctx->fimc_dev; | 1063 | struct fimc_dev *fimc = ctx->fimc_dev; |
1067 | unsigned long flags; | 1064 | unsigned long flags; |
1065 | int ret = 0; | ||
1068 | 1066 | ||
1069 | spin_lock_irqsave(&ctx->slock, flags); | 1067 | spin_lock_irqsave(&ctx->slock, flags); |
1070 | 1068 | ||
@@ -1084,6 +1082,20 @@ int fimc_s_ctrl(struct fimc_ctx *ctx, struct v4l2_control *ctrl) | |||
1084 | break; | 1082 | break; |
1085 | 1083 | ||
1086 | case V4L2_CID_ROTATE: | 1084 | case V4L2_CID_ROTATE: |
1085 | if (!(~ctx->state & (FIMC_DST_FMT | FIMC_SRC_FMT))) { | ||
1086 | ret = fimc_check_scaler_ratio(ctx->s_frame.width, | ||
1087 | ctx->s_frame.height, | ||
1088 | ctx->d_frame.width, | ||
1089 | ctx->d_frame.height, | ||
1090 | ctrl->value); | ||
1091 | if (ret) { | ||
1092 | v4l2_err(&fimc->m2m.v4l2_dev, | ||
1093 | "Out of scaler range"); | ||
1094 | spin_unlock_irqrestore(&ctx->slock, flags); | ||
1095 | return -EINVAL; | ||
1096 | } | ||
1097 | } | ||
1098 | |||
1087 | /* Check for the output rotator availability */ | 1099 | /* Check for the output rotator availability */ |
1088 | if ((ctrl->value == 90 || ctrl->value == 270) && | 1100 | if ((ctrl->value == 90 || ctrl->value == 270) && |
1089 | (ctx->in_path == FIMC_DMA && !variant->has_out_rot)) { | 1101 | (ctx->in_path == FIMC_DMA && !variant->has_out_rot)) { |
@@ -1232,18 +1244,27 @@ static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr) | |||
1232 | &ctx->s_frame : &ctx->d_frame; | 1244 | &ctx->s_frame : &ctx->d_frame; |
1233 | 1245 | ||
1234 | spin_lock_irqsave(&ctx->slock, flags); | 1246 | spin_lock_irqsave(&ctx->slock, flags); |
1235 | if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) { | 1247 | /* Check to see if scaling ratio is within supported range */ |
1236 | /* Check to see if scaling ratio is within supported range */ | 1248 | if (!(~ctx->state & (FIMC_DST_FMT | FIMC_SRC_FMT))) { |
1237 | if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | 1249 | if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { |
1238 | ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame); | 1250 | ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height, |
1239 | else | 1251 | ctx->d_frame.width, |
1240 | ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame); | 1252 | ctx->d_frame.height, |
1253 | ctx->rotation); | ||
1254 | } else { | ||
1255 | ret = fimc_check_scaler_ratio(ctx->s_frame.width, | ||
1256 | ctx->s_frame.height, | ||
1257 | cr->c.width, cr->c.height, | ||
1258 | ctx->rotation); | ||
1259 | } | ||
1260 | |||
1241 | if (ret) { | 1261 | if (ret) { |
1242 | v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range"); | 1262 | v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range"); |
1243 | spin_unlock_irqrestore(&ctx->slock, flags); | 1263 | spin_unlock_irqrestore(&ctx->slock, flags); |
1244 | return -EINVAL; | 1264 | return -EINVAL; |
1245 | } | 1265 | } |
1246 | } | 1266 | } |
1267 | |||
1247 | ctx->state |= FIMC_PARAMS; | 1268 | ctx->state |= FIMC_PARAMS; |
1248 | 1269 | ||
1249 | f->offs_h = cr->c.left; | 1270 | f->offs_h = cr->c.left; |