From: Gary King Date: Sun, 15 Aug 2010 18:26:49 +0000 (-0700) Subject: video: tegra: add utility function to compute framebuffer stride X-Git-Tag: firefly_0821_release~9833^2~163^2~5 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=10c751b8f5bb78f674d4939b47be933934bb23dd;p=firefly-linux-kernel-4.4.55.git video: tegra: add utility function to compute framebuffer stride framebuffers will generally not be exactly width * bpp / 8 bytes wide; on tegra, linearly-addressed framebuffers will generally be rounded up so that the stride is a multiple of 16B (so that they are compatible with rendering from the hardware engines), and tiled framebuffers will be a multiple of the tile width (64B). add a utility function to tegra_dc to compute the correct stride given a width, bpp and pixel layout, and use this in set_par. Change-Id: I803a55b49c12476f20d5644707899c3fe1336c2d Signed-off-by: Gary King --- diff --git a/arch/arm/mach-tegra/include/mach/dc.h b/arch/arm/mach-tegra/include/mach/dc.h index ae0273ca057d..ce562e5634f7 100644 --- a/arch/arm/mach-tegra/include/mach/dc.h +++ b/arch/arm/mach-tegra/include/mach/dc.h @@ -25,6 +25,15 @@ #define TEGRA_MAX_DC 2 #define DC_N_WINDOWS 3 +#define TEGRA_DC_PITCH_ATOM 16 +#define TEGRA_DC_TILED_ATOM 16 + +enum tegra_win_layout { + TEGRA_WIN_LAYOUT_PITCH, + TEGRA_WIN_LAYOUT_TILED, + TEGRA_WIN_LAYOUT_LINEAR_TILED, +}; + struct tegra_dc_mode { int pclk; int h_ref_to_sync; @@ -95,6 +104,7 @@ struct tegra_dc_win { unsigned out_w; unsigned out_h; unsigned z; + enum tegra_win_layout layout; int dirty; struct tegra_dc *dc; @@ -163,4 +173,7 @@ int tegra_dc_sync_windows(struct tegra_dc_win *windows[], int n); int tegra_dc_set_mode(struct tegra_dc *dc, const struct tegra_dc_mode *mode); +ssize_t tegra_dc_compute_stride(int xres, int bpp, + enum tegra_win_layout layout); + #endif diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 55ecf100de05..fadecf4796e1 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -325,6 +325,20 @@ struct tegra_dc *tegra_dc_get_dc(unsigned idx) } EXPORT_SYMBOL(tegra_dc_get_dc); +ssize_t tegra_dc_compute_stride(int xres, int bpp, enum tegra_win_layout layout) +{ + unsigned int raw_stride = (xres * bpp) / 8; + unsigned int k, n = 0; + + if (layout == TEGRA_WIN_LAYOUT_PITCH) + return ALIGN(raw_stride, TEGRA_DC_PITCH_ATOM); + else if (layout == TEGRA_WIN_LAYOUT_TILED) + return ALIGN(raw_stride, TEGRA_DC_TILED_ATOM); + else + return -EINVAL; +} +EXPORT_SYMBOL(tegra_dc_compute_stride); + struct tegra_dc_win *tegra_dc_get_window(struct tegra_dc *dc, unsigned win) { if (win >= dc->n_windows) diff --git a/drivers/video/tegra/fb.c b/drivers/video/tegra/fb.c index ac07c551fb5d..7e4ffa8ba0b9 100644 --- a/drivers/video/tegra/fb.c +++ b/drivers/video/tegra/fb.c @@ -113,7 +113,10 @@ static int tegra_fb_set_par(struct fb_info *info) default: return -EINVAL; } - info->fix.line_length = var->xres * var->bits_per_pixel / 8; + + info->fix.line_length = tegra_dc_compute_stride(var->xres, + var->bits_per_pixel, TEGRA_WIN_LAYOUT_PITCH); + tegra_fb->win->stride = info->fix.line_length; if (var->pixclock) { struct tegra_dc_mode mode; @@ -371,7 +374,9 @@ 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->stride = fb_data->xres * fb_data->bits_per_pixel / 8; + win->layout = TEGRA_WIN_LAYOUT_PITCH; + win->stride = tegra_dc_compute_stride(fb_data->xres, + fb_data->bits_per_pixel, win->layout); win->flags = TEGRA_WIN_FLAG_ENABLED; if (fb_mem)