Commit 2ee76792 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Tomi Valkeinen

drm/omap: Group CRTC, encoder, connector and dssdev in a structure

Create an omap_drm_pipeline structure to model display pipelines, made
of a CRTC, an encoder, a connector and a DSS display device. This allows
grouping related parameters together instead of storing them in
independent arrays and thus improves code readability.
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: default avatarSebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
parent ac3b1318
...@@ -474,8 +474,8 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) ...@@ -474,8 +474,8 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc)
* has been changed to the DRM model. * has been changed to the DRM model.
*/ */
for (i = 0; i < priv->num_encoders; ++i) { for (i = 0; i < priv->num_pipes; ++i) {
struct drm_encoder *encoder = priv->encoders[i]; struct drm_encoder *encoder = priv->pipes[i].encoder;
if (encoder->crtc == crtc) { if (encoder->crtc == crtc) {
struct omap_dss_device *dssdev; struct omap_dss_device *dssdev;
......
...@@ -129,9 +129,9 @@ static const struct drm_mode_config_funcs omap_mode_config_funcs = { ...@@ -129,9 +129,9 @@ static const struct drm_mode_config_funcs omap_mode_config_funcs = {
.atomic_commit = drm_atomic_helper_commit, .atomic_commit = drm_atomic_helper_commit,
}; };
static int get_connector_type(struct omap_dss_device *dssdev) static int get_connector_type(struct omap_dss_device *display)
{ {
switch (dssdev->type) { switch (display->type) {
case OMAP_DISPLAY_TYPE_HDMI: case OMAP_DISPLAY_TYPE_HDMI:
return DRM_MODE_CONNECTOR_HDMIA; return DRM_MODE_CONNECTOR_HDMIA;
case OMAP_DISPLAY_TYPE_DVI: case OMAP_DISPLAY_TYPE_DVI:
...@@ -151,65 +151,65 @@ static int get_connector_type(struct omap_dss_device *dssdev) ...@@ -151,65 +151,65 @@ static int get_connector_type(struct omap_dss_device *dssdev)
} }
} }
static void omap_disconnect_dssdevs(struct drm_device *ddev) static void omap_disconnect_pipelines(struct drm_device *ddev)
{ {
struct omap_drm_private *priv = ddev->dev_private; struct omap_drm_private *priv = ddev->dev_private;
unsigned int i; unsigned int i;
for (i = 0; i < priv->num_dssdevs; i++) { for (i = 0; i < priv->num_pipes; i++) {
struct omap_dss_device *dssdev = priv->dssdevs[i]; struct omap_dss_device *display = priv->pipes[i].display;
omapdss_device_disconnect(dssdev, NULL); omapdss_device_disconnect(display, NULL);
priv->dssdevs[i] = NULL; priv->pipes[i].display = NULL;
omapdss_device_put(dssdev); omapdss_device_put(display);
} }
priv->num_dssdevs = 0; priv->num_pipes = 0;
} }
static int omap_compare_dssdevs(const void *a, const void *b) static int omap_compare_pipes(const void *a, const void *b)
{ {
const struct omap_dss_device *dssdev1 = *(struct omap_dss_device **)a; const struct omap_drm_pipeline *pipe1 = a;
const struct omap_dss_device *dssdev2 = *(struct omap_dss_device **)b; const struct omap_drm_pipeline *pipe2 = b;
if (dssdev1->alias_id > dssdev2->alias_id) if (pipe1->display->alias_id > pipe2->display->alias_id)
return 1; return 1;
else if (dssdev1->alias_id < dssdev2->alias_id) else if (pipe1->display->alias_id < pipe2->display->alias_id)
return -1; return -1;
return 0; return 0;
} }
static int omap_connect_dssdevs(struct drm_device *ddev) static int omap_connect_pipelines(struct drm_device *ddev)
{ {
struct omap_drm_private *priv = ddev->dev_private; struct omap_drm_private *priv = ddev->dev_private;
struct omap_dss_device *dssdev = NULL; struct omap_dss_device *display = NULL;
int r; int r;
if (!omapdss_stack_is_ready()) if (!omapdss_stack_is_ready())
return -EPROBE_DEFER; return -EPROBE_DEFER;
for_each_dss_display(dssdev) { for_each_dss_display(display) {
r = omapdss_device_connect(priv->dss, dssdev, NULL); r = omapdss_device_connect(priv->dss, display, NULL);
if (r == -EPROBE_DEFER) { if (r == -EPROBE_DEFER) {
omapdss_device_put(dssdev); omapdss_device_put(display);
goto cleanup; goto cleanup;
} else if (r) { } else if (r) {
dev_warn(dssdev->dev, "could not connect display: %s\n", dev_warn(display->dev, "could not connect display: %s\n",
dssdev->name); display->name);
} else { } else {
omapdss_device_get(dssdev); omapdss_device_get(display);
priv->dssdevs[priv->num_dssdevs++] = dssdev; priv->pipes[priv->num_pipes++].display = display;
if (priv->num_dssdevs == ARRAY_SIZE(priv->dssdevs)) { if (priv->num_pipes == ARRAY_SIZE(priv->pipes)) {
/* To balance the 'for_each_dss_display' loop */ /* To balance the 'for_each_dss_display' loop */
omapdss_device_put(dssdev); omapdss_device_put(display);
break; break;
} }
} }
} }
/* Sort the list by DT aliases */ /* Sort the list by DT aliases */
sort(priv->dssdevs, priv->num_dssdevs, sizeof(priv->dssdevs[0]), sort(priv->pipes, priv->num_pipes, sizeof(priv->pipes[0]),
omap_compare_dssdevs, NULL); omap_compare_pipes, NULL);
return 0; return 0;
...@@ -218,7 +218,7 @@ static int omap_connect_dssdevs(struct drm_device *ddev) ...@@ -218,7 +218,7 @@ static int omap_connect_dssdevs(struct drm_device *ddev)
* if we are deferring probe, we disconnect the devices we previously * if we are deferring probe, we disconnect the devices we previously
* connected * connected
*/ */
omap_disconnect_dssdevs(ddev); omap_disconnect_pipelines(ddev);
return r; return r;
} }
...@@ -241,7 +241,6 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -241,7 +241,6 @@ static int omap_modeset_init(struct drm_device *dev)
struct omap_drm_private *priv = dev->dev_private; struct omap_drm_private *priv = dev->dev_private;
int num_ovls = priv->dispc_ops->get_num_ovls(priv->dispc); int num_ovls = priv->dispc_ops->get_num_ovls(priv->dispc);
int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc); int num_mgrs = priv->dispc_ops->get_num_mgrs(priv->dispc);
int num_crtcs;
unsigned int i; unsigned int i;
int ret; int ret;
u32 plane_crtc_mask; u32 plane_crtc_mask;
...@@ -260,22 +259,17 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -260,22 +259,17 @@ static int omap_modeset_init(struct drm_device *dev)
* configuration does not match the expectations or exceeds * configuration does not match the expectations or exceeds
* the available resources, the configuration is rejected. * the available resources, the configuration is rejected.
*/ */
num_crtcs = priv->num_dssdevs; if (priv->num_pipes > num_mgrs || priv->num_pipes > num_ovls) {
if (num_crtcs > num_mgrs || num_crtcs > num_ovls ||
num_crtcs > ARRAY_SIZE(priv->crtcs) ||
num_crtcs > ARRAY_SIZE(priv->planes) ||
num_crtcs > ARRAY_SIZE(priv->encoders) ||
num_crtcs > ARRAY_SIZE(priv->connectors)) {
dev_err(dev->dev, "%s(): Too many connected displays\n", dev_err(dev->dev, "%s(): Too many connected displays\n",
__func__); __func__);
return -EINVAL; return -EINVAL;
} }
/* Create all planes first. They can all be put to any CRTC. */ /* Create all planes first. They can all be put to any CRTC. */
plane_crtc_mask = (1 << num_crtcs) - 1; plane_crtc_mask = (1 << priv->num_pipes) - 1;
for (i = 0; i < num_ovls; i++) { for (i = 0; i < num_ovls; i++) {
enum drm_plane_type type = i < priv->num_dssdevs enum drm_plane_type type = i < priv->num_pipes
? DRM_PLANE_TYPE_PRIMARY ? DRM_PLANE_TYPE_PRIMARY
: DRM_PLANE_TYPE_OVERLAY; : DRM_PLANE_TYPE_OVERLAY;
struct drm_plane *plane; struct drm_plane *plane;
...@@ -291,36 +285,36 @@ static int omap_modeset_init(struct drm_device *dev) ...@@ -291,36 +285,36 @@ static int omap_modeset_init(struct drm_device *dev)
} }
/* Create the CRTCs, encoders and connectors. */ /* Create the CRTCs, encoders and connectors. */
for (i = 0; i < priv->num_dssdevs; i++) { for (i = 0; i < priv->num_pipes; i++) {
struct omap_dss_device *dssdev = priv->dssdevs[i]; struct omap_drm_pipeline *pipe = &priv->pipes[i];
struct omap_dss_device *display = pipe->display;
struct drm_connector *connector; struct drm_connector *connector;
struct drm_encoder *encoder; struct drm_encoder *encoder;
struct drm_crtc *crtc; struct drm_crtc *crtc;
encoder = omap_encoder_init(dev, dssdev); encoder = omap_encoder_init(dev, display);
if (!encoder) if (!encoder)
return -ENOMEM; return -ENOMEM;
connector = omap_connector_init(dev, connector = omap_connector_init(dev,
get_connector_type(dssdev), dssdev, encoder); get_connector_type(display), display, encoder);
if (!connector) if (!connector)
return -ENOMEM; return -ENOMEM;
crtc = omap_crtc_init(dev, priv->planes[i], dssdev); crtc = omap_crtc_init(dev, priv->planes[i], display);
if (IS_ERR(crtc)) if (IS_ERR(crtc))
return PTR_ERR(crtc); return PTR_ERR(crtc);
drm_connector_attach_encoder(connector, encoder); drm_connector_attach_encoder(connector, encoder);
encoder->possible_crtcs = 1 << i; encoder->possible_crtcs = 1 << i;
priv->crtcs[priv->num_crtcs++] = crtc; pipe->crtc = crtc;
priv->encoders[priv->num_encoders++] = encoder; pipe->encoder = encoder;
priv->connectors[priv->num_connectors++] = connector; pipe->connector = connector;
} }
DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n", DBG("registered %u planes, %u crtcs/encoders/connectors\n",
priv->num_planes, priv->num_crtcs, priv->num_encoders, priv->num_planes, priv->num_pipes);
priv->num_connectors);
dev->mode_config.min_width = 8; dev->mode_config.min_width = 8;
dev->mode_config.min_height = 2; dev->mode_config.min_height = 2;
...@@ -355,11 +349,11 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev) ...@@ -355,11 +349,11 @@ static void omap_modeset_enable_external_hpd(struct drm_device *ddev)
struct omap_drm_private *priv = ddev->dev_private; struct omap_drm_private *priv = ddev->dev_private;
int i; int i;
for (i = 0; i < priv->num_dssdevs; i++) { for (i = 0; i < priv->num_pipes; i++) {
struct omap_dss_device *dssdev = priv->dssdevs[i]; struct omap_dss_device *display = priv->pipes[i].display;
if (dssdev->driver->enable_hpd) if (display->driver->enable_hpd)
dssdev->driver->enable_hpd(dssdev); display->driver->enable_hpd(display);
} }
} }
...@@ -371,11 +365,11 @@ static void omap_modeset_disable_external_hpd(struct drm_device *ddev) ...@@ -371,11 +365,11 @@ static void omap_modeset_disable_external_hpd(struct drm_device *ddev)
struct omap_drm_private *priv = ddev->dev_private; struct omap_drm_private *priv = ddev->dev_private;
int i; int i;
for (i = 0; i < priv->num_dssdevs; i++) { for (i = 0; i < priv->num_pipes; i++) {
struct omap_dss_device *dssdev = priv->dssdevs[i]; struct omap_dss_device *display = priv->pipes[i].display;
if (dssdev->driver->disable_hpd) if (display->driver->disable_hpd)
dssdev->driver->disable_hpd(dssdev); display->driver->disable_hpd(display);
} }
} }
...@@ -561,7 +555,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) ...@@ -561,7 +555,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
omap_crtc_pre_init(priv); omap_crtc_pre_init(priv);
ret = omap_connect_dssdevs(ddev); ret = omap_connect_pipelines(ddev);
if (ret) if (ret)
goto err_crtc_uninit; goto err_crtc_uninit;
...@@ -586,14 +580,14 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) ...@@ -586,14 +580,14 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
} }
/* Initialize vblank handling, start with all CRTCs disabled. */ /* Initialize vblank handling, start with all CRTCs disabled. */
ret = drm_vblank_init(ddev, priv->num_crtcs); ret = drm_vblank_init(ddev, priv->num_pipes);
if (ret) { if (ret) {
dev_err(priv->dev, "could not init vblank\n"); dev_err(priv->dev, "could not init vblank\n");
goto err_cleanup_modeset; goto err_cleanup_modeset;
} }
for (i = 0; i < priv->num_crtcs; i++) for (i = 0; i < priv->num_pipes; i++)
drm_crtc_vblank_off(priv->crtcs[i]); drm_crtc_vblank_off(priv->pipes[i].crtc);
omap_fbdev_init(ddev); omap_fbdev_init(ddev);
...@@ -621,7 +615,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) ...@@ -621,7 +615,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev)
err_gem_deinit: err_gem_deinit:
omap_gem_deinit(ddev); omap_gem_deinit(ddev);
destroy_workqueue(priv->wq); destroy_workqueue(priv->wq);
omap_disconnect_dssdevs(ddev); omap_disconnect_pipelines(ddev);
err_crtc_uninit: err_crtc_uninit:
omap_crtc_pre_uninit(priv); omap_crtc_pre_uninit(priv);
drm_dev_unref(ddev); drm_dev_unref(ddev);
...@@ -650,7 +644,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) ...@@ -650,7 +644,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv)
destroy_workqueue(priv->wq); destroy_workqueue(priv->wq);
omap_disconnect_dssdevs(ddev); omap_disconnect_pipelines(ddev);
omap_crtc_pre_uninit(priv); omap_crtc_pre_uninit(priv);
drm_dev_unref(ddev); drm_dev_unref(ddev);
...@@ -700,17 +694,17 @@ static int omap_drm_suspend_all_displays(struct drm_device *ddev) ...@@ -700,17 +694,17 @@ static int omap_drm_suspend_all_displays(struct drm_device *ddev)
struct omap_drm_private *priv = ddev->dev_private; struct omap_drm_private *priv = ddev->dev_private;
int i; int i;
for (i = 0; i < priv->num_dssdevs; i++) { for (i = 0; i < priv->num_pipes; i++) {
struct omap_dss_device *dssdev = priv->dssdevs[i]; struct omap_dss_device *display = priv->pipes[i].display;
if (!dssdev->driver) if (!display->driver)
continue; continue;
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) { if (display->state == OMAP_DSS_DISPLAY_ACTIVE) {
dssdev->driver->disable(dssdev); display->driver->disable(display);
dssdev->activate_after_resume = true; display->activate_after_resume = true;
} else { } else {
dssdev->activate_after_resume = false; display->activate_after_resume = false;
} }
} }
...@@ -722,15 +716,15 @@ static int omap_drm_resume_all_displays(struct drm_device *ddev) ...@@ -722,15 +716,15 @@ static int omap_drm_resume_all_displays(struct drm_device *ddev)
struct omap_drm_private *priv = ddev->dev_private; struct omap_drm_private *priv = ddev->dev_private;
int i; int i;
for (i = 0; i < priv->num_dssdevs; i++) { for (i = 0; i < priv->num_pipes; i++) {
struct omap_dss_device *dssdev = priv->dssdevs[i]; struct omap_dss_device *display = priv->pipes[i].display;
if (!dssdev->driver) if (!display->driver)
continue; continue;
if (dssdev->activate_after_resume) { if (display->activate_after_resume) {
dssdev->driver->enable(dssdev); display->driver->enable(display);
dssdev->activate_after_resume = false; display->activate_after_resume = false;
} }
} }
......
...@@ -45,6 +45,13 @@ ...@@ -45,6 +45,13 @@
struct omap_drm_usergart; struct omap_drm_usergart;
struct omap_drm_pipeline {
struct drm_crtc *crtc;
struct drm_encoder *encoder;
struct drm_connector *connector;
struct omap_dss_device *display;
};
struct omap_drm_private { struct omap_drm_private {
struct drm_device *ddev; struct drm_device *ddev;
struct device *dev; struct device *dev;
...@@ -54,21 +61,12 @@ struct omap_drm_private { ...@@ -54,21 +61,12 @@ struct omap_drm_private {
struct dispc_device *dispc; struct dispc_device *dispc;
const struct dispc_ops *dispc_ops; const struct dispc_ops *dispc_ops;
unsigned int num_dssdevs; unsigned int num_pipes;
struct omap_dss_device *dssdevs[8]; struct omap_drm_pipeline pipes[8];
unsigned int num_crtcs;
struct drm_crtc *crtcs[8];
unsigned int num_planes; unsigned int num_planes;
struct drm_plane *planes[8]; struct drm_plane *planes[8];
unsigned int num_encoders;
struct drm_encoder *encoders[8];
unsigned int num_connectors;
struct drm_connector *connectors[8];
struct drm_fb_helper *fbdev; struct drm_fb_helper *fbdev;
struct workqueue_struct *wq; struct workqueue_struct *wq;
......
...@@ -243,7 +243,7 @@ void omap_fbdev_init(struct drm_device *dev) ...@@ -243,7 +243,7 @@ void omap_fbdev_init(struct drm_device *dev)
struct drm_fb_helper *helper; struct drm_fb_helper *helper;
int ret = 0; int ret = 0;
if (!priv->num_crtcs || !priv->num_connectors) if (!priv->num_pipes)
return; return;
fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL);
...@@ -256,7 +256,7 @@ void omap_fbdev_init(struct drm_device *dev) ...@@ -256,7 +256,7 @@ void omap_fbdev_init(struct drm_device *dev)
drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs); drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
ret = drm_fb_helper_init(dev, helper, priv->num_connectors); ret = drm_fb_helper_init(dev, helper, priv->num_pipes);
if (ret) if (ret)
goto fail; goto fail;
......
...@@ -206,8 +206,8 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) ...@@ -206,8 +206,8 @@ static irqreturn_t omap_irq_handler(int irq, void *arg)
VERB("irqs: %08x", irqstatus); VERB("irqs: %08x", irqstatus);
for (id = 0; id < priv->num_crtcs; id++) { for (id = 0; id < priv->num_pipes; id++) {
struct drm_crtc *crtc = priv->crtcs[id]; struct drm_crtc *crtc = priv->pipes[id].crtc;
enum omap_channel channel = omap_crtc_channel(crtc); enum omap_channel channel = omap_crtc_channel(crtc);
if (irqstatus & priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel)) { if (irqstatus & priv->dispc_ops->mgr_get_vsync_irq(priv->dispc, channel)) {
......
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