diff options
author | Thierry Reding <treding@nvidia.com> | 2013-12-20 07:58:33 -0500 |
---|---|---|
committer | Thierry Reding <treding@nvidia.com> | 2014-06-05 17:14:47 -0400 |
commit | e687651bc1ed96b0ad2ee9464f341c53563b5353 (patch) | |
tree | bf0cedd7a722568042b31cb82f899cd7422f57df | |
parent | 9910f5c455de10f0eb2559093a7adad65f6c05cd (diff) |
drm/tegra: Add hardware cursor support
Enable hardware cursor support on Tegra124. Earlier generations support
the hardware cursor to some degree as well, but not in a way that can be
generically exposed.
Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r-- | drivers/gpu/drm/tegra/dc.c | 111 | ||||
-rw-r--r-- | drivers/gpu/drm/tegra/dc.h | 30 |
2 files changed, 138 insertions, 3 deletions
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 323216789b69..ef40381f3909 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | struct tegra_dc_soc_info { | 18 | struct tegra_dc_soc_info { |
19 | bool supports_interlacing; | 19 | bool supports_interlacing; |
20 | bool supports_cursor; | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | struct tegra_plane { | 23 | struct tegra_plane { |
@@ -477,6 +478,109 @@ void tegra_dc_disable_vblank(struct tegra_dc *dc) | |||
477 | spin_unlock_irqrestore(&dc->lock, flags); | 478 | spin_unlock_irqrestore(&dc->lock, flags); |
478 | } | 479 | } |
479 | 480 | ||
481 | static int tegra_dc_cursor_set2(struct drm_crtc *crtc, struct drm_file *file, | ||
482 | uint32_t handle, uint32_t width, | ||
483 | uint32_t height, int32_t hot_x, int32_t hot_y) | ||
484 | { | ||
485 | unsigned long value = CURSOR_CLIP_DISPLAY; | ||
486 | struct tegra_dc *dc = to_tegra_dc(crtc); | ||
487 | struct drm_gem_object *gem; | ||
488 | struct tegra_bo *bo = NULL; | ||
489 | |||
490 | if (!dc->soc->supports_cursor) | ||
491 | return -ENXIO; | ||
492 | |||
493 | if (width != height) | ||
494 | return -EINVAL; | ||
495 | |||
496 | switch (width) { | ||
497 | case 32: | ||
498 | value |= CURSOR_SIZE_32x32; | ||
499 | break; | ||
500 | |||
501 | case 64: | ||
502 | value |= CURSOR_SIZE_64x64; | ||
503 | break; | ||
504 | |||
505 | case 128: | ||
506 | value |= CURSOR_SIZE_128x128; | ||
507 | |||
508 | case 256: | ||
509 | value |= CURSOR_SIZE_256x256; | ||
510 | break; | ||
511 | |||
512 | default: | ||
513 | return -EINVAL; | ||
514 | } | ||
515 | |||
516 | if (handle) { | ||
517 | gem = drm_gem_object_lookup(crtc->dev, file, handle); | ||
518 | if (!gem) | ||
519 | return -ENOENT; | ||
520 | |||
521 | bo = to_tegra_bo(gem); | ||
522 | } | ||
523 | |||
524 | if (bo) { | ||
525 | unsigned long addr = (bo->paddr & 0xfffffc00) >> 10; | ||
526 | #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT | ||
527 | unsigned long high = (bo->paddr & 0xfffffffc) >> 32; | ||
528 | #endif | ||
529 | |||
530 | tegra_dc_writel(dc, value | addr, DC_DISP_CURSOR_START_ADDR); | ||
531 | |||
532 | #ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT | ||
533 | tegra_dc_writel(dc, high, DC_DISP_CURSOR_START_ADDR_HI); | ||
534 | #endif | ||
535 | |||
536 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
537 | value |= CURSOR_ENABLE; | ||
538 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
539 | |||
540 | value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL); | ||
541 | value &= ~CURSOR_DST_BLEND_MASK; | ||
542 | value &= ~CURSOR_SRC_BLEND_MASK; | ||
543 | value |= CURSOR_MODE_NORMAL; | ||
544 | value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC; | ||
545 | value |= CURSOR_SRC_BLEND_K1_TIMES_SRC; | ||
546 | value |= CURSOR_ALPHA; | ||
547 | tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL); | ||
548 | } else { | ||
549 | value = tegra_dc_readl(dc, DC_DISP_DISP_WIN_OPTIONS); | ||
550 | value &= ~CURSOR_ENABLE; | ||
551 | tegra_dc_writel(dc, value, DC_DISP_DISP_WIN_OPTIONS); | ||
552 | } | ||
553 | |||
554 | tegra_dc_writel(dc, CURSOR_ACT_REQ << 8, DC_CMD_STATE_CONTROL); | ||
555 | tegra_dc_writel(dc, CURSOR_ACT_REQ, DC_CMD_STATE_CONTROL); | ||
556 | |||
557 | tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); | ||
558 | tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); | ||
559 | |||
560 | return 0; | ||
561 | } | ||
562 | |||
563 | static int tegra_dc_cursor_move(struct drm_crtc *crtc, int x, int y) | ||
564 | { | ||
565 | struct tegra_dc *dc = to_tegra_dc(crtc); | ||
566 | unsigned long value; | ||
567 | |||
568 | if (!dc->soc->supports_cursor) | ||
569 | return -ENXIO; | ||
570 | |||
571 | value = ((y & 0x3fff) << 16) | (x & 0x3fff); | ||
572 | tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION); | ||
573 | |||
574 | tegra_dc_writel(dc, CURSOR_ACT_REQ << 8, DC_CMD_STATE_CONTROL); | ||
575 | tegra_dc_writel(dc, CURSOR_ACT_REQ, DC_CMD_STATE_CONTROL); | ||
576 | |||
577 | /* XXX: only required on generations earlier than Tegra124? */ | ||
578 | tegra_dc_writel(dc, GENERAL_ACT_REQ << 8, DC_CMD_STATE_CONTROL); | ||
579 | tegra_dc_writel(dc, GENERAL_ACT_REQ, DC_CMD_STATE_CONTROL); | ||
580 | |||
581 | return 0; | ||
582 | } | ||
583 | |||
480 | static void tegra_dc_finish_page_flip(struct tegra_dc *dc) | 584 | static void tegra_dc_finish_page_flip(struct tegra_dc *dc) |
481 | { | 585 | { |
482 | struct drm_device *drm = dc->base.dev; | 586 | struct drm_device *drm = dc->base.dev; |
@@ -553,6 +657,8 @@ static void tegra_dc_destroy(struct drm_crtc *crtc) | |||
553 | } | 657 | } |
554 | 658 | ||
555 | static const struct drm_crtc_funcs tegra_crtc_funcs = { | 659 | static const struct drm_crtc_funcs tegra_crtc_funcs = { |
660 | .cursor_set2 = tegra_dc_cursor_set2, | ||
661 | .cursor_move = tegra_dc_cursor_move, | ||
556 | .page_flip = tegra_dc_page_flip, | 662 | .page_flip = tegra_dc_page_flip, |
557 | .set_config = drm_crtc_helper_set_config, | 663 | .set_config = drm_crtc_helper_set_config, |
558 | .destroy = tegra_dc_destroy, | 664 | .destroy = tegra_dc_destroy, |
@@ -999,6 +1105,8 @@ static int tegra_dc_show_regs(struct seq_file *s, void *data) | |||
999 | DUMP_REG(DC_DISP_SD_BL_CONTROL); | 1105 | DUMP_REG(DC_DISP_SD_BL_CONTROL); |
1000 | DUMP_REG(DC_DISP_SD_HW_K_VALUES); | 1106 | DUMP_REG(DC_DISP_SD_HW_K_VALUES); |
1001 | DUMP_REG(DC_DISP_SD_MAN_K_VALUES); | 1107 | DUMP_REG(DC_DISP_SD_MAN_K_VALUES); |
1108 | DUMP_REG(DC_DISP_CURSOR_START_ADDR_HI); | ||
1109 | DUMP_REG(DC_DISP_BLEND_CURSOR_CONTROL); | ||
1002 | DUMP_REG(DC_WIN_WIN_OPTIONS); | 1110 | DUMP_REG(DC_WIN_WIN_OPTIONS); |
1003 | DUMP_REG(DC_WIN_BYTE_SWAP); | 1111 | DUMP_REG(DC_WIN_BYTE_SWAP); |
1004 | DUMP_REG(DC_WIN_BUFFER_CONTROL); | 1112 | DUMP_REG(DC_WIN_BUFFER_CONTROL); |
@@ -1168,14 +1276,17 @@ static const struct host1x_client_ops dc_client_ops = { | |||
1168 | 1276 | ||
1169 | static const struct tegra_dc_soc_info tegra20_dc_soc_info = { | 1277 | static const struct tegra_dc_soc_info tegra20_dc_soc_info = { |
1170 | .supports_interlacing = false, | 1278 | .supports_interlacing = false, |
1279 | .supports_cursor = false, | ||
1171 | }; | 1280 | }; |
1172 | 1281 | ||
1173 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { | 1282 | static const struct tegra_dc_soc_info tegra30_dc_soc_info = { |
1174 | .supports_interlacing = false, | 1283 | .supports_interlacing = false, |
1284 | .supports_cursor = false, | ||
1175 | }; | 1285 | }; |
1176 | 1286 | ||
1177 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { | 1287 | static const struct tegra_dc_soc_info tegra124_dc_soc_info = { |
1178 | .supports_interlacing = true, | 1288 | .supports_interlacing = true, |
1289 | .supports_cursor = true, | ||
1179 | }; | 1290 | }; |
1180 | 1291 | ||
1181 | static const struct of_device_id tegra_dc_of_match[] = { | 1292 | static const struct of_device_id tegra_dc_of_match[] = { |
diff --git a/drivers/gpu/drm/tegra/dc.h b/drivers/gpu/drm/tegra/dc.h index 44e31aefe899..78c5feff95d2 100644 --- a/drivers/gpu/drm/tegra/dc.h +++ b/drivers/gpu/drm/tegra/dc.h | |||
@@ -67,10 +67,12 @@ | |||
67 | #define WIN_A_ACT_REQ (1 << 1) | 67 | #define WIN_A_ACT_REQ (1 << 1) |
68 | #define WIN_B_ACT_REQ (1 << 2) | 68 | #define WIN_B_ACT_REQ (1 << 2) |
69 | #define WIN_C_ACT_REQ (1 << 3) | 69 | #define WIN_C_ACT_REQ (1 << 3) |
70 | #define CURSOR_ACT_REQ (1 << 7) | ||
70 | #define GENERAL_UPDATE (1 << 8) | 71 | #define GENERAL_UPDATE (1 << 8) |
71 | #define WIN_A_UPDATE (1 << 9) | 72 | #define WIN_A_UPDATE (1 << 9) |
72 | #define WIN_B_UPDATE (1 << 10) | 73 | #define WIN_B_UPDATE (1 << 10) |
73 | #define WIN_C_UPDATE (1 << 11) | 74 | #define WIN_C_UPDATE (1 << 11) |
75 | #define CURSOR_UPDATE (1 << 15) | ||
74 | #define NC_HOST_TRIG (1 << 24) | 76 | #define NC_HOST_TRIG (1 << 24) |
75 | 77 | ||
76 | #define DC_CMD_DISPLAY_WINDOW_HEADER 0x042 | 78 | #define DC_CMD_DISPLAY_WINDOW_HEADER 0x042 |
@@ -116,9 +118,10 @@ | |||
116 | #define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401 | 118 | #define DC_DISP_DISP_SIGNAL_OPTIONS1 0x401 |
117 | 119 | ||
118 | #define DC_DISP_DISP_WIN_OPTIONS 0x402 | 120 | #define DC_DISP_DISP_WIN_OPTIONS 0x402 |
119 | #define HDMI_ENABLE (1 << 30) | 121 | #define HDMI_ENABLE (1 << 30) |
120 | #define DSI_ENABLE (1 << 29) | 122 | #define DSI_ENABLE (1 << 29) |
121 | #define SOR_ENABLE (1 << 25) | 123 | #define SOR_ENABLE (1 << 25) |
124 | #define CURSOR_ENABLE (1 << 16) | ||
122 | 125 | ||
123 | #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 | 126 | #define DC_DISP_DISP_MEM_HIGH_PRIORITY 0x403 |
124 | #define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) | 127 | #define CURSOR_THRESHOLD(x) (((x) & 0x03) << 24) |
@@ -266,6 +269,14 @@ | |||
266 | #define DC_DISP_CURSOR_BACKGROUND 0x43d | 269 | #define DC_DISP_CURSOR_BACKGROUND 0x43d |
267 | 270 | ||
268 | #define DC_DISP_CURSOR_START_ADDR 0x43e | 271 | #define DC_DISP_CURSOR_START_ADDR 0x43e |
272 | #define CURSOR_CLIP_DISPLAY (0 << 28) | ||
273 | #define CURSOR_CLIP_WIN_A (1 << 28) | ||
274 | #define CURSOR_CLIP_WIN_B (2 << 28) | ||
275 | #define CURSOR_CLIP_WIN_C (3 << 28) | ||
276 | #define CURSOR_SIZE_32x32 (0 << 24) | ||
277 | #define CURSOR_SIZE_64x64 (1 << 24) | ||
278 | #define CURSOR_SIZE_128x128 (2 << 24) | ||
279 | #define CURSOR_SIZE_256x256 (3 << 24) | ||
269 | #define DC_DISP_CURSOR_START_ADDR_NS 0x43f | 280 | #define DC_DISP_CURSOR_START_ADDR_NS 0x43f |
270 | 281 | ||
271 | #define DC_DISP_CURSOR_POSITION 0x440 | 282 | #define DC_DISP_CURSOR_POSITION 0x440 |
@@ -302,6 +313,19 @@ | |||
302 | #define INTERLACE_START (1 << 1) | 313 | #define INTERLACE_START (1 << 1) |
303 | #define INTERLACE_ENABLE (1 << 0) | 314 | #define INTERLACE_ENABLE (1 << 0) |
304 | 315 | ||
316 | #define DC_DISP_CURSOR_START_ADDR_HI 0x4ec | ||
317 | #define DC_DISP_BLEND_CURSOR_CONTROL 0x4f1 | ||
318 | #define CURSOR_MODE_LEGACY (0 << 24) | ||
319 | #define CURSOR_MODE_NORMAL (1 << 24) | ||
320 | #define CURSOR_DST_BLEND_ZERO (0 << 16) | ||
321 | #define CURSOR_DST_BLEND_K1 (1 << 16) | ||
322 | #define CURSOR_DST_BLEND_NEG_K1_TIMES_SRC (2 << 16) | ||
323 | #define CURSOR_DST_BLEND_MASK (3 << 16) | ||
324 | #define CURSOR_SRC_BLEND_K1 (0 << 8) | ||
325 | #define CURSOR_SRC_BLEND_K1_TIMES_SRC (1 << 8) | ||
326 | #define CURSOR_SRC_BLEND_MASK (3 << 8) | ||
327 | #define CURSOR_ALPHA 0xff | ||
328 | |||
305 | #define DC_WIN_CSC_YOF 0x611 | 329 | #define DC_WIN_CSC_YOF 0x611 |
306 | #define DC_WIN_CSC_KYRGB 0x612 | 330 | #define DC_WIN_CSC_KYRGB 0x612 |
307 | #define DC_WIN_CSC_KUR 0x613 | 331 | #define DC_WIN_CSC_KUR 0x613 |