diff options
Diffstat (limited to 'drivers/video/tegra/dc/ext')
-rw-r--r-- | drivers/video/tegra/dc/ext/dev.c | 78 | ||||
-rw-r--r-- | drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h | 10 |
2 files changed, 70 insertions, 18 deletions
diff --git a/drivers/video/tegra/dc/ext/dev.c b/drivers/video/tegra/dc/ext/dev.c index 6e1110725aa0..01454f5a8235 100644 --- a/drivers/video/tegra/dc/ext/dev.c +++ b/drivers/video/tegra/dc/ext/dev.c @@ -44,9 +44,10 @@ static int head_count; struct tegra_dc_ext_flip_win { struct tegra_dc_ext_flip_windowattr attr; - struct nvmap_handle_ref *handle; - /* ugh. is this really necessary */ + struct nvmap_handle_ref *handle[TEGRA_DC_NUM_PLANES]; dma_addr_t phys_addr; + dma_addr_t phys_addr_u; + dma_addr_t phys_addr_v; u32 syncpt_max; }; @@ -177,9 +178,9 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext, { struct tegra_dc_ext_win *ext_win = &ext->win[win->idx]; - if (flip_win->handle == NULL) { + if (flip_win->handle[TEGRA_DC_Y] == NULL) { win->flags = 0; - ext_win->cur_handle = NULL; + memset(ext_win->cur_handle, 0, sizeof(ext_win->cur_handle)); return 0; } @@ -199,12 +200,20 @@ static int tegra_dc_ext_set_windowattr(struct tegra_dc_ext *ext, win->out_w = flip_win->attr.out_w; win->out_h = flip_win->attr.out_h; win->z = flip_win->attr.z; - ext_win->cur_handle = flip_win->handle; + memcpy(ext_win->cur_handle, flip_win->handle, + sizeof(ext_win->cur_handle)); /* XXX verify that this won't read outside of the surface */ win->phys_addr = flip_win->phys_addr + flip_win->attr.offset; - win->offset_u = flip_win->attr.offset_u + flip_win->attr.offset; - win->offset_v = flip_win->attr.offset_v + flip_win->attr.offset; + + win->phys_addr_u = flip_win->handle[TEGRA_DC_U] ? + flip_win->phys_addr_u : flip_win->phys_addr; + win->phys_addr_u += flip_win->attr.offset_u; + + win->phys_addr_v = flip_win->handle[TEGRA_DC_V] ? + flip_win->phys_addr_v : flip_win->phys_addr; + win->phys_addr_v += flip_win->attr.offset_v; + win->stride = flip_win->attr.stride; win->stride_uv = flip_win->attr.stride_uv; @@ -225,7 +234,8 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work) container_of(work, struct tegra_dc_ext_flip_data, work); struct tegra_dc_ext *ext = data->ext; struct tegra_dc_win *wins[DC_N_WINDOWS]; - struct nvmap_handle_ref *unpin_handles[DC_N_WINDOWS]; + struct nvmap_handle_ref *unpin_handles[DC_N_WINDOWS * + TEGRA_DC_NUM_PLANES]; int i, nr_unpin = 0, nr_win = 0; for (i = 0; i < DC_N_WINDOWS; i++) { @@ -240,9 +250,16 @@ static void tegra_dc_ext_flip_worker(struct work_struct *work) win = tegra_dc_get_window(ext->dc, index); ext_win = &ext->win[index]; - if ((win->flags & TEGRA_WIN_FLAG_ENABLED) && - ext_win->cur_handle) - unpin_handles[nr_unpin++] = ext_win->cur_handle; + if (win->flags & TEGRA_WIN_FLAG_ENABLED) { + int j; + for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) { + if (!ext_win->cur_handle[j]) + continue; + + unpin_handles[nr_unpin++] = + ext_win->cur_handle[j]; + } + } tegra_dc_ext_set_windowattr(ext, win, &data->win[i]); @@ -383,10 +400,34 @@ static int tegra_dc_ext_flip(struct tegra_dc_ext_user *user, continue; ret = tegra_dc_ext_pin_window(user, flip_win->attr.buff_id, - &flip_win->handle, + &flip_win->handle[TEGRA_DC_Y], &flip_win->phys_addr); if (ret) goto fail_pin; + + if (flip_win->attr.buff_id_u) { + ret = tegra_dc_ext_pin_window(user, + flip_win->attr.buff_id_u, + &flip_win->handle[TEGRA_DC_U], + &flip_win->phys_addr_u); + if (ret) + goto fail_pin; + } else { + flip_win->handle[TEGRA_DC_U] = NULL; + flip_win->phys_addr_u = 0; + } + + if (flip_win->attr.buff_id_v) { + ret = tegra_dc_ext_pin_window(user, + flip_win->attr.buff_id_v, + &flip_win->handle[TEGRA_DC_V], + &flip_win->phys_addr_v); + if (ret) + goto fail_pin; + } else { + flip_win->handle[TEGRA_DC_V] = NULL; + flip_win->phys_addr_v = 0; + } } ret = lock_windows_for_flip(user, args); @@ -427,12 +468,15 @@ unlock: unlock_windows_for_flip(user, args); fail_pin: - while (i--) { - if (!data->win[i].handle) - continue; + for (i = 0; i < DC_N_WINDOWS; i++) { + int j; + for (j = 0; j < TEGRA_DC_NUM_PLANES; j++) { + if (!data->win[i].handle[j]) + continue; - nvmap_unpin(ext->nvmap, data->win[i].handle); - nvmap_free(ext->nvmap, data->win[i].handle); + nvmap_unpin(ext->nvmap, data->win[i].handle[j]); + nvmap_free(ext->nvmap, data->win[i].handle[j]); + } } kfree(data); diff --git a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h index 6f0d0e4e732b..54a10b2c8682 100644 --- a/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h +++ b/drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h @@ -36,6 +36,13 @@ struct tegra_dc_ext_user { struct nvmap_client *nvmap; }; +enum { + TEGRA_DC_Y, + TEGRA_DC_U, + TEGRA_DC_V, + TEGRA_DC_NUM_PLANES, +}; + struct tegra_dc_ext_win { struct tegra_dc_ext *ext; @@ -45,7 +52,8 @@ struct tegra_dc_ext_win { struct mutex lock; - struct nvmap_handle_ref *cur_handle; + /* Current nvmap handle (if any) for Y, U, V planes */ + struct nvmap_handle_ref *cur_handle[TEGRA_DC_NUM_PLANES]; struct workqueue_struct *flip_wq; }; |