From patchwork Tue Aug 20 01:17:00 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 11102477 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id C21AC1398 for ; Tue, 20 Aug 2019 01:18:14 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id ABF8822CF5 for ; Tue, 20 Aug 2019 01:18:14 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org ABF8822CF5 Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=ideasonboard.com Authentication-Results: mail.kernel.org; spf=none smtp.mailfrom=dri-devel-bounces@lists.freedesktop.org Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id E379D6E56D; Tue, 20 Aug 2019 01:18:03 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by gabe.freedesktop.org (Postfix) with ESMTPS id AD9936E520 for ; Tue, 20 Aug 2019 01:17:58 +0000 (UTC) Received: from pendragon.bb.dnainternet.fi (dfj612yhrgyx302h3jwwy-3.rev.dnainternet.fi [IPv6:2001:14ba:21f5:5b00:ce28:277f:58d7:3ca4]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 292EA9C5; Tue, 20 Aug 2019 03:17:52 +0200 (CEST) From: Laurent Pinchart To: dri-devel@lists.freedesktop.org Subject: [PATCH v2 29/50] drm/omap: hdmi4: Move mode set, enable and disable operations to bridge Date: Tue, 20 Aug 2019 04:17:00 +0300 Message-Id: <20190820011721.30136-30-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190820011721.30136-1-laurent.pinchart@ideasonboard.com> References: <20190820011721.30136-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1566263872; bh=wx943xwggQjeMpXSar5BksOK16B88yPCEYf8VS/WAbA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=k5URE8oU9f6tS8wKub6lSAEOVxRputmqd3BZgjO3YMe4GXJxbgsp1o63BVY5oWcAs 1VF+5kyVhz+U2gfUOatdEY+L6SZIdwPjvM4GyeJf9rL5rk2dq5FCTFX67AZXeFvAxW lw6U/m4faiM/oX3dWkH0+0IQZYm0J9GyZUK8TZcQ= X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Maxime Ripard , Tomi Valkeinen , Sean Paul , Sebastian Reichel Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Move the omap_dss_device .set_timings(), .enable() and .disable() operations to the drm_bridge functions. As the drm_bridge for the HDMI encoder is unconditionally registered and attached, those operations will be called at the appropriate time. Signed-off-by: Laurent Pinchart --- drivers/gpu/drm/omapdrm/dss/hdmi4.c | 201 +++++++++++++++------------- 1 file changed, 106 insertions(+), 95 deletions(-) diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index 8b6fcd724d66..2211a7a3dad3 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -28,6 +28,8 @@ #include #include +#include + #include "omapdss.h" #include "hdmi4_core.h" #include "hdmi4_cec.h" @@ -237,20 +239,6 @@ static void hdmi_power_off_full(struct omap_hdmi *hdmi) hdmi_power_off_core(hdmi); } -static void hdmi_display_set_timings(struct omap_dss_device *dssdev, - const struct drm_display_mode *mode) -{ - struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev); - - mutex_lock(&hdmi->lock); - - drm_display_mode_to_videomode(mode, &hdmi->cfg.vm); - - dispc_set_tv_pclk(hdmi->dss->dispc, mode->clock * 1000); - - mutex_unlock(&hdmi->lock); -} - static int hdmi_dump_regs(struct seq_file *s, void *p) { struct omap_hdmi *hdmi = s->private; @@ -284,62 +272,6 @@ static void hdmi_stop_audio_stream(struct omap_hdmi *hd) hdmi_wp_audio_enable(&hd->wp, false); } -static void hdmi_display_enable(struct omap_dss_device *dssdev) -{ - struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev); - unsigned long flags; - int r; - - DSSDBG("ENTER hdmi_display_enable\n"); - - mutex_lock(&hdmi->lock); - - r = hdmi_power_on_full(hdmi); - if (r) { - DSSERR("failed to power on device\n"); - goto done; - } - - if (hdmi->audio_configured) { - r = hdmi4_audio_config(&hdmi->core, &hdmi->wp, - &hdmi->audio_config, - hdmi->cfg.vm.pixelclock); - if (r) { - DSSERR("Error restoring audio configuration: %d", r); - hdmi->audio_abort_cb(&hdmi->pdev->dev); - hdmi->audio_configured = false; - } - } - - spin_lock_irqsave(&hdmi->audio_playing_lock, flags); - if (hdmi->audio_configured && hdmi->audio_playing) - hdmi_start_audio_stream(hdmi); - hdmi->display_enabled = true; - spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags); - -done: - mutex_unlock(&hdmi->lock); -} - -static void hdmi_display_disable(struct omap_dss_device *dssdev) -{ - struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev); - unsigned long flags; - - DSSDBG("Enter hdmi_display_disable\n"); - - mutex_lock(&hdmi->lock); - - spin_lock_irqsave(&hdmi->audio_playing_lock, flags); - hdmi_stop_audio_stream(hdmi); - hdmi->display_enabled = false; - spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags); - - hdmi_power_off_full(hdmi); - - mutex_unlock(&hdmi->lock); -} - int hdmi4_core_enable(struct hdmi_core_data *core) { struct omap_hdmi *hdmi = container_of(core, struct omap_hdmi, core); @@ -491,39 +423,14 @@ static void hdmi_lost_hotplug(struct omap_dss_device *dssdev) hdmi4_cec_set_phys_addr(&hdmi->core, CEC_PHYS_ADDR_INVALID); } -static int hdmi_set_infoframe(struct omap_dss_device *dssdev, - const struct hdmi_avi_infoframe *avi) -{ - struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev); - - hdmi->cfg.infoframe = *avi; - return 0; -} - -static int hdmi_set_hdmi_mode(struct omap_dss_device *dssdev, - bool hdmi_mode) -{ - struct omap_hdmi *hdmi = dssdev_to_hdmi(dssdev); - - hdmi->cfg.hdmi_dvi_mode = hdmi_mode ? HDMI_HDMI : HDMI_DVI; - return 0; -} - static const struct omap_dss_device_ops hdmi_ops = { .connect = hdmi_connect, .disconnect = hdmi_disconnect, - .enable = hdmi_display_enable, - .disable = hdmi_display_disable, - - .set_timings = hdmi_display_set_timings, - .read_edid = hdmi_read_edid, .hdmi = { .lost_hotplug = hdmi_lost_hotplug, - .set_infoframe = hdmi_set_infoframe, - .set_hdmi_mode = hdmi_set_hdmi_mode, }, }; @@ -543,6 +450,107 @@ static int hdmi4_bridge_attach(struct drm_bridge *bridge, bridge, flags); } +static void hdmi4_bridge_mode_set(struct drm_bridge *bridge, + const struct drm_display_mode *mode, + const struct drm_display_mode *adjusted_mode) +{ + struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); + + mutex_lock(&hdmi->lock); + + drm_display_mode_to_videomode(adjusted_mode, &hdmi->cfg.vm); + + dispc_set_tv_pclk(hdmi->dss->dispc, adjusted_mode->clock * 1000); + + mutex_unlock(&hdmi->lock); +} + +static void hdmi4_bridge_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); + struct drm_connector_state *conn_state; + struct drm_connector *connector; + struct drm_crtc_state *crtc_state; + unsigned long flags; + int ret; + + /* + * None of these should fail, as the bridge can't be enabled without a + * valid CRTC to connector path with fully populated new states. + */ + connector = drm_atomic_get_new_connector_for_encoder(state, + bridge->encoder); + if (WARN_ON(!connector)) + return; + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return; + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (WARN_ON(!crtc_state)) + return; + + hdmi->cfg.hdmi_dvi_mode = connector->display_info.is_hdmi + ? HDMI_HDMI : HDMI_DVI; + + if (connector->display_info.is_hdmi) { + const struct drm_display_mode *mode; + struct hdmi_avi_infoframe avi; + + mode = &crtc_state->adjusted_mode; + ret = drm_hdmi_avi_infoframe_from_display_mode(&avi, connector, + mode); + if (ret == 0) + hdmi->cfg.infoframe = avi; + } + + mutex_lock(&hdmi->lock); + + ret = hdmi_power_on_full(hdmi); + if (ret) { + DSSERR("failed to power on device\n"); + goto done; + } + + if (hdmi->audio_configured) { + ret = hdmi4_audio_config(&hdmi->core, &hdmi->wp, + &hdmi->audio_config, + hdmi->cfg.vm.pixelclock); + if (ret) { + DSSERR("Error restoring audio configuration: %d", ret); + hdmi->audio_abort_cb(&hdmi->pdev->dev); + hdmi->audio_configured = false; + } + } + + spin_lock_irqsave(&hdmi->audio_playing_lock, flags); + if (hdmi->audio_configured && hdmi->audio_playing) + hdmi_start_audio_stream(hdmi); + hdmi->display_enabled = true; + spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags); + +done: + mutex_unlock(&hdmi->lock); +} + +static void hdmi4_bridge_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct omap_hdmi *hdmi = drm_bridge_to_hdmi(bridge); + unsigned long flags; + + mutex_lock(&hdmi->lock); + + spin_lock_irqsave(&hdmi->audio_playing_lock, flags); + hdmi_stop_audio_stream(hdmi); + hdmi->display_enabled = false; + spin_unlock_irqrestore(&hdmi->audio_playing_lock, flags); + + hdmi_power_off_full(hdmi); + + mutex_unlock(&hdmi->lock); +} + static struct edid *hdmi4_bridge_read_edid(struct omap_hdmi *hdmi, struct drm_connector *connector) { @@ -559,6 +567,9 @@ static struct edid *hdmi4_bridge_get_edid(struct drm_bridge *bridge, static const struct drm_bridge_funcs hdmi4_bridge_funcs = { .attach = hdmi4_bridge_attach, + .mode_set = hdmi4_bridge_mode_set, + .atomic_enable = hdmi4_bridge_enable, + .atomic_disable = hdmi4_bridge_disable, .get_edid = hdmi4_bridge_get_edid, };