summaryrefslogtreecommitdiff
path: root/drivers/video/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/tegra')
-rw-r--r--drivers/video/tegra/dc/dc.c9
-rw-r--r--drivers/video/tegra/dc/ext/dev.c78
-rw-r--r--drivers/video/tegra/dc/ext/tegra_dc_ext_priv.h10
-rw-r--r--drivers/video/tegra/dc/overlay.c4
-rw-r--r--drivers/video/tegra/fb.c8
5 files changed, 79 insertions, 30 deletions
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);