Skip to content

Commit 12fc11b

Browse files
committed
Merge tag 'drm/tegra/for-5.13-rc1' of ssh://git.freedesktop.org/git/tegra/linux into drm-next
drm/tegra: Changes for v5.13-rc1 The changes this time around contain a couple of fixes for host1x along with some improvements for Tegra DRM. Most notably the Tegra DRM driver now supports the hardware cursor on Tegra186 and later, more correctly reflects the capabilities of the display pipelines on various Tegra SoC generations and knows how to deal with the dGPU sector layout by using framebuffer modifiers. Signed-off-by: Dave Airlie <[email protected]> From: Thierry Reding <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
2 parents a1a1ca7 + 7b6f846 commit 12fc11b

File tree

27 files changed

+460
-150
lines changed

27 files changed

+460
-150
lines changed

drivers/gpu/drm/tegra/dc.c

Lines changed: 103 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -832,10 +832,14 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
832832
return &plane->base;
833833
}
834834

835-
static const u32 tegra_cursor_plane_formats[] = {
835+
static const u32 tegra_legacy_cursor_plane_formats[] = {
836836
DRM_FORMAT_RGBA8888,
837837
};
838838

839+
static const u32 tegra_cursor_plane_formats[] = {
840+
DRM_FORMAT_ARGB8888,
841+
};
842+
839843
static int tegra_cursor_atomic_check(struct drm_plane *plane,
840844
struct drm_atomic_state *state)
841845
{
@@ -875,12 +879,24 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
875879
plane);
876880
struct tegra_plane_state *tegra_plane_state = to_tegra_plane_state(new_state);
877881
struct tegra_dc *dc = to_tegra_dc(new_state->crtc);
878-
u32 value = CURSOR_CLIP_DISPLAY;
882+
struct tegra_drm *tegra = plane->dev->dev_private;
883+
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
884+
u64 dma_mask = *dc->dev->dma_mask;
885+
#endif
886+
unsigned int x, y;
887+
u32 value = 0;
879888

880889
/* rien ne va plus */
881890
if (!new_state->crtc || !new_state->fb)
882891
return;
883892

893+
/*
894+
* Legacy display supports hardware clipping of the cursor, but
895+
* nvdisplay relies on software to clip the cursor to the screen.
896+
*/
897+
if (!dc->soc->has_nvdisplay)
898+
value |= CURSOR_CLIP_DISPLAY;
899+
884900
switch (new_state->crtc_w) {
885901
case 32:
886902
value |= CURSOR_SIZE_32x32;
@@ -908,7 +924,7 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
908924
tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR);
909925

910926
#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
911-
value = (tegra_plane_state->iova[0] >> 32) & 0x3;
927+
value = (tegra_plane_state->iova[0] >> 32) & (dma_mask >> 32);
912928
tegra_dc_writel(dc, value, DC_DISP_CURSOR_START_ADDR_HI);
913929
#endif
914930

@@ -920,15 +936,39 @@ static void tegra_cursor_atomic_update(struct drm_plane *plane,
920936
value = tegra_dc_readl(dc, DC_DISP_BLEND_CURSOR_CONTROL);
921937
value &= ~CURSOR_DST_BLEND_MASK;
922938
value &= ~CURSOR_SRC_BLEND_MASK;
923-
value |= CURSOR_MODE_NORMAL;
939+
940+
if (dc->soc->has_nvdisplay)
941+
value &= ~CURSOR_COMPOSITION_MODE_XOR;
942+
else
943+
value |= CURSOR_MODE_NORMAL;
944+
924945
value |= CURSOR_DST_BLEND_NEG_K1_TIMES_SRC;
925946
value |= CURSOR_SRC_BLEND_K1_TIMES_SRC;
926947
value |= CURSOR_ALPHA;
927948
tegra_dc_writel(dc, value, DC_DISP_BLEND_CURSOR_CONTROL);
928949

950+
/* nvdisplay relies on software for clipping */
951+
if (dc->soc->has_nvdisplay) {
952+
struct drm_rect src;
953+
954+
x = new_state->dst.x1;
955+
y = new_state->dst.y1;
956+
957+
drm_rect_fp_to_int(&src, &new_state->src);
958+
959+
value = (src.y1 & tegra->vmask) << 16 | (src.x1 & tegra->hmask);
960+
tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR);
961+
962+
value = (drm_rect_height(&src) & tegra->vmask) << 16 |
963+
(drm_rect_width(&src) & tegra->hmask);
964+
tegra_dc_writel(dc, value, DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR);
965+
} else {
966+
x = new_state->crtc_x;
967+
y = new_state->crtc_y;
968+
}
969+
929970
/* position the cursor */
930-
value = (new_state->crtc_y & 0x3fff) << 16 |
931-
(new_state->crtc_x & 0x3fff);
971+
value = ((y & tegra->vmask) << 16) | (x & tegra->hmask);
932972
tegra_dc_writel(dc, value, DC_DISP_CURSOR_POSITION);
933973
}
934974

@@ -982,8 +1022,13 @@ static struct drm_plane *tegra_dc_cursor_plane_create(struct drm_device *drm,
9821022
plane->index = 6;
9831023
plane->dc = dc;
9841024

985-
num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
986-
formats = tegra_cursor_plane_formats;
1025+
if (!dc->soc->has_nvdisplay) {
1026+
num_formats = ARRAY_SIZE(tegra_legacy_cursor_plane_formats);
1027+
formats = tegra_legacy_cursor_plane_formats;
1028+
} else {
1029+
num_formats = ARRAY_SIZE(tegra_cursor_plane_formats);
1030+
formats = tegra_cursor_plane_formats;
1031+
}
9871032

9881033
err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
9891034
&tegra_plane_funcs, formats,
@@ -2035,6 +2080,16 @@ static bool tegra_dc_has_window_groups(struct tegra_dc *dc)
20352080
return false;
20362081
}
20372082

2083+
static int tegra_dc_early_init(struct host1x_client *client)
2084+
{
2085+
struct drm_device *drm = dev_get_drvdata(client->host);
2086+
struct tegra_drm *tegra = drm->dev_private;
2087+
2088+
tegra->num_crtcs++;
2089+
2090+
return 0;
2091+
}
2092+
20382093
static int tegra_dc_init(struct host1x_client *client)
20392094
{
20402095
struct drm_device *drm = dev_get_drvdata(client->host);
@@ -2045,6 +2100,12 @@ static int tegra_dc_init(struct host1x_client *client)
20452100
struct drm_plane *cursor = NULL;
20462101
int err;
20472102

2103+
/*
2104+
* DC has been reset by now, so VBLANK syncpoint can be released
2105+
* for general use.
2106+
*/
2107+
host1x_syncpt_release_vblank_reservation(client, 26 + dc->pipe);
2108+
20482109
/*
20492110
* XXX do not register DCs with no window groups because we cannot
20502111
* assign a primary plane to them, which in turn will cause KMS to
@@ -2111,6 +2172,12 @@ static int tegra_dc_init(struct host1x_client *client)
21112172
if (dc->soc->pitch_align > tegra->pitch_align)
21122173
tegra->pitch_align = dc->soc->pitch_align;
21132174

2175+
/* track maximum resolution */
2176+
if (dc->soc->has_nvdisplay)
2177+
drm->mode_config.max_width = drm->mode_config.max_height = 16384;
2178+
else
2179+
drm->mode_config.max_width = drm->mode_config.max_height = 4096;
2180+
21142181
err = tegra_dc_rgb_init(drm, dc);
21152182
if (err < 0 && err != -ENODEV) {
21162183
dev_err(dc->dev, "failed to initialize RGB output: %d\n", err);
@@ -2141,7 +2208,7 @@ static int tegra_dc_init(struct host1x_client *client)
21412208
drm_plane_cleanup(primary);
21422209

21432210
host1x_client_iommu_detach(client);
2144-
host1x_syncpt_free(dc->syncpt);
2211+
host1x_syncpt_put(dc->syncpt);
21452212

21462213
return err;
21472214
}
@@ -2166,7 +2233,17 @@ static int tegra_dc_exit(struct host1x_client *client)
21662233
}
21672234

21682235
host1x_client_iommu_detach(client);
2169-
host1x_syncpt_free(dc->syncpt);
2236+
host1x_syncpt_put(dc->syncpt);
2237+
2238+
return 0;
2239+
}
2240+
2241+
static int tegra_dc_late_exit(struct host1x_client *client)
2242+
{
2243+
struct drm_device *drm = dev_get_drvdata(client->host);
2244+
struct tegra_drm *tegra = drm->dev_private;
2245+
2246+
tegra->num_crtcs--;
21702247

21712248
return 0;
21722249
}
@@ -2235,8 +2312,10 @@ static int tegra_dc_runtime_resume(struct host1x_client *client)
22352312
}
22362313

22372314
static const struct host1x_client_ops dc_client_ops = {
2315+
.early_init = tegra_dc_early_init,
22382316
.init = tegra_dc_init,
22392317
.exit = tegra_dc_exit,
2318+
.late_exit = tegra_dc_late_exit,
22402319
.suspend = tegra_dc_runtime_suspend,
22412320
.resume = tegra_dc_runtime_resume,
22422321
};
@@ -2246,6 +2325,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
22462325
.supports_interlacing = false,
22472326
.supports_cursor = false,
22482327
.supports_block_linear = false,
2328+
.supports_sector_layout = false,
22492329
.has_legacy_blending = true,
22502330
.pitch_align = 8,
22512331
.has_powergate = false,
@@ -2265,6 +2345,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
22652345
.supports_interlacing = false,
22662346
.supports_cursor = false,
22672347
.supports_block_linear = false,
2348+
.supports_sector_layout = false,
22682349
.has_legacy_blending = true,
22692350
.pitch_align = 8,
22702351
.has_powergate = false,
@@ -2284,6 +2365,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
22842365
.supports_interlacing = false,
22852366
.supports_cursor = false,
22862367
.supports_block_linear = false,
2368+
.supports_sector_layout = false,
22872369
.has_legacy_blending = true,
22882370
.pitch_align = 64,
22892371
.has_powergate = true,
@@ -2303,6 +2385,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
23032385
.supports_interlacing = true,
23042386
.supports_cursor = true,
23052387
.supports_block_linear = true,
2388+
.supports_sector_layout = false,
23062389
.has_legacy_blending = false,
23072390
.pitch_align = 64,
23082391
.has_powergate = true,
@@ -2322,6 +2405,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
23222405
.supports_interlacing = true,
23232406
.supports_cursor = true,
23242407
.supports_block_linear = true,
2408+
.supports_sector_layout = false,
23252409
.has_legacy_blending = false,
23262410
.pitch_align = 64,
23272411
.has_powergate = true,
@@ -2375,6 +2459,7 @@ static const struct tegra_dc_soc_info tegra186_dc_soc_info = {
23752459
.supports_interlacing = true,
23762460
.supports_cursor = true,
23772461
.supports_block_linear = true,
2462+
.supports_sector_layout = false,
23782463
.has_legacy_blending = false,
23792464
.pitch_align = 64,
23802465
.has_powergate = false,
@@ -2423,6 +2508,7 @@ static const struct tegra_dc_soc_info tegra194_dc_soc_info = {
24232508
.supports_interlacing = true,
24242509
.supports_cursor = true,
24252510
.supports_block_linear = true,
2511+
.supports_sector_layout = true,
24262512
.has_legacy_blending = false,
24272513
.pitch_align = 64,
24282514
.has_powergate = false,
@@ -2532,9 +2618,16 @@ static int tegra_dc_couple(struct tegra_dc *dc)
25322618

25332619
static int tegra_dc_probe(struct platform_device *pdev)
25342620
{
2621+
u64 dma_mask = dma_get_mask(pdev->dev.parent);
25352622
struct tegra_dc *dc;
25362623
int err;
25372624

2625+
err = dma_coerce_mask_and_coherent(&pdev->dev, dma_mask);
2626+
if (err < 0) {
2627+
dev_err(&pdev->dev, "failed to set DMA mask: %d\n", err);
2628+
return err;
2629+
}
2630+
25382631
dc = devm_kzalloc(&pdev->dev, sizeof(*dc), GFP_KERNEL);
25392632
if (!dc)
25402633
return -ENOMEM;

drivers/gpu/drm/tegra/dc.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct tegra_dc_soc_info {
5252
bool supports_interlacing;
5353
bool supports_cursor;
5454
bool supports_block_linear;
55+
bool supports_sector_layout;
5556
bool has_legacy_blending;
5657
unsigned int pitch_align;
5758
bool has_powergate;
@@ -511,6 +512,8 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
511512

512513
#define DC_DISP_CURSOR_START_ADDR_HI 0x4ec
513514
#define DC_DISP_BLEND_CURSOR_CONTROL 0x4f1
515+
#define CURSOR_COMPOSITION_MODE_BLEND (0 << 25)
516+
#define CURSOR_COMPOSITION_MODE_XOR (1 << 25)
514517
#define CURSOR_MODE_LEGACY (0 << 24)
515518
#define CURSOR_MODE_NORMAL (1 << 24)
516519
#define CURSOR_DST_BLEND_ZERO (0 << 16)
@@ -705,6 +708,9 @@ int tegra_dc_rgb_exit(struct tegra_dc *dc);
705708
#define PROTOCOL_MASK (0xf << 8)
706709
#define PROTOCOL_SINGLE_TMDS_A (0x1 << 8)
707710

711+
#define DC_DISP_PCALC_HEAD_SET_CROPPED_POINT_IN_CURSOR 0x442
712+
#define DC_DISP_PCALC_HEAD_SET_CROPPED_SIZE_IN_CURSOR 0x446
713+
708714
#define DC_WIN_CORE_WINDOWGROUP_SET_CONTROL 0x702
709715
#define OWNER_MASK (0xf << 0)
710716
#define OWNER(x) (((x) & 0xf) << 0)

drivers/gpu/drm/tegra/drm.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
174174
struct drm_tegra_syncpt syncpt;
175175
struct host1x *host1x = dev_get_drvdata(drm->dev->parent);
176176
struct drm_gem_object **refs;
177-
struct host1x_syncpt *sp;
177+
struct host1x_syncpt *sp = NULL;
178178
struct host1x_job *job;
179179
unsigned int num_refs;
180180
int err;
@@ -301,8 +301,8 @@ int tegra_drm_submit(struct tegra_drm_context *context,
301301
goto fail;
302302
}
303303

304-
/* check whether syncpoint ID is valid */
305-
sp = host1x_syncpt_get(host1x, syncpt.id);
304+
/* Syncpoint ref will be dropped on job release. */
305+
sp = host1x_syncpt_get_by_id(host1x, syncpt.id);
306306
if (!sp) {
307307
err = -ENOENT;
308308
goto fail;
@@ -311,7 +311,7 @@ int tegra_drm_submit(struct tegra_drm_context *context,
311311
job->is_addr_reg = context->client->ops->is_addr_reg;
312312
job->is_valid_class = context->client->ops->is_valid_class;
313313
job->syncpt_incrs = syncpt.incrs;
314-
job->syncpt_id = syncpt.id;
314+
job->syncpt = sp;
315315
job->timeout = 10000;
316316

317317
if (args->timeout && args->timeout < 10000)
@@ -383,7 +383,7 @@ static int tegra_syncpt_read(struct drm_device *drm, void *data,
383383
struct drm_tegra_syncpt_read *args = data;
384384
struct host1x_syncpt *sp;
385385

386-
sp = host1x_syncpt_get(host, args->id);
386+
sp = host1x_syncpt_get_by_id_noref(host, args->id);
387387
if (!sp)
388388
return -EINVAL;
389389

@@ -398,7 +398,7 @@ static int tegra_syncpt_incr(struct drm_device *drm, void *data,
398398
struct drm_tegra_syncpt_incr *args = data;
399399
struct host1x_syncpt *sp;
400400

401-
sp = host1x_syncpt_get(host1x, args->id);
401+
sp = host1x_syncpt_get_by_id_noref(host1x, args->id);
402402
if (!sp)
403403
return -EINVAL;
404404

@@ -412,7 +412,7 @@ static int tegra_syncpt_wait(struct drm_device *drm, void *data,
412412
struct drm_tegra_syncpt_wait *args = data;
413413
struct host1x_syncpt *sp;
414414

415-
sp = host1x_syncpt_get(host1x, args->id);
415+
sp = host1x_syncpt_get_by_id_noref(host1x, args->id);
416416
if (!sp)
417417
return -EINVAL;
418418

@@ -1121,9 +1121,8 @@ static int host1x_drm_probe(struct host1x_device *dev)
11211121

11221122
drm->mode_config.min_width = 0;
11231123
drm->mode_config.min_height = 0;
1124-
1125-
drm->mode_config.max_width = 4096;
1126-
drm->mode_config.max_height = 4096;
1124+
drm->mode_config.max_width = 0;
1125+
drm->mode_config.max_height = 0;
11271126

11281127
drm->mode_config.allow_fb_modifiers = true;
11291128

@@ -1142,6 +1141,14 @@ static int host1x_drm_probe(struct host1x_device *dev)
11421141
if (err < 0)
11431142
goto fbdev;
11441143

1144+
/*
1145+
* Now that all display controller have been initialized, the maximum
1146+
* supported resolution is known and the bitmask for horizontal and
1147+
* vertical bitfields can be computed.
1148+
*/
1149+
tegra->hmask = drm->mode_config.max_width - 1;
1150+
tegra->vmask = drm->mode_config.max_height - 1;
1151+
11451152
if (tegra->use_explicit_iommu) {
11461153
u64 carveout_start, carveout_end, gem_start, gem_end;
11471154
u64 dma_mask = dma_get_mask(&dev->dev);

drivers/gpu/drm/tegra/drm.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
#include "hub.h"
2525
#include "trace.h"
2626

27+
/* XXX move to include/uapi/drm/drm_fourcc.h? */
28+
#define DRM_FORMAT_MOD_NVIDIA_SECTOR_LAYOUT BIT(22)
29+
2730
struct reset_control;
2831

2932
#ifdef CONFIG_DRM_FBDEV_EMULATION
@@ -54,7 +57,9 @@ struct tegra_drm {
5457
struct tegra_fbdev *fbdev;
5558
#endif
5659

60+
unsigned int hmask, vmask;
5761
unsigned int pitch_align;
62+
unsigned int num_crtcs;
5863

5964
struct tegra_display_hub *hub;
6065
};

0 commit comments

Comments
 (0)