Skip to content

Commit

Permalink
Merge tag 'drm/tegra/for-4.17-rc1' of git://anongit.freedesktop.org/t…
Browse files Browse the repository at this point in the history
…egra/linux into drm-next

drm/tegra: Changes for v4.17-rc1

This fixes mmap() for fbdev devices by providing a custom implementation
based on the KMS variant. This is a fairly exotic case these days, hence
why it is not flagged for stable.

There is also support for dedicating one of the overlay planes to serve
as a hardware cursor on older Tegra that did support hardware cursors
but not RGBA formats for it.

Planes will now also export the IN_FORMATS property by supporting the
various block-linear tiling modifiers for RGBA pixel formats.

Other than that, there's a bit of cleanup of DMA API abuse, use of the
private object infrastructure for global state (rather than subclassing
atomic state objects) and an implementation of ->{begin,end}_cpu_access
callbacks for PRIME exported buffers, which allow users to perform cache
maintenance on these buffers.

* tag 'drm/tegra/for-4.17-rc1' of git://anongit.freedesktop.org/tegra/linux:
  drm/tegra: prime: Implement ->{begin,end}_cpu_access()
  drm/tegra: gem: Map pages via the DMA API
  drm/tegra: hub: Use private object for global state
  drm/tegra: fb: Properly support linear modifier
  drm/tegra: plane: Support format modifiers
  drm/tegra: dc: Dedicate overlay plane to cursor on older Tegra's
  drm/tegra: plane: Make tegra_plane_get_overlap_index() static
  drm/tegra: fb: Implement ->fb_mmap() callback
  drm/tegra: gem: Make __tegra_gem_mmap() available more widely
  drm/tegra: gem: Reshuffle declarations
  • Loading branch information
Dave Airlie committed Mar 21, 2018
2 parents 4f6dd8d + 27e92f1 commit 19c800c
Show file tree
Hide file tree
Showing 10 changed files with 280 additions and 114 deletions.
82 changes: 50 additions & 32 deletions drivers/gpu/drm/tegra/dc.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,12 @@ static const u32 tegra20_primary_formats[] = {
DRM_FORMAT_XRGB8888,
};

static const u64 tegra20_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED,
DRM_FORMAT_MOD_INVALID
};

static const u32 tegra114_primary_formats[] = {
DRM_FORMAT_ARGB4444,
DRM_FORMAT_ARGB1555,
Expand Down Expand Up @@ -430,6 +436,17 @@ static const u32 tegra124_primary_formats[] = {
DRM_FORMAT_BGRX8888,
};

static const u64 tegra124_modifiers[] = {
DRM_FORMAT_MOD_LINEAR,
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(0),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(1),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(2),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(3),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(4),
DRM_FORMAT_MOD_NVIDIA_16BX2_BLOCK(5),
DRM_FORMAT_MOD_INVALID
};

static int tegra_plane_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
Expand Down Expand Up @@ -596,6 +613,7 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,
enum drm_plane_type type = DRM_PLANE_TYPE_PRIMARY;
struct tegra_plane *plane;
unsigned int num_formats;
const u64 *modifiers;
const u32 *formats;
int err;

Expand All @@ -610,10 +628,11 @@ static struct drm_plane *tegra_primary_plane_create(struct drm_device *drm,

num_formats = dc->soc->num_primary_formats;
formats = dc->soc->primary_formats;
modifiers = dc->soc->modifiers;

err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
&tegra_plane_funcs, formats,
num_formats, NULL, type, NULL);
num_formats, modifiers, type, NULL);
if (err < 0) {
kfree(plane);
return ERR_PTR(err);
Expand Down Expand Up @@ -864,11 +883,13 @@ static const u32 tegra124_overlay_formats[] = {

static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
struct tegra_dc *dc,
unsigned int index)
unsigned int index,
bool cursor)
{
unsigned long possible_crtcs = tegra_plane_get_possible_crtcs(drm);
struct tegra_plane *plane;
unsigned int num_formats;
enum drm_plane_type type;
const u32 *formats;
int err;

Expand All @@ -883,10 +904,14 @@ static struct drm_plane *tegra_dc_overlay_plane_create(struct drm_device *drm,
num_formats = dc->soc->num_overlay_formats;
formats = dc->soc->overlay_formats;

if (!cursor)
type = DRM_PLANE_TYPE_OVERLAY;
else
type = DRM_PLANE_TYPE_CURSOR;

err = drm_universal_plane_init(drm, &plane->base, possible_crtcs,
&tegra_plane_funcs, formats,
num_formats, NULL,
DRM_PLANE_TYPE_OVERLAY, NULL);
num_formats, NULL, type, NULL);
if (err < 0) {
kfree(plane);
return ERR_PTR(err);
Expand Down Expand Up @@ -938,15 +963,22 @@ static struct drm_plane *tegra_dc_add_planes(struct drm_device *drm,
struct tegra_dc *dc)
{
struct drm_plane *planes[2], *primary;
unsigned int planes_num;
unsigned int i;
int err;

primary = tegra_primary_plane_create(drm, dc);
if (IS_ERR(primary))
return primary;

for (i = 0; i < 2; i++) {
planes[i] = tegra_dc_overlay_plane_create(drm, dc, 1 + i);
if (dc->soc->supports_cursor)
planes_num = 2;
else
planes_num = 1;

for (i = 0; i < planes_num; i++) {
planes[i] = tegra_dc_overlay_plane_create(drm, dc, 1 + i,
false);
if (IS_ERR(planes[i])) {
err = PTR_ERR(planes[i]);

Expand Down Expand Up @@ -1704,31 +1736,6 @@ static void tegra_crtc_atomic_enable(struct drm_crtc *crtc,
drm_crtc_vblank_on(crtc);
}

static int tegra_crtc_atomic_check(struct drm_crtc *crtc,
struct drm_crtc_state *state)
{
struct tegra_atomic_state *s = to_tegra_atomic_state(state->state);
struct tegra_dc_state *tegra = to_dc_state(state);

/*
* The display hub display clock needs to be fed by the display clock
* with the highest frequency to ensure proper functioning of all the
* displays.
*
* Note that this isn't used before Tegra186, but it doesn't hurt and
* conditionalizing it would make the code less clean.
*/
if (state->active) {
if (!s->clk_disp || tegra->pclk > s->rate) {
s->dc = to_tegra_dc(crtc);
s->clk_disp = s->dc->clk;
s->rate = tegra->pclk;
}
}

return 0;
}

static void tegra_crtc_atomic_begin(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
Expand Down Expand Up @@ -1765,7 +1772,6 @@ static void tegra_crtc_atomic_flush(struct drm_crtc *crtc,
}

static const struct drm_crtc_helper_funcs tegra_crtc_helper_funcs = {
.atomic_check = tegra_crtc_atomic_check,
.atomic_begin = tegra_crtc_atomic_begin,
.atomic_flush = tegra_crtc_atomic_flush,
.atomic_enable = tegra_crtc_atomic_enable,
Expand Down Expand Up @@ -1864,6 +1870,13 @@ static int tegra_dc_init(struct host1x_client *client)
err = PTR_ERR(cursor);
goto cleanup;
}
} else {
/* dedicate one overlay to mouse cursor */
cursor = tegra_dc_overlay_plane_create(drm, dc, 2, true);
if (IS_ERR(cursor)) {
err = PTR_ERR(cursor);
goto cleanup;
}
}

err = drm_crtc_init_with_planes(drm, &dc->base, primary, cursor,
Expand Down Expand Up @@ -1954,6 +1967,7 @@ static const struct tegra_dc_soc_info tegra20_dc_soc_info = {
.primary_formats = tegra20_primary_formats,
.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
.overlay_formats = tegra20_overlay_formats,
.modifiers = tegra20_modifiers,
};

static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
Expand All @@ -1970,6 +1984,7 @@ static const struct tegra_dc_soc_info tegra30_dc_soc_info = {
.primary_formats = tegra20_primary_formats,
.num_overlay_formats = ARRAY_SIZE(tegra20_overlay_formats),
.overlay_formats = tegra20_overlay_formats,
.modifiers = tegra20_modifiers,
};

static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
Expand All @@ -1986,6 +2001,7 @@ static const struct tegra_dc_soc_info tegra114_dc_soc_info = {
.primary_formats = tegra114_primary_formats,
.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
.overlay_formats = tegra114_overlay_formats,
.modifiers = tegra20_modifiers,
};

static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
Expand All @@ -2002,6 +2018,7 @@ static const struct tegra_dc_soc_info tegra124_dc_soc_info = {
.primary_formats = tegra114_primary_formats,
.num_overlay_formats = ARRAY_SIZE(tegra124_overlay_formats),
.overlay_formats = tegra114_overlay_formats,
.modifiers = tegra124_modifiers,
};

static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
Expand All @@ -2018,6 +2035,7 @@ static const struct tegra_dc_soc_info tegra210_dc_soc_info = {
.primary_formats = tegra114_primary_formats,
.num_overlay_formats = ARRAY_SIZE(tegra114_overlay_formats),
.overlay_formats = tegra114_overlay_formats,
.modifiers = tegra124_modifiers,
};

static const struct tegra_windowgroup_soc tegra186_dc_wgrps[] = {
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/tegra/dc.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ struct tegra_dc_soc_info {
unsigned int num_primary_formats;
const u32 *overlay_formats;
unsigned int num_overlay_formats;
const u64 *modifiers;
};

struct tegra_dc {
Expand Down
36 changes: 4 additions & 32 deletions drivers/gpu/drm/tegra/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ static int tegra_atomic_check(struct drm_device *drm,
if (err < 0)
return err;

err = tegra_display_hub_atomic_check(drm, state);
if (err < 0)
return err;

err = drm_atomic_normalize_zpos(drm, state);
if (err < 0)
return err;
Expand All @@ -56,45 +60,13 @@ static int tegra_atomic_check(struct drm_device *drm,
return 0;
}

static struct drm_atomic_state *
tegra_atomic_state_alloc(struct drm_device *drm)
{
struct tegra_atomic_state *state = kzalloc(sizeof(*state), GFP_KERNEL);

if (!state || drm_atomic_state_init(drm, &state->base) < 0) {
kfree(state);
return NULL;
}

return &state->base;
}

static void tegra_atomic_state_clear(struct drm_atomic_state *state)
{
struct tegra_atomic_state *tegra = to_tegra_atomic_state(state);

drm_atomic_state_default_clear(state);
tegra->clk_disp = NULL;
tegra->dc = NULL;
tegra->rate = 0;
}

static void tegra_atomic_state_free(struct drm_atomic_state *state)
{
drm_atomic_state_default_release(state);
kfree(state);
}

static const struct drm_mode_config_funcs tegra_drm_mode_config_funcs = {
.fb_create = tegra_fb_create,
#ifdef CONFIG_DRM_FBDEV_EMULATION
.output_poll_changed = drm_fb_helper_output_poll_changed,
#endif
.atomic_check = tegra_atomic_check,
.atomic_commit = drm_atomic_helper_commit,
.atomic_state_alloc = tegra_atomic_state_alloc,
.atomic_state_clear = tegra_atomic_state_clear,
.atomic_state_free = tegra_atomic_state_free,
};

static void tegra_atomic_commit_tail(struct drm_atomic_state *old_state)
Expand Down
14 changes: 0 additions & 14 deletions drivers/gpu/drm/tegra/drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,6 @@ struct tegra_fbdev {
};
#endif

struct tegra_atomic_state {
struct drm_atomic_state base;

struct clk *clk_disp;
struct tegra_dc *dc;
unsigned long rate;
};

static inline struct tegra_atomic_state *
to_tegra_atomic_state(struct drm_atomic_state *state)
{
return container_of(state, struct tegra_atomic_state, base);
}

struct tegra_drm {
struct drm_device *drm;

Expand Down
25 changes: 22 additions & 3 deletions drivers/gpu/drm/tegra/fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
uint64_t modifier = fb->base.modifier;

switch (modifier) {
case DRM_FORMAT_MOD_LINEAR:
tiling->mode = TEGRA_BO_TILING_MODE_PITCH;
tiling->value = 0;
break;

case DRM_FORMAT_MOD_NVIDIA_TEGRA_TILED:
tiling->mode = TEGRA_BO_TILING_MODE_TILED;
tiling->value = 0;
Expand Down Expand Up @@ -91,9 +96,7 @@ int tegra_fb_get_tiling(struct drm_framebuffer *framebuffer,
break;

default:
/* TODO: handle YUV formats? */
*tiling = fb->planes[0]->tiling;
break;
return -EINVAL;
}

return 0;
Expand Down Expand Up @@ -224,12 +227,28 @@ struct drm_framebuffer *tegra_fb_create(struct drm_device *drm,
}

#ifdef CONFIG_DRM_FBDEV_EMULATION
static int tegra_fb_mmap(struct fb_info *info, struct vm_area_struct *vma)
{
struct drm_fb_helper *helper = info->par;
struct tegra_bo *bo;
int err;

bo = tegra_fb_get_plane(helper->fb, 0);

err = drm_gem_mmap_obj(&bo->gem, bo->gem.size, vma);
if (err < 0)
return err;

return __tegra_gem_mmap(&bo->gem, vma);
}

static struct fb_ops tegra_fb_ops = {
.owner = THIS_MODULE,
DRM_FB_HELPER_DEFAULT_OPS,
.fb_fillrect = drm_fb_helper_sys_fillrect,
.fb_copyarea = drm_fb_helper_sys_copyarea,
.fb_imageblit = drm_fb_helper_sys_imageblit,
.fb_mmap = tegra_fb_mmap,
};

static int tegra_fbdev_probe(struct drm_fb_helper *helper,
Expand Down
Loading

0 comments on commit 19c800c

Please sign in to comment.