From nobody Wed Dec 17 14:10:41 2025 Received: from mail-lj1-f181.google.com (mail-lj1-f181.google.com [209.85.208.181]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2C34383CCC for ; Sat, 22 Jun 2024 22:02:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.181 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719093748; cv=none; b=Mb2EZ9bGVdPXbbPa8YXuwaZAPX4ES3x3+SUFINEzWuixjWpFdYzMDKPzesVDJOOdCI1907aBGbZ3ISiWXbcnd0NuPRJSHgwN6hr+qaEugDab8CmE6zRGhwTMcPXk5budEQ81xaBf/sgzSRTxruGlhDET//t5+O9XOEJxLosuXUw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1719093748; c=relaxed/simple; bh=mQloSjtrsjqhU2L6hIFvR1BP80Q+I1J3zHW4IrRsJTI=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Fmked4TcQVl/6jwGJ8itlplbQ6q3sX9+9iw6sapziflh4vbTV6lFSe0oe1crtLsCo4fMTMpdQg2O08OANdgzeVh2uYhgVdVUsZfJQQGShAf1jNHob0YDN8B6Ua8j/e7+DrOuos/SJJqW7iyKq9UwFoRrQ5gYZM+Zxu1fWdbvERI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org; spf=pass smtp.mailfrom=linaro.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b=oprBbN45; arc=none smtp.client-ip=209.85.208.181 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linaro.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linaro.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linaro.org header.i=@linaro.org header.b="oprBbN45" Received: by mail-lj1-f181.google.com with SMTP id 38308e7fff4ca-2ec3f875e68so35126951fa.0 for ; Sat, 22 Jun 2024 15:02:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1719093744; x=1719698544; darn=vger.kernel.org; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:from:to:cc:subject:date:message-id :reply-to; bh=uT8pxGU5UTAsCymYW05fV+pVSft8bYR/hRo4Hqglb7k=; b=oprBbN45XhESpkXsa5INCCLNETIlHZX7JAuRuqA7z6WghFjWUNbYB5jBTolGtbpeAb 0HFxjOnDkMehWbE+1Jsu21Y3Oy6tu4dWZ4X65itMWKIByqGa0bKVRWhYFOykGNhkX13u MppOeMR75kdwDWliG23a5eqij2eJSCptnhpxt/1HSy312Gnu8qLAZQvhvc2BpEp3vLfu qK/G1O6zec4fkd3sVi/OAt0h+feiMmMRnRh4CLuPs8gK3VNSwOMw3QZ958XfuAVzmKjf nIJug4cEDZS1mrSlmz3EqyjYvM+7wnRROv0L4vOnMUz4UyYTExwQluQ1z/BqebOREDJ8 faKQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1719093744; x=1719698544; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:subject:date:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=uT8pxGU5UTAsCymYW05fV+pVSft8bYR/hRo4Hqglb7k=; b=XaOCIFsBjZ7nrRQ+PRQltoYxk+a70DuqWKFviNpTow9EOxezJ39OG/WHgboeyxKHdm ssAmX5KHhRPPuIHTGNK1HZGS7ZsiPnzqNr+uEcrAZJNo3M0KmeiFHc8ap0rMNP8/xU6T TRtzLBx8ipTtOACR4TjU0D3tj3BO475v0G4UTsQHqH0hW4u/suKg1gjNDdrbRPVstr0S J81SlF9ObSNtFZDt64RTsBuQvqkGwOAf8HVTkmiJnyUyH4nEq+8v/bF461B/fwVYSB78 W89fPpPjfnTuzIQyVkHpXQTK7ne4X9nR0zHEGGNBR0F9CDSjqR8wikn01i6K83C4GO2R w4hQ== X-Forwarded-Encrypted: i=1; AJvYcCVAMr221bx7QtcXynEYJd7RIAMW62+cRb+MhCdX/jnjI1zsLvG1JRcYhrg25e8tO4KyWHpv30PEN21BRyPRVJlsgj0AG/eEp0I3OFKB X-Gm-Message-State: AOJu0YwbFJRTh3ten4sBUNsTIZ6rVtcLR/l7L71ettcX1I7nGygaBUch F3JVlG8vhipi9HEmzwVBN+GEl7ZigblwhDUfVs/Bn/NLcwavWq+936CWkGvwQoM= X-Google-Smtp-Source: AGHT+IHRYo0K72vEZY8snfrX/bOUeGz2EYtECl/EEjoK3IEoWA2Ma+QZrP7byvh9lydf6kpApuJ/cA== X-Received: by 2002:a2e:7e0f:0:b0:2ec:56b9:259f with SMTP id 38308e7fff4ca-2ec5b3e24d7mr3668581fa.48.1719093744389; Sat, 22 Jun 2024 15:02:24 -0700 (PDT) Received: from umbar.lan ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id 38308e7fff4ca-2ec55e56ea5sm2502051fa.112.2024.06.22.15.02.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 Jun 2024 15:02:23 -0700 (PDT) From: Dmitry Baryshkov Date: Sun, 23 Jun 2024 01:02:21 +0300 Subject: [PATCH v3 08/13] drm/msm/hdmi: implement proper runtime PM handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20240623-fd-hdmi-hpd-v3-8-8645a64cbd63@linaro.org> References: <20240623-fd-hdmi-hpd-v3-0-8645a64cbd63@linaro.org> In-Reply-To: <20240623-fd-hdmi-hpd-v3-0-8645a64cbd63@linaro.org> To: Rob Clark , Abhinav Kumar , Sean Paul , Marijn Suijten , David Airlie , Daniel Vetter Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org, Jessica Zhang X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=9172; i=dmitry.baryshkov@linaro.org; h=from:subject:message-id; bh=mQloSjtrsjqhU2L6hIFvR1BP80Q+I1J3zHW4IrRsJTI=; b=owGbwMvMwMXYbdNlx6SpcZXxtFoSQ1q558sreXotoTe8XGbfXnFwS0D0ioe/g+yZrjYpLbvfE qW6TOpvJ6MxCwMjF4OsmCKLT0HL1JhNyWEfdkythxnEygQyhYGLUwAmstmPg6FRV6PP6ua1ln2G Cy5pL0lN2mDd+YVVt1Y2ceXDyECXD3l9vTvf3lSYxNW0e5rr7Jnl1VwbC1dkdJutD/F+fP7hOuN ZJ2flnf/spdLavqTRKbAno7puf5BXyPVIydgT1jbszYsc5/GsuRQiyt9dELtH4DBXW/+e/mjvqd v5vVyFj6Qlrvi9Rfnzv+e9Zxom79j1Vz/WXeVwkwfjtDfep1304racqC5xzxBzZGdiyVHhad3ga dX79OEh1XV6f9xcf3g5Gr49vEZdN9rswqfiibF31j+Y1J4f2LODO3ziXPGcvc9Y3s2TivwiezCR b8b1Rvm4oJ1b9VlV1LZeuC+ekuiu7KHq1fpvvclx38RiAA== X-Developer-Key: i=dmitry.baryshkov@linaro.org; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A It is completely not obvious, but the so-called 'hpd' clocks and regulators are required for the HDMI host to function properly. Merge pwr and hpd regulators. Use regulators, clocks and pinctrl to implement proper runtime PM callbacks. Reviewed-by: Jessica Zhang Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 62 +++++++++++++++++++++++++-----= ---- drivers/gpu/drm/msm/hdmi/hdmi.h | 7 +--- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 12 ------- drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 42 +---------------------- 4 files changed, 48 insertions(+), 75 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdm= i.c index 34c1aac5feab..ba9d4671e722 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -8,6 +8,7 @@ #include #include #include +#include #include =20 #include @@ -225,11 +226,11 @@ int msm_hdmi_modeset_init(struct hdmi *hdmi, .item ## _names =3D item ##_names_ ## entry, \ .item ## _cnt =3D ARRAY_SIZE(item ## _names_ ## entry) =20 -static const char *hpd_reg_names_8960[] =3D {"core-vdda"}; +static const char *pwr_reg_names_8960[] =3D {"core-vdda"}; static const char *hpd_clk_names_8960[] =3D {"core", "master_iface", "slav= e_iface"}; =20 static const struct hdmi_platform_config hdmi_tx_8960_config =3D { - HDMI_CFG(hpd_reg, 8960), + HDMI_CFG(pwr_reg, 8960), HDMI_CFG(hpd_clk, 8960), }; =20 @@ -409,20 +410,6 @@ static int msm_hdmi_dev_probe(struct platform_device *= pdev) if (hdmi->irq < 0) return hdmi->irq; =20 - hdmi->hpd_regs =3D devm_kcalloc(&pdev->dev, - config->hpd_reg_cnt, - sizeof(hdmi->hpd_regs[0]), - GFP_KERNEL); - if (!hdmi->hpd_regs) - return -ENOMEM; - - for (i =3D 0; i < config->hpd_reg_cnt; i++) - hdmi->hpd_regs[i].supply =3D config->hpd_reg_names[i]; - - ret =3D devm_regulator_bulk_get(&pdev->dev, config->hpd_reg_cnt, hdmi->hp= d_regs); - if (ret) - return dev_err_probe(dev, ret, "failed to get hpd regulators\n"); - hdmi->pwr_regs =3D devm_kcalloc(&pdev->dev, config->pwr_reg_cnt, sizeof(hdmi->pwr_regs[0]), @@ -500,6 +487,48 @@ static void msm_hdmi_dev_remove(struct platform_device= *pdev) msm_hdmi_put_phy(hdmi); } =20 +static int msm_hdmi_runtime_suspend(struct device *dev) +{ + struct hdmi *hdmi =3D dev_get_drvdata(dev); + const struct hdmi_platform_config *config =3D hdmi->config; + + clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); + + pinctrl_pm_select_sleep_state(dev); + + regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); + + return 0; +} + +static int msm_hdmi_runtime_resume(struct device *dev) +{ + struct hdmi *hdmi =3D dev_get_drvdata(dev); + const struct hdmi_platform_config *config =3D hdmi->config; + int ret; + + ret =3D regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); + if (ret) + return ret; + + ret =3D pinctrl_pm_select_default_state(dev); + if (ret) + goto fail; + + ret =3D clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); + if (ret) + goto fail; + + return 0; + +fail: + pinctrl_pm_select_sleep_state(dev); + + return ret; +} + +DEFINE_RUNTIME_DEV_PM_OPS(msm_hdmi_pm_ops, msm_hdmi_runtime_suspend, msm_h= dmi_runtime_resume, NULL); + static const struct of_device_id msm_hdmi_dt_match[] =3D { { .compatible =3D "qcom,hdmi-tx-8996", .data =3D &hdmi_tx_8974_config }, { .compatible =3D "qcom,hdmi-tx-8994", .data =3D &hdmi_tx_8974_config }, @@ -516,6 +545,7 @@ static struct platform_driver msm_hdmi_driver =3D { .driver =3D { .name =3D "hdmi_msm", .of_match_table =3D msm_hdmi_dt_match, + .pm =3D &msm_hdmi_pm_ops, }, }; =20 diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdm= i.h index 287e6d33fb85..07a1b3641cb4 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -48,7 +48,6 @@ struct hdmi { void __iomem *qfprom_mmio; phys_addr_t mmio_phy_addr; =20 - struct regulator_bulk_data *hpd_regs; struct regulator_bulk_data *pwr_regs; struct clk_bulk_data *hpd_clks; struct clk *extp_clk; @@ -84,11 +83,7 @@ struct hdmi { =20 /* platform config data (ie. from DT, or pdata) */ struct hdmi_platform_config { - /* regulators that need to be on for hpd: */ - const char **hpd_reg_names; - int hpd_reg_cnt; - - /* regulators that need to be on for screen pwr: */ + /* regulators that need to be on: */ const char **pwr_reg_names; int pwr_reg_cnt; =20 diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/h= dmi/hdmi_bridge.c index 34085fd9739b..c15c49c08d30 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -18,15 +18,10 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) struct drm_device *dev =3D bridge->dev; struct hdmi_bridge *hdmi_bridge =3D to_hdmi_bridge(bridge); struct hdmi *hdmi =3D hdmi_bridge->hdmi; - const struct hdmi_platform_config *config =3D hdmi->config; int ret; =20 pm_runtime_resume_and_get(&hdmi->pdev->dev); =20 - ret =3D regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); - if (hdmi->extp_clk) { DBG("pixclock: %lu", hdmi->pixclock); ret =3D clk_set_rate(hdmi->extp_clk, hdmi->pixclock); @@ -41,11 +36,8 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) =20 static void power_off(struct drm_bridge *bridge) { - struct drm_device *dev =3D bridge->dev; struct hdmi_bridge *hdmi_bridge =3D to_hdmi_bridge(bridge); struct hdmi *hdmi =3D hdmi_bridge->hdmi; - const struct hdmi_platform_config *config =3D hdmi->config; - int ret; =20 /* TODO do we need to wait for final vblank somewhere before * cutting the clocks? @@ -55,10 +47,6 @@ static void power_off(struct drm_bridge *bridge) if (hdmi->extp_clk) clk_disable_unprepare(hdmi->extp_clk); =20 - ret =3D regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %d\n", ret); - pm_runtime_put(&hdmi->pdev->dev); } =20 diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c b/drivers/gpu/drm/msm/hdmi= /hdmi_hpd.c index fc21ad3b01dc..32e447267e3b 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_hpd.c @@ -64,36 +64,17 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) { struct hdmi_bridge *hdmi_bridge =3D to_hdmi_bridge(bridge); struct hdmi *hdmi =3D hdmi_bridge->hdmi; - const struct hdmi_platform_config *config =3D hdmi->config; struct device *dev =3D &hdmi->pdev->dev; uint32_t hpd_ctrl; int ret; unsigned long flags; =20 - ret =3D regulator_bulk_enable(config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) { - DRM_DEV_ERROR(dev, "failed to enable hpd regulators: %d\n", ret); - goto fail; - } - - ret =3D pinctrl_pm_select_default_state(dev); - if (ret) { - DRM_DEV_ERROR(dev, "pinctrl state chg failed: %d\n", ret); - goto fail; - } - if (hdmi->hpd_gpiod) gpiod_set_value_cansleep(hdmi->hpd_gpiod, 1); =20 ret =3D pm_runtime_resume_and_get(dev); - if (ret) { - DRM_DEV_ERROR(dev, "runtime resume failed: %d\n", ret); - goto fail; - } - - ret =3D clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); if (ret) - goto fail; + return ret; =20 msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_reset(hdmi); @@ -119,32 +100,18 @@ int msm_hdmi_hpd_enable(struct drm_bridge *bridge) spin_unlock_irqrestore(&hdmi->reg_lock, flags); =20 return 0; - -fail: - return ret; } =20 void msm_hdmi_hpd_disable(struct hdmi *hdmi) { - const struct hdmi_platform_config *config =3D hdmi->config; struct device *dev =3D &hdmi->pdev->dev; - int ret; =20 /* Disable HPD interrupt */ hdmi_write(hdmi, REG_HDMI_HPD_INT_CTRL, 0); =20 msm_hdmi_set_mode(hdmi, false); =20 - clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); pm_runtime_put(dev); - - ret =3D pinctrl_pm_select_sleep_state(dev); - if (ret) - dev_warn(dev, "pinctrl state chg failed: %d\n", ret); - - ret =3D regulator_bulk_disable(config->hpd_reg_cnt, hdmi->hpd_regs); - if (ret) - dev_warn(dev, "failed to disable hpd regulator: %d\n", ret); } =20 void msm_hdmi_hpd_irq(struct drm_bridge *bridge) @@ -179,7 +146,6 @@ void msm_hdmi_hpd_irq(struct drm_bridge *bridge) =20 static enum drm_connector_status detect_reg(struct hdmi *hdmi) { - const struct hdmi_platform_config *config =3D hdmi->config; uint32_t hpd_int_status =3D 0; int ret; =20 @@ -187,14 +153,8 @@ static enum drm_connector_status detect_reg(struct hdm= i *hdmi) if (ret) goto out; =20 - ret =3D clk_bulk_prepare_enable(config->hpd_clk_cnt, hdmi->hpd_clks); - if (ret) - goto out; - hpd_int_status =3D hdmi_read(hdmi, REG_HDMI_HPD_INT_STATUS); =20 - clk_bulk_disable_unprepare(config->hpd_clk_cnt, hdmi->hpd_clks); - out: pm_runtime_put(&hdmi->pdev->dev); =20 --=20 2.39.2