diff options
-rw-r--r-- | arch/arm/mach-tegra/include/mach/dc.h | 5 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 9 | ||||
-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 | ||||
-rw-r--r-- | drivers/video/tegra/dc/overlay.c | 4 | ||||
-rw-r--r-- | drivers/video/tegra/fb.c | 8 | ||||
-rw-r--r-- | include/video/tegra_dc_ext.h | 5 |
7 files changed, 85 insertions, 34 deletions
diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index ec24c3277260..5aac57586e70 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -370,9 +370,8 @@ struct tegra_dc_win { void *virt_addr; dma_addr_t phys_addr; - unsigned offset; - unsigned offset_u; - unsigned offset_v; + dma_addr_t phys_addr_u; + dma_addr_t phys_addr_v; unsigned stride; unsigned stride_uv; fixed20_12 x; diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index c996a38d1f74..50b761c4389f 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1030,20 +1030,17 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) tegra_dc_writel(dc, 0, DC_WIN_BUF_STRIDE); tegra_dc_writel(dc, 0, DC_WIN_UV_BUF_STRIDE); tegra_dc_writel(dc, - (unsigned long)win->phys_addr + - (unsigned long)win->offset, + (unsigned long)win->phys_addr, DC_WINBUF_START_ADDR); if (!yuvp) { tegra_dc_writel(dc, win->stride, DC_WIN_LINE_STRIDE); } else { tegra_dc_writel(dc, - (unsigned long)win->phys_addr + - (unsigned long)win->offset_u, + (unsigned long)win->phys_addr_u, DC_WINBUF_START_ADDR_U); tegra_dc_writel(dc, - (unsigned long)win->phys_addr + - (unsigned long)win->offset_v, + (unsigned long)win->phys_addr_v, DC_WINBUF_START_ADDR_V); tegra_dc_writel(dc, LINE_STRIDE(win->stride) | 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; }; diff --git a/drivers/video/tegra/dc/overlay.c b/drivers/video/tegra/dc/overlay.c index 623c26ae98d4..057241e86c81 100644 --- a/drivers/video/tegra/dc/overlay.c +++ b/drivers/video/tegra/dc/overlay.c @@ -213,8 +213,8 @@ static int tegra_overlay_set_windowattr(struct tegra_overlay_info *overlay, /* STOPSHIP 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->phys_addr + flip_win->attr.offset_u; + win->phys_addr_v = flip_win->phys_addr + flip_win->attr.offset_v; win->stride = flip_win->attr.stride; win->stride_uv = flip_win->attr.stride_uv; diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index b7acecc8f562..b170bcdcba2c 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -111,8 +111,8 @@ static int tegra_fb_set_par(struct fb_info *info) tegra_fb->win->stride = round_up(info->fix.line_length, TEGRA_LINEAR_PITCH_ALIGNMENT); tegra_fb->win->stride_uv = 0; - tegra_fb->win->offset_u = 0; - tegra_fb->win->offset_v = 0; + tegra_fb->win->phys_addr_u = 0; + tegra_fb->win->phys_addr_v = 0; } if (var->pixclock) { @@ -436,8 +436,8 @@ struct tegra_fb_info *tegra_fb_register(struct nvhost_device *ndev, win->z = 0; win->phys_addr = fb_phys; win->virt_addr = fb_base; - win->offset_u = 0; - win->offset_v = 0; + win->phys_addr_u = 0; + win->phys_addr_v = 0; win->stride = fb_data->xres * fb_data->bits_per_pixel / 8; /* Pad the stride to 16-byte boundary. */ win->stride = round_up(win->stride, TEGRA_LINEAR_PITCH_ALIGNMENT); diff --git a/include/video/tegra_dc_ext.h b/include/video/tegra_dc_ext.h index 118184849d1b..824afeaf147b 100644 --- a/include/video/tegra_dc_ext.h +++ b/include/video/tegra_dc_ext.h @@ -82,8 +82,11 @@ struct tegra_dc_ext_flip_windowattr { struct timespec timestamp; __u32 pre_syncpt_id; __u32 pre_syncpt_val; + /* These are optional; if zero, U and V are taken from buff_id */ + __u32 buff_id_u; + __u32 buff_id_v; /* Leave some wiggle room for future expansion */ - __u32 pad[8]; + __u32 pad[6]; }; #define TEGRA_DC_EXT_FLIP_N_WINDOWS 3 |