aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThierry Reding <treding@nvidia.com>2013-12-20 07:58:33 -0500
committerThierry Reding <treding@nvidia.com>2014-06-05 17:14:47 -0400
commite687651bc1ed96b0ad2ee9464f341c53563b5353 (patch)
treebf0cedd7a722568042b31cb82f899cd7422f57df
parent9910f5c455de10f0eb2559093a7adad65f6c05cd (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.c111
-rw-r--r--drivers/gpu/drm/tegra/dc.h30
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
18struct tegra_dc_soc_info { 18struct tegra_dc_soc_info {
19 bool supports_interlacing; 19 bool supports_interlacing;
20 bool supports_cursor;
20}; 21};
21 22
22struct tegra_plane { 23struct 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
481static 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
563static 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
480static void tegra_dc_finish_page_flip(struct tegra_dc *dc) 584static 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
555static const struct drm_crtc_funcs tegra_crtc_funcs = { 659static 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
1169static const struct tegra_dc_soc_info tegra20_dc_soc_info = { 1277static 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
1173static const struct tegra_dc_soc_info tegra30_dc_soc_info = { 1282static 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
1177static const struct tegra_dc_soc_info tegra124_dc_soc_info = { 1287static 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
1181static const struct of_device_id tegra_dc_of_match[] = { 1292static 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