Hi,
This is v2 of the series.
I've rebased these on top of Laurent's latest patches. I also dropped most of Peter's patches, as they need rebasing and some work. I think I addressed all of Laurent's comments to the patches in this v2.
Tomi
Benoit Parrot (2): drm/omap: dispc: disp_wb_setup to check return code drm/omap: Add pclk setting case when channel is DSS_WB
Jyri Sarha (1): drm/omap: Allow HDMI audio setup even if we do not have video configured
Peter Ujfalusi (1): drm/omap: Init fbdev emulation only when we have displays
Tomi Valkeinen (13): drm/omap: fix omap_fbdev_free() when omap_fbdev_create() wasn't called drm/omap: cleanup fbdev init/free drm/omap: add HPD support to connector-dvi dt-bindings: display: add HPD gpio to DVI connector drm/omap: remove leftover enums drm/omap: set WB channel-in in wb_setup() drm/omap: fix WBDELAYCOUNT for HDMI drm/omap: fix WBDELAYCOUNT with interlace drm/omap: fix WB height with interlace drm/omap: fix scaling limits for WB drm/omap: add writeback funcs to dispc_ops drm/omap: fix maximum sizes drm/omap: cleanup color space conversion
.../bindings/display/connector/dvi-connector.txt | 1 + drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 118 +++++++++++++++ drivers/gpu/drm/omapdrm/dss/dispc.c | 160 +++++++++++++++------ drivers/gpu/drm/omapdrm/dss/dss.h | 20 --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 33 ++--- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 37 +++-- drivers/gpu/drm/omapdrm/dss/omapdss.h | 35 +++-- drivers/gpu/drm/omapdrm/omap_drv.c | 20 +-- drivers/gpu/drm/omapdrm/omap_fbdev.c | 24 ++-- drivers/gpu/drm/omapdrm/omap_fbdev.h | 9 +- 10 files changed, 311 insertions(+), 146 deletions(-)
If we have no crtcs/connectors, fbdev init goes fine, but omap_fbdev_create() is never called. This means that omap_fbdev->bo is NULL and omap_fbdev_free() crashes.
Add a check to omap_fbdev_free() to handle the NULL case.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/omapdrm/omap_fbdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 1ace63e2ff22..632ebcf2165f 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -303,7 +303,8 @@ void omap_fbdev_free(struct drm_device *dev) fbdev = to_omap_fbdev(priv->fbdev);
/* unpin the GEM object pinned in omap_fbdev_create() */ - omap_gem_unpin(fbdev->bo); + if (fbdev->bo) + omap_gem_unpin(fbdev->bo);
/* this will free the backing object */ if (fbdev->fb)
Hi,
On Wed, Feb 28, 2018 at 01:25:58PM +0200, Tomi Valkeinen wrote:
If we have no crtcs/connectors, fbdev init goes fine, but omap_fbdev_create() is never called. This means that omap_fbdev->bo is NULL and omap_fbdev_free() crashes.
Add a check to omap_fbdev_free() to handle the NULL case.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
Reviewed-by: Sebastian Reichel sebastian.reichel@collabora.co.uk
-- Sebastian
drivers/gpu/drm/omapdrm/omap_fbdev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 1ace63e2ff22..632ebcf2165f 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -303,7 +303,8 @@ void omap_fbdev_free(struct drm_device *dev) fbdev = to_omap_fbdev(priv->fbdev);
/* unpin the GEM object pinned in omap_fbdev_create() */
- omap_gem_unpin(fbdev->bo);
if (fbdev->bo)
omap_gem_unpin(fbdev->bo);
/* this will free the backing object */ if (fbdev->fb)
-- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
omap_fbdev_init() and omap_fbdev_free() use priv->fbdev directly. However, omap_fbdev_init() returns the fbdev, and omap_drv.c also assigns the return value to priv->fbdev. This is slightly confusing.
Clean this up by removing the omap_fbdev_init() return value, as we don't care whether fbdev init succeeded or not. Also change omap_drv.c to call omap_fbdev_free() always, and omap_fbdev_free() does the check if fbdev was initialized.
While at it, rename omap_fbdev_free() to omap_fbdev_fini() to better match the "init" counterpart.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_drv.c | 9 ++++----- drivers/gpu/drm/omapdrm/omap_fbdev.c | 18 ++++++++---------- drivers/gpu/drm/omapdrm/omap_fbdev.h | 9 ++++----- 3 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 65a567dcf3ab..4f48b908bdc6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -570,7 +570,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) for (i = 0; i < priv->num_crtcs; i++) drm_crtc_vblank_off(priv->crtcs[i]);
- priv->fbdev = omap_fbdev_init(ddev); + omap_fbdev_init(ddev);
drm_kms_helper_poll_init(ddev); omap_modeset_enable_external_hpd(); @@ -588,8 +588,8 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) err_cleanup_helpers: omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev); - if (priv->fbdev) - omap_fbdev_free(ddev); + + omap_fbdev_fini(ddev); err_cleanup_modeset: drm_mode_config_cleanup(ddev); omap_drm_irq_uninstall(ddev); @@ -615,8 +615,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev);
- if (priv->fbdev) - omap_fbdev_free(ddev); + omap_fbdev_fini(ddev);
drm_atomic_helper_shutdown(ddev);
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 632ebcf2165f..be94480326d7 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -242,7 +242,7 @@ static struct drm_fb_helper *get_fb(struct fb_info *fbi) }
/* initialize fbdev helper */ -struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) +void omap_fbdev_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct omap_fbdev *fbdev = NULL; @@ -260,10 +260,8 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
ret = drm_fb_helper_init(dev, helper, priv->num_connectors); - if (ret) { - dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret); + if (ret) goto fail; - }
ret = drm_fb_helper_single_add_all_connectors(helper); if (ret) @@ -275,7 +273,7 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
priv->fbdev = helper;
- return helper; + return;
fini: drm_fb_helper_fini(helper); @@ -283,12 +281,9 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) kfree(fbdev);
dev_warn(dev->dev, "omap_fbdev_init failed\n"); - /* well, limp along without an fbdev.. maybe X11 will work? */ - - return NULL; }
-void omap_fbdev_free(struct drm_device *dev) +void omap_fbdev_fini(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct drm_fb_helper *helper = priv->fbdev; @@ -296,11 +291,14 @@ void omap_fbdev_free(struct drm_device *dev)
DBG();
+ if (!helper) + return; + drm_fb_helper_unregister_fbi(helper);
drm_fb_helper_fini(helper);
- fbdev = to_omap_fbdev(priv->fbdev); + fbdev = to_omap_fbdev(helper);
/* unpin the GEM object pinned in omap_fbdev_create() */ if (fbdev->bo) diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.h b/drivers/gpu/drm/omapdrm/omap_fbdev.h index 1f5ba0996a1a..7dfd843f73f1 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.h +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.h @@ -24,14 +24,13 @@ struct drm_device; struct drm_fb_helper;
#ifdef CONFIG_DRM_FBDEV_EMULATION -struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); -void omap_fbdev_free(struct drm_device *dev); +void omap_fbdev_init(struct drm_device *dev); +void omap_fbdev_fini(struct drm_device *dev); #else -static inline struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) +static inline void omap_fbdev_init(struct drm_device *dev) { - return NULL; } -static inline void omap_fbdev_free(struct drm_device *dev) +static inline void omap_fbdev_fini(struct drm_device *dev) { } #endif
Hi Tomi,
Thank you for the patch.
On Wednesday, 28 February 2018 13:25:59 EET Tomi Valkeinen wrote:
omap_fbdev_init() and omap_fbdev_free() use priv->fbdev directly. However, omap_fbdev_init() returns the fbdev, and omap_drv.c also assigns the return value to priv->fbdev. This is slightly confusing.
Clean this up by removing the omap_fbdev_init() return value, as we don't care whether fbdev init succeeded or not. Also change omap_drv.c to call omap_fbdev_free() always, and omap_fbdev_free() does the check if fbdev was initialized.
While at it, rename omap_fbdev_free() to omap_fbdev_fini() to better match the "init" counterpart.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
drivers/gpu/drm/omapdrm/omap_drv.c | 9 ++++----- drivers/gpu/drm/omapdrm/omap_fbdev.c | 18 ++++++++---------- drivers/gpu/drm/omapdrm/omap_fbdev.h | 9 ++++----- 3 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 65a567dcf3ab..4f48b908bdc6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -570,7 +570,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) for (i = 0; i < priv->num_crtcs; i++) drm_crtc_vblank_off(priv->crtcs[i]);
- priv->fbdev = omap_fbdev_init(ddev);
omap_fbdev_init(ddev);
drm_kms_helper_poll_init(ddev); omap_modeset_enable_external_hpd();
@@ -588,8 +588,8 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) err_cleanup_helpers: omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev);
- if (priv->fbdev)
omap_fbdev_free(ddev);
- omap_fbdev_fini(ddev);
err_cleanup_modeset: drm_mode_config_cleanup(ddev); omap_drm_irq_uninstall(ddev); @@ -615,8 +615,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev);
- if (priv->fbdev)
omap_fbdev_free(ddev);
omap_fbdev_fini(ddev);
drm_atomic_helper_shutdown(ddev);
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 632ebcf2165f..be94480326d7 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -242,7 +242,7 @@ static struct drm_fb_helper *get_fb(struct fb_info *fbi) }
/* initialize fbdev helper */ -struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) +void omap_fbdev_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct omap_fbdev *fbdev = NULL; @@ -260,10 +260,8 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
ret = drm_fb_helper_init(dev, helper, priv->num_connectors);
- if (ret) {
dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret);
- if (ret) goto fail;
}
ret = drm_fb_helper_single_add_all_connectors(helper); if (ret)
@@ -275,7 +273,7 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
priv->fbdev = helper;
- return helper;
- return;
fini: drm_fb_helper_fini(helper); @@ -283,12 +281,9 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) kfree(fbdev);
dev_warn(dev->dev, "omap_fbdev_init failed\n");
- /* well, limp along without an fbdev.. maybe X11 will work? */
- return NULL;
}
-void omap_fbdev_free(struct drm_device *dev) +void omap_fbdev_fini(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct drm_fb_helper *helper = priv->fbdev; @@ -296,11 +291,14 @@ void omap_fbdev_free(struct drm_device *dev)
DBG();
if (!helper)
return;
drm_fb_helper_unregister_fbi(helper);
drm_fb_helper_fini(helper);
- fbdev = to_omap_fbdev(priv->fbdev);
fbdev = to_omap_fbdev(helper);
/* unpin the GEM object pinned in omap_fbdev_create() */ if (fbdev->bo)
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.h b/drivers/gpu/drm/omapdrm/omap_fbdev.h index 1f5ba0996a1a..7dfd843f73f1 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.h +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.h @@ -24,14 +24,13 @@ struct drm_device; struct drm_fb_helper;
#ifdef CONFIG_DRM_FBDEV_EMULATION -struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); -void omap_fbdev_free(struct drm_device *dev); +void omap_fbdev_init(struct drm_device *dev); +void omap_fbdev_fini(struct drm_device *dev); #else -static inline struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) +static inline void omap_fbdev_init(struct drm_device *dev) {
- return NULL;
} -static inline void omap_fbdev_free(struct drm_device *dev) +static inline void omap_fbdev_fini(struct drm_device *dev) { } #endif
Hi,
On Wed, Feb 28, 2018 at 01:25:59PM +0200, Tomi Valkeinen wrote:
omap_fbdev_init() and omap_fbdev_free() use priv->fbdev directly. However, omap_fbdev_init() returns the fbdev, and omap_drv.c also assigns the return value to priv->fbdev. This is slightly confusing.
Clean this up by removing the omap_fbdev_init() return value, as we don't care whether fbdev init succeeded or not. Also change omap_drv.c to call omap_fbdev_free() always, and omap_fbdev_free() does the check if fbdev was initialized.
While at it, rename omap_fbdev_free() to omap_fbdev_fini() to better match the "init" counterpart.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com
Reviewed-by: Sebastian Reichel sebastian.reichel@collabora.co.uk
-- Sebastian
drivers/gpu/drm/omapdrm/omap_drv.c | 9 ++++----- drivers/gpu/drm/omapdrm/omap_fbdev.c | 18 ++++++++---------- drivers/gpu/drm/omapdrm/omap_fbdev.h | 9 ++++----- 3 files changed, 16 insertions(+), 20 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 65a567dcf3ab..4f48b908bdc6 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -570,7 +570,7 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) for (i = 0; i < priv->num_crtcs; i++) drm_crtc_vblank_off(priv->crtcs[i]);
- priv->fbdev = omap_fbdev_init(ddev);
omap_fbdev_init(ddev);
drm_kms_helper_poll_init(ddev); omap_modeset_enable_external_hpd();
@@ -588,8 +588,8 @@ static int omapdrm_init(struct omap_drm_private *priv, struct device *dev) err_cleanup_helpers: omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev);
- if (priv->fbdev)
omap_fbdev_free(ddev);
- omap_fbdev_fini(ddev);
err_cleanup_modeset: drm_mode_config_cleanup(ddev); omap_drm_irq_uninstall(ddev); @@ -615,8 +615,7 @@ static void omapdrm_cleanup(struct omap_drm_private *priv) omap_modeset_disable_external_hpd(); drm_kms_helper_poll_fini(ddev);
- if (priv->fbdev)
omap_fbdev_free(ddev);
omap_fbdev_fini(ddev);
drm_atomic_helper_shutdown(ddev);
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 632ebcf2165f..be94480326d7 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -242,7 +242,7 @@ static struct drm_fb_helper *get_fb(struct fb_info *fbi) }
/* initialize fbdev helper */ -struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) +void omap_fbdev_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct omap_fbdev *fbdev = NULL; @@ -260,10 +260,8 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) drm_fb_helper_prepare(dev, helper, &omap_fb_helper_funcs);
ret = drm_fb_helper_init(dev, helper, priv->num_connectors);
- if (ret) {
dev_err(dev->dev, "could not init fbdev: ret=%d\n", ret);
- if (ret) goto fail;
}
ret = drm_fb_helper_single_add_all_connectors(helper); if (ret)
@@ -275,7 +273,7 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev)
priv->fbdev = helper;
- return helper;
- return;
fini: drm_fb_helper_fini(helper); @@ -283,12 +281,9 @@ struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) kfree(fbdev);
dev_warn(dev->dev, "omap_fbdev_init failed\n");
- /* well, limp along without an fbdev.. maybe X11 will work? */
- return NULL;
}
-void omap_fbdev_free(struct drm_device *dev) +void omap_fbdev_fini(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct drm_fb_helper *helper = priv->fbdev; @@ -296,11 +291,14 @@ void omap_fbdev_free(struct drm_device *dev)
DBG();
if (!helper)
return;
drm_fb_helper_unregister_fbi(helper);
drm_fb_helper_fini(helper);
- fbdev = to_omap_fbdev(priv->fbdev);
fbdev = to_omap_fbdev(helper);
/* unpin the GEM object pinned in omap_fbdev_create() */ if (fbdev->bo)
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.h b/drivers/gpu/drm/omapdrm/omap_fbdev.h index 1f5ba0996a1a..7dfd843f73f1 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.h +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.h @@ -24,14 +24,13 @@ struct drm_device; struct drm_fb_helper;
#ifdef CONFIG_DRM_FBDEV_EMULATION -struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); -void omap_fbdev_free(struct drm_device *dev); +void omap_fbdev_init(struct drm_device *dev); +void omap_fbdev_fini(struct drm_device *dev); #else -static inline struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev) +static inline void omap_fbdev_init(struct drm_device *dev) {
- return NULL;
} -static inline void omap_fbdev_free(struct drm_device *dev) +static inline void omap_fbdev_fini(struct drm_device *dev) { }
#endif
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Peter Ujfalusi peter.ujfalusi@ti.com
Do not try to init the fbdev if either num_crtcs or num_connectors is 0. In this case we do not have display so the fbdev init would fail anyways.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/omapdrm/omap_fbdev.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index be94480326d7..0f66c74a54b0 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -249,6 +249,9 @@ void omap_fbdev_init(struct drm_device *dev) struct drm_fb_helper *helper; int ret = 0;
+ if (!priv->num_crtcs || !priv->num_connectors) + return; + fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); if (!fbdev) goto fail;
Hi,
On Wed, Feb 28, 2018 at 01:26:00PM +0200, Tomi Valkeinen wrote:
From: Peter Ujfalusi peter.ujfalusi@ti.com
Do not try to init the fbdev if either num_crtcs or num_connectors is 0. In this case we do not have display so the fbdev init would fail anyways.
Signed-off-by: Peter Ujfalusi peter.ujfalusi@ti.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
Reviewed-by: Sebastian Reichel sebastian.reichel@collabora.co.uk
-- Sebastian
drivers/gpu/drm/omapdrm/omap_fbdev.c | 3 +++ 1 file changed, 3 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index be94480326d7..0f66c74a54b0 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -249,6 +249,9 @@ void omap_fbdev_init(struct drm_device *dev) struct drm_fb_helper *helper; int ret = 0;
- if (!priv->num_crtcs || !priv->num_connectors)
return;
- fbdev = kzalloc(sizeof(*fbdev), GFP_KERNEL); if (!fbdev) goto fail;
-- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Add HPD support to the DVI connector driver. The code is almost identical to the HPD code in the HDMI connector driver.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 118 +++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 391d80364346..6d8cbd9e2110 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -9,6 +9,7 @@ * the Free Software Foundation. */
+#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -44,6 +45,14 @@ struct panel_drv_data { struct videomode vm;
struct i2c_adapter *i2c_adapter; + + struct gpio_desc *hpd_gpio; + + void (*hpd_cb)(void *cb_data, enum drm_connector_status status); + void *hpd_cb_data; + bool hpd_enabled; + /* mutex for hpd fields above */ + struct mutex hpd_lock; };
#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -189,6 +198,9 @@ static int dvic_read_edid(struct omap_dss_device *dssdev, struct panel_drv_data *ddata = to_panel_data(dssdev); int r, l, bytes_read;
+ if (ddata->hpd_gpio && !gpiod_get_value_cansleep(ddata->hpd_gpio)) + return -ENODEV; + if (!ddata->i2c_adapter) return -ENODEV;
@@ -220,6 +232,9 @@ static bool dvic_detect(struct omap_dss_device *dssdev) unsigned char out; int r;
+ if (ddata->hpd_gpio) + return gpiod_get_value_cansleep(ddata->hpd_gpio); + if (!ddata->i2c_adapter) return true;
@@ -228,6 +243,60 @@ static bool dvic_detect(struct omap_dss_device *dssdev) return r == 0; }
+static int dvic_register_hpd_cb(struct omap_dss_device *dssdev, + void (*cb)(void *cb_data, + enum drm_connector_status status), + void *cb_data) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + + if (!ddata->hpd_gpio) + return -ENOTSUPP; + + mutex_lock(&ddata->hpd_lock); + ddata->hpd_cb = cb; + ddata->hpd_cb_data = cb_data; + mutex_unlock(&ddata->hpd_lock); + return 0; +} + +static void dvic_unregister_hpd_cb(struct omap_dss_device *dssdev) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + + if (!ddata->hpd_gpio) + return; + + mutex_lock(&ddata->hpd_lock); + ddata->hpd_cb = NULL; + ddata->hpd_cb_data = NULL; + mutex_unlock(&ddata->hpd_lock); +} + +static void dvic_enable_hpd(struct omap_dss_device *dssdev) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + + if (!ddata->hpd_gpio) + return; + + mutex_lock(&ddata->hpd_lock); + ddata->hpd_enabled = true; + mutex_unlock(&ddata->hpd_lock); +} + +static void dvic_disable_hpd(struct omap_dss_device *dssdev) +{ + struct panel_drv_data *ddata = to_panel_data(dssdev); + + if (!ddata->hpd_gpio) + return; + + mutex_lock(&ddata->hpd_lock); + ddata->hpd_enabled = false; + mutex_unlock(&ddata->hpd_lock); +} + static struct omap_dss_driver dvic_driver = { .connect = dvic_connect, .disconnect = dvic_disconnect, @@ -241,14 +310,60 @@ static struct omap_dss_driver dvic_driver = {
.read_edid = dvic_read_edid, .detect = dvic_detect, + + .register_hpd_cb = dvic_register_hpd_cb, + .unregister_hpd_cb = dvic_unregister_hpd_cb, + .enable_hpd = dvic_enable_hpd, + .disable_hpd = dvic_disable_hpd, };
+static irqreturn_t dvic_hpd_isr(int irq, void *data) +{ + struct panel_drv_data *ddata = data; + + mutex_lock(&ddata->hpd_lock); + if (ddata->hpd_enabled && ddata->hpd_cb) { + enum drm_connector_status status; + + if (dvic_detect(&ddata->dssdev)) + status = connector_status_connected; + else + status = connector_status_disconnected; + + ddata->hpd_cb(ddata->hpd_cb_data, status); + } + mutex_unlock(&ddata->hpd_lock); + + return IRQ_HANDLED; +} + static int dvic_probe_of(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; struct device_node *adapter_node; struct i2c_adapter *adapter; + struct gpio_desc *gpio; + int r; + + gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN); + if (IS_ERR(gpio)) { + dev_err(&pdev->dev, "failed to parse HPD gpio\n"); + return PTR_ERR(gpio); + } + + ddata->hpd_gpio = gpio; + + mutex_init(&ddata->hpd_lock); + + if (ddata->hpd_gpio) { + r = devm_request_threaded_irq(&pdev->dev, + gpiod_to_irq(ddata->hpd_gpio), NULL, dvic_hpd_isr, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, + "DVI HPD", ddata); + if (r) + return r; + }
adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0); if (adapter_node) { @@ -300,6 +415,7 @@ static int dvic_probe(struct platform_device *pdev)
err_reg: i2c_put_adapter(ddata->i2c_adapter); + mutex_destroy(&ddata->hpd_lock);
return r; } @@ -316,6 +432,8 @@ static int __exit dvic_remove(struct platform_device *pdev)
i2c_put_adapter(ddata->i2c_adapter);
+ mutex_destroy(&ddata->hpd_lock); + return 0; }
Hi Tomi,
Thank you for the patch.
On Wednesday, 28 February 2018 13:26:01 EET Tomi Valkeinen wrote:
Add HPD support to the DVI connector driver. The code is almost identical to the HPD code in the HDMI connector driver.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 118 ++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 391d80364346..6d8cbd9e2110 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -9,6 +9,7 @@
- the Free Software Foundation.
*/
+#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -44,6 +45,14 @@ struct panel_drv_data { struct videomode vm;
struct i2c_adapter *i2c_adapter;
- struct gpio_desc *hpd_gpio;
- void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
- void *hpd_cb_data;
- bool hpd_enabled;
- /* mutex for hpd fields above */
- struct mutex hpd_lock;
};
#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -189,6 +198,9 @@ static int dvic_read_edid(struct omap_dss_device *dssdev, struct panel_drv_data *ddata = to_panel_data(dssdev); int r, l, bytes_read;
- if (ddata->hpd_gpio && !gpiod_get_value_cansleep(ddata->hpd_gpio))
return -ENODEV;
- if (!ddata->i2c_adapter) return -ENODEV;
@@ -220,6 +232,9 @@ static bool dvic_detect(struct omap_dss_device *dssdev) unsigned char out; int r;
- if (ddata->hpd_gpio)
return gpiod_get_value_cansleep(ddata->hpd_gpio);
- if (!ddata->i2c_adapter) return true;
@@ -228,6 +243,60 @@ static bool dvic_detect(struct omap_dss_device *dssdev) return r == 0; }
+static int dvic_register_hpd_cb(struct omap_dss_device *dssdev,
void (*cb)(void *cb_data,
enum drm_connector_status status),
void *cb_data)
+{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return -ENOTSUPP;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_cb = cb;
- ddata->hpd_cb_data = cb_data;
- mutex_unlock(&ddata->hpd_lock);
- return 0;
+}
+static void dvic_unregister_hpd_cb(struct omap_dss_device *dssdev) +{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_cb = NULL;
- ddata->hpd_cb_data = NULL;
- mutex_unlock(&ddata->hpd_lock);
+}
+static void dvic_enable_hpd(struct omap_dss_device *dssdev) +{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = true;
- mutex_unlock(&ddata->hpd_lock);
+}
+static void dvic_disable_hpd(struct omap_dss_device *dssdev) +{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = false;
- mutex_unlock(&ddata->hpd_lock);
+}
static struct omap_dss_driver dvic_driver = { .connect = dvic_connect, .disconnect = dvic_disconnect, @@ -241,14 +310,60 @@ static struct omap_dss_driver dvic_driver = {
.read_edid = dvic_read_edid, .detect = dvic_detect,
- .register_hpd_cb = dvic_register_hpd_cb,
- .unregister_hpd_cb = dvic_unregister_hpd_cb,
- .enable_hpd = dvic_enable_hpd,
- .disable_hpd = dvic_disable_hpd,
};
+static irqreturn_t dvic_hpd_isr(int irq, void *data) +{
- struct panel_drv_data *ddata = data;
- mutex_lock(&ddata->hpd_lock);
- if (ddata->hpd_enabled && ddata->hpd_cb) {
enum drm_connector_status status;
if (dvic_detect(&ddata->dssdev))
status = connector_status_connected;
else
status = connector_status_disconnected;
ddata->hpd_cb(ddata->hpd_cb_data, status);
- }
- mutex_unlock(&ddata->hpd_lock);
- return IRQ_HANDLED;
+}
static int dvic_probe_of(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; struct device_node *adapter_node; struct i2c_adapter *adapter;
struct gpio_desc *gpio;
int r;
gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to parse HPD gpio\n");
return PTR_ERR(gpio);
}
ddata->hpd_gpio = gpio;
mutex_init(&ddata->hpd_lock);
if (ddata->hpd_gpio) {
r = devm_request_threaded_irq(&pdev->dev,
gpiod_to_irq(ddata->hpd_gpio), NULL, dvic_hpd_isr,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"DVI HPD", ddata);
if (r)
return r;
}
adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0); if (adapter_node) {
@@ -300,6 +415,7 @@ static int dvic_probe(struct platform_device *pdev)
err_reg: i2c_put_adapter(ddata->i2c_adapter);
mutex_destroy(&ddata->hpd_lock);
return r;
} @@ -316,6 +432,8 @@ static int __exit dvic_remove(struct platform_device *pdev)
i2c_put_adapter(ddata->i2c_adapter);
- mutex_destroy(&ddata->hpd_lock);
- return 0;
}
Hi,
On Wed, Feb 28, 2018 at 01:26:01PM +0200, Tomi Valkeinen wrote:
Add HPD support to the DVI connector driver. The code is almost identical to the HPD code in the HDMI connector driver.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com
Reviewed-by: Sebastian Reichel sebastian.reichel@collabora.co.uk
-- Sebastian
drivers/gpu/drm/omapdrm/displays/connector-dvi.c | 118 +++++++++++++++++++++++ 1 file changed, 118 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c index 391d80364346..6d8cbd9e2110 100644 --- a/drivers/gpu/drm/omapdrm/displays/connector-dvi.c +++ b/drivers/gpu/drm/omapdrm/displays/connector-dvi.c @@ -9,6 +9,7 @@
- the Free Software Foundation.
*/
+#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/platform_device.h> @@ -44,6 +45,14 @@ struct panel_drv_data { struct videomode vm;
struct i2c_adapter *i2c_adapter;
- struct gpio_desc *hpd_gpio;
- void (*hpd_cb)(void *cb_data, enum drm_connector_status status);
- void *hpd_cb_data;
- bool hpd_enabled;
- /* mutex for hpd fields above */
- struct mutex hpd_lock;
};
#define to_panel_data(x) container_of(x, struct panel_drv_data, dssdev) @@ -189,6 +198,9 @@ static int dvic_read_edid(struct omap_dss_device *dssdev, struct panel_drv_data *ddata = to_panel_data(dssdev); int r, l, bytes_read;
- if (ddata->hpd_gpio && !gpiod_get_value_cansleep(ddata->hpd_gpio))
return -ENODEV;
- if (!ddata->i2c_adapter) return -ENODEV;
@@ -220,6 +232,9 @@ static bool dvic_detect(struct omap_dss_device *dssdev) unsigned char out; int r;
- if (ddata->hpd_gpio)
return gpiod_get_value_cansleep(ddata->hpd_gpio);
- if (!ddata->i2c_adapter) return true;
@@ -228,6 +243,60 @@ static bool dvic_detect(struct omap_dss_device *dssdev) return r == 0; }
+static int dvic_register_hpd_cb(struct omap_dss_device *dssdev,
void (*cb)(void *cb_data,
enum drm_connector_status status),
void *cb_data)
+{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return -ENOTSUPP;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_cb = cb;
- ddata->hpd_cb_data = cb_data;
- mutex_unlock(&ddata->hpd_lock);
- return 0;
+}
+static void dvic_unregister_hpd_cb(struct omap_dss_device *dssdev) +{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_cb = NULL;
- ddata->hpd_cb_data = NULL;
- mutex_unlock(&ddata->hpd_lock);
+}
+static void dvic_enable_hpd(struct omap_dss_device *dssdev) +{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = true;
- mutex_unlock(&ddata->hpd_lock);
+}
+static void dvic_disable_hpd(struct omap_dss_device *dssdev) +{
- struct panel_drv_data *ddata = to_panel_data(dssdev);
- if (!ddata->hpd_gpio)
return;
- mutex_lock(&ddata->hpd_lock);
- ddata->hpd_enabled = false;
- mutex_unlock(&ddata->hpd_lock);
+}
static struct omap_dss_driver dvic_driver = { .connect = dvic_connect, .disconnect = dvic_disconnect, @@ -241,14 +310,60 @@ static struct omap_dss_driver dvic_driver = {
.read_edid = dvic_read_edid, .detect = dvic_detect,
- .register_hpd_cb = dvic_register_hpd_cb,
- .unregister_hpd_cb = dvic_unregister_hpd_cb,
- .enable_hpd = dvic_enable_hpd,
- .disable_hpd = dvic_disable_hpd,
};
+static irqreturn_t dvic_hpd_isr(int irq, void *data) +{
- struct panel_drv_data *ddata = data;
- mutex_lock(&ddata->hpd_lock);
- if (ddata->hpd_enabled && ddata->hpd_cb) {
enum drm_connector_status status;
if (dvic_detect(&ddata->dssdev))
status = connector_status_connected;
else
status = connector_status_disconnected;
ddata->hpd_cb(ddata->hpd_cb_data, status);
- }
- mutex_unlock(&ddata->hpd_lock);
- return IRQ_HANDLED;
+}
static int dvic_probe_of(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; struct device_node *adapter_node; struct i2c_adapter *adapter;
struct gpio_desc *gpio;
int r;
gpio = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN);
if (IS_ERR(gpio)) {
dev_err(&pdev->dev, "failed to parse HPD gpio\n");
return PTR_ERR(gpio);
}
ddata->hpd_gpio = gpio;
mutex_init(&ddata->hpd_lock);
if (ddata->hpd_gpio) {
r = devm_request_threaded_irq(&pdev->dev,
gpiod_to_irq(ddata->hpd_gpio), NULL, dvic_hpd_isr,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
"DVI HPD", ddata);
if (r)
return r;
}
adapter_node = of_parse_phandle(node, "ddc-i2c-bus", 0); if (adapter_node) {
@@ -300,6 +415,7 @@ static int dvic_probe(struct platform_device *pdev)
err_reg: i2c_put_adapter(ddata->i2c_adapter);
mutex_destroy(&ddata->hpd_lock);
return r;
} @@ -316,6 +432,8 @@ static int __exit dvic_remove(struct platform_device *pdev)
i2c_put_adapter(ddata->i2c_adapter);
- mutex_destroy(&ddata->hpd_lock);
- return 0;
}
-- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Add hpd-gpios property to dvi-connector.txt.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring robh@kernel.org Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- Documentation/devicetree/bindings/display/connector/dvi-connector.txt | 1 + 1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/display/connector/dvi-connector.txt b/Documentation/devicetree/bindings/display/connector/dvi-connector.txt index fc53f7c60bc6..207e42e9eba0 100644 --- a/Documentation/devicetree/bindings/display/connector/dvi-connector.txt +++ b/Documentation/devicetree/bindings/display/connector/dvi-connector.txt @@ -10,6 +10,7 @@ Optional properties: - analog: the connector has DVI analog pins - digital: the connector has DVI digital pins - dual-link: the connector has pins for DVI dual-link +- hpd-gpios: HPD GPIO number
Required nodes: - Video port for DVI input
Hi,
On Wed, Feb 28, 2018 at 01:26:02PM +0200, Tomi Valkeinen wrote:
Add hpd-gpios property to dvi-connector.txt.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring robh@kernel.org Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
Reviewed-by: Sebastian Reichel sebastian.reichel@collabora.co.uk
-- Sebastian
Documentation/devicetree/bindings/display/connector/dvi-connector.txt | 1 + 1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/display/connector/dvi-connector.txt b/Documentation/devicetree/bindings/display/connector/dvi-connector.txt index fc53f7c60bc6..207e42e9eba0 100644 --- a/Documentation/devicetree/bindings/display/connector/dvi-connector.txt +++ b/Documentation/devicetree/bindings/display/connector/dvi-connector.txt @@ -10,6 +10,7 @@ Optional properties:
- analog: the connector has DVI analog pins
- digital: the connector has DVI digital pins
- dual-link: the connector has pins for DVI dual-link
+- hpd-gpios: HPD GPIO number
Required nodes:
- Video port for DVI input
-- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
A few enums are not used anywhere, so remove them.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/omapdrm/dss/omapdss.h | 15 --------------- 1 file changed, 15 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index a4f71e082c1c..162f36fa3431 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -163,21 +163,6 @@ enum omap_overlay_caps { OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5, };
-enum omap_dss_clk_source { - OMAP_DSS_CLK_SRC_FCK = 0, /* OMAP2/3: DSS1_ALWON_FCLK - * OMAP4: DSS_FCLK */ - OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK - * OMAP4: PLL1_CLK1 */ - OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK - * OMAP4: PLL1_CLK2 */ - OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, /* OMAP4: PLL2_CLK1 */ - OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */ -}; - -enum omap_hdmi_flags { - OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0, -}; - enum omap_dss_output_id { OMAP_DSS_OUTPUT_DPI = 1 << 0, OMAP_DSS_OUTPUT_DBI = 1 << 1,
Hi,
On Wed, Feb 28, 2018 at 01:26:03PM +0200, Tomi Valkeinen wrote:
A few enums are not used anywhere, so remove them.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
Reviewed-by: Sebastian Reichel sebastian.reichel@collabora.co.uk
-- Sebastian
drivers/gpu/drm/omapdrm/dss/omapdss.h | 15 --------------- 1 file changed, 15 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index a4f71e082c1c..162f36fa3431 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -163,21 +163,6 @@ enum omap_overlay_caps { OMAP_DSS_OVL_CAP_REPLICATION = 1 << 5, };
-enum omap_dss_clk_source {
- OMAP_DSS_CLK_SRC_FCK = 0, /* OMAP2/3: DSS1_ALWON_FCLK
* OMAP4: DSS_FCLK */
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC, /* OMAP3: DSI1_PLL_FCLK
* OMAP4: PLL1_CLK1 */
- OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI, /* OMAP3: DSI2_PLL_FCLK
* OMAP4: PLL1_CLK2 */
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC, /* OMAP4: PLL2_CLK1 */
- OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI, /* OMAP4: PLL2_CLK2 */
-};
-enum omap_hdmi_flags {
- OMAP_HDMI_SDA_SCL_EXTERNAL_PULLUP = 1 << 0,
-};
enum omap_dss_output_id { OMAP_DSS_OUTPUT_DPI = 1 << 0, OMAP_DSS_OUTPUT_DBI = 1 << 1, -- Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Benoit Parrot bparrot@ti.com
When dispc_wb_setup() calls dispc_ovl_setup_common() it does not check for failure but instead keeps on partially setting up WB. This causes the WB H/W to be partially initialized and yield unexpected behavior.
Make sure return code is successful before proceeding.
Signed-off-by: Benoit Parrot bparrot@ti.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index d2d95c76a313..f0f729fc4ca2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2783,6 +2783,8 @@ int dispc_wb_setup(struct dispc_device *dispc, wi->height, wi->fourcc, wi->rotation, zorder, wi->pre_mult_alpha, global_alpha, wi->rotation_type, replication, vm, mem_to_mem); + if (r) + return r;
switch (wi->fourcc) { case DRM_FORMAT_RGB565: @@ -2823,7 +2825,7 @@ int dispc_wb_setup(struct dispc_device *dispc, REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0); }
- return r; + return 0; }
static int dispc_ovl_enable(struct dispc_device *dispc,
Hi,
On Wed, Feb 28, 2018 at 01:26:04PM +0200, Tomi Valkeinen wrote:
From: Benoit Parrot bparrot@ti.com
When dispc_wb_setup() calls dispc_ovl_setup_common() it does not check for failure but instead keeps on partially setting up WB. This causes the WB H/W to be partially initialized and yield unexpected behavior.
Make sure return code is successful before proceeding.
Signed-off-by: Benoit Parrot bparrot@ti.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
Reviewed-by: Sebastian Reichel sebastian.reichel@collabora.co.uk
-- Sebastian
drivers/gpu/drm/omapdrm/dss/dispc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index d2d95c76a313..f0f729fc4ca2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2783,6 +2783,8 @@ int dispc_wb_setup(struct dispc_device *dispc, wi->height, wi->fourcc, wi->rotation, zorder, wi->pre_mult_alpha, global_alpha, wi->rotation_type, replication, vm, mem_to_mem);
if (r)
return r;
switch (wi->fourcc) { case DRM_FORMAT_RGB565:
@@ -2823,7 +2825,7 @@ int dispc_wb_setup(struct dispc_device *dispc, REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0); }
- return r;
- return 0;
}
static int dispc_ovl_enable(struct dispc_device *dispc,
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki. Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
From: Benoit Parrot bparrot@ti.com
In dispc_set_ovl_common() we need to initialize pclk to a valid value when we use WB in capture mode (i.e. mem_2_mem is false). Otherwise dispc_ovl_calc_scaling() fails.
Signed-off-by: Benoit Parrot bparrot@ti.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 4 ++++ 1 file changed, 4 insertions(+)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index f0f729fc4ca2..3ad56b30c90a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2590,6 +2590,10 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc, unsigned long pclk = dispc_plane_pclk_rate(dispc, plane); unsigned long lclk = dispc_plane_lclk_rate(dispc, plane);
+ /* when setting up WB, dispc_plane_pclk_rate() returns 0 */ + if (plane == OMAP_DSS_WB) + pclk = vm->pixelclock; + if (paddr == 0 && rotation_type != OMAP_DSS_ROT_TILER) return -EINVAL;
We need to know the WB channel-in in wb_setup() to be able to configure WB properly for capture mode. At the moment channel-in is set separately.
This patch moves channel-in to wb_setup().
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 12 +++--------- drivers/gpu/drm/omapdrm/dss/dss.h | 3 ++- 2 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 3ad56b30c90a..ccfafce1ea89 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -1234,14 +1234,6 @@ static enum omap_channel dispc_ovl_get_channel_out(struct dispc_device *dispc, } }
-void dispc_wb_set_channel_in(struct dispc_device *dispc, - enum dss_writeback_channel channel) -{ - enum omap_plane_id plane = OMAP_DSS_WB; - - REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16); -} - static void dispc_ovl_set_burst_size(struct dispc_device *dispc, enum omap_plane_id plane, enum omap_burst_size burst_size) @@ -2764,7 +2756,8 @@ static int dispc_ovl_setup(struct dispc_device *dispc,
int dispc_wb_setup(struct dispc_device *dispc, const struct omap_dss_writeback_info *wi, - bool mem_to_mem, const struct videomode *vm) + bool mem_to_mem, const struct videomode *vm, + enum dss_writeback_channel channel_in) { int r; u32 l; @@ -2809,6 +2802,7 @@ int dispc_wb_setup(struct dispc_device *dispc, /* setup extra DISPC_WB_ATTRIBUTES */ l = dispc_read_reg(dispc, DISPC_OVL_ATTRIBUTES(plane)); l = FLD_MOD(l, truncation, 10, 10); /* TRUNCATIONENABLE */ + l = FLD_MOD(l, channel_in, 18, 16); /* CHANNELIN */ l = FLD_MOD(l, mem_to_mem, 19, 19); /* WRITEBACKMODE */ if (mem_to_mem) l = FLD_MOD(l, 1, 26, 24); /* CAPTUREMODE */ diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 6f6fd3d1b159..c56c3c59bf18 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -455,7 +455,8 @@ void dispc_wb_set_channel_in(struct dispc_device *dispc, enum dss_writeback_channel channel); int dispc_wb_setup(struct dispc_device *dispc, const struct omap_dss_writeback_info *wi, - bool mem_to_mem, const struct videomode *vm); + bool mem_to_mem, const struct videomode *vm, + enum dss_writeback_channel channel_in);
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS static inline void dss_collect_irq_stats(u32 irqstatus, unsigned int *irq_arr)
For HDMI, WBDELAYCOUNT starts counting at the start of vsync, not at the start of vfp.
This patch adjusts the wbdelay for HDMI accordingly.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index ccfafce1ea89..7398039954a5 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2816,8 +2816,12 @@ int dispc_wb_setup(struct dispc_device *dispc, } else { int wbdelay;
- wbdelay = min(vm->vfront_porch + - vm->vsync_len + vm->vback_porch, (u32)255); + if (channel_in == DSS_WB_TV_MGR) + wbdelay = min(vm->vsync_len + vm->vback_porch, + (u32)255); + else + wbdelay = min(vm->vfront_porch + + vm->vsync_len + vm->vback_porch, (u32)255);
/* WBDELAYCOUNT */ REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0);
Vertical blanking needs to be halved on interlace modes. WBDELAYCOUNT was calculated without such halving, resulting in WBUNCOMPLETE errors.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Acked-by: Benoit Parrot bparrot@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 7398039954a5..000a3d4a27bf 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2814,14 +2814,18 @@ int dispc_wb_setup(struct dispc_device *dispc, /* WBDELAYCOUNT */ REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), 0, 7, 0); } else { - int wbdelay; + u32 wbdelay;
if (channel_in == DSS_WB_TV_MGR) - wbdelay = min(vm->vsync_len + vm->vback_porch, - (u32)255); + wbdelay = vm->vsync_len + vm->vback_porch; else - wbdelay = min(vm->vfront_porch + - vm->vsync_len + vm->vback_porch, (u32)255); + wbdelay = vm->vfront_porch + vm->vsync_len + + vm->vback_porch; + + if (vm->flags & DISPLAY_FLAGS_INTERLACED) + wbdelay /= 2; + + wbdelay = min(wbdelay, 255u);
/* WBDELAYCOUNT */ REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES2(plane), wbdelay, 7, 0);
When using WB capture from interlaced source, we need to halve the picture heights correctly.
Unfortunately the current dispc_ovl_setup_common() doesn't deal with interlace very neatly, so the end result is a bit messy.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com Acked-by: Benoit Parrot bparrot@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 000a3d4a27bf..72f00e8a1329 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2597,18 +2597,19 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc, out_width = out_width == 0 ? width : out_width; out_height = out_height == 0 ? height : out_height;
- if (ilace && height == out_height) - fieldmode = true; - - if (ilace) { - if (fieldmode) - in_height /= 2; - pos_y /= 2; - out_height /= 2; - - DSSDBG("adjusting for ilace: height %d, pos_y %d, " - "out_height %d\n", in_height, pos_y, - out_height); + if (plane != OMAP_DSS_WB) { + if (ilace && height == out_height) + fieldmode = true; + + if (ilace) { + if (fieldmode) + in_height /= 2; + pos_y /= 2; + out_height /= 2; + + DSSDBG("adjusting for ilace: height %d, pos_y %d, out_height %d\n", + in_height, pos_y, out_height); + } }
if (!dispc_ovl_color_mode_supported(dispc, plane, fourcc)) @@ -2771,6 +2772,9 @@ int dispc_wb_setup(struct dispc_device *dispc, enum omap_overlay_caps caps = OMAP_DSS_OVL_CAP_SCALE | OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA;
+ if (vm->flags & DISPLAY_FLAGS_INTERLACED) + in_height /= 2; + DSSDBG("dispc_wb_setup, pa %x, pa_uv %x, %d,%d -> %dx%d, cmode %x, " "rot %d\n", wi->paddr, wi->p_uv_addr, in_width, in_height, wi->width, wi->height, wi->fourcc, wi->rotation);
WB has additional scaling limits when the output color format is one of the YUV formats. These limits are not handled at the moment, causing bad scaling and/or NULL dereference crash.
This patchs adds the check so that dispc returns an error for bad scaling request.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 72f00e8a1329..2aa72845f819 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -2475,6 +2475,7 @@ static int dispc_ovl_calc_scaling_44xx(struct dispc_device *dispc, ((dividend) * 100 / (divisor) - ((dividend) / (divisor) * 100))
static int dispc_ovl_calc_scaling(struct dispc_device *dispc, + enum omap_plane_id plane, unsigned long pclk, unsigned long lclk, enum omap_overlay_caps caps, const struct videomode *vm, @@ -2485,7 +2486,8 @@ static int dispc_ovl_calc_scaling(struct dispc_device *dispc, enum omap_dss_rotation_type rotation_type, bool mem_to_mem) { - const int maxdownscale = dispc->feat->max_downscale; + int maxhdownscale = dispc->feat->max_downscale; + int maxvdownscale = dispc->feat->max_downscale; const int max_decim_limit = 16; unsigned long core_clk = 0; int decim_x, decim_y, ret; @@ -2493,6 +2495,20 @@ static int dispc_ovl_calc_scaling(struct dispc_device *dispc, if (width == out_width && height == out_height) return 0;
+ if (plane == OMAP_DSS_WB) { + switch (fourcc) { + case DRM_FORMAT_NV12: + maxhdownscale = maxvdownscale = 2; + break; + case DRM_FORMAT_YUYV: + case DRM_FORMAT_UYVY: + maxhdownscale = 2; + maxvdownscale = 4; + break; + default: + break; + } + } if (!mem_to_mem && (pclk == 0 || vm->pixelclock == 0)) { DSSERR("cannot calculate scaling settings: pclk is zero\n"); return -EINVAL; @@ -2510,8 +2526,8 @@ static int dispc_ovl_calc_scaling(struct dispc_device *dispc, 2 : max_decim_limit; }
- decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxdownscale); - decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxdownscale); + decim_x = DIV_ROUND_UP(DIV_ROUND_UP(width, out_width), maxhdownscale); + decim_y = DIV_ROUND_UP(DIV_ROUND_UP(height, out_height), maxvdownscale);
if (decim_x > *x_predecim || out_width > width * 8) return -EINVAL; @@ -2615,7 +2631,7 @@ static int dispc_ovl_setup_common(struct dispc_device *dispc, if (!dispc_ovl_color_mode_supported(dispc, plane, fourcc)) return -EINVAL;
- r = dispc_ovl_calc_scaling(dispc, pclk, lclk, caps, vm, in_width, + r = dispc_ovl_calc_scaling(dispc, plane, pclk, lclk, caps, vm, in_width, in_height, out_width, out_height, fourcc, &five_taps, &x_predecim, &y_predecim, pos_x, rotation_type, mem_to_mem);
Add writeback specific dispc functions to dispc_ops so that omapdrm can use them. Also move 'enum dss_writeback_channel' to the public omapdss.h for omapdrm.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 19 +++++++++++++++---- drivers/gpu/drm/omapdrm/dss/dss.h | 21 --------------------- drivers/gpu/drm/omapdrm/dss/omapdss.h | 20 ++++++++++++++++++++ 3 files changed, 35 insertions(+), 25 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 2aa72845f819..57960df1517a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -715,7 +715,7 @@ static u32 dispc_mgr_get_sync_lost_irq(struct dispc_device *dispc, return mgr_desc[channel].sync_lost_irq; }
-u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc) +static u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc) { return DISPC_IRQ_FRAMEDONEWB; } @@ -750,12 +750,12 @@ static void dispc_mgr_go(struct dispc_device *dispc, enum omap_channel channel) mgr_fld_write(dispc, channel, DISPC_MGR_FLD_GO, 1); }
-bool dispc_wb_go_busy(struct dispc_device *dispc) +static bool dispc_wb_go_busy(struct dispc_device *dispc) { return REG_GET(dispc, DISPC_CONTROL2, 6, 6) == 1; }
-void dispc_wb_go(struct dispc_device *dispc) +static void dispc_wb_go(struct dispc_device *dispc) { enum omap_plane_id plane = OMAP_DSS_WB; bool enable, go; @@ -2771,7 +2771,7 @@ static int dispc_ovl_setup(struct dispc_device *dispc, return r; }
-int dispc_wb_setup(struct dispc_device *dispc, +static int dispc_wb_setup(struct dispc_device *dispc, const struct omap_dss_writeback_info *wi, bool mem_to_mem, const struct videomode *vm, enum dss_writeback_channel channel_in) @@ -2854,6 +2854,11 @@ int dispc_wb_setup(struct dispc_device *dispc, return 0; }
+static bool dispc_has_writeback(struct dispc_device *dispc) +{ + return dispc->feat->has_writeback; +} + static int dispc_ovl_enable(struct dispc_device *dispc, enum omap_plane_id plane, bool enable) { @@ -4709,6 +4714,12 @@ static const struct dispc_ops dispc_ops = { .ovl_enable = dispc_ovl_enable, .ovl_setup = dispc_ovl_setup, .ovl_get_color_modes = dispc_ovl_get_color_modes, + + .wb_get_framedone_irq = dispc_wb_get_framedone_irq, + .wb_setup = dispc_wb_setup, + .has_writeback = dispc_has_writeback, + .wb_go_busy = dispc_wb_go_busy, + .wb_go = dispc_wb_go, };
/* DISPC HW IP initialisation */ diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index c56c3c59bf18..c601ed9a09c2 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -102,17 +102,6 @@ enum dss_dsi_content_type { DSS_DSI_CONTENT_GENERIC, };
-enum dss_writeback_channel { - DSS_WB_LCD1_MGR = 0, - DSS_WB_LCD2_MGR = 1, - DSS_WB_TV_MGR = 2, - DSS_WB_OVL0 = 3, - DSS_WB_OVL1 = 4, - DSS_WB_OVL2 = 5, - DSS_WB_OVL3 = 6, - DSS_WB_LCD3_MGR = 7, -}; - enum dss_clk_source { DSS_CLK_SRC_FCK = 0,
@@ -448,16 +437,6 @@ int dispc_mgr_get_clock_div(struct dispc_device *dispc, struct dispc_clock_info *cinfo); void dispc_set_tv_pclk(struct dispc_device *dispc, unsigned long pclk);
-u32 dispc_wb_get_framedone_irq(struct dispc_device *dispc); -bool dispc_wb_go_busy(struct dispc_device *dispc); -void dispc_wb_go(struct dispc_device *dispc); -void dispc_wb_set_channel_in(struct dispc_device *dispc, - enum dss_writeback_channel channel); -int dispc_wb_setup(struct dispc_device *dispc, - const struct omap_dss_writeback_info *wi, - bool mem_to_mem, const struct videomode *vm, - enum dss_writeback_channel channel_in); - #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS static inline void dss_collect_irq_stats(u32 irqstatus, unsigned int *irq_arr) { diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 162f36fa3431..14d74adb13fb 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -626,6 +626,17 @@ omapdss_of_find_source_for_first_ep(struct device_node *node); struct device_node *dss_of_port_get_parent_device(struct device_node *port); u32 dss_of_port_get_port_number(struct device_node *port);
+enum dss_writeback_channel { + DSS_WB_LCD1_MGR = 0, + DSS_WB_LCD2_MGR = 1, + DSS_WB_TV_MGR = 2, + DSS_WB_OVL0 = 3, + DSS_WB_OVL1 = 4, + DSS_WB_OVL2 = 5, + DSS_WB_OVL3 = 6, + DSS_WB_LCD3_MGR = 7, +}; + struct dss_mgr_ops { int (*connect)(struct omap_drm_private *priv, enum omap_channel channel, @@ -732,6 +743,15 @@ struct dispc_ops {
const u32 *(*ovl_get_color_modes)(struct dispc_device *dispc, enum omap_plane_id plane); + + u32 (*wb_get_framedone_irq)(struct dispc_device *dispc); + int (*wb_setup)(struct dispc_device *dispc, + const struct omap_dss_writeback_info *wi, + bool mem_to_mem, const struct videomode *vm, + enum dss_writeback_channel channel_in); + bool (*has_writeback)(struct dispc_device *dispc); + bool (*wb_go_busy)(struct dispc_device *dispc); + void (*wb_go)(struct dispc_device *dispc); };
struct dispc_device *dispc_get_dispc(struct dss_device *dss);
We define max width and height in mode_config to 2048. These maximums affect many things, which are independent and depend on platform. We need to do more fine grained checks in the code paths for each component, and so the maximum values in mode_config should just be "big enough" to cover all use cases.
Change the maximum width & height to 8192.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/omap_drv.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 4f48b908bdc6..3632854c2b91 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -310,11 +310,14 @@ static int omap_modeset_init(struct drm_device *dev) dev->mode_config.min_width = 8; dev->mode_config.min_height = 2;
- /* note: eventually will need some cpu_is_omapXYZ() type stuff here - * to fill in these limits properly on different OMAP generations.. + /* + * Note: these values are used for multiple independent things: + * connector mode filtering, buffer sizes, crtc sizes... + * Use big enough values here to cover all use cases, and do more + * specific checking in the respective code paths. */ - dev->mode_config.max_width = 2048; - dev->mode_config.max_height = 2048; + dev->mode_config.max_width = 8192; + dev->mode_config.max_height = 8192;
dev->mode_config.funcs = &omap_mode_config_funcs; dev->mode_config.helper_private = &omap_mode_config_helper_funcs;
From: Jyri Sarha jsarha@ti.com
Allow HDMI audio setup even if we do not have video configured. Audio will get configured at the same time with video if the video is configured soon enough. If it is not the audio DMA will timeout in couple of seconds and audio playback will be aborted.
Signed-off-by: Jyri Sarha jsarha@ti.com Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 33 ++++++++++++++------------------- drivers/gpu/drm/omapdrm/dss/hdmi5.c | 37 ++++++++++++++++--------------------- 2 files changed, 30 insertions(+), 40 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 1f7897c58f2f..97c88861d67a 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -615,21 +615,16 @@ static int hdmi_audio_startup(struct device *dev, void (*abort_cb)(struct device *dev)) { struct omap_hdmi *hd = dev_get_drvdata(dev); - int ret = 0;
mutex_lock(&hd->lock);
- if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { - ret = -EPERM; - goto out; - } + WARN_ON(hd->audio_abort_cb != NULL);
hd->audio_abort_cb = abort_cb;
-out: mutex_unlock(&hd->lock);
- return ret; + return 0; }
static int hdmi_audio_shutdown(struct device *dev) @@ -650,12 +645,14 @@ static int hdmi_audio_start(struct device *dev) struct omap_hdmi *hd = dev_get_drvdata(dev); unsigned long flags;
- WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); - spin_lock_irqsave(&hd->audio_playing_lock, flags);
- if (hd->display_enabled) + if (hd->display_enabled) { + if (!hdmi_mode_has_audio(&hd->cfg)) + DSSERR("%s: Video mode does not support audio\n", + __func__); hdmi_start_audio_stream(hd); + } hd->audio_playing = true;
spin_unlock_irqrestore(&hd->audio_playing_lock, flags); @@ -686,17 +683,15 @@ static int hdmi_audio_config(struct device *dev,
mutex_lock(&hd->lock);
- if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { - ret = -EPERM; - goto out; + if (hd->display_enabled) { + ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio, + hd->cfg.vm.pixelclock); + if (ret) + goto out; }
- ret = hdmi4_audio_config(&hd->core, &hd->wp, dss_audio, - hd->cfg.vm.pixelclock); - if (!ret) { - hd->audio_configured = true; - hd->audio_config = *dss_audio; - } + hd->audio_configured = true; + hd->audio_config = *dss_audio; out: mutex_unlock(&hd->lock);
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 4a0178ab8016..d28da9ac3e90 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -606,21 +606,16 @@ static int hdmi_audio_startup(struct device *dev, void (*abort_cb)(struct device *dev)) { struct omap_hdmi *hd = dev_get_drvdata(dev); - int ret = 0;
mutex_lock(&hd->lock);
- if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { - ret = -EPERM; - goto out; - } + WARN_ON(hd->audio_abort_cb != NULL);
hd->audio_abort_cb = abort_cb;
-out: mutex_unlock(&hd->lock);
- return ret; + return 0; }
static int hdmi_audio_shutdown(struct device *dev) @@ -641,12 +636,14 @@ static int hdmi_audio_start(struct device *dev) struct omap_hdmi *hd = dev_get_drvdata(dev); unsigned long flags;
- WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); - spin_lock_irqsave(&hd->audio_playing_lock, flags);
- if (hd->display_enabled) + if (hd->display_enabled) { + if (!hdmi_mode_has_audio(&hd->cfg)) + DSSERR("%s: Video mode does not support audio\n", + __func__); hdmi_start_audio_stream(hd); + } hd->audio_playing = true;
spin_unlock_irqrestore(&hd->audio_playing_lock, flags); @@ -658,7 +655,8 @@ static void hdmi_audio_stop(struct device *dev) struct omap_hdmi *hd = dev_get_drvdata(dev); unsigned long flags;
- WARN_ON(!hdmi_mode_has_audio(&hd->cfg)); + if (!hdmi_mode_has_audio(&hd->cfg)) + DSSERR("%s: Video mode does not support audio\n", __func__);
spin_lock_irqsave(&hd->audio_playing_lock, flags);
@@ -677,18 +675,15 @@ static int hdmi_audio_config(struct device *dev,
mutex_lock(&hd->lock);
- if (!hdmi_mode_has_audio(&hd->cfg) || !hd->display_enabled) { - ret = -EPERM; - goto out; + if (hd->display_enabled) { + ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio, + hd->cfg.vm.pixelclock); + if (ret) + goto out; }
- ret = hdmi5_audio_config(&hd->core, &hd->wp, dss_audio, - hd->cfg.vm.pixelclock); - - if (!ret) { - hd->audio_configured = true; - hd->audio_config = *dss_audio; - } + hd->audio_configured = true; + hd->audio_config = *dss_audio; out: mutex_unlock(&hd->lock);
The setup code for color space conversion is a bit messy. This patch cleans it up.
For some reason the TRM uses values in YCrCb order, which is also used in the current driver, whereas everywhere else it's YCbCr (which also matches YUV order). This patch changes the tables to use the common order to avoid confusion.
The tables are split into separate lines, and comments added for clarity.
WB color conversion registers are similar but different than non-WB, but the same function was used to write both. It worked fine because the coef table was adjusted accordingly, but that was rather confusing. This patch adds a separate function to write the WB values so that the coef table can be written in an understandable way.
Recalculation also showed that 'bcb' value in yuv-to-rgb conversion had been rounded wrongly, and it should be 516 instead of 517.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com --- drivers/gpu/drm/omapdrm/dss/dispc.c | 59 +++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 57960df1517a..f688f09b4eae 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -352,11 +352,6 @@ static const struct { }, };
-struct color_conv_coef { - int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb; - int full_range; -}; - static unsigned long dispc_fclk_rate(struct dispc_device *dispc); static unsigned long dispc_core_clk_rate(struct dispc_device *dispc); static unsigned long dispc_mgr_lclk_rate(struct dispc_device *dispc, @@ -868,10 +863,19 @@ static void dispc_ovl_set_scale_coef(struct dispc_device *dispc, } }
+struct csc_coef_yuv2rgb { + int ry, rcb, rcr, gy, gcb, gcr, by, bcb, bcr; + bool full_range; +}; + +struct csc_coef_rgb2yuv { + int yr, yg, yb, cbr, cbg, cbb, crr, crg, crb; + bool full_range; +};
static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc, enum omap_plane_id plane, - const struct color_conv_coef *ct) + const struct csc_coef_yuv2rgb *ct) { #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
@@ -886,25 +890,50 @@ static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc, #undef CVAL }
+static void dispc_wb_write_color_conv_coef(struct dispc_device *dispc, + const struct csc_coef_rgb2yuv *ct) +{ + const enum omap_plane_id plane = OMAP_DSS_WB; + +#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) + + dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->yg, ct->yr)); + dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->crr, ct->yb)); + dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->crb, ct->crg)); + dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->cbg, ct->cbr)); + dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->cbb)); + + REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), !!ct->full_range, 11, 11); + +#undef CVAL +} + static void dispc_setup_color_conv_coef(struct dispc_device *dispc) { int i; int num_ovl = dispc_get_num_ovls(dispc); - const struct color_conv_coef ctbl_bt601_5_ovl = { - /* YUV -> RGB */ - 298, 409, 0, 298, -208, -100, 298, 0, 517, 0, + + /* YUV -> RGB, ITU-R BT.601, limited range */ + const struct csc_coef_yuv2rgb coefs_yuv2rgb_bt601_lim = { + 298, 0, 409, /* ry, rcb, rcr */ + 298, -100, -208, /* gy, gcb, gcr */ + 298, 516, 0, /* by, bcb, bcr */ + false, /* limited range */ }; - const struct color_conv_coef ctbl_bt601_5_wb = { - /* RGB -> YUV */ - 66, 129, 25, 112, -94, -18, -38, -74, 112, 0, + + /* RGB -> YUV, ITU-R BT.601, limited range */ + const struct csc_coef_rgb2yuv coefs_rgb2yuv_bt601_lim = { + 66, 129, 25, /* yr, yg, yb */ + -38, -74, 112, /* cbr, cbg, cbb */ + 112, -94, -18, /* crr, crg, crb */ + false, /* limited range */ };
for (i = 1; i < num_ovl; i++) - dispc_ovl_write_color_conv_coef(dispc, i, &ctbl_bt601_5_ovl); + dispc_ovl_write_color_conv_coef(dispc, i, &coefs_yuv2rgb_bt601_lim);
if (dispc->feat->has_writeback) - dispc_ovl_write_color_conv_coef(dispc, OMAP_DSS_WB, - &ctbl_bt601_5_wb); + dispc_wb_write_color_conv_coef(dispc, &coefs_rgb2yuv_bt601_lim); }
static void dispc_ovl_set_ba0(struct dispc_device *dispc,
Hi Tomi,
Thank you for the patch.
On Wednesday, 28 February 2018 13:26:14 EET Tomi Valkeinen wrote:
The setup code for color space conversion is a bit messy. This patch cleans it up.
For some reason the TRM uses values in YCrCb order, which is also used in the current driver, whereas everywhere else it's YCbCr (which also matches YUV order). This patch changes the tables to use the common order to avoid confusion.
The tables are split into separate lines, and comments added for clarity.
WB color conversion registers are similar but different than non-WB, but the same function was used to write both. It worked fine because the coef table was adjusted accordingly, but that was rather confusing. This patch adds a separate function to write the WB values so that the coef table can be written in an understandable way.
Recalculation also showed that 'bcb' value in yuv-to-rgb conversion had been rounded wrongly, and it should be 516 instead of 517.
Signed-off-by: Tomi Valkeinen tomi.valkeinen@ti.com
drivers/gpu/drm/omapdrm/dss/dispc.c | 59 +++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index 57960df1517a..f688f09b4eae 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -352,11 +352,6 @@ static const struct { }, };
-struct color_conv_coef {
- int ry, rcr, rcb, gy, gcr, gcb, by, bcr, bcb;
- int full_range;
-};
static unsigned long dispc_fclk_rate(struct dispc_device *dispc); static unsigned long dispc_core_clk_rate(struct dispc_device *dispc); static unsigned long dispc_mgr_lclk_rate(struct dispc_device *dispc, @@ -868,10 +863,19 @@ static void dispc_ovl_set_scale_coef(struct dispc_device *dispc, } }
+struct csc_coef_yuv2rgb {
- int ry, rcb, rcr, gy, gcb, gcr, by, bcb, bcr;
- bool full_range;
+};
+struct csc_coef_rgb2yuv {
- int yr, yg, yb, cbr, cbg, cbb, crr, crg, crb;
- bool full_range;
+};
static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc, enum omap_plane_id plane,
const struct color_conv_coef *ct)
const struct csc_coef_yuv2rgb *ct)
{ #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
@@ -886,25 +890,50 @@ static void dispc_ovl_write_color_conv_coef(struct dispc_device *dispc, #undef CVAL }
+static void dispc_wb_write_color_conv_coef(struct dispc_device *dispc,
const struct csc_coef_rgb2yuv *ct)
+{
- const enum omap_plane_id plane = OMAP_DSS_WB;
+#define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0))
- dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 0), CVAL(ct->yg,
ct->yr));
- dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 1), CVAL(ct->crr,
ct->yb));
- dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 2), CVAL(ct->crb,
ct->crg));
- dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 3), CVAL(ct->cbg,
ct->cbr));
- dispc_write_reg(dispc, DISPC_OVL_CONV_COEF(plane, 4), CVAL(0, ct->cbb));
- REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), !!ct->full_range, 11, 11);
I think I mentioned in my review of v1 that you can drop the !!. Apart from that,
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
+#undef CVAL +}
static void dispc_setup_color_conv_coef(struct dispc_device *dispc) { int i; int num_ovl = dispc_get_num_ovls(dispc);
- const struct color_conv_coef ctbl_bt601_5_ovl = {
/* YUV -> RGB */
298, 409, 0, 298, -208, -100, 298, 0, 517, 0,
- /* YUV -> RGB, ITU-R BT.601, limited range */
- const struct csc_coef_yuv2rgb coefs_yuv2rgb_bt601_lim = {
298, 0, 409, /* ry, rcb, rcr */
298, -100, -208, /* gy, gcb, gcr */
298, 516, 0, /* by, bcb, bcr */
};false, /* limited range */
- const struct color_conv_coef ctbl_bt601_5_wb = {
/* RGB -> YUV */
66, 129, 25, 112, -94, -18, -38, -74, 112, 0,
/* RGB -> YUV, ITU-R BT.601, limited range */
const struct csc_coef_rgb2yuv coefs_rgb2yuv_bt601_lim = {
66, 129, 25, /* yr, yg, yb */
-38, -74, 112, /* cbr, cbg, cbb */
112, -94, -18, /* crr, crg, crb */
false, /* limited range */
};
for (i = 1; i < num_ovl; i++)
dispc_ovl_write_color_conv_coef(dispc, i, &ctbl_bt601_5_ovl);
dispc_ovl_write_color_conv_coef(dispc, i, &coefs_yuv2rgb_bt601_lim);
if (dispc->feat->has_writeback)
dispc_ovl_write_color_conv_coef(dispc, OMAP_DSS_WB,
&ctbl_bt601_5_wb);
dispc_wb_write_color_conv_coef(dispc, &coefs_rgb2yuv_bt601_lim);
}
static void dispc_ovl_set_ba0(struct dispc_device *dispc,
On 28/02/18 23:23, Laurent Pinchart wrote:
- REG_FLD_MOD(dispc, DISPC_OVL_ATTRIBUTES(plane), !!ct->full_range, 11, 11);
I think I mentioned in my review of v1 that you can drop the !!. Apart from that,
Reviewed-by: Laurent Pinchart laurent.pinchart@ideasonboard.com
Sorry about. I did remove it, but I made a few versions of the change, and apparently missed this in the final one. Now it's gone.
Tomi
dri-devel@lists.freedesktop.org