diff options
author | Thierry Reding <treding@nvidia.com> | 2014-07-11 02:29:14 -0400 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-08-04 04:07:38 -0400 |
commit | d1f3e1e0b38d49cbb996dcf0fde5b5205d12a23d (patch) | |
tree | ad6a7bb3489938730f1d7b95e472889880ba7bb4 | |
parent | 3f4f3b5fede02d338383619ff57744a8415ccceb (diff) |
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>
-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 { | |||
19 | bool supports_interlacing; | 19 | bool supports_interlacing; |
20 | bool supports_cursor; | 20 | bool supports_cursor; |
21 | bool supports_block_linear; | 21 | bool supports_block_linear; |
22 | unsigned int pitch_align; | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | struct tegra_plane { | 25 | struct tegra_plane { |
@@ -1283,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client) | |||
1283 | { | 1284 | { |
1284 | struct drm_device *drm = dev_get_drvdata(client->parent); | 1285 | struct drm_device *drm = dev_get_drvdata(client->parent); |
1285 | struct tegra_dc *dc = host1x_client_to_dc(client); | 1286 | struct tegra_dc *dc = host1x_client_to_dc(client); |
1287 | struct tegra_drm *tegra = drm->dev_private; | ||
1286 | int err; | 1288 | int err; |
1287 | 1289 | ||
1288 | drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); | 1290 | drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); |
1289 | drm_mode_crtc_set_gamma_size(&dc->base, 256); | 1291 | drm_mode_crtc_set_gamma_size(&dc->base, 256); |
1290 | drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); | 1292 | drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); |
1291 | 1293 | ||
1294 | /* | ||
1295 | * Keep track of the minimum pitch alignment across all display | ||
1296 | * controllers. | ||
1297 | */ | ||
1298 | if (dc->soc->pitch_align > tegra->pitch_align) | ||
1299 | tegra->pitch_align = dc->soc->pitch_align; | ||
1300 | |||
1292 | err = tegra_dc_rgb_init(drm, dc); | 1301 | err = tegra_dc_rgb_init(drm, dc); |
1293 | if (err < 0 && err != -ENODEV) { | 1302 | if (err < 0 && err != -ENODEV) { |
1294 | dev_err(dc->dev, "failed to initialize RGB output: %d\n", err); | 1303 | 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 = { | |||
1347 | .supports_interlacing = false, | 1356 | .supports_interlacing = false, |
1348 | .supports_cursor = false, | 1357 | .supports_cursor = false, |
1349 | .supports_block_linear = false, | 1358 | .supports_block_linear = false, |
1359 | .pitch_align = 8, | ||
1350 | }; | 1360 | }; |
1351 | 1361 | ||
1352 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { | 1362 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { |
1353 | .supports_interlacing = false, | 1363 | .supports_interlacing = false, |
1354 | .supports_cursor = false, | 1364 | .supports_cursor = false, |
1355 | .supports_block_linear = false, | 1365 | .supports_block_linear = false, |
1366 | .pitch_align = 8, | ||
1367 | }; | ||
1368 | |||
1369 | static const struct tegra_dc_soc_info tegra114_dc_soc_info = { | ||
1370 | .supports_interlacing = false, | ||
1371 | .supports_cursor = false, | ||
1372 | .supports_block_linear = false, | ||
1373 | .pitch_align = 64, | ||
1356 | }; | 1374 | }; |
1357 | 1375 | ||
1358 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { | 1376 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { |
1359 | .supports_interlacing = true, | 1377 | .supports_interlacing = true, |
1360 | .supports_cursor = true, | 1378 | .supports_cursor = true, |
1361 | .supports_block_linear = true, | 1379 | .supports_block_linear = true, |
1380 | .pitch_align = 64, | ||
1362 | }; | 1381 | }; |
1363 | 1382 | ||
1364 | static const struct of_device_id tegra_dc_of_match[] = { | 1383 | 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 { | |||
45 | #ifdef CONFIG_DRM_TEGRA_FBDEV | 45 | #ifdef CONFIG_DRM_TEGRA_FBDEV |
46 | struct tegra_fbdev *fbdev; | 46 | struct tegra_fbdev *fbdev; |
47 | #endif | 47 | #endif |
48 | |||
49 | unsigned int pitch_align; | ||
48 | }; | 50 | }; |
49 | 51 | ||
50 | struct tegra_drm_client; | 52 | 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, | |||
194 | struct drm_fb_helper_surface_size *sizes) | 194 | struct drm_fb_helper_surface_size *sizes) |
195 | { | 195 | { |
196 | struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); | 196 | struct tegra_fbdev *fbdev = to_tegra_fbdev(helper); |
197 | struct tegra_drm *tegra = helper->dev->dev_private; | ||
197 | struct drm_device *drm = helper->dev; | 198 | struct drm_device *drm = helper->dev; |
198 | struct drm_mode_fb_cmd2 cmd = { 0 }; | 199 | struct drm_mode_fb_cmd2 cmd = { 0 }; |
199 | unsigned int bytes_per_pixel; | 200 | unsigned int bytes_per_pixel; |
@@ -208,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper, | |||
208 | 209 | ||
209 | cmd.width = sizes->surface_width; | 210 | cmd.width = sizes->surface_width; |
210 | cmd.height = sizes->surface_height; | 211 | cmd.height = sizes->surface_height; |
211 | cmd.pitches[0] = sizes->surface_width * bytes_per_pixel; | 212 | cmd.pitches[0] = round_up(sizes->surface_width * bytes_per_pixel, |
213 | tegra->pitch_align); | ||
212 | cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, | 214 | cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, |
213 | sizes->surface_depth); | 215 | sizes->surface_depth); |
214 | 216 | ||
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 @@ | |||
16 | #include <linux/dma-buf.h> | 16 | #include <linux/dma-buf.h> |
17 | #include <drm/tegra_drm.h> | 17 | #include <drm/tegra_drm.h> |
18 | 18 | ||
19 | #include "drm.h" | ||
19 | #include "gem.h" | 20 | #include "gem.h" |
20 | 21 | ||
21 | static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) | 22 | 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, | |||
259 | struct drm_mode_create_dumb *args) | 260 | struct drm_mode_create_dumb *args) |
260 | { | 261 | { |
261 | int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); | 262 | int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8); |
263 | struct tegra_drm *tegra = drm->dev_private; | ||
262 | struct tegra_bo *bo; | 264 | struct tegra_bo *bo; |
263 | 265 | ||
266 | min_pitch = round_up(min_pitch, tegra->pitch_align); | ||
264 | if (args->pitch < min_pitch) | 267 | if (args->pitch < min_pitch) |
265 | args->pitch = min_pitch; | 268 | args->pitch = min_pitch; |
266 | 269 | ||