diff options
Diffstat (limited to 'drivers/media/video/s5p-tv/mixer_video.c')
-rw-r--r-- | drivers/media/video/s5p-tv/mixer_video.c | 342 |
1 files changed, 222 insertions, 120 deletions
diff --git a/drivers/media/video/s5p-tv/mixer_video.c b/drivers/media/video/s5p-tv/mixer_video.c index b47d0c06ecf5..7884baeff76a 100644 --- a/drivers/media/video/s5p-tv/mixer_video.c +++ b/drivers/media/video/s5p-tv/mixer_video.c | |||
@@ -170,18 +170,22 @@ static int mxr_querycap(struct file *file, void *priv, | |||
170 | return 0; | 170 | return 0; |
171 | } | 171 | } |
172 | 172 | ||
173 | /* Geometry handling */ | 173 | static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo) |
174 | static void mxr_layer_geo_fix(struct mxr_layer *layer) | ||
175 | { | 174 | { |
176 | struct mxr_device *mdev = layer->mdev; | 175 | mxr_dbg(mdev, "src.full_size = (%u, %u)\n", |
177 | struct v4l2_mbus_framefmt mbus_fmt; | 176 | geo->src.full_width, geo->src.full_height); |
178 | 177 | mxr_dbg(mdev, "src.size = (%u, %u)\n", | |
179 | /* TODO: add some dirty flag to avoid unnecessary adjustments */ | 178 | geo->src.width, geo->src.height); |
180 | mxr_get_mbus_fmt(mdev, &mbus_fmt); | 179 | mxr_dbg(mdev, "src.offset = (%u, %u)\n", |
181 | layer->geo.dst.full_width = mbus_fmt.width; | 180 | geo->src.x_offset, geo->src.y_offset); |
182 | layer->geo.dst.full_height = mbus_fmt.height; | 181 | mxr_dbg(mdev, "dst.full_size = (%u, %u)\n", |
183 | layer->geo.dst.field = mbus_fmt.field; | 182 | geo->dst.full_width, geo->dst.full_height); |
184 | layer->ops.fix_geometry(layer); | 183 | mxr_dbg(mdev, "dst.size = (%u, %u)\n", |
184 | geo->dst.width, geo->dst.height); | ||
185 | mxr_dbg(mdev, "dst.offset = (%u, %u)\n", | ||
186 | geo->dst.x_offset, geo->dst.y_offset); | ||
187 | mxr_dbg(mdev, "ratio = (%u, %u)\n", | ||
188 | geo->x_ratio, geo->y_ratio); | ||
185 | } | 189 | } |
186 | 190 | ||
187 | static void mxr_layer_default_geo(struct mxr_layer *layer) | 191 | static void mxr_layer_default_geo(struct mxr_layer *layer) |
@@ -204,27 +208,29 @@ static void mxr_layer_default_geo(struct mxr_layer *layer) | |||
204 | layer->geo.src.width = layer->geo.src.full_width; | 208 | layer->geo.src.width = layer->geo.src.full_width; |
205 | layer->geo.src.height = layer->geo.src.full_height; | 209 | layer->geo.src.height = layer->geo.src.full_height; |
206 | 210 | ||
207 | layer->ops.fix_geometry(layer); | 211 | mxr_geometry_dump(mdev, &layer->geo); |
212 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0); | ||
213 | mxr_geometry_dump(mdev, &layer->geo); | ||
208 | } | 214 | } |
209 | 215 | ||
210 | static void mxr_geometry_dump(struct mxr_device *mdev, struct mxr_geometry *geo) | 216 | static void mxr_layer_update_output(struct mxr_layer *layer) |
211 | { | 217 | { |
212 | mxr_dbg(mdev, "src.full_size = (%u, %u)\n", | 218 | struct mxr_device *mdev = layer->mdev; |
213 | geo->src.full_width, geo->src.full_height); | 219 | struct v4l2_mbus_framefmt mbus_fmt; |
214 | mxr_dbg(mdev, "src.size = (%u, %u)\n", | 220 | |
215 | geo->src.width, geo->src.height); | 221 | mxr_get_mbus_fmt(mdev, &mbus_fmt); |
216 | mxr_dbg(mdev, "src.offset = (%u, %u)\n", | 222 | /* checking if update is needed */ |
217 | geo->src.x_offset, geo->src.y_offset); | 223 | if (layer->geo.dst.full_width == mbus_fmt.width && |
218 | mxr_dbg(mdev, "dst.full_size = (%u, %u)\n", | 224 | layer->geo.dst.full_height == mbus_fmt.width) |
219 | geo->dst.full_width, geo->dst.full_height); | 225 | return; |
220 | mxr_dbg(mdev, "dst.size = (%u, %u)\n", | ||
221 | geo->dst.width, geo->dst.height); | ||
222 | mxr_dbg(mdev, "dst.offset = (%u, %u)\n", | ||
223 | geo->dst.x_offset, geo->dst.y_offset); | ||
224 | mxr_dbg(mdev, "ratio = (%u, %u)\n", | ||
225 | geo->x_ratio, geo->y_ratio); | ||
226 | } | ||
227 | 226 | ||
227 | layer->geo.dst.full_width = mbus_fmt.width; | ||
228 | layer->geo.dst.full_height = mbus_fmt.height; | ||
229 | layer->geo.dst.field = mbus_fmt.field; | ||
230 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SINK, 0); | ||
231 | |||
232 | mxr_geometry_dump(mdev, &layer->geo); | ||
233 | } | ||
228 | 234 | ||
229 | static const struct mxr_format *find_format_by_fourcc( | 235 | static const struct mxr_format *find_format_by_fourcc( |
230 | struct mxr_layer *layer, unsigned long fourcc); | 236 | struct mxr_layer *layer, unsigned long fourcc); |
@@ -249,37 +255,6 @@ static int mxr_enum_fmt(struct file *file, void *priv, | |||
249 | return 0; | 255 | return 0; |
250 | } | 256 | } |
251 | 257 | ||
252 | static int mxr_s_fmt(struct file *file, void *priv, | ||
253 | struct v4l2_format *f) | ||
254 | { | ||
255 | struct mxr_layer *layer = video_drvdata(file); | ||
256 | const struct mxr_format *fmt; | ||
257 | struct v4l2_pix_format_mplane *pix; | ||
258 | struct mxr_device *mdev = layer->mdev; | ||
259 | struct mxr_geometry *geo = &layer->geo; | ||
260 | |||
261 | mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__); | ||
262 | |||
263 | pix = &f->fmt.pix_mp; | ||
264 | fmt = find_format_by_fourcc(layer, pix->pixelformat); | ||
265 | if (fmt == NULL) { | ||
266 | mxr_warn(mdev, "not recognized fourcc: %08x\n", | ||
267 | pix->pixelformat); | ||
268 | return -EINVAL; | ||
269 | } | ||
270 | layer->fmt = fmt; | ||
271 | geo->src.full_width = pix->width; | ||
272 | geo->src.width = pix->width; | ||
273 | geo->src.full_height = pix->height; | ||
274 | geo->src.height = pix->height; | ||
275 | /* assure consistency of geometry */ | ||
276 | mxr_layer_geo_fix(layer); | ||
277 | mxr_dbg(mdev, "width=%u height=%u span=%u\n", | ||
278 | geo->src.width, geo->src.height, geo->src.full_width); | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static unsigned int divup(unsigned int divident, unsigned int divisor) | 258 | static unsigned int divup(unsigned int divident, unsigned int divisor) |
284 | { | 259 | { |
285 | return (divident + divisor - 1) / divisor; | 260 | return (divident + divisor - 1) / divisor; |
@@ -299,6 +274,10 @@ static void mxr_mplane_fill(struct v4l2_plane_pix_format *planes, | |||
299 | { | 274 | { |
300 | int i; | 275 | int i; |
301 | 276 | ||
277 | /* checking if nothing to fill */ | ||
278 | if (!planes) | ||
279 | return; | ||
280 | |||
302 | memset(planes, 0, sizeof(*planes) * fmt->num_subframes); | 281 | memset(planes, 0, sizeof(*planes) * fmt->num_subframes); |
303 | for (i = 0; i < fmt->num_planes; ++i) { | 282 | for (i = 0; i < fmt->num_planes; ++i) { |
304 | struct v4l2_plane_pix_format *plane = planes | 283 | struct v4l2_plane_pix_format *plane = planes |
@@ -332,73 +311,194 @@ static int mxr_g_fmt(struct file *file, void *priv, | |||
332 | return 0; | 311 | return 0; |
333 | } | 312 | } |
334 | 313 | ||
335 | static inline struct mxr_crop *choose_crop_by_type(struct mxr_geometry *geo, | 314 | static int mxr_s_fmt(struct file *file, void *priv, |
336 | enum v4l2_buf_type type) | 315 | struct v4l2_format *f) |
337 | { | ||
338 | switch (type) { | ||
339 | case V4L2_BUF_TYPE_VIDEO_OUTPUT: | ||
340 | case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: | ||
341 | return &geo->dst; | ||
342 | case V4L2_BUF_TYPE_VIDEO_OVERLAY: | ||
343 | return &geo->src; | ||
344 | default: | ||
345 | return NULL; | ||
346 | } | ||
347 | } | ||
348 | |||
349 | static int mxr_g_crop(struct file *file, void *fh, struct v4l2_crop *a) | ||
350 | { | 316 | { |
351 | struct mxr_layer *layer = video_drvdata(file); | 317 | struct mxr_layer *layer = video_drvdata(file); |
352 | struct mxr_crop *crop; | 318 | const struct mxr_format *fmt; |
319 | struct v4l2_pix_format_mplane *pix; | ||
320 | struct mxr_device *mdev = layer->mdev; | ||
321 | struct mxr_geometry *geo = &layer->geo; | ||
353 | 322 | ||
354 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); | 323 | mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__); |
355 | crop = choose_crop_by_type(&layer->geo, a->type); | 324 | |
356 | if (crop == NULL) | 325 | pix = &f->fmt.pix_mp; |
326 | fmt = find_format_by_fourcc(layer, pix->pixelformat); | ||
327 | if (fmt == NULL) { | ||
328 | mxr_warn(mdev, "not recognized fourcc: %08x\n", | ||
329 | pix->pixelformat); | ||
357 | return -EINVAL; | 330 | return -EINVAL; |
358 | mxr_layer_geo_fix(layer); | 331 | } |
359 | a->c.left = crop->x_offset; | 332 | layer->fmt = fmt; |
360 | a->c.top = crop->y_offset; | 333 | /* set source size to highest accepted value */ |
361 | a->c.width = crop->width; | 334 | geo->src.full_width = max(geo->dst.full_width, pix->width); |
362 | a->c.height = crop->height; | 335 | geo->src.full_height = max(geo->dst.full_height, pix->height); |
336 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); | ||
337 | mxr_geometry_dump(mdev, &layer->geo); | ||
338 | /* set cropping to total visible screen */ | ||
339 | geo->src.width = pix->width; | ||
340 | geo->src.height = pix->height; | ||
341 | geo->src.x_offset = 0; | ||
342 | geo->src.y_offset = 0; | ||
343 | /* assure consistency of geometry */ | ||
344 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_CROP, MXR_NO_OFFSET); | ||
345 | mxr_geometry_dump(mdev, &layer->geo); | ||
346 | /* set full size to lowest possible value */ | ||
347 | geo->src.full_width = 0; | ||
348 | geo->src.full_height = 0; | ||
349 | layer->ops.fix_geometry(layer, MXR_GEOMETRY_SOURCE, 0); | ||
350 | mxr_geometry_dump(mdev, &layer->geo); | ||
351 | |||
352 | /* returning results */ | ||
353 | mxr_g_fmt(file, priv, f); | ||
354 | |||
363 | return 0; | 355 | return 0; |
364 | } | 356 | } |
365 | 357 | ||
366 | static int mxr_s_crop(struct file *file, void *fh, struct v4l2_crop *a) | 358 | static int mxr_g_selection(struct file *file, void *fh, |
359 | struct v4l2_selection *s) | ||
367 | { | 360 | { |
368 | struct mxr_layer *layer = video_drvdata(file); | 361 | struct mxr_layer *layer = video_drvdata(file); |
369 | struct mxr_crop *crop; | 362 | struct mxr_geometry *geo = &layer->geo; |
370 | 363 | ||
371 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); | 364 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); |
372 | crop = choose_crop_by_type(&layer->geo, a->type); | 365 | |
373 | if (crop == NULL) | 366 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && |
367 | s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
368 | return -EINVAL; | ||
369 | |||
370 | switch (s->target) { | ||
371 | case V4L2_SEL_TGT_CROP_ACTIVE: | ||
372 | s->r.left = geo->src.x_offset; | ||
373 | s->r.top = geo->src.y_offset; | ||
374 | s->r.width = geo->src.width; | ||
375 | s->r.height = geo->src.height; | ||
376 | break; | ||
377 | case V4L2_SEL_TGT_CROP_DEFAULT: | ||
378 | case V4L2_SEL_TGT_CROP_BOUNDS: | ||
379 | s->r.left = 0; | ||
380 | s->r.top = 0; | ||
381 | s->r.width = geo->src.full_width; | ||
382 | s->r.height = geo->src.full_height; | ||
383 | break; | ||
384 | case V4L2_SEL_TGT_COMPOSE_ACTIVE: | ||
385 | case V4L2_SEL_TGT_COMPOSE_PADDED: | ||
386 | s->r.left = geo->dst.x_offset; | ||
387 | s->r.top = geo->dst.y_offset; | ||
388 | s->r.width = geo->dst.width; | ||
389 | s->r.height = geo->dst.height; | ||
390 | break; | ||
391 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
392 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
393 | s->r.left = 0; | ||
394 | s->r.top = 0; | ||
395 | s->r.width = geo->dst.full_width; | ||
396 | s->r.height = geo->dst.full_height; | ||
397 | break; | ||
398 | default: | ||
374 | return -EINVAL; | 399 | return -EINVAL; |
375 | crop->x_offset = a->c.left; | 400 | } |
376 | crop->y_offset = a->c.top; | 401 | |
377 | crop->width = a->c.width; | ||
378 | crop->height = a->c.height; | ||
379 | mxr_layer_geo_fix(layer); | ||
380 | return 0; | 402 | return 0; |
381 | } | 403 | } |
382 | 404 | ||
383 | static int mxr_cropcap(struct file *file, void *fh, struct v4l2_cropcap *a) | 405 | /* returns 1 if rectangle 'a' is inside 'b' */ |
406 | static int mxr_is_rect_inside(struct v4l2_rect *a, struct v4l2_rect *b) | ||
407 | { | ||
408 | if (a->left < b->left) | ||
409 | return 0; | ||
410 | if (a->top < b->top) | ||
411 | return 0; | ||
412 | if (a->left + a->width > b->left + b->width) | ||
413 | return 0; | ||
414 | if (a->top + a->height > b->top + b->height) | ||
415 | return 0; | ||
416 | return 1; | ||
417 | } | ||
418 | |||
419 | static int mxr_s_selection(struct file *file, void *fh, | ||
420 | struct v4l2_selection *s) | ||
384 | { | 421 | { |
385 | struct mxr_layer *layer = video_drvdata(file); | 422 | struct mxr_layer *layer = video_drvdata(file); |
386 | struct mxr_crop *crop; | 423 | struct mxr_geometry *geo = &layer->geo; |
424 | struct mxr_crop *target = NULL; | ||
425 | enum mxr_geometry_stage stage; | ||
426 | struct mxr_geometry tmp; | ||
427 | struct v4l2_rect res; | ||
387 | 428 | ||
388 | mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__); | 429 | memset(&res, 0, sizeof res); |
389 | crop = choose_crop_by_type(&layer->geo, a->type); | 430 | |
390 | if (crop == NULL) | 431 | mxr_dbg(layer->mdev, "%s: rect: %dx%d@%d,%d\n", __func__, |
432 | s->r.width, s->r.height, s->r.left, s->r.top); | ||
433 | |||
434 | if (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT && | ||
435 | s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) | ||
391 | return -EINVAL; | 436 | return -EINVAL; |
392 | mxr_layer_geo_fix(layer); | 437 | |
393 | a->bounds.left = 0; | 438 | switch (s->target) { |
394 | a->bounds.top = 0; | 439 | /* ignore read-only targets */ |
395 | a->bounds.width = crop->full_width; | 440 | case V4L2_SEL_TGT_CROP_DEFAULT: |
396 | a->bounds.top = crop->full_height; | 441 | case V4L2_SEL_TGT_CROP_BOUNDS: |
397 | a->defrect = a->bounds; | 442 | res.width = geo->src.full_width; |
398 | /* setting pixel aspect to 1/1 */ | 443 | res.height = geo->src.full_height; |
399 | a->pixelaspect.numerator = 1; | 444 | break; |
400 | a->pixelaspect.denominator = 1; | 445 | |
446 | /* ignore read-only targets */ | ||
447 | case V4L2_SEL_TGT_COMPOSE_DEFAULT: | ||
448 | case V4L2_SEL_TGT_COMPOSE_BOUNDS: | ||
449 | res.width = geo->dst.full_width; | ||
450 | res.height = geo->dst.full_height; | ||
451 | break; | ||
452 | |||
453 | case V4L2_SEL_TGT_CROP_ACTIVE: | ||
454 | target = &geo->src; | ||
455 | stage = MXR_GEOMETRY_CROP; | ||
456 | break; | ||
457 | case V4L2_SEL_TGT_COMPOSE_ACTIVE: | ||
458 | case V4L2_SEL_TGT_COMPOSE_PADDED: | ||
459 | target = &geo->dst; | ||
460 | stage = MXR_GEOMETRY_COMPOSE; | ||
461 | break; | ||
462 | default: | ||
463 | return -EINVAL; | ||
464 | } | ||
465 | /* apply change and update geometry if needed */ | ||
466 | if (target) { | ||
467 | /* backup current geometry if setup fails */ | ||
468 | memcpy(&tmp, geo, sizeof tmp); | ||
469 | |||
470 | /* apply requested selection */ | ||
471 | target->x_offset = s->r.left; | ||
472 | target->y_offset = s->r.top; | ||
473 | target->width = s->r.width; | ||
474 | target->height = s->r.height; | ||
475 | |||
476 | layer->ops.fix_geometry(layer, stage, s->flags); | ||
477 | |||
478 | /* retrieve update selection rectangle */ | ||
479 | res.left = target->x_offset; | ||
480 | res.top = target->y_offset; | ||
481 | res.width = target->width; | ||
482 | res.height = target->height; | ||
483 | |||
484 | mxr_geometry_dump(layer->mdev, &layer->geo); | ||
485 | } | ||
486 | |||
487 | /* checking if the rectangle satisfies constraints */ | ||
488 | if ((s->flags & V4L2_SEL_FLAG_LE) && !mxr_is_rect_inside(&res, &s->r)) | ||
489 | goto fail; | ||
490 | if ((s->flags & V4L2_SEL_FLAG_GE) && !mxr_is_rect_inside(&s->r, &res)) | ||
491 | goto fail; | ||
492 | |||
493 | /* return result rectangle */ | ||
494 | s->r = res; | ||
495 | |||
401 | return 0; | 496 | return 0; |
497 | fail: | ||
498 | /* restore old geometry, which is not touched if target is NULL */ | ||
499 | if (target) | ||
500 | memcpy(geo, &tmp, sizeof tmp); | ||
501 | return -ERANGE; | ||
402 | } | 502 | } |
403 | 503 | ||
404 | static int mxr_enum_dv_presets(struct file *file, void *fh, | 504 | static int mxr_enum_dv_presets(struct file *file, void *fh, |
@@ -438,6 +538,8 @@ static int mxr_s_dv_preset(struct file *file, void *fh, | |||
438 | 538 | ||
439 | mutex_unlock(&mdev->mutex); | 539 | mutex_unlock(&mdev->mutex); |
440 | 540 | ||
541 | mxr_layer_update_output(layer); | ||
542 | |||
441 | /* any failure should return EINVAL according to V4L2 doc */ | 543 | /* any failure should return EINVAL according to V4L2 doc */ |
442 | return ret ? -EINVAL : 0; | 544 | return ret ? -EINVAL : 0; |
443 | } | 545 | } |
@@ -478,6 +580,8 @@ static int mxr_s_std(struct file *file, void *fh, v4l2_std_id *norm) | |||
478 | 580 | ||
479 | mutex_unlock(&mdev->mutex); | 581 | mutex_unlock(&mdev->mutex); |
480 | 582 | ||
583 | mxr_layer_update_output(layer); | ||
584 | |||
481 | return ret ? -EINVAL : 0; | 585 | return ret ? -EINVAL : 0; |
482 | } | 586 | } |
483 | 587 | ||
@@ -526,25 +630,27 @@ static int mxr_s_output(struct file *file, void *fh, unsigned int i) | |||
526 | struct video_device *vfd = video_devdata(file); | 630 | struct video_device *vfd = video_devdata(file); |
527 | struct mxr_layer *layer = video_drvdata(file); | 631 | struct mxr_layer *layer = video_drvdata(file); |
528 | struct mxr_device *mdev = layer->mdev; | 632 | struct mxr_device *mdev = layer->mdev; |
529 | int ret = 0; | ||
530 | 633 | ||
531 | if (i >= mdev->output_cnt || mdev->output[i] == NULL) | 634 | if (i >= mdev->output_cnt || mdev->output[i] == NULL) |
532 | return -EINVAL; | 635 | return -EINVAL; |
533 | 636 | ||
534 | mutex_lock(&mdev->mutex); | 637 | mutex_lock(&mdev->mutex); |
535 | if (mdev->n_output > 0) { | 638 | if (mdev->n_output > 0) { |
536 | ret = -EBUSY; | 639 | mutex_unlock(&mdev->mutex); |
537 | goto done; | 640 | return -EBUSY; |
538 | } | 641 | } |
539 | mdev->current_output = i; | 642 | mdev->current_output = i; |
540 | vfd->tvnorms = 0; | 643 | vfd->tvnorms = 0; |
541 | v4l2_subdev_call(to_outsd(mdev), video, g_tvnorms_output, | 644 | v4l2_subdev_call(to_outsd(mdev), video, g_tvnorms_output, |
542 | &vfd->tvnorms); | 645 | &vfd->tvnorms); |
646 | mutex_unlock(&mdev->mutex); | ||
647 | |||
648 | /* update layers geometry */ | ||
649 | mxr_layer_update_output(layer); | ||
650 | |||
543 | mxr_dbg(mdev, "tvnorms = %08llx\n", vfd->tvnorms); | 651 | mxr_dbg(mdev, "tvnorms = %08llx\n", vfd->tvnorms); |
544 | 652 | ||
545 | done: | 653 | return 0; |
546 | mutex_unlock(&mdev->mutex); | ||
547 | return ret; | ||
548 | } | 654 | } |
549 | 655 | ||
550 | static int mxr_g_output(struct file *file, void *fh, unsigned int *p) | 656 | static int mxr_g_output(struct file *file, void *fh, unsigned int *p) |
@@ -633,10 +739,9 @@ static const struct v4l2_ioctl_ops mxr_ioctl_ops = { | |||
633 | .vidioc_enum_output = mxr_enum_output, | 739 | .vidioc_enum_output = mxr_enum_output, |
634 | .vidioc_s_output = mxr_s_output, | 740 | .vidioc_s_output = mxr_s_output, |
635 | .vidioc_g_output = mxr_g_output, | 741 | .vidioc_g_output = mxr_g_output, |
636 | /* Crop ioctls */ | 742 | /* selection ioctls */ |
637 | .vidioc_g_crop = mxr_g_crop, | 743 | .vidioc_g_selection = mxr_g_selection, |
638 | .vidioc_s_crop = mxr_s_crop, | 744 | .vidioc_s_selection = mxr_s_selection, |
639 | .vidioc_cropcap = mxr_cropcap, | ||
640 | }; | 745 | }; |
641 | 746 | ||
642 | static int mxr_video_open(struct file *file) | 747 | static int mxr_video_open(struct file *file) |
@@ -805,10 +910,7 @@ static int start_streaming(struct vb2_queue *vq, unsigned int count) | |||
805 | /* block any changes in output configuration */ | 910 | /* block any changes in output configuration */ |
806 | mxr_output_get(mdev); | 911 | mxr_output_get(mdev); |
807 | 912 | ||
808 | /* update layers geometry */ | 913 | mxr_layer_update_output(layer); |
809 | mxr_layer_geo_fix(layer); | ||
810 | mxr_geometry_dump(mdev, &layer->geo); | ||
811 | |||
812 | layer->ops.format_set(layer); | 914 | layer->ops.format_set(layer); |
813 | /* enabling layer in hardware */ | 915 | /* enabling layer in hardware */ |
814 | spin_lock_irqsave(&layer->enq_slock, flags); | 916 | spin_lock_irqsave(&layer->enq_slock, flags); |