From 0396162ab9c571ee31f01866cbf168066dbf395d Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 8 Feb 2017 13:26:00 +0200 Subject: drm/omap: use vblank hooks in struct drm_crtc_funcs The vblank hooks in struct drm_driver are deprecated and only meant for legacy drivers. For modern drivers with DRIVER_MODESET flag, the hooks in struct drm_crtc_funcs should be used instead. Signed-off-by: Tomi Valkeinen Reviewed-by: Laurent Pinchart Signed-off-by: Daniel Vetter --- drivers/gpu/drm/omapdrm/omap_crtc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index dd47dc191e6b..bd18e8c4f1d0 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -501,6 +501,8 @@ static const struct drm_crtc_funcs omap_crtc_funcs = { .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .atomic_set_property = omap_crtc_atomic_set_property, .atomic_get_property = omap_crtc_atomic_get_property, + .enable_vblank = omap_irq_enable_vblank, + .disable_vblank = omap_irq_disable_vblank, }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { -- cgit From 7e3d92749dd773b8a1bd35b02e2aa1271cb7a31b Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Mon, 10 Aug 2015 12:08:50 +0300 Subject: drm/omap: refactor CRTC HW property setup The current driver doesn't expose any of the CRTC HW properties like background color or transparency key, and sets them at CRTC enable time. Refactor this into a separate function and call that function from omap_crtc_atomic_flush(). This is the behavior we want when the properties can be configured, so this patch makes it easier to add patches later which implement those properties. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 2fe735c269fc..49fc61963af4 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -198,15 +198,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) static int omap_crtc_dss_enable(enum omap_channel channel) { struct omap_crtc *omap_crtc = omap_crtcs[channel]; - struct omap_overlay_manager_info info; - memset(&info, 0, sizeof(info)); - info.default_color = 0x00000000; - info.trans_key = 0x00000000; - info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; - info.trans_enabled = false; - - dispc_mgr_setup(omap_crtc->channel, &info); dispc_mgr_set_timings(omap_crtc->channel, &omap_crtc->vm); omap_crtc_set_enabled(&omap_crtc->base, true); @@ -313,6 +305,21 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc) DBG("%s: apply done", omap_crtc->name); } +static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) +{ + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_overlay_manager_info info; + + memset(&info, 0, sizeof(info)); + + info.default_color = 0x000000; + info.trans_enabled = false; + info.partial_alpha_enabled = false; + info.cpr_enable = false; + + dispc_mgr_setup(omap_crtc->channel, &info); +} + /* ----------------------------------------------------------------------------- * CRTC Functions */ @@ -410,6 +417,8 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, dispc_mgr_set_gamma(omap_crtc->channel, lut, length); } + omap_crtc_write_crtc_properties(crtc); + /* Only flush the CRTC if it is currently enabled. */ if (!omap_crtc->enabled) return; -- cgit From 9f759225e42b00ad0c5a55907f443b388e8960f4 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Thu, 5 Nov 2015 18:39:52 +0200 Subject: drm/omap: use dispc_ops Change omapdrm to get dispc_ops and use that to call the dispc functions instead or direct function calls. The change is very straightforward. The only problem was in omap_crtc_init() which calls pipe2vbl(crtc), and at that point of time the crtc->dev link, which is used to get the dispc_ops, has not been set up yet. This patch makes omap_crtc_init() skip the call to pipe2vbl() and instead calls dispc_ops->mgr_get_vsync_irq() directly. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 36 +++++++++++++++++++++++------------- 1 file changed, 23 insertions(+), 13 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 49fc61963af4..1db96b077ae8 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -107,10 +107,12 @@ static struct omap_dss_device *omap_crtc_output[8]; static int omap_crtc_dss_connect(enum omap_channel channel, struct omap_dss_device *dst) { + const struct dispc_ops *dispc_ops = dispc_get_ops(); + if (omap_crtc_output[channel]) return -EINVAL; - if ((dispc_mgr_get_supported_outputs(channel) & dst->id) == 0) + if ((dispc_ops->mgr_get_supported_outputs(channel) & dst->id) == 0) return -EINVAL; omap_crtc_output[channel] = dst; @@ -134,6 +136,7 @@ static void omap_crtc_dss_start_update(enum omap_channel channel) static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) { struct drm_device *dev = crtc->dev; + struct omap_drm_private *priv = dev->dev_private; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); enum omap_channel channel = omap_crtc->channel; struct omap_irq_wait *wait; @@ -144,7 +147,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) return; if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { - dispc_mgr_enable(channel, enable); + priv->dispc_ops->mgr_enable(channel, enable); omap_crtc->enabled = enable; return; } @@ -157,8 +160,8 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) omap_crtc->ignore_digit_sync_lost = true; } - framedone_irq = dispc_mgr_get_framedone_irq(channel); - vsync_irq = dispc_mgr_get_vsync_irq(channel); + framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(channel); + vsync_irq = priv->dispc_ops->mgr_get_vsync_irq(channel); if (enable) { wait = omap_irq_wait_init(dev, vsync_irq, 1); @@ -178,7 +181,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) wait = omap_irq_wait_init(dev, vsync_irq, 2); } - dispc_mgr_enable(channel, enable); + priv->dispc_ops->mgr_enable(channel, enable); omap_crtc->enabled = enable; ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); @@ -198,9 +201,9 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) static int omap_crtc_dss_enable(enum omap_channel channel) { struct omap_crtc *omap_crtc = omap_crtcs[channel]; + struct omap_drm_private *priv = omap_crtc->base.dev->dev_private; - dispc_mgr_set_timings(omap_crtc->channel, - &omap_crtc->vm); + priv->dispc_ops->mgr_set_timings(omap_crtc->channel, &omap_crtc->vm); omap_crtc_set_enabled(&omap_crtc->base, true); return 0; @@ -225,8 +228,10 @@ static void omap_crtc_dss_set_lcd_config(enum omap_channel channel, const struct dss_lcd_mgr_config *config) { struct omap_crtc *omap_crtc = omap_crtcs[channel]; + struct omap_drm_private *priv = omap_crtc->base.dev->dev_private; + DBG("%s", omap_crtc->name); - dispc_mgr_set_lcd_config(omap_crtc->channel, config); + priv->dispc_ops->mgr_set_lcd_config(omap_crtc->channel, config); } static int omap_crtc_dss_register_framedone( @@ -274,6 +279,8 @@ void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus) void omap_crtc_vblank_irq(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct drm_device *dev = omap_crtc->base.dev; + struct omap_drm_private *priv = dev->dev_private; bool pending; spin_lock(&crtc->dev->event_lock); @@ -281,7 +288,7 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc) * If the dispc is busy we're racing the flush operation. Try again on * the next vblank interrupt. */ - if (dispc_mgr_go_busy(omap_crtc->channel)) { + if (priv->dispc_ops->mgr_go_busy(omap_crtc->channel)) { spin_unlock(&crtc->dev->event_lock); return; } @@ -307,6 +314,7 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc) static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) { + struct omap_drm_private *priv = crtc->dev->dev_private; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct omap_overlay_manager_info info; @@ -317,7 +325,7 @@ static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) info.partial_alpha_enabled = false; info.cpr_enable = false; - dispc_mgr_setup(omap_crtc->channel, &info); + priv->dispc_ops->mgr_setup(omap_crtc->channel, &info); } /* ----------------------------------------------------------------------------- @@ -401,6 +409,7 @@ static void omap_crtc_atomic_begin(struct drm_crtc *crtc, static void omap_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { + struct omap_drm_private *priv = crtc->dev->dev_private; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); int ret; @@ -414,7 +423,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, length = crtc->state->gamma_lut->length / sizeof(*lut); } - dispc_mgr_set_gamma(omap_crtc->channel, lut, length); + priv->dispc_ops->mgr_set_gamma(omap_crtc->channel, lut, length); } omap_crtc_write_crtc_properties(crtc); @@ -429,7 +438,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, WARN_ON(ret != 0); spin_lock_irq(&crtc->dev->event_lock); - dispc_mgr_go(omap_crtc->channel); + priv->dispc_ops->mgr_go(omap_crtc->channel); WARN_ON(omap_crtc->pending); omap_crtc->pending = true; @@ -542,6 +551,7 @@ void omap_crtc_pre_uninit(void) struct drm_crtc *omap_crtc_init(struct drm_device *dev, struct drm_plane *plane, enum omap_channel channel, int id) { + struct omap_drm_private *priv = dev->dev_private; struct drm_crtc *crtc = NULL; struct omap_crtc *omap_crtc; int ret; @@ -575,7 +585,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, * extracted with dispc_mgr_gamma_size(). If it returns 0 * gamma table is not supprted. */ - if (dispc_mgr_gamma_size(channel)) { + if (priv->dispc_ops->mgr_gamma_size(channel)) { uint gamma_lut_size = 256; drm_crtc_enable_color_mgmt(crtc, 0, false, gamma_lut_size); -- cgit From 50fa9f0bb8c1eb7d0dbd404766a67c34756d5a80 Mon Sep 17 00:00:00 2001 From: Tomi Valkeinen Date: Wed, 23 Nov 2016 13:24:00 +0200 Subject: drm/omap: fix display SYNC/DE flags At the moment VSYNC/HSYNC/DE high/low flags set by the panel/encoder drivers get lost when the videotimings are translated to DRM's videomode, as DRM's mode does not have corresponding flags. DRM has bus-flags for this purpose, and while it lacks a few flags at the moment, it should be used here. However, until we rewrite omapdrm's device model, using bus-flags is rather difficult. As a short term fix, this patch makes sure that every time the videomode is set in omap_crtc_mode_set_nofb(), the driver asks for the SYNC/DE flags from the panel/encoder drivers, and thus we get the correct flags into use. Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 40 ++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 1db96b077ae8..4f03f74685f0 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -373,6 +373,11 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_display_mode *mode = &crtc->state->adjusted_mode; + struct omap_drm_private *priv = crtc->dev->dev_private; + const u32 flags_mask = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_DE_LOW | + DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_PIXDATA_NEGEDGE | + DISPLAY_FLAGS_SYNC_POSEDGE | DISPLAY_FLAGS_SYNC_NEGEDGE; + unsigned int i; DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", omap_crtc->name, mode->base.id, mode->name, @@ -382,9 +387,38 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) mode->type, mode->flags); drm_display_mode_to_videomode(mode, &omap_crtc->vm); - omap_crtc->vm.flags |= DISPLAY_FLAGS_DE_HIGH | - DISPLAY_FLAGS_PIXDATA_POSEDGE | - DISPLAY_FLAGS_SYNC_NEGEDGE; + + /* + * HACK: This fixes the vm flags. + * struct drm_display_mode does not contain the VSYNC/HSYNC/DE flags + * and they get lost when converting back and forth between + * struct drm_display_mode and struct videomode. The hack below + * goes and fetches the missing flags from the panel drivers. + * + * Correct solution would be to use DRM's bus-flags, but that's not + * easily possible before the omapdrm's panel/encoder driver model + * has been changed to the DRM model. + */ + + for (i = 0; i < priv->num_encoders; ++i) { + struct drm_encoder *encoder = priv->encoders[i]; + + if (encoder->crtc == crtc) { + struct omap_dss_device *dssdev; + + dssdev = omap_encoder_get_dssdev(encoder); + + if (dssdev) { + struct videomode vm = {0}; + + dssdev->driver->get_timings(dssdev, &vm); + + omap_crtc->vm.flags |= vm.flags & flags_mask; + } + + break; + } + } } static int omap_crtc_atomic_check(struct drm_crtc *crtc, -- cgit From e8e13b1521678af0df7b07f30745d77e8de1820a Mon Sep 17 00:00:00 2001 From: Jyri Sarha Date: Fri, 24 Mar 2017 16:47:55 +0200 Subject: drm/omap: Major omap_modeset_init() cleanup Cleanup overly complex omap_modeset_init(). The function is trying to support many unusual configuration, that have never been tested and are not supported by other parts of the dirver. After cleanup the init function creates exactly one connector, encoder, crtc, and primary plane per each connected dss-device. Each connector->encoder->crtc chain is expected to be separate and each crtc is connect to a single dss-channel. If the configuration does not match the expectations or exceeds the available resources, the configuration is rejected. Signed-off-by: Jyri Sarha Signed-off-by: Tomi Valkeinen --- drivers/gpu/drm/omapdrm/omap_crtc.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c') diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 4f03f74685f0..dccd03726796 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -573,6 +573,8 @@ static const char *channel_names[] = { void omap_crtc_pre_init(void) { + memset(omap_crtcs, 0, sizeof(omap_crtcs)); + dss_install_mgr_ops(&mgr_ops); } @@ -583,18 +585,28 @@ void omap_crtc_pre_uninit(void) /* initialize crtc */ struct drm_crtc *omap_crtc_init(struct drm_device *dev, - struct drm_plane *plane, enum omap_channel channel, int id) + struct drm_plane *plane, struct omap_dss_device *dssdev) { struct omap_drm_private *priv = dev->dev_private; struct drm_crtc *crtc = NULL; struct omap_crtc *omap_crtc; + enum omap_channel channel; + struct omap_dss_device *out; int ret; + out = omapdss_find_output_from_display(dssdev); + channel = out->dispc_channel; + omap_dss_put_device(out); + DBG("%s", channel_names[channel]); + /* Multiple displays on same channel is not allowed */ + if (WARN_ON(omap_crtcs[channel] != NULL)) + return ERR_PTR(-EINVAL); + omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); if (!omap_crtc) - return NULL; + return ERR_PTR(-ENOMEM); crtc = &omap_crtc->base; @@ -606,8 +618,10 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, &omap_crtc_funcs, NULL); if (ret < 0) { + dev_err(dev->dev, "%s(): could not init crtc for: %s\n", + __func__, dssdev->name); kfree(omap_crtc); - return NULL; + return ERR_PTR(ret); } drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); -- cgit