diff options
author | Thierry Reding <treding@nvidia.com> | 2014-07-11 08:29:14 +0200 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-08-04 10:07:38 +0200 |
commit | d1f3e1e0b38d49cbb996dcf0fde5b5205d12a23d (patch) | |
tree | ad6a7bb3489938730f1d7b95e472889880ba7bb4 /drivers/gpu/drm/tegra | |
parent | 3f4f3b5fede02d338383619ff57744a8415ccceb (diff) | |
download | linux-stable-d1f3e1e0b38d49cbb996dcf0fde5b5205d12a23d.tar.gz linux-stable-d1f3e1e0b38d49cbb996dcf0fde5b5205d12a23d.tar.bz2 linux-stable-d1f3e1e0b38d49cbb996dcf0fde5b5205d12a23d.zip |
drm/tegra: Properly align stride for framebuffers
Tegra20 and Tegra30 both required the buffer line stride to be aligned
on 8 byte boundaries. Tegra114 and Tegra124 increased the alignment to
64 bytes. Introduce a parameter to specify the alignment requirements
for each display controller and round up the pitch of newly allocated
framebuffers appropriately.
Originally-by: Stéphane Marchesin <marcheu@chromium.org>
Signed-off-by: Thierry Reding <treding@nvidia.com>
Diffstat (limited to 'drivers/gpu/drm/tegra')
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 19 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/drm.h | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/fb.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/gem.c | 3 |
4 files changed, 27 insertions, 1 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index afcca04f5367..8886907d44b0 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -19,6 +19,7 @@ struct tegra_dc_soc_info { bool supports_interlacing; bool supports_cursor; bool supports_block_linear; + unsigned int pitch_align; }; struct tegra_plane { @@ -1283,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client) { struct drm_device *drm = dev_get_drvdata(client->parent); struct tegra_dc *dc = host1x_client_to_dc(client); + struct tegra_drm *tegra = drm->dev_private; int err; drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); drm_mode_crtc_set_gamma_size(&dc->base, 256); drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); + /* + * Keep track of the minimum pitch alignment across all display + * controllers. + */ + if (dc->soc->pitch_align > tegra->pitch_align) + tegra->pitch_align = dc->soc->pitch_align; + err = tegra_dc_rgb_init(drm, dc); if (err < 0 && err != -ENODEV) { dev_err(dc->dev, "failed to initialize RGB output: %d\n", err); @@ -1347,18 +1356,28 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .pitch_align = 8, }; static const struct tegra_dc_soc_info tegra30_dc_soc_info = { .supports_interlacing = false, .supports_cursor = false, .supports_block_linear = false, + .pitch_align = 8, +}; + +static const struct tegra_dc_soc_info tegra114_dc_soc_info = { + .supports_interlacing = false, + .supports_cursor = false, + .supports_block_linear = false, + .pitch_align = 64, }; static const struct tegra_dc_soc_info tegra124_dc_soc_info = { .supports_interlacing = true, .supports_cursor = true, .supports_block_linear = true, + .pitch_align = 64, }; static const struct of_device_id tegra_dc_of_match[] = { diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h index 96d754e7b3eb..e89c70fa82d5 100644 --- a/drivers/gpu/drm/tegra/drm.h +++ b/drivers/gpu/drm/tegra/drm.h @@ -45,6 +45,8 @@ struct tegra_drm { #ifdef CONFIG_DRM_TEGRA_FBDEV struct tegra_fbdev *fbdev; #endif + + unsigned int pitch_align; }; struct tegra_drm_client; diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c index 7790d43ad082..3513d12d5aa1 100644 --- a/drivers/gpu/drm/tegra/fb.c +++ b/drivers/gpu/drm/tegra/fb.c @@ -194,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, struct drm_fb_helper_surface_size *sizes) { struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); + struct tegra_drm *tegra = helper->dev->dev_private; struct drm_device *drm = helper->dev; struct drm_mode_fb_cmd2 cmd = { 0 }; unsigned int bytes_per_pixel; @@ -208,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, cmd.width = sizes->surface_width; cmd.height = sizes->surface_height; - cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; + cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, + tegra->pitch_align); cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, sizes->surface_depth); diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index c1e4e8b6e5ca..2545c7a468a2 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -16,6 +16,7 @@ #include <linux/dma-buf.h> #include <drm/tegra_drm.h> +#include "drm.h" #include "gem.h" static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) @@ -259,8 +260,10 @@ int tegra_bo_dumb_create(struct drm_file *file, struct drm_device *drm, struct drm_mode_create_dumb *args) { int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); + struct tegra_drm *tegra = drm->dev_private; struct tegra_bo *bo; + min_pitch = round_up(min_pitch, tegra->pitch_align); if (args->pitch < min_pitch) args->pitch = min_pitch; |