aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2014-08-07 05:53:22 -0400
committerDave Airlie <airlied@gmail.com>2014-08-07 05:53:22 -0400
commitfa1d0ee69ca8c123dd791d52830a2e146985ce85 (patch)
treef8c60a43cd9de72939d8fffe00f64b820ddd0442
parent0c6287ec12fa8f7e295a6ebc5fd331647c5a5469 (diff)
parentef70728c7a6571a1a7115031e932b811f1740b2e (diff)
Merge tag 'drm/tegra/for-3.17-rc1' of git://anongit.freedesktop.org/tegra/linux into drm-next
drm/tegra: Changes for v3.17-rc1 Mostly some cleanup all over the place. Pitch alignment limitations of the display controller are now honored and job submission is 64-bit safe. The SOR output (used for eDP) properly configures sync signal polarities according to the display mode rather than hard-coding them to some value and the number of bits per color is now taken from the panel rather than hard-coded to properly support 24-bit vs. 18-bit panels. The DSI controller now properly supports non-continuous clock mode. GEM objects can now have their flags and tiling mode modified via IOCTLs to allow buffers imported from Nouveau to be properly displayed. Newer generations of the Tegra display controller can also detile block linear buffers at scan-out time. Finally the driver now properly exports MODULE_DEVICE_TABLEs to allow it to be automatically loaded when built as a module. * tag 'drm/tegra/for-3.17-rc1' of git://anongit.freedesktop.org/tegra/linux: drm/tegra: add MODULE_DEVICE_TABLEs drm/tegra: dc - Reset controller on driver remove drm/tegra: Properly align stride for framebuffers drm/tegra: sor - Configure proper sync polarities drm/tegra: sor - Use bits-per-color from panel drm/tegra: Make job submission 64-bit safe drm/tegra: Allow non-authenticated processes to create buffer objects drm/tegra: Add SET/GET_FLAGS IOCTLs drm/tegra: Add SET/GET_TILING IOCTLs drm/tegra: Implement more tiling modes drm/tegra: dsi - Handle non-continuous clock flag drm/tegra: sor - missing unlock on error
-rw-r--r--drivers/gpu/drm/tegra/dc.c123
-rw-r--r--drivers/gpu/drm/tegra/dc.h5
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c1
-rw-r--r--drivers/gpu/drm/tegra/drm.c208
-rw-r--r--drivers/gpu/drm/tegra/drm.h10
-rw-r--r--drivers/gpu/drm/tegra/dsi.c4
-rw-r--r--drivers/gpu/drm/tegra/fb.c13
-rw-r--r--drivers/gpu/drm/tegra/gem.c5
-rw-r--r--drivers/gpu/drm/tegra/gem.h16
-rw-r--r--drivers/gpu/drm/tegra/gr2d.c1
-rw-r--r--drivers/gpu/drm/tegra/gr3d.c1
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c1
-rw-r--r--drivers/gpu/drm/tegra/sor.c21
-rw-r--r--drivers/gpu/host1x/job.c22
-rw-r--r--include/linux/host1x.h15
-rw-r--r--include/uapi/drm/tegra_drm.h46
16 files changed, 425 insertions, 67 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index ef40381f3909..6553fd238685 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -18,6 +18,8 @@
18struct tegra_dc_soc_info { 18struct 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;
22 unsigned int pitch_align;
21}; 23};
22 24
23struct tegra_plane { 25struct tegra_plane {
@@ -212,15 +214,44 @@ static int tegra_dc_setup_window(struct tegra_dc *dc, unsigned int index,
212 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET); 214 tegra_dc_writel(dc, h_offset, DC_WINBUF_ADDR_H_OFFSET);
213 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET); 215 tegra_dc_writel(dc, v_offset, DC_WINBUF_ADDR_V_OFFSET);
214 216
215 if (window->tiled) { 217 if (dc->soc->supports_block_linear) {
216 value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | 218 unsigned long height = window->tiling.value;
217 DC_WIN_BUFFER_ADDR_MODE_TILE; 219
220 switch (window->tiling.mode) {
221 case TEGRA_BO_TILING_MODE_PITCH:
222 value = DC_WINBUF_SURFACE_KIND_PITCH;
223 break;
224
225 case TEGRA_BO_TILING_MODE_TILED:
226 value = DC_WINBUF_SURFACE_KIND_TILED;
227 break;
228
229 case TEGRA_BO_TILING_MODE_BLOCK:
230 value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
231 DC_WINBUF_SURFACE_KIND_BLOCK;
232 break;
233 }
234
235 tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
218 } else { 236 } else {
219 value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | 237 switch (window->tiling.mode) {
220 DC_WIN_BUFFER_ADDR_MODE_LINEAR; 238 case TEGRA_BO_TILING_MODE_PITCH:
221 } 239 value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
240 DC_WIN_BUFFER_ADDR_MODE_LINEAR;
241 break;
222 242
223 tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); 243 case TEGRA_BO_TILING_MODE_TILED:
244 value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
245 DC_WIN_BUFFER_ADDR_MODE_TILE;
246 break;
247
248 case TEGRA_BO_TILING_MODE_BLOCK:
249 DRM_ERROR("hardware doesn't support block linear mode\n");
250 return -EINVAL;
251 }
252
253 tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
254 }
224 255
225 value = WIN_ENABLE; 256 value = WIN_ENABLE;
226 257
@@ -288,6 +319,7 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
288 struct tegra_dc *dc = to_tegra_dc(crtc); 319 struct tegra_dc *dc = to_tegra_dc(crtc);
289 struct tegra_dc_window window; 320 struct tegra_dc_window window;
290 unsigned int i; 321 unsigned int i;
322 int err;
291 323
292 memset(&window, 0, sizeof(window)); 324 memset(&window, 0, sizeof(window));
293 window.src.x = src_x >> 16; 325 window.src.x = src_x >> 16;
@@ -301,7 +333,10 @@ static int tegra_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
301 window.format = tegra_dc_format(fb->pixel_format, &window.swap); 333 window.format = tegra_dc_format(fb->pixel_format, &window.swap);
302 window.bits_per_pixel = fb->bits_per_pixel; 334 window.bits_per_pixel = fb->bits_per_pixel;
303 window.bottom_up = tegra_fb_is_bottom_up(fb); 335 window.bottom_up = tegra_fb_is_bottom_up(fb);
304 window.tiled = tegra_fb_is_tiled(fb); 336
337 err = tegra_fb_get_tiling(fb, &window.tiling);
338 if (err < 0)
339 return err;
305 340
306 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) { 341 for (i = 0; i < drm_format_num_planes(fb->pixel_format); i++) {
307 struct tegra_bo *bo = tegra_fb_get_plane(fb, i); 342 struct tegra_bo *bo = tegra_fb_get_plane(fb, i);
@@ -402,8 +437,14 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
402{ 437{
403 struct tegra_bo *bo = tegra_fb_get_plane(fb, 0); 438 struct tegra_bo *bo = tegra_fb_get_plane(fb, 0);
404 unsigned int h_offset = 0, v_offset = 0; 439 unsigned int h_offset = 0, v_offset = 0;
440 struct tegra_bo_tiling tiling;
405 unsigned int format, swap; 441 unsigned int format, swap;
406 unsigned long value; 442 unsigned long value;
443 int err;
444
445 err = tegra_fb_get_tiling(fb, &tiling);
446 if (err < 0)
447 return err;
407 448
408 tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER); 449 tegra_dc_writel(dc, WINDOW_A_SELECT, DC_CMD_DISPLAY_WINDOW_HEADER);
409 450
@@ -417,15 +458,44 @@ static int tegra_dc_set_base(struct tegra_dc *dc, int x, int y,
417 tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH); 458 tegra_dc_writel(dc, format, DC_WIN_COLOR_DEPTH);
418 tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP); 459 tegra_dc_writel(dc, swap, DC_WIN_BYTE_SWAP);
419 460
420 if (tegra_fb_is_tiled(fb)) { 461 if (dc->soc->supports_block_linear) {
421 value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV | 462 unsigned long height = tiling.value;
422 DC_WIN_BUFFER_ADDR_MODE_TILE; 463
464 switch (tiling.mode) {
465 case TEGRA_BO_TILING_MODE_PITCH:
466 value = DC_WINBUF_SURFACE_KIND_PITCH;
467 break;
468
469 case TEGRA_BO_TILING_MODE_TILED:
470 value = DC_WINBUF_SURFACE_KIND_TILED;
471 break;
472
473 case TEGRA_BO_TILING_MODE_BLOCK:
474 value = DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(height) |
475 DC_WINBUF_SURFACE_KIND_BLOCK;
476 break;
477 }
478
479 tegra_dc_writel(dc, value, DC_WINBUF_SURFACE_KIND);
423 } else { 480 } else {
424 value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV | 481 switch (tiling.mode) {
425 DC_WIN_BUFFER_ADDR_MODE_LINEAR; 482 case TEGRA_BO_TILING_MODE_PITCH:
426 } 483 value = DC_WIN_BUFFER_ADDR_MODE_LINEAR_UV |
484 DC_WIN_BUFFER_ADDR_MODE_LINEAR;
485 break;
486
487 case TEGRA_BO_TILING_MODE_TILED:
488 value = DC_WIN_BUFFER_ADDR_MODE_TILE_UV |
489 DC_WIN_BUFFER_ADDR_MODE_TILE;
490 break;
491
492 case TEGRA_BO_TILING_MODE_BLOCK:
493 DRM_ERROR("hardware doesn't support block linear mode\n");
494 return -EINVAL;
495 }
427 496
428 tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE); 497 tegra_dc_writel(dc, value, DC_WIN_BUFFER_ADDR_MODE);
498 }
429 499
430 /* make sure bottom-up buffers are properly displayed */ 500 /* make sure bottom-up buffers are properly displayed */
431 if (tegra_fb_is_bottom_up(fb)) { 501 if (tegra_fb_is_bottom_up(fb)) {
@@ -1214,12 +1284,20 @@ static int tegra_dc_init(struct host1x_client *client)
1214{ 1284{
1215 struct drm_device *drm = dev_get_drvdata(client->parent); 1285 struct drm_device *drm = dev_get_drvdata(client->parent);
1216 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;
1217 int err; 1288 int err;
1218 1289
1219 drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs); 1290 drm_crtc_init(drm, &dc->base, &tegra_crtc_funcs);
1220 drm_mode_crtc_set_gamma_size(&dc->base, 256); 1291 drm_mode_crtc_set_gamma_size(&dc->base, 256);
1221 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs); 1292 drm_crtc_helper_add(&dc->base, &tegra_crtc_helper_funcs);
1222 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
1223 err = tegra_dc_rgb_init(drm, dc); 1301 err = tegra_dc_rgb_init(drm, dc);
1224 if (err < 0 && err != -ENODEV) { 1302 if (err < 0 && err != -ENODEV) {
1225 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);
@@ -1277,16 +1355,29 @@ static const struct host1x_client_ops dc_client_ops = {
1277static const struct tegra_dc_soc_info tegra20_dc_soc_info = { 1355static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
1278 .supports_interlacing = false, 1356 .supports_interlacing = false,
1279 .supports_cursor = false, 1357 .supports_cursor = false,
1358 .supports_block_linear = false,
1359 .pitch_align = 8,
1280}; 1360};
1281 1361
1282static const struct tegra_dc_soc_info tegra30_dc_soc_info = { 1362static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
1283 .supports_interlacing = false, 1363 .supports_interlacing = false,
1284 .supports_cursor = false, 1364 .supports_cursor = false,
1365 .supports_block_linear = false,
1366 .pitch_align = 8,
1367};
1368
1369static 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,
1285}; 1374};
1286 1375
1287static const struct tegra_dc_soc_info tegra124_dc_soc_info = { 1376static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
1288 .supports_interlacing = true, 1377 .supports_interlacing = true,
1289 .supports_cursor = true, 1378 .supports_cursor = true,
1379 .supports_block_linear = true,
1380 .pitch_align = 64,
1290}; 1381};
1291 1382
1292static const struct of_device_id tegra_dc_of_match[] = { 1383static const struct of_device_id tegra_dc_of_match[] = {
@@ -1303,6 +1394,7 @@ static const struct of_device_id tegra_dc_of_match[] = {
1303 /* sentinel */ 1394 /* sentinel */
1304 } 1395 }
1305}; 1396};
1397MODULE_DEVICE_TABLE(of, tegra_dc_of_match);
1306 1398
1307static int tegra_dc_parse_dt(struct tegra_dc *dc) 1399static int tegra_dc_parse_dt(struct tegra_dc *dc)
1308{ 1400{
@@ -1430,6 +1522,7 @@ static int tegra_dc_remove(struct platform_device *pdev)
1430 return err; 1522 return err;
1431 } 1523 }
1432 1524
1525 reset_control_assert(dc->rst);
1433 clk_disable_unprepare(dc->clk); 1526 clk_disable_unprepare(dc->clk);
1434 1527
1435 return 0; 1528 return 0;
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h
index 78c5feff95d2..705c93b00794 100644
--- a/drivers/gpu/drm/tegra/dc.h
+++ b/drivers/gpu/drm/tegra/dc.h
@@ -428,6 +428,11 @@
428#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809 428#define DC_WINBUF_ADDR_V_OFFSET_NS 0x809
429 429
430#define DC_WINBUF_UFLOW_STATUS 0x80a 430#define DC_WINBUF_UFLOW_STATUS 0x80a
431#define DC_WINBUF_SURFACE_KIND 0x80b
432#define DC_WINBUF_SURFACE_KIND_PITCH (0 << 0)
433#define DC_WINBUF_SURFACE_KIND_TILED (1 << 0)
434#define DC_WINBUF_SURFACE_KIND_BLOCK (2 << 0)
435#define DC_WINBUF_SURFACE_KIND_BLOCK_HEIGHT(x) (((x) & 0x7) << 4)
431 436
432#define DC_WINBUF_AD_UFLOW_STATUS 0xbca 437#define DC_WINBUF_AD_UFLOW_STATUS 0xbca
433#define DC_WINBUF_BD_UFLOW_STATUS 0xdca 438#define DC_WINBUF_BD_UFLOW_STATUS 0xdca
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index 3f132e356e9c..708f783ead47 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -382,6 +382,7 @@ static const struct of_device_id tegra_dpaux_of_match[] = {
382 { .compatible = "nvidia,tegra124-dpaux", }, 382 { .compatible = "nvidia,tegra124-dpaux", },
383 { }, 383 { },
384}; 384};
385MODULE_DEVICE_TABLE(of, tegra_dpaux_of_match);
385 386
386struct platform_driver tegra_dpaux_driver = { 387struct platform_driver tegra_dpaux_driver = {
387 .driver = { 388 .driver = {
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index fd736efd14bd..59736bb810cd 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -132,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle)
132 return &bo->base; 132 return &bo->base;
133} 133}
134 134
135static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
136 struct drm_tegra_reloc __user *src,
137 struct drm_device *drm,
138 struct drm_file *file)
139{
140 u32 cmdbuf, target;
141 int err;
142
143 err = get_user(cmdbuf, &src->cmdbuf.handle);
144 if (err < 0)
145 return err;
146
147 err = get_user(dest->cmdbuf.offset, &src->cmdbuf.offset);
148 if (err < 0)
149 return err;
150
151 err = get_user(target, &src->target.handle);
152 if (err < 0)
153 return err;
154
155 err = get_user(dest->target.offset, &src->cmdbuf.offset);
156 if (err < 0)
157 return err;
158
159 err = get_user(dest->shift, &src->shift);
160 if (err < 0)
161 return err;
162
163 dest->cmdbuf.bo = host1x_bo_lookup(drm, file, cmdbuf);
164 if (!dest->cmdbuf.bo)
165 return -ENOENT;
166
167 dest->target.bo = host1x_bo_lookup(drm, file, target);
168 if (!dest->target.bo)
169 return -ENOENT;
170
171 return 0;
172}
173
135int tegra_drm_submit(struct tegra_drm_context *context, 174int tegra_drm_submit(struct tegra_drm_context *context,
136 struct drm_tegra_submit *args, struct drm_device *drm, 175 struct drm_tegra_submit *args, struct drm_device *drm,
137 struct drm_file *file) 176 struct drm_file *file)
@@ -184,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_context *context,
184 cmdbufs++; 223 cmdbufs++;
185 } 224 }
186 225
187 if (copy_from_user(job->relocarray, relocs, 226 /* copy and resolve relocations from submit */
188 sizeof(*relocs) * num_relocs)) {
189 err = -EFAULT;
190 goto fail;
191 }
192
193 while (num_relocs--) { 227 while (num_relocs--) {
194 struct host1x_reloc *reloc = &job->relocarray[num_relocs]; 228 err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs],
195 struct host1x_bo *cmdbuf, *target; 229 &relocs[num_relocs], drm,
196 230 file);
197 cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf); 231 if (err < 0)
198 target = host1x_bo_lookup(drm, file, (u32)reloc->target);
199
200 reloc->cmdbuf = cmdbuf;
201 reloc->target = target;
202
203 if (!reloc->target || !reloc->cmdbuf) {
204 err = -ENOENT;
205 goto fail; 232 goto fail;
206 }
207 } 233 }
208 234
209 if (copy_from_user(job->waitchk, waitchks, 235 if (copy_from_user(job->waitchk, waitchks,
@@ -455,11 +481,151 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
455 481
456 return 0; 482 return 0;
457} 483}
484
485static int tegra_gem_set_tiling(struct drm_device *drm, void *data,
486 struct drm_file *file)
487{
488 struct drm_tegra_gem_set_tiling *args = data;
489 enum tegra_bo_tiling_mode mode;
490 struct drm_gem_object *gem;
491 unsigned long value = 0;
492 struct tegra_bo *bo;
493
494 switch (args->mode) {
495 case DRM_TEGRA_GEM_TILING_MODE_PITCH:
496 mode = TEGRA_BO_TILING_MODE_PITCH;
497
498 if (args->value != 0)
499 return -EINVAL;
500
501 break;
502
503 case DRM_TEGRA_GEM_TILING_MODE_TILED:
504 mode = TEGRA_BO_TILING_MODE_TILED;
505
506 if (args->value != 0)
507 return -EINVAL;
508
509 break;
510
511 case DRM_TEGRA_GEM_TILING_MODE_BLOCK:
512 mode = TEGRA_BO_TILING_MODE_BLOCK;
513
514 if (args->value > 5)
515 return -EINVAL;
516
517 value = args->value;
518 break;
519
520 default:
521 return -EINVAL;
522 }
523
524 gem = drm_gem_object_lookup(drm, file, args->handle);
525 if (!gem)
526 return -ENOENT;
527
528 bo = to_tegra_bo(gem);
529
530 bo->tiling.mode = mode;
531 bo->tiling.value = value;
532
533 drm_gem_object_unreference(gem);
534
535 return 0;
536}
537
538static int tegra_gem_get_tiling(struct drm_device *drm, void *data,
539 struct drm_file *file)
540{
541 struct drm_tegra_gem_get_tiling *args = data;
542 struct drm_gem_object *gem;
543 struct tegra_bo *bo;
544 int err = 0;
545
546 gem = drm_gem_object_lookup(drm, file, args->handle);
547 if (!gem)
548 return -ENOENT;
549
550 bo = to_tegra_bo(gem);
551
552 switch (bo->tiling.mode) {
553 case TEGRA_BO_TILING_MODE_PITCH:
554 args->mode = DRM_TEGRA_GEM_TILING_MODE_PITCH;
555 args->value = 0;
556 break;
557
558 case TEGRA_BO_TILING_MODE_TILED:
559 args->mode = DRM_TEGRA_GEM_TILING_MODE_TILED;
560 args->value = 0;
561 break;
562
563 case TEGRA_BO_TILING_MODE_BLOCK:
564 args->mode = DRM_TEGRA_GEM_TILING_MODE_BLOCK;
565 args->value = bo->tiling.value;
566 break;
567
568 default:
569 err = -EINVAL;
570 break;
571 }
572
573 drm_gem_object_unreference(gem);
574
575 return err;
576}
577
578static int tegra_gem_set_flags(struct drm_device *drm, void *data,
579 struct drm_file *file)
580{
581 struct drm_tegra_gem_set_flags *args = data;
582 struct drm_gem_object *gem;
583 struct tegra_bo *bo;
584
585 if (args->flags & ~DRM_TEGRA_GEM_FLAGS)
586 return -EINVAL;
587
588 gem = drm_gem_object_lookup(drm, file, args->handle);
589 if (!gem)
590 return -ENOENT;
591
592 bo = to_tegra_bo(gem);
593 bo->flags = 0;
594
595 if (args->flags & DRM_TEGRA_GEM_BOTTOM_UP)
596 bo->flags |= TEGRA_BO_BOTTOM_UP;
597
598 drm_gem_object_unreference(gem);
599
600 return 0;
601}
602
603static int tegra_gem_get_flags(struct drm_device *drm, void *data,
604 struct drm_file *file)
605{
606 struct drm_tegra_gem_get_flags *args = data;
607 struct drm_gem_object *gem;
608 struct tegra_bo *bo;
609
610 gem = drm_gem_object_lookup(drm, file, args->handle);
611 if (!gem)
612 return -ENOENT;
613
614 bo = to_tegra_bo(gem);
615 args->flags = 0;
616
617 if (bo->flags & TEGRA_BO_BOTTOM_UP)
618 args->flags |= DRM_TEGRA_GEM_BOTTOM_UP;
619
620 drm_gem_object_unreference(gem);
621
622 return 0;
623}
458#endif 624#endif
459 625
460static const struct drm_ioctl_desc tegra_drm_ioctls[] = { 626static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
461#ifdef CONFIG_DRM_TEGRA_STAGING 627#ifdef CONFIG_DRM_TEGRA_STAGING
462 DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED | DRM_AUTH), 628 DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, DRM_UNLOCKED),
463 DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED), 629 DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, DRM_UNLOCKED),
464 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED), 630 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, DRM_UNLOCKED),
465 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED), 631 DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, DRM_UNLOCKED),
@@ -469,6 +635,10 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
469 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED), 635 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, DRM_UNLOCKED),
470 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), 636 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
471 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED), 637 DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, DRM_UNLOCKED),
638 DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, DRM_UNLOCKED),
639 DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, DRM_UNLOCKED),
640 DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, DRM_UNLOCKED),
641 DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, DRM_UNLOCKED),
472#endif 642#endif
473}; 643};
474 644
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 0d30689dff01..e89c70fa82d5 100644
--- a/drivers/gpu/drm/tegra/drm.h
+++ b/drivers/gpu/drm/tegra/drm.h
@@ -19,6 +19,8 @@
19#include <drm/drm_fb_helper.h> 19#include <drm/drm_fb_helper.h>
20#include <drm/drm_fixed.h> 20#include <drm/drm_fixed.h>
21 21
22#include "gem.h"
23
22struct reset_control; 24struct reset_control;
23 25
24struct tegra_fb { 26struct tegra_fb {
@@ -43,6 +45,8 @@ struct tegra_drm {
43#ifdef CONFIG_DRM_TEGRA_FBDEV 45#ifdef CONFIG_DRM_TEGRA_FBDEV
44 struct tegra_fbdev *fbdev; 46 struct tegra_fbdev *fbdev;
45#endif 47#endif
48
49 unsigned int pitch_align;
46}; 50};
47 51
48struct tegra_drm_client; 52struct tegra_drm_client;
@@ -160,7 +164,8 @@ struct tegra_dc_window {
160 unsigned int stride[2]; 164 unsigned int stride[2];
161 unsigned long base[3]; 165 unsigned long base[3];
162 bool bottom_up; 166 bool bottom_up;
163 bool tiled; 167
168 struct tegra_bo_tiling tiling;
164}; 169};
165 170
166/* from dc.c */ 171/* from dc.c */
@@ -279,7 +284,8 @@ int tegra_dpaux_train(struct tegra_dpaux *dpaux, struct drm_dp_link *link,
279struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer, 284struct tegra_bo *tegra_fb_get_plane(struct drm_framebuffer *framebuffer,
280 unsigned int index); 285 unsigned int index);
281bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer); 286bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer);
282bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer); 287int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
288 struct tegra_bo_tiling *tiling);
283int tegra_drm_fb_prepare(struct drm_device *drm); 289int tegra_drm_fb_prepare(struct drm_device *drm);
284int tegra_drm_fb_init(struct drm_device *drm); 290int tegra_drm_fb_init(struct drm_device *drm);
285void tegra_drm_fb_exit(struct drm_device *drm); 291void tegra_drm_fb_exit(struct drm_device *drm);
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index bd56f2affa78..f7874458926a 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -474,7 +474,8 @@ static int tegra_output_dsi_enable(struct tegra_output *output)
474 tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL); 474 tegra_dsi_writel(dsi, value, DSI_HOST_CONTROL);
475 475
476 value = tegra_dsi_readl(dsi, DSI_CONTROL); 476 value = tegra_dsi_readl(dsi, DSI_CONTROL);
477 value |= DSI_CONTROL_HS_CLK_CTRL; 477 if (dsi->flags & MIPI_DSI_CLOCK_NON_CONTINUOUS)
478 value |= DSI_CONTROL_HS_CLK_CTRL;
478 value &= ~DSI_CONTROL_TX_TRIG(3); 479 value &= ~DSI_CONTROL_TX_TRIG(3);
479 value &= ~DSI_CONTROL_DCS_ENABLE; 480 value &= ~DSI_CONTROL_DCS_ENABLE;
480 value |= DSI_CONTROL_VIDEO_ENABLE; 481 value |= DSI_CONTROL_VIDEO_ENABLE;
@@ -982,6 +983,7 @@ static const struct of_device_id tegra_dsi_of_match[] = {
982 { .compatible = "nvidia,tegra114-dsi", }, 983 { .compatible = "nvidia,tegra114-dsi", },
983 { }, 984 { },
984}; 985};
986MODULE_DEVICE_TABLE(of, tegra_dsi_of_match);
985 987
986struct platform_driver tegra_dsi_driver = { 988struct platform_driver tegra_dsi_driver = {
987 .driver = { 989 .driver = {
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index fc1528e0bda1..3513d12d5aa1 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -46,14 +46,15 @@ bool tegra_fb_is_bottom_up(struct drm_framebuffer *framebuffer)
46 return false; 46 return false;
47} 47}
48 48
49bool tegra_fb_is_tiled(struct drm_framebuffer *framebuffer) 49int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
50 struct tegra_bo_tiling *tiling)
50{ 51{
51 struct tegra_fb *fb = to_tegra_fb(framebuffer); 52 struct tegra_fb *fb = to_tegra_fb(framebuffer);
52 53
53 if (fb->planes[0]->flags & TEGRA_BO_TILED) 54 /* TODO: handle YUV formats? */
54 return true; 55 *tiling = fb->planes[0]->tiling;
55 56
56 return false; 57 return 0;
57} 58}
58 59
59static void tegra_fb_destroy(struct drm_framebuffer *framebuffer) 60static void tegra_fb_destroy(struct drm_framebuffer *framebuffer)
@@ -193,6 +194,7 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
193 struct drm_fb_helper_surface_size *sizes) 194 struct drm_fb_helper_surface_size *sizes)
194{ 195{
195 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;
196 struct drm_device *drm = helper->dev; 198 struct drm_device *drm = helper->dev;
197 struct drm_mode_fb_cmd2 cmd = { 0 }; 199 struct drm_mode_fb_cmd2 cmd = { 0 };
198 unsigned int bytes_per_pixel; 200 unsigned int bytes_per_pixel;
@@ -207,7 +209,8 @@ static int tegra_fbdev_probe(struct drm_fb_helper *helper,
207 209
208 cmd.width = sizes->surface_width; 210 cmd.width = sizes->surface_width;
209 cmd.height = sizes->surface_height; 211 cmd.height = sizes->surface_height;
210 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);
211 cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, 214 cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
212 sizes->surface_depth); 215 sizes->surface_depth);
213 216
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index aa85b7b26f10..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
21static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo) 22static inline struct tegra_bo *host1x_to_tegra_bo(struct host1x_bo *bo)
@@ -126,7 +127,7 @@ struct tegra_bo *tegra_bo_create(struct drm_device *drm, unsigned int size,
126 goto err_mmap; 127 goto err_mmap;
127 128
128 if (flags & DRM_TEGRA_GEM_CREATE_TILED) 129 if (flags & DRM_TEGRA_GEM_CREATE_TILED)
129 bo->flags |= TEGRA_BO_TILED; 130 bo->tiling.mode = TEGRA_BO_TILING_MODE_TILED;
130 131
131 if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP) 132 if (flags & DRM_TEGRA_GEM_CREATE_BOTTOM_UP)
132 bo->flags |= TEGRA_BO_BOTTOM_UP; 133 bo->flags |= TEGRA_BO_BOTTOM_UP;
@@ -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
diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h
index 2f3fe96c5154..43a25c853357 100644
--- a/drivers/gpu/drm/tegra/gem.h
+++ b/drivers/gpu/drm/tegra/gem.h
@@ -16,8 +16,18 @@
16#include <drm/drm.h> 16#include <drm/drm.h>
17#include <drm/drmP.h> 17#include <drm/drmP.h>
18 18
19#define TEGRA_BO_TILED (1 << 0) 19#define TEGRA_BO_BOTTOM_UP (1 << 0)
20#define TEGRA_BO_BOTTOM_UP (1 << 1) 20
21enum tegra_bo_tiling_mode {
22 TEGRA_BO_TILING_MODE_PITCH,
23 TEGRA_BO_TILING_MODE_TILED,
24 TEGRA_BO_TILING_MODE_BLOCK,
25};
26
27struct tegra_bo_tiling {
28 enum tegra_bo_tiling_mode mode;
29 unsigned long value;
30};
21 31
22struct tegra_bo { 32struct tegra_bo {
23 struct drm_gem_object gem; 33 struct drm_gem_object gem;
@@ -26,6 +36,8 @@ struct tegra_bo {
26 struct sg_table *sgt; 36 struct sg_table *sgt;
27 dma_addr_t paddr; 37 dma_addr_t paddr;
28 void *vaddr; 38 void *vaddr;
39
40 struct tegra_bo_tiling tiling;
29}; 41};
30 42
31static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem) 43static inline struct tegra_bo *to_tegra_bo(struct drm_gem_object *gem)
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index 7c53941f2a9e..02cd3e37a6ec 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -121,6 +121,7 @@ static const struct of_device_id gr2d_match[] = {
121 { .compatible = "nvidia,tegra20-gr2d" }, 121 { .compatible = "nvidia,tegra20-gr2d" },
122 { }, 122 { },
123}; 123};
124MODULE_DEVICE_TABLE(of, gr2d_match);
124 125
125static const u32 gr2d_addr_regs[] = { 126static const u32 gr2d_addr_regs[] = {
126 GR2D_UA_BASE_ADDR, 127 GR2D_UA_BASE_ADDR,
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index 30f5ba9bd6d0..2bea2b2d204e 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -130,6 +130,7 @@ static const struct of_device_id tegra_gr3d_match[] = {
130 { .compatible = "nvidia,tegra20-gr3d" }, 130 { .compatible = "nvidia,tegra20-gr3d" },
131 { } 131 { }
132}; 132};
133MODULE_DEVICE_TABLE(of, tegra_gr3d_match);
133 134
134static const u32 gr3d_addr_regs[] = { 135static const u32 gr3d_addr_regs[] = {
135 GR3D_IDX_ATTRIBUTE( 0), 136 GR3D_IDX_ATTRIBUTE( 0),
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index ba067bb767e3..ffe26547328d 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1450,6 +1450,7 @@ static const struct of_device_id tegra_hdmi_of_match[] = {
1450 { .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config }, 1450 { .compatible = "nvidia,tegra20-hdmi", .data = &tegra20_hdmi_config },
1451 { }, 1451 { },
1452}; 1452};
1453MODULE_DEVICE_TABLE(of, tegra_hdmi_of_match);
1453 1454
1454static int tegra_hdmi_probe(struct platform_device *pdev) 1455static int tegra_hdmi_probe(struct platform_device *pdev)
1455{ 1456{
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index 27c979b50111..0410e467b828 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -516,7 +516,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
516 if (err < 0) { 516 if (err < 0) {
517 dev_err(sor->dev, "failed to probe eDP link: %d\n", 517 dev_err(sor->dev, "failed to probe eDP link: %d\n",
518 err); 518 err);
519 return err; 519 goto unlock;
520 } 520 }
521 } 521 }
522 522
@@ -525,7 +525,7 @@ static int tegra_output_sor_enable(struct tegra_output *output)
525 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err); 525 dev_err(sor->dev, "failed to set safe parent clock: %d\n", err);
526 526
527 memset(&config, 0, sizeof(config)); 527 memset(&config, 0, sizeof(config));
528 config.bits_per_pixel = 24; /* XXX: don't hardcode? */ 528 config.bits_per_pixel = output->connector.display_info.bpc * 3;
529 529
530 err = tegra_sor_calc_config(sor, mode, &config, &link); 530 err = tegra_sor_calc_config(sor, mode, &config, &link);
531 if (err < 0) 531 if (err < 0)
@@ -815,12 +815,22 @@ static int tegra_output_sor_enable(struct tegra_output *output)
815 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete 815 * configure panel (24bpp, vsync-, hsync-, DP-A protocol, complete
816 * raster, associate with display controller) 816 * raster, associate with display controller)
817 */ 817 */
818 value = SOR_STATE_ASY_VSYNCPOL | 818 value = SOR_STATE_ASY_PROTOCOL_DP_A |
819 SOR_STATE_ASY_HSYNCPOL |
820 SOR_STATE_ASY_PROTOCOL_DP_A |
821 SOR_STATE_ASY_CRC_MODE_COMPLETE | 819 SOR_STATE_ASY_CRC_MODE_COMPLETE |
822 SOR_STATE_ASY_OWNER(dc->pipe + 1); 820 SOR_STATE_ASY_OWNER(dc->pipe + 1);
823 821
822 if (mode->flags & DRM_MODE_FLAG_PHSYNC)
823 value &= ~SOR_STATE_ASY_HSYNCPOL;
824
825 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
826 value |= SOR_STATE_ASY_HSYNCPOL;
827
828 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
829 value &= ~SOR_STATE_ASY_VSYNCPOL;
830
831 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
832 value |= SOR_STATE_ASY_VSYNCPOL;
833
824 switch (config.bits_per_pixel) { 834 switch (config.bits_per_pixel) {
825 case 24: 835 case 24:
826 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444; 836 value |= SOR_STATE_ASY_PIXELDEPTH_BPP_24_444;
@@ -1455,6 +1465,7 @@ static const struct of_device_id tegra_sor_of_match[] = {
1455 { .compatible = "nvidia,tegra124-sor", }, 1465 { .compatible = "nvidia,tegra124-sor", },
1456 { }, 1466 { },
1457}; 1467};
1468MODULE_DEVICE_TABLE(of, tegra_sor_of_match);
1458 1469
1459struct platform_driver tegra_sor_driver = { 1470struct platform_driver tegra_sor_driver = {
1460 .driver = { 1471 .driver = {
diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c
index 112f27e51bc7..63bd63f3c7df 100644
--- a/drivers/gpu/host1x/job.c
+++ b/drivers/gpu/host1x/job.c
@@ -185,16 +185,16 @@ static unsigned int pin_job(struct host1x_job *job)
185 struct sg_table *sgt; 185 struct sg_table *sgt;
186 dma_addr_t phys_addr; 186 dma_addr_t phys_addr;
187 187
188 reloc->target = host1x_bo_get(reloc->target); 188 reloc->target.bo = host1x_bo_get(reloc->target.bo);
189 if (!reloc->target) 189 if (!reloc->target.bo)
190 goto unpin; 190 goto unpin;
191 191
192 phys_addr = host1x_bo_pin(reloc->target, &sgt); 192 phys_addr = host1x_bo_pin(reloc->target.bo, &sgt);
193 if (!phys_addr) 193 if (!phys_addr)
194 goto unpin; 194 goto unpin;
195 195
196 job->addr_phys[job->num_unpins] = phys_addr; 196 job->addr_phys[job->num_unpins] = phys_addr;
197 job->unpins[job->num_unpins].bo = reloc->target; 197 job->unpins[job->num_unpins].bo = reloc->target.bo;
198 job->unpins[job->num_unpins].sgt = sgt; 198 job->unpins[job->num_unpins].sgt = sgt;
199 job->num_unpins++; 199 job->num_unpins++;
200 } 200 }
@@ -235,21 +235,21 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
235 for (i = 0; i < job->num_relocs; i++) { 235 for (i = 0; i < job->num_relocs; i++) {
236 struct host1x_reloc *reloc = &job->relocarray[i]; 236 struct host1x_reloc *reloc = &job->relocarray[i];
237 u32 reloc_addr = (job->reloc_addr_phys[i] + 237 u32 reloc_addr = (job->reloc_addr_phys[i] +
238 reloc->target_offset) >> reloc->shift; 238 reloc->target.offset) >> reloc->shift;
239 u32 *target; 239 u32 *target;
240 240
241 /* skip all other gathers */ 241 /* skip all other gathers */
242 if (cmdbuf != reloc->cmdbuf) 242 if (cmdbuf != reloc->cmdbuf.bo)
243 continue; 243 continue;
244 244
245 if (last_page != reloc->cmdbuf_offset >> PAGE_SHIFT) { 245 if (last_page != reloc->cmdbuf.offset >> PAGE_SHIFT) {
246 if (cmdbuf_page_addr) 246 if (cmdbuf_page_addr)
247 host1x_bo_kunmap(cmdbuf, last_page, 247 host1x_bo_kunmap(cmdbuf, last_page,
248 cmdbuf_page_addr); 248 cmdbuf_page_addr);
249 249
250 cmdbuf_page_addr = host1x_bo_kmap(cmdbuf, 250 cmdbuf_page_addr = host1x_bo_kmap(cmdbuf,
251 reloc->cmdbuf_offset >> PAGE_SHIFT); 251 reloc->cmdbuf.offset >> PAGE_SHIFT);
252 last_page = reloc->cmdbuf_offset >> PAGE_SHIFT; 252 last_page = reloc->cmdbuf.offset >> PAGE_SHIFT;
253 253
254 if (unlikely(!cmdbuf_page_addr)) { 254 if (unlikely(!cmdbuf_page_addr)) {
255 pr_err("Could not map cmdbuf for relocation\n"); 255 pr_err("Could not map cmdbuf for relocation\n");
@@ -257,7 +257,7 @@ static unsigned int do_relocs(struct host1x_job *job, struct host1x_bo *cmdbuf)
257 } 257 }
258 } 258 }
259 259
260 target = cmdbuf_page_addr + (reloc->cmdbuf_offset & ~PAGE_MASK); 260 target = cmdbuf_page_addr + (reloc->cmdbuf.offset & ~PAGE_MASK);
261 *target = reloc_addr; 261 *target = reloc_addr;
262 } 262 }
263 263
@@ -272,7 +272,7 @@ static bool check_reloc(struct host1x_reloc *reloc, struct host1x_bo *cmdbuf,
272{ 272{
273 offset *= sizeof(u32); 273 offset *= sizeof(u32);
274 274
275 if (reloc->cmdbuf != cmdbuf || reloc->cmdbuf_offset != offset) 275 if (reloc->cmdbuf.bo != cmdbuf || reloc->cmdbuf.offset != offset)
276 return false; 276 return false;
277 277
278 return true; 278 return true;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index d2b52999e771..bb9840fd1e18 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -164,12 +164,15 @@ int host1x_job_submit(struct host1x_job *job);
164 */ 164 */
165 165
166struct host1x_reloc { 166struct host1x_reloc {
167 struct host1x_bo *cmdbuf; 167 struct {
168 u32 cmdbuf_offset; 168 struct host1x_bo *bo;
169 struct host1x_bo *target; 169 unsigned long offset;
170 u32 target_offset; 170 } cmdbuf;
171 u32 shift; 171 struct {
172 u32 pad; 172 struct host1x_bo *bo;
173 unsigned long offset;
174 } target;
175 unsigned long shift;
173}; 176};
174 177
175struct host1x_job { 178struct host1x_job {
diff --git a/include/uapi/drm/tegra_drm.h b/include/uapi/drm/tegra_drm.h
index b75482112428..c15d781ecc0f 100644
--- a/include/uapi/drm/tegra_drm.h
+++ b/include/uapi/drm/tegra_drm.h
@@ -129,6 +129,44 @@ struct drm_tegra_submit {
129 __u32 reserved[5]; /* future expansion */ 129 __u32 reserved[5]; /* future expansion */
130}; 130};
131 131
132#define DRM_TEGRA_GEM_TILING_MODE_PITCH 0
133#define DRM_TEGRA_GEM_TILING_MODE_TILED 1
134#define DRM_TEGRA_GEM_TILING_MODE_BLOCK 2
135
136struct drm_tegra_gem_set_tiling {
137 /* input */
138 __u32 handle;
139 __u32 mode;
140 __u32 value;
141 __u32 pad;
142};
143
144struct drm_tegra_gem_get_tiling {
145 /* input */
146 __u32 handle;
147 /* output */
148 __u32 mode;
149 __u32 value;
150 __u32 pad;
151};
152
153#define DRM_TEGRA_GEM_BOTTOM_UP (1 << 0)
154#define DRM_TEGRA_GEM_FLAGS (DRM_TEGRA_GEM_BOTTOM_UP)
155
156struct drm_tegra_gem_set_flags {
157 /* input */
158 __u32 handle;
159 /* output */
160 __u32 flags;
161};
162
163struct drm_tegra_gem_get_flags {
164 /* input */
165 __u32 handle;
166 /* output */
167 __u32 flags;
168};
169
132#define DRM_TEGRA_GEM_CREATE 0x00 170#define DRM_TEGRA_GEM_CREATE 0x00
133#define DRM_TEGRA_GEM_MMAP 0x01 171#define DRM_TEGRA_GEM_MMAP 0x01
134#define DRM_TEGRA_SYNCPT_READ 0x02 172#define DRM_TEGRA_SYNCPT_READ 0x02
@@ -139,6 +177,10 @@ struct drm_tegra_submit {
139#define DRM_TEGRA_GET_SYNCPT 0x07 177#define DRM_TEGRA_GET_SYNCPT 0x07
140#define DRM_TEGRA_SUBMIT 0x08 178#define DRM_TEGRA_SUBMIT 0x08
141#define DRM_TEGRA_GET_SYNCPT_BASE 0x09 179#define DRM_TEGRA_GET_SYNCPT_BASE 0x09
180#define DRM_TEGRA_GEM_SET_TILING 0x0a
181#define DRM_TEGRA_GEM_GET_TILING 0x0b
182#define DRM_TEGRA_GEM_SET_FLAGS 0x0c
183#define DRM_TEGRA_GEM_GET_FLAGS 0x0d
142 184
143#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create) 185#define DRM_IOCTL_TEGRA_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_CREATE, struct drm_tegra_gem_create)
144#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap) 186#define DRM_IOCTL_TEGRA_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_MMAP, struct drm_tegra_gem_mmap)
@@ -150,5 +192,9 @@ struct drm_tegra_submit {
150#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt) 192#define DRM_IOCTL_TEGRA_GET_SYNCPT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT, struct drm_tegra_get_syncpt)
151#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit) 193#define DRM_IOCTL_TEGRA_SUBMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_SUBMIT, struct drm_tegra_submit)
152#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base) 194#define DRM_IOCTL_TEGRA_GET_SYNCPT_BASE DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GET_SYNCPT_BASE, struct drm_tegra_get_syncpt_base)
195#define DRM_IOCTL_TEGRA_GEM_SET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_TILING, struct drm_tegra_gem_set_tiling)
196#define DRM_IOCTL_TEGRA_GEM_GET_TILING DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_TILING, struct drm_tegra_gem_get_tiling)
197#define DRM_IOCTL_TEGRA_GEM_SET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_SET_FLAGS, struct drm_tegra_gem_set_flags)
198#define DRM_IOCTL_TEGRA_GEM_GET_FLAGS DRM_IOWR(DRM_COMMAND_BASE + DRM_TEGRA_GEM_GET_FLAGS, struct drm_tegra_gem_get_flags)
153 199
154#endif 200#endif