From nobody Fri Dec 19 08:06:15 2025 Received: from mail-lf1-f50.google.com (mail-lf1-f50.google.com [209.85.167.50]) (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 66A3818A6DB for ; Sun, 9 Feb 2025 05:07:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.167.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739077633; cv=none; b=DZEIN6vIaHJzhURt38rAftcIxck1zayKcni6OvmsuRPhH11g25oNTsxd+YST6tA8bn586RN/Endf1781+ompOK8W5IwfAQ2wqx6wbgJSfSZmjkwJhk2OMb3PXqn/E34B9TeYVFcJnzn1moLFQYS8gOHgo7ieW5SHi+GJmAQsFbY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739077633; c=relaxed/simple; bh=FbKaceGiAg6TBff1fmSfXG39SERi268oL7jMv4TIAIc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=FIQfY1ijC9+M3bOJGz5F61OsQQIyeieQacjWHJCp005KBwogRonxMIkyvLUG9E4gazx/Xcs+ZXFl4Yoo0Z8H4U6/v0ZucJdO87Z2mIaUwoLGU5Ex5Zd32FSBLba+0D9j49BY/2QvpzDoVSc0jOBGEYO8uQDuiYhtgARYNbIP63M= 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=Nmg/tW1O; arc=none smtp.client-ip=209.85.167.50 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="Nmg/tW1O" Received: by mail-lf1-f50.google.com with SMTP id 2adb3069b0e04-5440d5aae5cso3565346e87.0 for ; Sat, 08 Feb 2025 21:07:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1739077629; x=1739682429; 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=J6Gr4uu/kJErVl7WJZNEAVi18tX3meOvk7rKvqbRQDw=; b=Nmg/tW1OjVz4ls3lbpAek0UpcHrd5tlcwGN4rRlrzeLCP5gdPBhFGkSEfY6UANrz58 +til2AzhuWwnMwnQzGmx7y/fRFVYQs7esbVDso+Nv1Y8OoCjwB9nXbXqerKdAbyHnRdr Ymktlo2a2+7FYUtASc1mNRoJJHdBxa9UbuLb59qU6mkyGeC1p1XBz7qrj7t3wkxotKlf RHbMN6ObRV6TqIZVStGvugStN0NQVDREQNgeWkTluIqpce4pEiMYuLWzfFNKX4KCzX7W O+sWIqFO1kOM+Cu4kcxZuOTPFxGpeRQkctJJU/FGRizeKNcBmfUd/89+DzqsW53ODNhS kf/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1739077629; x=1739682429; 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=J6Gr4uu/kJErVl7WJZNEAVi18tX3meOvk7rKvqbRQDw=; b=I0tnnZck5jF0Vat5BAJ86gaPFEvFTZcoGYoahE8kA+D810Ie1PE2VDBGr7s4UY3+cU rsNdQrOMRn6b1AAJkhKzjcRhDwrc0sxo0ik21JTMl/uskmvpv1muvVNFOa6dxB1tSdDX XI5+9EFaACk/X7cWp4pJrd7SToNjXO4q9stfFUe0z9/2QVcY6iAThxR+TZuCCTShfiRH XcX+5AqabjONjFXpJbH3qJbKYiZxp/X7bCnkiA7rdPx1vGWPW7JPLCnpv7u0qIh0EunF l6YPPlnIGj+FTCiPLPjuLW+oFaWfIEOuOh3hSy+jcZq6MiU4iDwd3xmoP796PnfuJHoR b6tQ== X-Forwarded-Encrypted: i=1; AJvYcCXdnrGSCXJxTPIFNilM6w2r4NLsFX5U+L4wkFPVDARANn790Gw87ocGaBGNPks5Olx5oO9gFqF2dB7fYVw=@vger.kernel.org X-Gm-Message-State: AOJu0YysHqPAdyaiHlm0pYpRSe83a9YQIHzQEkV76HDrlchDR7kgZQsl KNFJqCYWg0KWDn2lodMj+cwQfohO+BbQ4flRKeGvQVT0eWxwnUqoWtFl71fILns= X-Gm-Gg: ASbGncsxbVwYawqDTZQ0N1B6T8EeCIv7GEBXkVnJJQM+0b37TInTcrwm7XuUWwWQv4Y xgjj/T5i9esqVPI+EEiqfVPfWEvNOghLx1ArR723yVudHu7CITdHyxuVcwkOUdD4yUca7B5+Jss Il1dykmISlyiOWrJgFksyeMXd3Sqo5LKCYEh19Gw84a5/sS7yZOeDCurVzEmw4zORGSsQMFpHWq /ft9itgYB7MBKYVWfA8kjX54PGUtzxB/n3xXsGnfcDGR2CK+N7pEAoQaAdpKqdEXs2znd57anf7 HdlGcbe5/cT8GQONsaEXpjA= X-Google-Smtp-Source: AGHT+IEMz171/a3noyaNikNrBmsJ647KN8DT8QdriymS4YuVWPZiFxBKdSK++uLEoZfsKV6SZuZqLg== X-Received: by 2002:a05:6512:3d88:b0:544:1201:c0b3 with SMTP id 2adb3069b0e04-54414aae119mr2881240e87.11.1739077629496; Sat, 08 Feb 2025 21:07:09 -0800 (PST) Received: from umbar.lan ([192.130.178.90]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-54506ef1733sm245576e87.1.2025.02.08.21.07.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 08 Feb 2025 21:07:08 -0800 (PST) From: Dmitry Baryshkov Date: Sun, 09 Feb 2025 07:04:54 +0200 Subject: [PATCH v4 10/16] 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: <20250209-fd-hdmi-hpd-v4-10-6224568ed87f@linaro.org> References: <20250209-fd-hdmi-hpd-v4-0-6224568ed87f@linaro.org> In-Reply-To: <20250209-fd-hdmi-hpd-v4-0-6224568ed87f@linaro.org> To: Rob Clark , Abhinav Kumar , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Bjorn Andersson , Konrad Dybcio , Simona Vetter Cc: linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, Jessica Zhang X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9382; i=dmitry.baryshkov@linaro.org; h=from:subject:message-id; bh=FbKaceGiAg6TBff1fmSfXG39SERi268oL7jMv4TIAIc=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBnqDfjekR3ytdRsJ2xgXSruu+wiySdVD2A3OkWc romIolnABOJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCZ6g34wAKCRCLPIo+Aiko 1XBuB/43scQI8R13SZNUxuwJaZ+IhCr2eB31ophSF7KOoPzKejIQNs5xaV0bXzsvCxandCU2u4N 0w4pwZn2clkCyNLaYCdZQ3r59CpECFNxgtzyvws4Ur0BWqk9uPZf4e4wXTfytrlB6tS8//SKlWv T1eOB9bDsHcqmVDABaFA4uI4askTW1Iu9Aw+ag0GG68vqZctsgy/40llnAOOLTTIQZ6MAjspMWJ ZbyEmfEQzCHkYQVd6fZnOSc/uu1WiVYP5q5grf7ciFTHFAdmpQotKh7am9DIbcq2qo21OEl/K9L Z1pOUTRRVNHjnYxfTa7Mv2yCS+gtyXcGyyxkMXeFAZ/DP1Pu 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 | 5 --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 12 ------- drivers/gpu/drm/msm/hdmi/hdmi_hpd.c | 42 +---------------------- 4 files changed, 47 insertions(+), 74 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdm= i.c index 69e337d551799b4d35c8c8c7ecb5c4680b9a9e5f..ded20176aa805db98b0599e617e= b6ea9bce122d8 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 @@ -224,11 +225,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 * const hpd_reg_names_8960[] =3D {"core-vdda"}; +static const char * const pwr_reg_names_8960[] =3D {"core-vdda"}; static const char * const hpd_clk_names_8960[] =3D {"core", "master_iface"= , "slave_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 @@ -318,20 +319,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]), @@ -409,6 +396,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-8998", .data =3D &hdmi_tx_8974_config }, { .compatible =3D "qcom,hdmi-tx-8996", .data =3D &hdmi_tx_8974_config }, @@ -426,6 +455,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 3f87535bcf43e20f0618d3016307fe1642d7baf9..7e3c035cf913d713ed63379a843= 897fad96b23ab 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -47,7 +47,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; @@ -83,10 +82,6 @@ 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 * const *hpd_reg_names; - int hpd_reg_cnt; - /* regulators that need to be on for screen pwr: */ const char * const *pwr_reg_names; int pwr_reg_cnt; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/h= dmi/hdmi_bridge.c index d7d5d3755fb853377aa999e2a830debf54afe984..fedcefbf53d1d8d53a4882a5454= 27f5ce6570a76 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 d77c68914c5f525cf12971c1058b1abc33792b24..a42ed26a5b7c7d916d543aa2920= 754347903062a 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; u32 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.5