Commit c8fa1e73 authored by Benoit Parrot's avatar Benoit Parrot Committed by Tomi Valkeinen

drm/omap: introduce omap_hw_overlay

Split out the hardware overlay specifics from omap_plane.
To start, the hw overlays are statically assigned to planes.

The goal is to eventually assign hw overlays dynamically to planes
during plane->atomic_check() based on requested caps (scaling, YUV,
etc). And then perform hw overlay re-assignment if required.
Signed-off-by: default avatarBenoit Parrot <bparrot@ti.com>
Signed-off-by: default avatarNeil Armstrong <narmstrong@baylibre.com>
Reviewed-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ideasonboard.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211117141928.771082-5-narmstrong@baylibre.com
parent 0b0f7282
...@@ -9,6 +9,7 @@ omapdrm-y := omap_drv.o \ ...@@ -9,6 +9,7 @@ omapdrm-y := omap_drv.o \
omap_debugfs.o \ omap_debugfs.o \
omap_crtc.o \ omap_crtc.o \
omap_plane.o \ omap_plane.o \
omap_overlay.o \
omap_encoder.o \ omap_encoder.o \
omap_fb.o \ omap_fb.o \
omap_gem.o \ omap_gem.o \
......
...@@ -583,10 +583,14 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) ...@@ -583,10 +583,14 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
omap_gem_init(ddev); omap_gem_init(ddev);
ret = omap_hwoverlays_init(priv);
if (ret)
goto err_gem_deinit;
ret = omap_modeset_init(ddev); ret = omap_modeset_init(ddev);
if (ret) { if (ret) {
dev_err(priv->dev, "omap_modeset_init failed: ret=%d\n", ret); dev_err(priv->dev, "omap_modeset_init failed: ret=%d\n", ret);
goto err_gem_deinit; goto err_free_overlays;
} }
/* Initialize vblank handling, start with all CRTCs disabled. */ /* Initialize vblank handling, start with all CRTCs disabled. */
...@@ -618,6 +622,8 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) ...@@ -618,6 +622,8 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
omap_fbdev_fini(ddev); omap_fbdev_fini(ddev);
err_cleanup_modeset: err_cleanup_modeset:
omap_modeset_fini(ddev); omap_modeset_fini(ddev);
err_free_overlays:
omap_hwoverlays_destroy(priv);
err_gem_deinit: err_gem_deinit:
omap_gem_deinit(ddev); omap_gem_deinit(ddev);
destroy_workqueue(priv->wq); destroy_workqueue(priv->wq);
...@@ -642,6 +648,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) ...@@ -642,6 +648,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
drm_atomic_helper_shutdown(ddev); drm_atomic_helper_shutdown(ddev);
omap_modeset_fini(ddev); omap_modeset_fini(ddev);
omap_hwoverlays_destroy(priv);
omap_gem_deinit(ddev); omap_gem_deinit(ddev);
destroy_workqueue(priv->wq); destroy_workqueue(priv->wq);
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "omap_gem.h" #include "omap_gem.h"
#include "omap_irq.h" #include "omap_irq.h"
#include "omap_plane.h" #include "omap_plane.h"
#include "omap_overlay.h"
#define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__) #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
#define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) /* verbose debug */ #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt, ##__VA_ARGS__) /* verbose debug */
...@@ -57,6 +58,9 @@ struct omap_drm_private { ...@@ -57,6 +58,9 @@ struct omap_drm_private {
unsigned int num_planes; unsigned int num_planes;
struct drm_plane *planes[8]; struct drm_plane *planes[8];
unsigned int num_ovls;
struct omap_hw_overlay *overlays[8];
struct drm_fb_helper *fbdev; struct drm_fb_helper *fbdev;
struct workqueue_struct *wq; struct workqueue_struct *wq;
......
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Author: Benoit Parrot <bparrot@ti.com>
*/
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include "omap_dmm_tiler.h"
#include "omap_drv.h"
/*
* overlay funcs
*/
static const char * const overlay_id_to_name[] = {
[OMAP_DSS_GFX] = "gfx",
[OMAP_DSS_VIDEO1] = "vid1",
[OMAP_DSS_VIDEO2] = "vid2",
[OMAP_DSS_VIDEO3] = "vid3",
};
static void omap_overlay_destroy(struct omap_hw_overlay *overlay)
{
kfree(overlay);
}
static struct omap_hw_overlay *omap_overlay_init(enum omap_plane_id overlay_id,
enum omap_overlay_caps caps)
{
struct omap_hw_overlay *overlay;
overlay = kzalloc(sizeof(*overlay), GFP_KERNEL);
if (!overlay)
return ERR_PTR(-ENOMEM);
overlay->name = overlay_id_to_name[overlay_id];
overlay->id = overlay_id;
overlay->caps = caps;
return overlay;
}
int omap_hwoverlays_init(struct omap_drm_private *priv)
{
static const enum omap_plane_id hw_plane_ids[] = {
OMAP_DSS_GFX, OMAP_DSS_VIDEO1,
OMAP_DSS_VIDEO2, OMAP_DSS_VIDEO3,
};
u32 num_overlays = dispc_get_num_ovls(priv->dispc);
enum omap_overlay_caps caps;
int i, ret;
for (i = 0; i < num_overlays; i++) {
struct omap_hw_overlay *overlay;
caps = dispc_ovl_get_caps(priv->dispc, hw_plane_ids[i]);
overlay = omap_overlay_init(hw_plane_ids[i], caps);
if (IS_ERR(overlay)) {
ret = PTR_ERR(overlay);
dev_err(priv->dev, "failed to construct overlay for %s (%d)\n",
overlay_id_to_name[i], ret);
omap_hwoverlays_destroy(priv);
return ret;
}
overlay->idx = priv->num_ovls;
priv->overlays[priv->num_ovls++] = overlay;
}
return 0;
}
void omap_hwoverlays_destroy(struct omap_drm_private *priv)
{
int i;
for (i = 0; i < priv->num_ovls; i++) {
omap_overlay_destroy(priv->overlays[i]);
priv->overlays[i] = NULL;
}
priv->num_ovls = 0;
}
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
* Author: Benoit Parrot <bparrot@ti.com>
*/
#ifndef __OMAPDRM_OVERLAY_H__
#define __OMAPDRM_OVERLAY_H__
#include <linux/types.h>
enum drm_plane_type;
struct drm_device;
struct drm_mode_object;
struct drm_plane;
/* Used to associate a HW overlay/plane to a plane */
struct omap_hw_overlay {
unsigned int idx;
const char *name;
enum omap_plane_id id;
enum omap_overlay_caps caps;
};
int omap_hwoverlays_init(struct omap_drm_private *priv);
void omap_hwoverlays_destroy(struct omap_drm_private *priv);
#endif /* __OMAPDRM_OVERLAY_H__ */
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
struct omap_plane { struct omap_plane {
struct drm_plane base; struct drm_plane base;
enum omap_plane_id id; enum omap_plane_id id;
const char *name;
struct omap_hw_overlay *overlay;
}; };
static int omap_plane_prepare_fb(struct drm_plane *plane, static int omap_plane_prepare_fb(struct drm_plane *plane,
...@@ -49,10 +50,11 @@ static void omap_plane_atomic_update(struct drm_plane *plane, ...@@ -49,10 +50,11 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
struct omap_plane *omap_plane = to_omap_plane(plane); struct omap_plane *omap_plane = to_omap_plane(plane);
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state, struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
plane); plane);
enum omap_plane_id ovl_id = omap_plane->overlay->id;
struct omap_overlay_info info; struct omap_overlay_info info;
int ret; int ret;
DBG("%s, crtc=%p fb=%p", omap_plane->name, new_state->crtc, DBG("%s, crtc=%p fb=%p", plane->name, new_state->crtc,
new_state->fb); new_state->fb);
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
...@@ -77,17 +79,17 @@ static void omap_plane_atomic_update(struct drm_plane *plane, ...@@ -77,17 +79,17 @@ static void omap_plane_atomic_update(struct drm_plane *plane,
&info.paddr, &info.p_uv_addr); &info.paddr, &info.p_uv_addr);
/* and finally, update omapdss: */ /* and finally, update omapdss: */
ret = dispc_ovl_setup(priv->dispc, omap_plane->id, &info, ret = dispc_ovl_setup(priv->dispc, ovl_id, &info,
omap_crtc_timings(new_state->crtc), false, omap_crtc_timings(new_state->crtc), false,
omap_crtc_channel(new_state->crtc)); omap_crtc_channel(new_state->crtc));
if (ret) { if (ret) {
dev_err(plane->dev->dev, "Failed to setup plane %s\n", dev_err(plane->dev->dev, "Failed to setup plane %s\n",
omap_plane->name); plane->name);
dispc_ovl_enable(priv->dispc, omap_plane->id, false); dispc_ovl_enable(priv->dispc, ovl_id, false);
return; return;
} }
dispc_ovl_enable(priv->dispc, omap_plane->id, true); dispc_ovl_enable(priv->dispc, ovl_id, true);
} }
static void omap_plane_atomic_disable(struct drm_plane *plane, static void omap_plane_atomic_disable(struct drm_plane *plane,
...@@ -97,11 +99,12 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, ...@@ -97,11 +99,12 @@ static void omap_plane_atomic_disable(struct drm_plane *plane,
plane); plane);
struct omap_drm_private *priv = plane->dev->dev_private; struct omap_drm_private *priv = plane->dev->dev_private;
struct omap_plane *omap_plane = to_omap_plane(plane); struct omap_plane *omap_plane = to_omap_plane(plane);
enum omap_plane_id ovl_id = omap_plane->overlay->id;
new_state->rotation = DRM_MODE_ROTATE_0; new_state->rotation = DRM_MODE_ROTATE_0;
new_state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : omap_plane->id; new_state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : omap_plane->id;
dispc_ovl_enable(priv->dispc, omap_plane->id, false); dispc_ovl_enable(priv->dispc, ovl_id, false);
} }
#define FRAC_16_16(mult, div) (((mult) << 16) / (div)) #define FRAC_16_16(mult, div) (((mult) << 16) / (div))
...@@ -184,7 +187,7 @@ static void omap_plane_destroy(struct drm_plane *plane) ...@@ -184,7 +187,7 @@ static void omap_plane_destroy(struct drm_plane *plane)
{ {
struct omap_plane *omap_plane = to_omap_plane(plane); struct omap_plane *omap_plane = to_omap_plane(plane);
DBG("%s", omap_plane->name); DBG("%s", plane->name);
drm_plane_cleanup(plane); drm_plane_cleanup(plane);
...@@ -290,20 +293,6 @@ static bool omap_plane_supports_yuv(struct drm_plane *plane) ...@@ -290,20 +293,6 @@ static bool omap_plane_supports_yuv(struct drm_plane *plane)
return false; return false;
} }
static const char *plane_id_to_name[] = {
[OMAP_DSS_GFX] = "gfx",
[OMAP_DSS_VIDEO1] = "vid1",
[OMAP_DSS_VIDEO2] = "vid2",
[OMAP_DSS_VIDEO3] = "vid3",
};
static const enum omap_plane_id plane_idx_to_id[] = {
OMAP_DSS_GFX,
OMAP_DSS_VIDEO1,
OMAP_DSS_VIDEO2,
OMAP_DSS_VIDEO3,
};
/* initialize plane */ /* initialize plane */
struct drm_plane *omap_plane_init(struct drm_device *dev, struct drm_plane *omap_plane_init(struct drm_device *dev,
int idx, enum drm_plane_type type, int idx, enum drm_plane_type type,
...@@ -313,27 +302,26 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, ...@@ -313,27 +302,26 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
unsigned int num_planes = dispc_get_num_ovls(priv->dispc); unsigned int num_planes = dispc_get_num_ovls(priv->dispc);
struct drm_plane *plane; struct drm_plane *plane;
struct omap_plane *omap_plane; struct omap_plane *omap_plane;
enum omap_plane_id id;
int ret; int ret;
u32 nformats; u32 nformats;
const u32 *formats; const u32 *formats;
if (WARN_ON(idx >= ARRAY_SIZE(plane_idx_to_id))) if (WARN_ON(idx >= num_planes))
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
id = plane_idx_to_id[idx];
DBG("%s: type=%d", plane_id_to_name[id], type);
omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
if (!omap_plane) if (!omap_plane)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
formats = dispc_ovl_get_color_modes(priv->dispc, id); omap_plane->id = idx;
omap_plane->overlay = priv->overlays[idx];
DBG("%d: type=%d", omap_plane->id, type);
DBG(" crtc_mask: 0x%04x", possible_crtcs);
formats = dispc_ovl_get_color_modes(priv->dispc, omap_plane->overlay->id);
for (nformats = 0; formats[nformats]; ++nformats) for (nformats = 0; formats[nformats]; ++nformats)
; ;
omap_plane->id = id;
omap_plane->name = plane_id_to_name[id];
plane = &omap_plane->base; plane = &omap_plane->base;
...@@ -363,8 +351,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, ...@@ -363,8 +351,8 @@ struct drm_plane *omap_plane_init(struct drm_device *dev,
return plane; return plane;
error: error:
dev_err(dev->dev, "%s(): could not create plane: %s\n", dev_err(dev->dev, "%s(): could not create plane: %d\n",
__func__, plane_id_to_name[id]); __func__, omap_plane->id);
kfree(omap_plane); kfree(omap_plane);
return NULL; return NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment