aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/tegra
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/tegra')
-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.c216
-rw-r--r--drivers/gpu/drm/tegra/drm.h11
-rw-r--r--drivers/gpu/drm/tegra/dsi.c4
-rw-r--r--drivers/gpu/drm/tegra/fb.c66
-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/output.c6
-rw-r--r--drivers/gpu/drm/tegra/sor.c21
14 files changed, 404 insertions, 73 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 3396f9f6a9f7..59736bb810cd 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -40,6 +40,12 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
40 40
41 drm_mode_config_init(drm); 41 drm_mode_config_init(drm);
42 42
43 err = tegra_drm_fb_prepare(drm);
44 if (err < 0)
45 return err;
46
47 drm_kms_helper_poll_init(drm);
48
43 err = host1x_device_init(device); 49 err = host1x_device_init(device);
44 if (err < 0) 50 if (err < 0)
45 return err; 51 return err;
@@ -59,8 +65,6 @@ static int tegra_drm_load(struct drm_device *drm, unsigned long flags)
59 if (err < 0) 65 if (err < 0)
60 return err; 66 return err;
61 67
62 drm_kms_helper_poll_init(drm);
63
64 return 0; 68 return 0;
65} 69}
66 70
@@ -128,6 +132,45 @@ host1x_bo_lookup(struct drm_device *drm, struct drm_file *file, u32 handle)
128 return &bo->base; 132 return &bo->base;
129} 133}
130 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
131int tegra_drm_submit(struct tegra_drm_context *context, 174int tegra_drm_submit(struct tegra_drm_context *context,
132 struct drm_tegra_submit *args, struct drm_device *drm, 175 struct drm_tegra_submit *args, struct drm_device *drm,
133 struct drm_file *file) 176 struct drm_file *file)
@@ -180,26 +223,13 @@ int tegra_drm_submit(struct tegra_drm_context *context,
180 cmdbufs++; 223 cmdbufs++;
181 } 224 }
182 225
183 if (copy_from_user(job->relocarray, relocs, 226 /* copy and resolve relocations from submit */
184 sizeof(*relocs) * num_relocs)) {
185 err = -EFAULT;
186 goto fail;
187 }
188
189 while (num_relocs--) { 227 while (num_relocs--) {
190 struct host1x_reloc *reloc = &job->relocarray[num_relocs]; 228 err = host1x_reloc_copy_from_user(&job->relocarray[num_relocs],
191 struct host1x_bo *cmdbuf, *target; 229 &relocs[num_relocs], drm,
192 230 file);
193 cmdbuf = host1x_bo_lookup(drm, file, (u32)reloc->cmdbuf); 231 if (err < 0)
194 target = host1x_bo_lookup(drm, file, (u32)reloc->target);
195
196 reloc->cmdbuf = cmdbuf;
197 reloc->target = target;
198
199 if (!reloc->target || !reloc->cmdbuf) {
200 err = -ENOENT;
201 goto fail; 232 goto fail;
202 }
203 } 233 }
204 234
205 if (copy_from_user(job->waitchk, waitchks, 235 if (copy_from_user(job->waitchk, waitchks,
@@ -451,11 +481,151 @@ static int tegra_get_syncpt_base(struct drm_device *drm, void *data,
451 481
452 return 0; 482 return 0;
453} 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}
454#endif 624#endif
455 625
456static const struct drm_ioctl_desc tegra_drm_ioctls[] = { 626static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
457#ifdef CONFIG_DRM_TEGRA_STAGING 627#ifdef CONFIG_DRM_TEGRA_STAGING
458 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),
459 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),
460 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),
461 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),
@@ -465,6 +635,10 @@ static const struct drm_ioctl_desc tegra_drm_ioctls[] = {
465 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),
466 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED), 636 DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, DRM_UNLOCKED),
467 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),
468#endif 642#endif
469}; 643};
470 644
diff --git a/drivers/gpu/drm/tegra/drm.h b/drivers/gpu/drm/tegra/drm.h
index 6b8fe9d86ed4..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,9 @@ 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);
289int tegra_drm_fb_prepare(struct drm_device *drm);
283int tegra_drm_fb_init(struct drm_device *drm); 290int tegra_drm_fb_init(struct drm_device *drm);
284void tegra_drm_fb_exit(struct drm_device *drm); 291void tegra_drm_fb_exit(struct drm_device *drm);
285#ifdef CONFIG_DRM_TEGRA_FBDEV 292#ifdef CONFIG_DRM_TEGRA_FBDEV
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 9798a7080322..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
@@ -267,18 +270,13 @@ release:
267 return err; 270 return err;
268} 271}
269 272
270static struct drm_fb_helper_funcs tegra_fb_helper_funcs = { 273static const struct drm_fb_helper_funcs tegra_fb_helper_funcs = {
271 .fb_probe = tegra_fbdev_probe, 274 .fb_probe = tegra_fbdev_probe,
272}; 275};
273 276
274static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm, 277static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm)
275 unsigned int preferred_bpp,
276 unsigned int num_crtc,
277 unsigned int max_connectors)
278{ 278{
279 struct drm_fb_helper *helper;
280 struct tegra_fbdev *fbdev; 279 struct tegra_fbdev *fbdev;
281 int err;
282 280
283 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); 281 fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
284 if (!fbdev) { 282 if (!fbdev) {
@@ -286,13 +284,23 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
286 return ERR_PTR(-ENOMEM); 284 return ERR_PTR(-ENOMEM);
287 } 285 }
288 286
289 fbdev->base.funcs = &tegra_fb_helper_funcs; 287 drm_fb_helper_prepare(drm, &fbdev->base, &tegra_fb_helper_funcs);
290 helper = &fbdev->base; 288
289 return fbdev;
290}
291
292static int tegra_fbdev_init(struct tegra_fbdev *fbdev,
293 unsigned int preferred_bpp,
294 unsigned int num_crtc,
295 unsigned int max_connectors)
296{
297 struct drm_device *drm = fbdev->base.dev;
298 int err;
291 299
292 err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors); 300 err = drm_fb_helper_init(drm, &fbdev->base, num_crtc, max_connectors);
293 if (err < 0) { 301 if (err < 0) {
294 dev_err(drm->dev, "failed to initialize DRM FB helper\n"); 302 dev_err(drm->dev, "failed to initialize DRM FB helper\n");
295 goto free; 303 return err;
296 } 304 }
297 305
298 err = drm_fb_helper_single_add_all_connectors(&fbdev->base); 306 err = drm_fb_helper_single_add_all_connectors(&fbdev->base);
@@ -301,21 +309,17 @@ static struct tegra_fbdev *tegra_fbdev_create(struct drm_device *drm,
301 goto fini; 309 goto fini;
302 } 310 }
303 311
304 drm_helper_disable_unused_functions(drm);
305
306 err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp); 312 err = drm_fb_helper_initial_config(&fbdev->base, preferred_bpp);
307 if (err < 0) { 313 if (err < 0) {
308 dev_err(drm->dev, "failed to set initial configuration\n"); 314 dev_err(drm->dev, "failed to set initial configuration\n");
309 goto fini; 315 goto fini;
310 } 316 }
311 317
312 return fbdev; 318 return 0;
313 319
314fini: 320fini:
315 drm_fb_helper_fini(&fbdev->base); 321 drm_fb_helper_fini(&fbdev->base);
316free: 322 return err;
317 kfree(fbdev);
318 return ERR_PTR(err);
319} 323}
320 324
321static void tegra_fbdev_free(struct tegra_fbdev *fbdev) 325static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
@@ -366,7 +370,7 @@ static const struct drm_mode_config_funcs tegra_drm_mode_funcs = {
366#endif 370#endif
367}; 371};
368 372
369int tegra_drm_fb_init(struct drm_device *drm) 373int tegra_drm_fb_prepare(struct drm_device *drm)
370{ 374{
371#ifdef CONFIG_DRM_TEGRA_FBDEV 375#ifdef CONFIG_DRM_TEGRA_FBDEV
372 struct tegra_drm *tegra = drm->dev_private; 376 struct tegra_drm *tegra = drm->dev_private;
@@ -381,8 +385,7 @@ int tegra_drm_fb_init(struct drm_device *drm)
381 drm->mode_config.funcs = &tegra_drm_mode_funcs; 385 drm->mode_config.funcs = &tegra_drm_mode_funcs;
382 386
383#ifdef CONFIG_DRM_TEGRA_FBDEV 387#ifdef CONFIG_DRM_TEGRA_FBDEV
384 tegra->fbdev = tegra_fbdev_create(drm, 32, drm->mode_config.num_crtc, 388 tegra->fbdev = tegra_fbdev_create(drm);
385 drm->mode_config.num_connector);
386 if (IS_ERR(tegra->fbdev)) 389 if (IS_ERR(tegra->fbdev))
387 return PTR_ERR(tegra->fbdev); 390 return PTR_ERR(tegra->fbdev);
388#endif 391#endif
@@ -390,6 +393,21 @@ int tegra_drm_fb_init(struct drm_device *drm)
390 return 0; 393 return 0;
391} 394}
392 395
396int tegra_drm_fb_init(struct drm_device *drm)
397{
398#ifdef CONFIG_DRM_TEGRA_FBDEV
399 struct tegra_drm *tegra = drm->dev_private;
400 int err;
401
402 err = tegra_fbdev_init(tegra->fbdev, 32, drm->mode_config.num_crtc,
403 drm->mode_config.num_connector);
404 if (err < 0)
405 return err;
406#endif
407
408 return 0;
409}
410
393void tegra_drm_fb_exit(struct drm_device *drm) 411void tegra_drm_fb_exit(struct drm_device *drm)
394{ 412{
395#ifdef CONFIG_DRM_TEGRA_FBDEV 413#ifdef CONFIG_DRM_TEGRA_FBDEV
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index 78cc8143760a..ce023fa3e8ae 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/output.c b/drivers/gpu/drm/tegra/output.c
index a3e4f1eca6f7..0c67d7eebc94 100644
--- a/drivers/gpu/drm/tegra/output.c
+++ b/drivers/gpu/drm/tegra/output.c
@@ -105,7 +105,7 @@ static void drm_connector_clear(struct drm_connector *connector)
105 105
106static void tegra_connector_destroy(struct drm_connector *connector) 106static void tegra_connector_destroy(struct drm_connector *connector)
107{ 107{
108 drm_sysfs_connector_remove(connector); 108 drm_connector_unregister(connector);
109 drm_connector_cleanup(connector); 109 drm_connector_cleanup(connector);
110 drm_connector_clear(connector); 110 drm_connector_clear(connector);
111} 111}
@@ -140,7 +140,9 @@ static void tegra_encoder_dpms(struct drm_encoder *encoder, int mode)
140 if (mode != DRM_MODE_DPMS_ON) { 140 if (mode != DRM_MODE_DPMS_ON) {
141 drm_panel_disable(panel); 141 drm_panel_disable(panel);
142 tegra_output_disable(output); 142 tegra_output_disable(output);
143 drm_panel_unprepare(panel);
143 } else { 144 } else {
145 drm_panel_prepare(panel);
144 tegra_output_enable(output); 146 tegra_output_enable(output);
145 drm_panel_enable(panel); 147 drm_panel_enable(panel);
146 } 148 }
@@ -318,7 +320,7 @@ int tegra_output_init(struct drm_device *drm, struct tegra_output *output)
318 drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs); 320 drm_encoder_helper_add(&output->encoder, &encoder_helper_funcs);
319 321
320 drm_mode_connector_attach_encoder(&output->connector, &output->encoder); 322 drm_mode_connector_attach_encoder(&output->connector, &output->encoder);
321 drm_sysfs_connector_add(&output->connector); 323 drm_connector_register(&output->connector);
322 324
323 output->encoder.possible_crtcs = 0x3; 325 output->encoder.possible_crtcs = 0x3;
324 326
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 = {