diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm/omap_crtc.c')
-rw-r--r-- | drivers/gpu/drm/omapdrm/omap_crtc.c | 140 |
1 files changed, 71 insertions, 69 deletions
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index 2ed0754ed19e..075f2bb44867 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -34,14 +34,6 @@ struct omap_crtc { const char *name; enum omap_channel channel; - /* - * Temporary: eventually this will go away, but it is needed - * for now to keep the output's happy. (They only need - * mgr->id.) Eventually this will be replaced w/ something - * more common-panel-framework-y - */ - struct omap_overlay_manager *mgr; - struct omap_video_timings timings; struct omap_drm_irq vblank_irq; @@ -80,9 +72,13 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + /* + * Timeout is set to a "sufficiently" high value, which should cover + * a single frame refresh even on slower displays. + */ return wait_event_timeout(omap_crtc->pending_wait, !omap_crtc->pending, - msecs_to_jiffies(50)); + msecs_to_jiffies(250)); } /* ----------------------------------------------------------------------------- @@ -100,31 +96,32 @@ int omap_crtc_wait_pending(struct drm_crtc *crtc) /* ovl-mgr-id -> crtc */ static struct omap_crtc *omap_crtcs[8]; +static struct omap_dss_device *omap_crtc_output[8]; /* we can probably ignore these until we support command-mode panels: */ -static int omap_crtc_dss_connect(struct omap_overlay_manager *mgr, +static int omap_crtc_dss_connect(enum omap_channel channel, struct omap_dss_device *dst) { - if (mgr->output) + if (omap_crtc_output[channel]) return -EINVAL; - if ((mgr->supported_outputs & dst->id) == 0) + if ((dispc_mgr_get_supported_outputs(channel) & dst->id) == 0) return -EINVAL; - dst->manager = mgr; - mgr->output = dst; + omap_crtc_output[channel] = dst; + dst->dispc_channel_connected = true; return 0; } -static void omap_crtc_dss_disconnect(struct omap_overlay_manager *mgr, +static void omap_crtc_dss_disconnect(enum omap_channel channel, struct omap_dss_device *dst) { - mgr->output->manager = NULL; - mgr->output = NULL; + omap_crtc_output[channel] = NULL; + dst->dispc_channel_connected = false; } -static void omap_crtc_dss_start_update(struct omap_overlay_manager *mgr) +static void omap_crtc_dss_start_update(enum omap_channel channel) { } @@ -138,6 +135,11 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) u32 framedone_irq, vsync_irq; int ret; + if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { + dispc_mgr_enable(channel, enable); + return; + } + if (dispc_mgr_is_enabled(channel) == enable) return; @@ -186,9 +188,9 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) } -static int omap_crtc_dss_enable(struct omap_overlay_manager *mgr) +static int omap_crtc_dss_enable(enum omap_channel channel) { - struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; + struct omap_crtc *omap_crtc = omap_crtcs[channel]; struct omap_overlay_manager_info info; memset(&info, 0, sizeof(info)); @@ -205,38 +207,38 @@ static int omap_crtc_dss_enable(struct omap_overlay_manager *mgr) return 0; } -static void omap_crtc_dss_disable(struct omap_overlay_manager *mgr) +static void omap_crtc_dss_disable(enum omap_channel channel) { - struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; + struct omap_crtc *omap_crtc = omap_crtcs[channel]; omap_crtc_set_enabled(&omap_crtc->base, false); } -static void omap_crtc_dss_set_timings(struct omap_overlay_manager *mgr, +static void omap_crtc_dss_set_timings(enum omap_channel channel, const struct omap_video_timings *timings) { - struct omap_crtc *omap_crtc = omap_crtcs[mgr->id]; + struct omap_crtc *omap_crtc = omap_crtcs[channel]; DBG("%s", omap_crtc->name); omap_crtc->timings = *timings; } -static void omap_crtc_dss_set_lcd_config(struct omap_overlay_manager *mgr, +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[mgr->id]; + struct omap_crtc *omap_crtc = omap_crtcs[channel]; DBG("%s", omap_crtc->name); dispc_mgr_set_lcd_config(omap_crtc->channel, config); } static int omap_crtc_dss_register_framedone( - struct omap_overlay_manager *mgr, + enum omap_channel channel, void (*handler)(void *), void *data) { return 0; } static void omap_crtc_dss_unregister_framedone( - struct omap_overlay_manager *mgr, + enum omap_channel channel, void (*handler)(void *), void *data) { } @@ -269,18 +271,7 @@ static void omap_crtc_complete_page_flip(struct drm_crtc *crtc) return; spin_lock_irqsave(&dev->event_lock, flags); - - list_del(&event->base.link); - - /* - * Queue the event for delivery if it's still linked to a file - * handle, otherwise just destroy it. - */ - if (event->base.file_priv) - drm_crtc_send_vblank_event(crtc, event); - else - event->base.destroy(&event->base); - + drm_crtc_send_vblank_event(crtc, event); spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -341,13 +332,6 @@ static void omap_crtc_destroy(struct drm_crtc *crtc) kfree(omap_crtc); } -static bool omap_crtc_mode_fixup(struct drm_crtc *crtc, - const struct drm_display_mode *mode, - struct drm_display_mode *adjusted_mode) -{ - return true; -} - static void omap_crtc_enable(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); @@ -414,24 +398,40 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, } } +static bool omap_crtc_is_plane_prop(struct drm_device *dev, + struct drm_property *property) +{ + struct omap_drm_private *priv = dev->dev_private; + + return property == priv->zorder_prop || + property == dev->mode_config.rotation_property; +} + static int omap_crtc_atomic_set_property(struct drm_crtc *crtc, struct drm_crtc_state *state, struct drm_property *property, uint64_t val) { - struct drm_plane_state *plane_state; - struct drm_plane *plane = crtc->primary; + struct drm_device *dev = crtc->dev; - /* - * Delegate property set to the primary plane. Get the plane state and - * set the property directly. - */ + if (omap_crtc_is_plane_prop(dev, property)) { + struct drm_plane_state *plane_state; + struct drm_plane *plane = crtc->primary; - plane_state = drm_atomic_get_plane_state(state->state, plane); - if (!plane_state) - return -EINVAL; + /* + * Delegate property set to the primary plane. Get the plane + * state and set the property directly. + */ + + plane_state = drm_atomic_get_plane_state(state->state, plane); + if (IS_ERR(plane_state)) + return PTR_ERR(plane_state); + + return drm_atomic_plane_set_property(plane, plane_state, + property, val); + } - return drm_atomic_plane_set_property(plane, plane_state, property, val); + return -EINVAL; } static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, @@ -439,14 +439,20 @@ static int omap_crtc_atomic_get_property(struct drm_crtc *crtc, struct drm_property *property, uint64_t *val) { - /* - * Delegate property get to the primary plane. The - * drm_atomic_plane_get_property() function isn't exported, but can be - * called through drm_object_property_get_value() as that will call - * drm_atomic_get_property() for atomic drivers. - */ - return drm_object_property_get_value(&crtc->primary->base, property, - val); + struct drm_device *dev = crtc->dev; + + if (omap_crtc_is_plane_prop(dev, property)) { + /* + * Delegate property get to the primary plane. The + * drm_atomic_plane_get_property() function isn't exported, but + * can be called through drm_object_property_get_value() as that + * will call drm_atomic_get_property() for atomic drivers. + */ + return drm_object_property_get_value(&crtc->primary->base, + property, val); + } + + return -EINVAL; } static const struct drm_crtc_funcs omap_crtc_funcs = { @@ -462,7 +468,6 @@ static const struct drm_crtc_funcs omap_crtc_funcs = { }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { - .mode_fixup = omap_crtc_mode_fixup, .mode_set_nofb = omap_crtc_mode_set_nofb, .disable = omap_crtc_disable, .enable = omap_crtc_enable, @@ -520,9 +525,6 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, omap_crtc->error_irq.irq = omap_crtc_error_irq; omap_irq_register(dev, &omap_crtc->error_irq); - /* temporary: */ - omap_crtc->mgr = omap_dss_get_overlay_manager(channel); - ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, &omap_crtc_funcs, NULL); if (ret < 0) { |