diff options
author | Liu Ying <Ying.Liu@freescale.com> | 2013-09-26 01:41:17 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:05:41 -0400 |
commit | 4813da1d1e8c3e2f4d2690189c178e034586c06a (patch) | |
tree | 3e1ffbcd9f4623a6dbc8319ff2240851d296277e /drivers/media | |
parent | d8a42233b46ccc4bd8a7ca5be95d0ac685821cbf (diff) |
ENGR00279204-1 mxc vout: reconfig fb when necessary
Users may call VIDIOC_S_CTRL or VIDIOC_S_CROP ioctrls
to update streaming parameters on-the-fly after video
has been streamed on, such as for rotation/output
resolution/overlay output position change. Any
unnecessary frame buffer reconfiguration would cause
a pair of frame buffer blank/unblank events happen and
even makes the background framebuffer show up for a
short period of time if the video is rendered on an
overlay framebuffer. This patch compares the last time
video output pipe line settings with the current ones
to determine whether frame buffer reconfiguration is
necessary or not.
Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/platform/mxc/output/mxc_vout.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/drivers/media/platform/mxc/output/mxc_vout.c b/drivers/media/platform/mxc/output/mxc_vout.c index 7f20ecf0297f..17e8c4bb457d 100644 --- a/drivers/media/platform/mxc/output/mxc_vout.c +++ b/drivers/media/platform/mxc/output/mxc_vout.c | |||
@@ -1311,6 +1311,43 @@ static int mxc_vout_try_format(struct mxc_vout_output *vout, | |||
1311 | return ret; | 1311 | return ret; |
1312 | } | 1312 | } |
1313 | 1313 | ||
1314 | static bool mxc_vout_need_fb_reconfig(struct mxc_vout_output *vout, | ||
1315 | struct mxc_vout_output *pre_vout) | ||
1316 | { | ||
1317 | if (!vout->vbq.streaming) | ||
1318 | return false; | ||
1319 | |||
1320 | if (vout->tiled_bypass_pp) | ||
1321 | return true; | ||
1322 | |||
1323 | if (vout->linear_bypass_pp != pre_vout->linear_bypass_pp) | ||
1324 | return true; | ||
1325 | |||
1326 | /* cropped output resolution or format are changed */ | ||
1327 | if (vout->task.output.format != pre_vout->task.output.format || | ||
1328 | vout->task.output.crop.w != pre_vout->task.output.crop.w || | ||
1329 | vout->task.output.crop.h != pre_vout->task.output.crop.h) | ||
1330 | return true; | ||
1331 | |||
1332 | /* overlay: window position or resolution are changed */ | ||
1333 | if (vout->disp_support_windows && | ||
1334 | (vout->win_pos.x != pre_vout->win_pos.x || | ||
1335 | vout->win_pos.y != pre_vout->win_pos.y || | ||
1336 | vout->task.output.width != pre_vout->task.output.width || | ||
1337 | vout->task.output.height != pre_vout->task.output.height)) | ||
1338 | return true; | ||
1339 | |||
1340 | /* background: cropped position is changed */ | ||
1341 | if (!vout->disp_support_windows && | ||
1342 | (vout->task.output.crop.pos.x != | ||
1343 | pre_vout->task.output.crop.pos.x || | ||
1344 | vout->task.output.crop.pos.y != | ||
1345 | pre_vout->task.output.crop.pos.y)) | ||
1346 | return true; | ||
1347 | |||
1348 | return false; | ||
1349 | } | ||
1350 | |||
1314 | static int mxc_vidioc_s_fmt_vid_out(struct file *file, void *fh, | 1351 | static int mxc_vidioc_s_fmt_vid_out(struct file *file, void *fh, |
1315 | struct v4l2_format *f) | 1352 | struct v4l2_format *f) |
1316 | { | 1353 | { |
@@ -1376,7 +1413,7 @@ static int mxc_vidioc_g_crop(struct file *file, void *fh, | |||
1376 | static int mxc_vidioc_s_crop(struct file *file, void *fh, | 1413 | static int mxc_vidioc_s_crop(struct file *file, void *fh, |
1377 | const struct v4l2_crop *crop) | 1414 | const struct v4l2_crop *crop) |
1378 | { | 1415 | { |
1379 | struct mxc_vout_output *vout = fh; | 1416 | struct mxc_vout_output *vout = fh, pre_vout; |
1380 | struct v4l2_rect *b = &vout->crop_bounds; | 1417 | struct v4l2_rect *b = &vout->crop_bounds; |
1381 | struct v4l2_crop fix_up_crop; | 1418 | struct v4l2_crop fix_up_crop; |
1382 | int ret = 0; | 1419 | int ret = 0; |
@@ -1445,6 +1482,8 @@ static int mxc_vidioc_s_crop(struct file *file, void *fh, | |||
1445 | 1482 | ||
1446 | mutex_lock(&vout->task_lock); | 1483 | mutex_lock(&vout->task_lock); |
1447 | 1484 | ||
1485 | memcpy(&pre_vout, vout, sizeof(*vout)); | ||
1486 | |||
1448 | if (vout->disp_support_windows) { | 1487 | if (vout->disp_support_windows) { |
1449 | vout->task.output.crop.pos.x = 0; | 1488 | vout->task.output.crop.pos.x = 0; |
1450 | vout->task.output.crop.pos.y = 0; | 1489 | vout->task.output.crop.pos.y = 0; |
@@ -1466,9 +1505,6 @@ static int mxc_vidioc_s_crop(struct file *file, void *fh, | |||
1466 | * check ipu task too. | 1505 | * check ipu task too. |
1467 | */ | 1506 | */ |
1468 | if (vout->fmt_init) { | 1507 | if (vout->fmt_init) { |
1469 | if (vout->vbq.streaming) | ||
1470 | release_disp_output(vout); | ||
1471 | |||
1472 | memcpy(&vout->task.input.crop, &vout->in_rect, | 1508 | memcpy(&vout->task.input.crop, &vout->in_rect, |
1473 | sizeof(vout->in_rect)); | 1509 | sizeof(vout->in_rect)); |
1474 | ret = mxc_vout_try_task(vout); | 1510 | ret = mxc_vout_try_task(vout); |
@@ -1477,13 +1513,12 @@ static int mxc_vidioc_s_crop(struct file *file, void *fh, | |||
1477 | "vout check task failed\n"); | 1513 | "vout check task failed\n"); |
1478 | goto done; | 1514 | goto done; |
1479 | } | 1515 | } |
1480 | if (vout->vbq.streaming) { | 1516 | |
1517 | if (mxc_vout_need_fb_reconfig(vout, &pre_vout)) { | ||
1481 | ret = config_disp_output(vout); | 1518 | ret = config_disp_output(vout); |
1482 | if (ret < 0) { | 1519 | if (ret < 0) |
1483 | v4l2_err(vout->vfd->v4l2_dev, | 1520 | v4l2_err(vout->vfd->v4l2_dev, |
1484 | "Config display output failed\n"); | 1521 | "Config display output failed\n"); |
1485 | goto done; | ||
1486 | } | ||
1487 | } | 1522 | } |
1488 | } | 1523 | } |
1489 | 1524 | ||
@@ -1591,13 +1626,16 @@ static int mxc_vidioc_s_ctrl(struct file *file, void *fh, | |||
1591 | struct v4l2_control *ctrl) | 1626 | struct v4l2_control *ctrl) |
1592 | { | 1627 | { |
1593 | int ret = 0; | 1628 | int ret = 0; |
1594 | struct mxc_vout_output *vout = fh; | 1629 | struct mxc_vout_output *vout = fh, pre_vout; |
1595 | 1630 | ||
1596 | /* wait current work finish */ | 1631 | /* wait current work finish */ |
1597 | if (vout->vbq.streaming) | 1632 | if (vout->vbq.streaming) |
1598 | flush_workqueue(vout->v4l_wq); | 1633 | flush_workqueue(vout->v4l_wq); |
1599 | 1634 | ||
1600 | mutex_lock(&vout->task_lock); | 1635 | mutex_lock(&vout->task_lock); |
1636 | |||
1637 | memcpy(&pre_vout, vout, sizeof(*vout)); | ||
1638 | |||
1601 | switch (ctrl->id) { | 1639 | switch (ctrl->id) { |
1602 | case V4L2_CID_ROTATE: | 1640 | case V4L2_CID_ROTATE: |
1603 | { | 1641 | { |
@@ -1630,9 +1668,6 @@ static int mxc_vidioc_s_ctrl(struct file *file, void *fh, | |||
1630 | } | 1668 | } |
1631 | 1669 | ||
1632 | if (vout->fmt_init) { | 1670 | if (vout->fmt_init) { |
1633 | if (vout->vbq.streaming) | ||
1634 | release_disp_output(vout); | ||
1635 | |||
1636 | memcpy(&vout->task.input.crop, &vout->in_rect, | 1671 | memcpy(&vout->task.input.crop, &vout->in_rect, |
1637 | sizeof(vout->in_rect)); | 1672 | sizeof(vout->in_rect)); |
1638 | ret = mxc_vout_try_task(vout); | 1673 | ret = mxc_vout_try_task(vout); |
@@ -1641,13 +1676,12 @@ static int mxc_vidioc_s_ctrl(struct file *file, void *fh, | |||
1641 | "vout check task failed\n"); | 1676 | "vout check task failed\n"); |
1642 | goto done; | 1677 | goto done; |
1643 | } | 1678 | } |
1644 | if (vout->vbq.streaming) { | 1679 | |
1680 | if (mxc_vout_need_fb_reconfig(vout, &pre_vout)) { | ||
1645 | ret = config_disp_output(vout); | 1681 | ret = config_disp_output(vout); |
1646 | if (ret < 0) { | 1682 | if (ret < 0) |
1647 | v4l2_err(vout->vfd->v4l2_dev, | 1683 | v4l2_err(vout->vfd->v4l2_dev, |
1648 | "Config display output failed\n"); | 1684 | "Config display output failed\n"); |
1649 | goto done; | ||
1650 | } | ||
1651 | } | 1685 | } |
1652 | } | 1686 | } |
1653 | 1687 | ||