From nobody Fri Dec 19 11:32:35 2025 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7D37D28C85B for ; Tue, 20 May 2025 20:45:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773907; cv=none; b=qZgeBf5TEvxRBuat+K5udY7x/whM9hs4OEl7vr16GTDpWHgQ6wnCiBfagalw2Esnv74VjVg1pYlsz0syM8WqkDfH1h9vZcQVvyPeVnJZIIq2MYlFeP5Pmyvmx9Da9ZhG02EHvtalz4jIMTIc6GWdmXXqT3NuUiVXmqBgbvI1ZpM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773907; c=relaxed/simple; bh=ULF1qFHE4NEhx6YDwvhdqVxjBD5DrDQlMdk2A+TOTns=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ahmnwb99TYKjWgSLCZFzbO3JMEdF9M7VgA8HLbDWYRVMyin+XFIMounJ2sQmonrs0hVKLntvfQuG1JngTnEAcTmGL2EkckYjoYAtZpUgA0OOZyCecuERElK90J3K5HqmJl+uTNSRQEnAdsdqjszj09tVejJNis42Pb472aHFaPE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=GEixF0Ls; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="GEixF0Ls" Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 54KGf85n017331 for ; Tue, 20 May 2025 20:44:59 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= m67TFHeHsvgVLsmiNGRclVtEIGA6cCV1D/TyNxUHFNM=; b=GEixF0LsPzoA1dx/ WqqIHMO37t/Tn7gTOyHCAhjZ9KAnA0MYBNTMNbmaNjQYjNnrN5b2C158QEKZWk5f Jb42vmHDXpxfcwgdalg1n7vR8ueAUcoNQl5SxPjAWx0l4mweO3qZP7cHHg5Z4pZM vac2auJ2LpZKXR9Vd5R1WKZmhSeGq96vybHe/MW1xT/dhGHiLE5T9cl/kLxWrp5K 1w9aGGQFe4mXMYyVovywtxs7Ro2/NRJggHOrOfI4CspRZCEtBGyqNpemUV/96jNg W34zj5U0ane0lQ/ZSDTPP1rWhdOWleZjutkym378100+sEiRPmY2HNipqLy0oNGm o+VnAg== Received: from mail-qv1-f69.google.com (mail-qv1-f69.google.com [209.85.219.69]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwfb0k8h-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 20 May 2025 20:44:58 +0000 (GMT) Received: by mail-qv1-f69.google.com with SMTP id 6a1803df08f44-6f8e1d900e5so31638676d6.2 for ; Tue, 20 May 2025 13:44:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747773897; x=1748378697; 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=m67TFHeHsvgVLsmiNGRclVtEIGA6cCV1D/TyNxUHFNM=; b=YizU7namansh7GowjAj69jsE3bJs2RVIAqHCTSl/KkbYJm57WMuRbF/7JfaHxoPOxs OyddYHe8c/UkBoIJRChQabx17SwLZ57Hqpk+n41ZwoUsiyWr2C0Q2i3OAVTsXSG94DPf QOcYg+0DnGmHtOV/SMsGRPf/WXSNOe68wf20OwQq/BJi1pNVXlCioNTjGxVNWI0QHuy+ uBGrTle72dpyLX1D2ZXayLCKIpUcVCDkMi3+Y+4m4/ZWbxwuT7ovsrLa90wH3RlosJAq ZxKKdLFOW0Dz+O5oPu04fX/vgJtjCfENK7w1YDFYX88nUl898XBqUFRiXLE++ZrTmONT sGPw== X-Gm-Message-State: AOJu0YxD0VpUQv4Pqp//yPQkpNuUXz3PAbHM6F+9pS2WDgAu9KQXWrmW UyM4mc5kqKmoo5+TB7CmbWHh8EAx2mKBYcAqLnhQQ440S9RCMG7go/JKDQ/Jqp4/7qvpVIPX+hd KlC+WRB6IM1ydYjQVCAfpmV55tlVlIboQGUyExXTNseFiP/E9zjBaY2TjwCGp979DmBE= X-Gm-Gg: ASbGncsN/i7uSXWG+ZWsLiDQHvEwxIfOMW7lPi4dSFPM6yJGhVp3Z6vq29AEg50yGyq FEi945Yyk4i5E+UUy5+9CCPyVGzsdIcULtm8e95nexastzP66TWR1Bz3meY2D3kKbglwfLHIIOq 9URTyKrQ0REw1N3Tv0gEQnBpKRFw2huKDiundboXu3Cn2GwCaXhU0gTjF1DAg2L3itSNLkC+lYN AY7ABc54Zx82bEcWN46zC0ihM04fFHtjxIxKbl/e7JghoGFgkIVAhAz2xsxWksQlIP3db9/2ZwK 6GyH0/o2eDfSP7twHaJq+GaTdiNb5glaEynSi6Ncha56JW51+s9DmVN1bi6+j/qI2PqoFGr/Ooo UHq0H9lmtOEw1smj62OOKFu8T X-Received: by 2002:a05:6214:483:b0:6e6:61a5:aa57 with SMTP id 6a1803df08f44-6f8b087cdfdmr276357446d6.14.1747773895626; Tue, 20 May 2025 13:44:55 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG9OjJTAfQgWw6KPiwv7pMCD1Q/q0x201qdZavmVEpjfpJnZ4aXEQZofqwDfcqKtoqxE1e0Sw== X-Received: by 2002:a05:6214:483:b0:6e6:61a5:aa57 with SMTP id 6a1803df08f44-6f8b087cdfdmr276356596d6.14.1747773894476; Tue, 20 May 2025 13:44:54 -0700 (PDT) Received: from umbar.lan (2001-14ba-a0c3-3a00-264b-feff-fe8b-be8a.rev.dnainternet.fi. [2001:14ba:a0c3:3a00:264b:feff:fe8b:be8a]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-550e6f163ccsm2497950e87.39.2025.05.20.13.44.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 13:44:52 -0700 (PDT) From: Dmitry Baryshkov Date: Tue, 20 May 2025 23:44:43 +0300 Subject: [PATCH v4 1/5] drm/msm/hdmi: switch to generic PHY subsystem 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: <20250520-fd-hdmi-phy-v4-1-fcbaa652ad75@oss.qualcomm.com> References: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> In-Reply-To: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Vinod Koul , Kishon Vijay Abraham I Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org, Dmitry Baryshkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=162424; i=dmitry.baryshkov@oss.qualcomm.com; h=from:subject:message-id; bh=pT3eTmT2ZjUZPSAmnlTMn8hRKe3RMCM6JkXDQSulJgg=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBoLOnATTIidERZbnmRUgSikERfHE9elze7bQR/a prfgh3mPg6JATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCaCzpwAAKCRCLPIo+Aiko 1f/5B/4x50diWnozF/+yqYR22SbK7ueJk+eLWN52fuJVXy1t7wuKcaBwee49uFQCVuyP9k4RScG h6xtkBh+ONP/DFEGaSGeG48t886sX+tPjeyH8pcR6XC784wd5Mds7qVgoVNw5clNIutohQasuXz alYOwYthxu2Zlt9a6Vu/QcUVlAmx9VrDIp+a5jHyuhbL2nyxJtm8x29zsBBkP3gW68KZWOCKhz9 mC+3vQ0dJbAUiVL7UC9BpRdwTeaAvdHKYjt7uNSS6Ron2kLVfTIuuvZ95sLKHyPhhVuMbOOcMN9 9DWJ8EJ/1BybgcHsdwn2pJFAHDHbZzPoF3O9fEZEjMdhm1WZ X-Developer-Key: i=dmitry.baryshkov@oss.qualcomm.com; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-Proofpoint-ORIG-GUID: 4jw0R8ba1PxK2Jsr4ByL01a8Z5fDV9vU X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIwMDE2OCBTYWx0ZWRfX1lNveFbAQ6FG xmmMzJMGdLn4xM+vR9KeDefplnfGz3Iqh0eXf8pTDSWPCzuiWJbmHjYw4S9ZtBGy1EiVR4dzugK E5g5HzkvPNZv+NSRNyGIpSsj+5vjZu2/ewr80iOIaai9vFuZ0uXlUcUtFGu6+oq/ovyboE1dSNM bPrV2sA4RITrx76B6mAol1yEByD+Qg81z8ojPrhPUk+z1BV33jKs5yIEut45tpOYcBaT2eUZhFf quGKa0ZYmDDwxS8Bt75YfsvlPJupLpHIQNDDjHiX3DuElAT/zaTCy4mLPJBPUKz4cvxpE3Gs5nG dCcrxRm59WbHP6GxHkPv4BxKvJ9pY4vDUFuGIT3769skiqUAzIivP0k/PvKw/yj18IvUTCex44G u3oZE9pwe4HagmzEKwd60AOD2yshnoU/G6jdaMvHuAy6ygwat1lcJcdxxB7WHi9h/GdC839Z X-Proofpoint-GUID: 4jw0R8ba1PxK2Jsr4ByL01a8Z5fDV9vU X-Authority-Analysis: v=2.4 cv=dLCmmPZb c=1 sm=1 tr=0 ts=682ce9ca cx=c_pps a=wEM5vcRIz55oU/E2lInRtA==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=dt9VzEwgFbYA:10 a=KKAkSRfTAAAA:8 a=EUspDBNiAAAA:8 a=pGLkceISAAAA:8 a=qzgp7QZQiccVP5dvYDYA:9 a=QEXdDO2ut3YA:10 a=OIgjcC2v60KrkQgK7BGD:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 definitions=2025-05-20_09,2025-05-20_03,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 mlxscore=0 clxscore=1015 adultscore=0 bulkscore=0 phishscore=0 suspectscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 mlxlogscore=999 spamscore=0 priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 definitions=main-2505200168 From: Dmitry Baryshkov Change the MSM HDMI driver to use generic PHY subsystem. Moving PHY drivers allows better code sharing with the rest of the PHY system. Signed-off-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/Makefile | 7 - drivers/gpu/drm/msm/hdmi/hdmi.c | 58 +- drivers/gpu/drm/msm/hdmi/hdmi.h | 80 +-- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 32 +- drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 225 ------- drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c | 51 -- drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c | 765 -------------------= --- drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c | 769 -------------------= ---- drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c | 141 ----- drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c | 44 -- drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c | 458 -------------- drivers/phy/qualcomm/Kconfig | 21 + drivers/phy/qualcomm/Makefile | 14 + drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c | 71 +++ drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c | 441 +++++++++++++ drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c | 186 ++++++ drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c | 212 +++++++ drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h | 81 +++ drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c | 185 ++++++ drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c | 442 +++++++++++++ drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8998.c | 495 +++++++++++++++ drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h | 77 +++ 22 files changed, 2259 insertions(+), 2596 deletions(-) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 7a2ada6e2d74a902879e4f12a78ed475e5209ec2..8ea4a0ab2096574e3f6d42c1650= 76203f709a98c 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -35,13 +35,6 @@ msm-display-$(CONFIG_DRM_MSM_HDMI) +=3D \ hdmi/hdmi_bridge.o \ hdmi/hdmi_hpd.o \ hdmi/hdmi_i2c.o \ - hdmi/hdmi_phy.o \ - hdmi/hdmi_phy_8960.o \ - hdmi/hdmi_phy_8996.o \ - hdmi/hdmi_phy_8998.o \ - hdmi/hdmi_phy_8x60.o \ - hdmi/hdmi_phy_8x74.o \ - hdmi/hdmi_pll_8960.o \ =20 msm-display-$(CONFIG_DRM_MSM_MDP4) +=3D \ disp/mdp4/mdp4_crtc.o \ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdm= i.c index 2fd388b892dcb3d83cf57b4616b7a65f9ff674d1..23f6311e4ec9218aaccf61a466c= 7588fe7f3d164 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -10,6 +10,7 @@ #include #include #include +#include =20 #include #include @@ -75,44 +76,6 @@ static void msm_hdmi_destroy(struct hdmi *hdmi) msm_hdmi_i2c_destroy(hdmi->i2c); } =20 -static void msm_hdmi_put_phy(struct hdmi *hdmi) -{ - if (hdmi->phy_dev) { - put_device(hdmi->phy_dev); - hdmi->phy =3D NULL; - hdmi->phy_dev =3D NULL; - } -} - -static int msm_hdmi_get_phy(struct hdmi *hdmi) -{ - struct platform_device *pdev =3D hdmi->pdev; - struct platform_device *phy_pdev; - struct device_node *phy_node; - - phy_node =3D of_parse_phandle(pdev->dev.of_node, "phys", 0); - if (!phy_node) { - DRM_DEV_ERROR(&pdev->dev, "cannot find phy device\n"); - return -ENXIO; - } - - phy_pdev =3D of_find_device_by_node(phy_node); - of_node_put(phy_node); - - if (!phy_pdev) - return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready= \n"); - - hdmi->phy =3D platform_get_drvdata(phy_pdev); - if (!hdmi->phy) { - put_device(&phy_pdev->dev); - return dev_err_probe(&pdev->dev, -EPROBE_DEFER, "phy driver is not ready= \n"); - } - - hdmi->phy_dev =3D &phy_pdev->dev; - - return 0; -} - /* construct hdmi at bind/probe time, grab all the resources. If * we are to EPROBE_DEFER we want to do it here, rather than later * at modeset_init() time @@ -356,36 +319,31 @@ static int msm_hdmi_dev_probe(struct platform_device = *pdev) if (hdmi->hpd_gpiod) gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD"); =20 - ret =3D msm_hdmi_get_phy(hdmi); - if (ret) { + hdmi->phy =3D devm_phy_get(&pdev->dev, NULL); + if (IS_ERR(hdmi->phy)) { DRM_DEV_ERROR(&pdev->dev, "failed to get phy\n"); - return ret; + return PTR_ERR(hdmi->phy); } =20 ret =3D devm_pm_runtime_enable(&pdev->dev); if (ret) - goto err_put_phy; + goto err; =20 platform_set_drvdata(pdev, hdmi); =20 ret =3D component_add(&pdev->dev, &msm_hdmi_ops); if (ret) - goto err_put_phy; + goto err; =20 return 0; =20 -err_put_phy: - msm_hdmi_put_phy(hdmi); +err: return ret; } =20 static void msm_hdmi_dev_remove(struct platform_device *pdev) { - struct hdmi *hdmi =3D dev_get_drvdata(&pdev->dev); - component_del(&pdev->dev, &msm_hdmi_ops); - - msm_hdmi_put_phy(hdmi); } =20 static int msm_hdmi_runtime_suspend(struct device *dev) @@ -453,12 +411,10 @@ static struct platform_driver msm_hdmi_driver =3D { =20 void __init msm_hdmi_register(void) { - msm_hdmi_phy_driver_register(); platform_driver_register(&msm_hdmi_driver); } =20 void __exit msm_hdmi_unregister(void) { platform_driver_unregister(&msm_hdmi_driver); - msm_hdmi_phy_driver_unregister(); } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdm= i.h index d5e572d10d6a14b866f13c3a0d663cc6ae435ef5..807aef89ef1af3b7e6a21464cad= e5287914b0754 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -19,7 +19,6 @@ #include "msm_drv.h" #include "hdmi.xml.h" =20 -struct hdmi_phy; struct hdmi_platform_config; =20 struct hdmi_audio { @@ -55,8 +54,7 @@ struct hdmi { =20 struct gpio_desc *hpd_gpiod; =20 - struct hdmi_phy *phy; - struct device *phy_dev; + struct phy *phy; =20 struct i2c_adapter *i2c; struct drm_connector *connector; @@ -117,82 +115,6 @@ static inline u32 hdmi_qfprom_read(struct hdmi *hdmi, = u32 reg) return readl(hdmi->qfprom_mmio + reg); } =20 -/* - * hdmi phy: - */ - -enum hdmi_phy_type { - MSM_HDMI_PHY_8x60, - MSM_HDMI_PHY_8960, - MSM_HDMI_PHY_8x74, - MSM_HDMI_PHY_8996, - MSM_HDMI_PHY_8998, - MSM_HDMI_PHY_MAX, -}; - -struct hdmi_phy_cfg { - enum hdmi_phy_type type; - void (*powerup)(struct hdmi_phy *phy, unsigned long int pixclock); - void (*powerdown)(struct hdmi_phy *phy); - const char * const *reg_names; - int num_regs; - const char * const *clk_names; - int num_clks; -}; - -extern const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg; -extern const struct hdmi_phy_cfg msm_hdmi_phy_8960_cfg; -extern const struct hdmi_phy_cfg msm_hdmi_phy_8x74_cfg; -extern const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg; -extern const struct hdmi_phy_cfg msm_hdmi_phy_8998_cfg; - -struct hdmi_phy { - struct platform_device *pdev; - void __iomem *mmio; - struct hdmi_phy_cfg *cfg; - const struct hdmi_phy_funcs *funcs; - struct regulator_bulk_data *regs; - struct clk **clks; -}; - -static inline void hdmi_phy_write(struct hdmi_phy *phy, u32 reg, u32 data) -{ - writel(data, phy->mmio + reg); -} - -static inline u32 hdmi_phy_read(struct hdmi_phy *phy, u32 reg) -{ - return readl(phy->mmio + reg); -} - -int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy); -void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy); -void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long int pixclock= ); -void msm_hdmi_phy_powerdown(struct hdmi_phy *phy); -void __init msm_hdmi_phy_driver_register(void); -void __exit msm_hdmi_phy_driver_unregister(void); - -#ifdef CONFIG_COMMON_CLK -int msm_hdmi_pll_8960_init(struct platform_device *pdev); -int msm_hdmi_pll_8996_init(struct platform_device *pdev); -int msm_hdmi_pll_8998_init(struct platform_device *pdev); -#else -static inline int msm_hdmi_pll_8960_init(struct platform_device *pdev) -{ - return -ENODEV; -} - -static inline int msm_hdmi_pll_8996_init(struct platform_device *pdev) -{ - return -ENODEV; -} - -static inline int msm_hdmi_pll_8998_init(struct platform_device *pdev) -{ - return -ENODEV; -} -#endif - /* * audio: */ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/h= dmi/hdmi_bridge.c index 53a7ce8cc7bc7b6278eae2cbc42c3fda8d697f6d..1a00c26c1b40fc81623c9fb22ba= 25f448c27bffb 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -5,6 +5,7 @@ */ =20 #include +#include #include #include #include @@ -286,11 +287,12 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct = drm_bridge *bridge, { struct hdmi_bridge *hdmi_bridge =3D to_hdmi_bridge(bridge); struct hdmi *hdmi =3D hdmi_bridge->hdmi; - struct hdmi_phy *phy =3D hdmi->phy; struct drm_encoder *encoder =3D bridge->encoder; struct drm_connector *connector; struct drm_connector_state *conn_state; struct drm_crtc_state *crtc_state; + union phy_configure_opts phy_opts; + int ret; =20 DBG("power up"); =20 @@ -304,7 +306,7 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct dr= m_bridge *bridge, =20 mutex_lock(&hdmi->state_mutex); if (!hdmi->power_on) { - msm_hdmi_phy_resource_enable(phy); + phy_init(hdmi->phy); msm_hdmi_power_on(bridge); hdmi->power_on =3D true; } @@ -315,7 +317,23 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct d= rm_bridge *bridge, =20 drm_atomic_helper_connector_hdmi_update_infoframes(connector, state); =20 - msm_hdmi_phy_powerup(phy, hdmi->pixclock); + phy_opts.hdmi.tmds_char_rate =3D conn_state->hdmi.tmds_char_rate; + phy_opts.hdmi.bpc =3D 8; + phy_configure(hdmi->phy, &phy_opts); + + ret =3D phy_power_on(hdmi->phy); + if (WARN_ON(ret)) + return; + + if (hdmi->extp_clk) { + ret =3D clk_set_rate(hdmi->extp_clk, hdmi->pixclock); + if (ret) + DRM_DEV_ERROR(bridge->dev->dev, "failed to set extp clk rate: %d\n", re= t); + + ret =3D clk_prepare_enable(hdmi->extp_clk); + if (ret) + DRM_DEV_ERROR(bridge->dev->dev, "failed to enable extp clk: %d\n", ret); + } =20 msm_hdmi_set_mode(hdmi, true); =20 @@ -328,7 +346,6 @@ static void msm_hdmi_bridge_atomic_post_disable(struct = drm_bridge *bridge, { struct hdmi_bridge *hdmi_bridge =3D to_hdmi_bridge(bridge); struct hdmi *hdmi =3D hdmi_bridge->hdmi; - struct hdmi_phy *phy =3D hdmi->phy; =20 if (hdmi->hdcp_ctrl) msm_hdmi_hdcp_off(hdmi->hdcp_ctrl); @@ -339,14 +356,17 @@ static void msm_hdmi_bridge_atomic_post_disable(struc= t drm_bridge *bridge, mutex_lock(&hdmi->state_mutex); msm_hdmi_set_mode(hdmi, hdmi->hpd_enabled); =20 - msm_hdmi_phy_powerdown(phy); + if (hdmi->extp_clk) + clk_disable_unprepare(hdmi->extp_clk); + + phy_power_off(hdmi->phy); =20 if (hdmi->power_on) { power_off(bridge); hdmi->power_on =3D false; if (hdmi->connector->display_info.is_hdmi) msm_hdmi_audio_update(hdmi); - msm_hdmi_phy_resource_disable(phy); + phy_exit(hdmi->phy); } mutex_unlock(&hdmi->state_mutex); } diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi= /hdmi_phy.c deleted file mode 100644 index 667573f1db7c6bfef6c75828b5c581c147a86d0d..000000000000000000000000000= 0000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. - */ - -#include -#include - -#include "hdmi.h" - -static int msm_hdmi_phy_resource_init(struct hdmi_phy *phy) -{ - struct hdmi_phy_cfg *cfg =3D phy->cfg; - struct device *dev =3D &phy->pdev->dev; - int i, ret; - - phy->regs =3D devm_kcalloc(dev, cfg->num_regs, sizeof(phy->regs[0]), - GFP_KERNEL); - if (!phy->regs) - return -ENOMEM; - - phy->clks =3D devm_kcalloc(dev, cfg->num_clks, sizeof(phy->clks[0]), - GFP_KERNEL); - if (!phy->clks) - return -ENOMEM; - - for (i =3D 0; i < cfg->num_regs; i++) - phy->regs[i].supply =3D cfg->reg_names[i]; - - ret =3D devm_regulator_bulk_get(dev, cfg->num_regs, phy->regs); - if (ret) { - if (ret !=3D -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to get phy regulators: %d\n", ret); - - return ret; - } - - for (i =3D 0; i < cfg->num_clks; i++) { - struct clk *clk; - - clk =3D msm_clk_get(phy->pdev, cfg->clk_names[i]); - if (IS_ERR(clk)) { - ret =3D PTR_ERR(clk); - DRM_DEV_ERROR(dev, "failed to get phy clock: %s (%d)\n", - cfg->clk_names[i], ret); - return ret; - } - - phy->clks[i] =3D clk; - } - - return 0; -} - -int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy) -{ - struct hdmi_phy_cfg *cfg =3D phy->cfg; - struct device *dev =3D &phy->pdev->dev; - int i, ret =3D 0; - - ret =3D pm_runtime_resume_and_get(dev); - if (ret) { - DRM_DEV_ERROR(dev, "runtime resume failed: %d\n", ret); - return ret; - } - - ret =3D regulator_bulk_enable(cfg->num_regs, phy->regs); - if (ret) { - DRM_DEV_ERROR(dev, "failed to enable regulators: (%d)\n", ret); - return ret; - } - - for (i =3D 0; i < cfg->num_clks; i++) { - ret =3D clk_prepare_enable(phy->clks[i]); - if (ret) - DRM_DEV_ERROR(dev, "failed to enable clock: %s (%d)\n", - cfg->clk_names[i], ret); - } - - return ret; -} - -void msm_hdmi_phy_resource_disable(struct hdmi_phy *phy) -{ - struct hdmi_phy_cfg *cfg =3D phy->cfg; - struct device *dev =3D &phy->pdev->dev; - int i; - - for (i =3D cfg->num_clks - 1; i >=3D 0; i--) - clk_disable_unprepare(phy->clks[i]); - - regulator_bulk_disable(cfg->num_regs, phy->regs); - - pm_runtime_put_sync(dev); -} - -void msm_hdmi_phy_powerup(struct hdmi_phy *phy, unsigned long int pixclock) -{ - if (!phy || !phy->cfg->powerup) - return; - - phy->cfg->powerup(phy, pixclock); -} - -void msm_hdmi_phy_powerdown(struct hdmi_phy *phy) -{ - if (!phy || !phy->cfg->powerdown) - return; - - phy->cfg->powerdown(phy); -} - -static int msm_hdmi_phy_pll_init(struct platform_device *pdev, - enum hdmi_phy_type type) -{ - int ret; - - switch (type) { - case MSM_HDMI_PHY_8960: - ret =3D msm_hdmi_pll_8960_init(pdev); - break; - case MSM_HDMI_PHY_8996: - ret =3D msm_hdmi_pll_8996_init(pdev); - break; - case MSM_HDMI_PHY_8998: - ret =3D msm_hdmi_pll_8998_init(pdev); - break; - /* - * we don't have PLL support for these, don't report an error for now - */ - case MSM_HDMI_PHY_8x60: - case MSM_HDMI_PHY_8x74: - default: - ret =3D 0; - break; - } - - return ret; -} - -static int msm_hdmi_phy_probe(struct platform_device *pdev) -{ - struct device *dev =3D &pdev->dev; - struct hdmi_phy *phy; - int ret; - - phy =3D devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) - return -ENODEV; - - phy->cfg =3D (struct hdmi_phy_cfg *)of_device_get_match_data(dev); - if (!phy->cfg) - return -ENODEV; - - phy->mmio =3D msm_ioremap(pdev, "hdmi_phy"); - if (IS_ERR(phy->mmio)) { - DRM_DEV_ERROR(dev, "%s: failed to map phy base\n", __func__); - return -ENOMEM; - } - - phy->pdev =3D pdev; - - ret =3D msm_hdmi_phy_resource_init(phy); - if (ret) - return ret; - - pm_runtime_enable(&pdev->dev); - - ret =3D msm_hdmi_phy_resource_enable(phy); - if (ret) - return ret; - - ret =3D msm_hdmi_phy_pll_init(pdev, phy->cfg->type); - if (ret) { - DRM_DEV_ERROR(dev, "couldn't init PLL\n"); - msm_hdmi_phy_resource_disable(phy); - return ret; - } - - msm_hdmi_phy_resource_disable(phy); - - platform_set_drvdata(pdev, phy); - - return 0; -} - -static void msm_hdmi_phy_remove(struct platform_device *pdev) -{ - pm_runtime_disable(&pdev->dev); -} - -static const struct of_device_id msm_hdmi_phy_dt_match[] =3D { - { .compatible =3D "qcom,hdmi-phy-8660", - .data =3D &msm_hdmi_phy_8x60_cfg }, - { .compatible =3D "qcom,hdmi-phy-8960", - .data =3D &msm_hdmi_phy_8960_cfg }, - { .compatible =3D "qcom,hdmi-phy-8974", - .data =3D &msm_hdmi_phy_8x74_cfg }, - { .compatible =3D "qcom,hdmi-phy-8084", - .data =3D &msm_hdmi_phy_8x74_cfg }, - { .compatible =3D "qcom,hdmi-phy-8996", - .data =3D &msm_hdmi_phy_8996_cfg }, - { .compatible =3D "qcom,hdmi-phy-8998", - .data =3D &msm_hdmi_phy_8998_cfg }, - {} -}; - -static struct platform_driver msm_hdmi_phy_platform_driver =3D { - .probe =3D msm_hdmi_phy_probe, - .remove =3D msm_hdmi_phy_remove, - .driver =3D { - .name =3D "msm_hdmi_phy", - .of_match_table =3D msm_hdmi_phy_dt_match, - }, -}; - -void __init msm_hdmi_phy_driver_register(void) -{ - platform_driver_register(&msm_hdmi_phy_platform_driver); -} - -void __exit msm_hdmi_phy_driver_unregister(void) -{ - platform_driver_unregister(&msm_hdmi_phy_platform_driver); -} diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c b/drivers/gpu/drm/msm= /hdmi/hdmi_phy_8960.c deleted file mode 100644 index cf90a0c1f82205eb29b4903de0de65077ee80362..000000000000000000000000000= 0000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2013 Red Hat - * Author: Rob Clark - */ - -#include "hdmi.h" - -static void hdmi_phy_8960_powerup(struct hdmi_phy *phy, - unsigned long int pixclock) -{ - DBG("pixclock: %lu", pixclock); - - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG0, 0x1b); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG1, 0xf2); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG4, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG5, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG6, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG7, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG8, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG9, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG10, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG11, 0x00); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG3, 0x20); -} - -static void hdmi_phy_8960_powerdown(struct hdmi_phy *phy) -{ - DBG(""); - - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x7f); -} - -static const char * const hdmi_phy_8960_reg_names[] =3D { - "core-vdda", -}; - -static const char * const hdmi_phy_8960_clk_names[] =3D { - "slave_iface", -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8960_cfg =3D { - .type =3D MSM_HDMI_PHY_8960, - .powerup =3D hdmi_phy_8960_powerup, - .powerdown =3D hdmi_phy_8960_powerdown, - .reg_names =3D hdmi_phy_8960_reg_names, - .num_regs =3D ARRAY_SIZE(hdmi_phy_8960_reg_names), - .clk_names =3D hdmi_phy_8960_clk_names, - .num_clks =3D ARRAY_SIZE(hdmi_phy_8960_clk_names), -}; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c b/drivers/gpu/drm/msm= /hdmi/hdmi_phy_8996.c deleted file mode 100644 index 8c8d80b59573a37a4008752b16e094a218802508..000000000000000000000000000= 0000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c +++ /dev/null @@ -1,765 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. - */ - -#include -#include - -#include "hdmi.h" - -#define HDMI_VCO_MAX_FREQ 12000000000UL -#define HDMI_VCO_MIN_FREQ 8000000000UL - -#define HDMI_PCLK_MAX_FREQ 600000000 -#define HDMI_PCLK_MIN_FREQ 25000000 - -#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL -#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL -#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000UL -#define HDMI_CORECLK_DIV 5 -#define HDMI_DEFAULT_REF_CLOCK 19200000 -#define HDMI_PLL_CMP_CNT 1024 - -#define HDMI_PLL_POLL_MAX_READS 100 -#define HDMI_PLL_POLL_TIMEOUT_US 150 - -#define HDMI_NUM_TX_CHANNEL 4 - -struct hdmi_pll_8996 { - struct platform_device *pdev; - struct clk_hw clk_hw; - - /* pll mmio base */ - void __iomem *mmio_qserdes_com; - /* tx channel base */ - void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL]; -}; - -#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8996, clk_hw) - -struct hdmi_8996_phy_pll_reg_cfg { - u32 tx_lx_lane_mode[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL]; - u32 com_svs_mode_clk_sel; - u32 com_hsclk_sel; - u32 com_pll_cctrl_mode0; - u32 com_pll_rctrl_mode0; - u32 com_cp_ctrl_mode0; - u32 com_dec_start_mode0; - u32 com_div_frac_start1_mode0; - u32 com_div_frac_start2_mode0; - u32 com_div_frac_start3_mode0; - u32 com_integloop_gain0_mode0; - u32 com_integloop_gain1_mode0; - u32 com_lock_cmp_en; - u32 com_lock_cmp1_mode0; - u32 com_lock_cmp2_mode0; - u32 com_lock_cmp3_mode0; - u32 com_core_clk_en; - u32 com_coreclk_div; - u32 com_vco_tune_ctrl; - - u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_vmode_ctrl1[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_vmode_ctrl2[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_res_code_lane_tx[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_hp_pd_enables[HDMI_NUM_TX_CHANNEL]; - - u32 phy_mode; -}; - -struct hdmi_8996_post_divider { - u64 vco_freq; - int hsclk_divsel; - int vco_ratio; - int tx_band_sel; - int half_rate_mode; -}; - -static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8996 *pll) -{ - return platform_get_drvdata(pll->pdev); -} - -static inline void hdmi_pll_write(struct hdmi_pll_8996 *pll, int offset, - u32 data) -{ - writel(data, pll->mmio_qserdes_com + offset); -} - -static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset) -{ - return readl(pll->mmio_qserdes_com + offset); -} - -static inline void hdmi_tx_chan_write(struct hdmi_pll_8996 *pll, int chann= el, - int offset, int data) -{ - writel(data, pll->mmio_qserdes_tx[channel] + offset); -} - -static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk, - bool gen_ssc) -{ - if ((frac_start !=3D 0) || gen_ssc) - return (11000000 / (ref_clk / 20)); - - return 0x23; -} - -static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start !=3D 0) || gen_ssc) - return 0x16; - - return 0x10; -} - -static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start !=3D 0) || gen_ssc) - return 0x28; - - return 0x1; -} - -static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref= _clk, - bool gen_ssc) -{ - int digclk_divsel =3D bclk >=3D HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2; - u64 base; - - if ((frac_start !=3D 0) || gen_ssc) - base =3D (64 * ref_clk) / HDMI_DEFAULT_REF_CLOCK; - else - base =3D (1022 * ref_clk) / 100; - - base <<=3D digclk_divsel; - - return (base <=3D 2046 ? base : 2046); -} - -static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk) -{ - u64 dividend =3D HDMI_PLL_CMP_CNT * fdata; - u32 divisor =3D ref_clk * 10; - u32 rem; - - rem =3D do_div(dividend, divisor); - if (rem > (divisor >> 1)) - dividend++; - - return dividend - 1; -} - -static inline u64 pll_cmp_to_fdata(u32 pll_cmp, unsigned long ref_clk) -{ - u64 fdata =3D ((u64)pll_cmp) * ref_clk * 10; - - do_div(fdata, HDMI_PLL_CMP_CNT); - - return fdata; -} - -static int pll_get_post_div(struct hdmi_8996_post_divider *pd, u64 bclk) -{ - int ratio[] =3D { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 }; - int hs_divsel[] =3D { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 }; - int tx_band_sel[] =3D { 0, 1, 2, 3 }; - u64 vco_freq[60]; - u64 vco, vco_optimal; - int half_rate_mode =3D 0; - int vco_optimal_index, vco_freq_index; - int i, j; - -retry: - vco_optimal =3D HDMI_VCO_MAX_FREQ; - vco_optimal_index =3D -1; - vco_freq_index =3D 0; - for (i =3D 0; i < 15; i++) { - for (j =3D 0; j < 4; j++) { - u32 ratio_mult =3D ratio[i] << tx_band_sel[j]; - - vco =3D bclk >> half_rate_mode; - vco *=3D ratio_mult; - vco_freq[vco_freq_index++] =3D vco; - } - } - - for (i =3D 0; i < 60; i++) { - u64 vco_tmp =3D vco_freq[i]; - - if ((vco_tmp >=3D HDMI_VCO_MIN_FREQ) && - (vco_tmp <=3D vco_optimal)) { - vco_optimal =3D vco_tmp; - vco_optimal_index =3D i; - } - } - - if (vco_optimal_index =3D=3D -1) { - if (!half_rate_mode) { - half_rate_mode =3D 1; - goto retry; - } - } else { - pd->vco_freq =3D vco_optimal; - pd->tx_band_sel =3D tx_band_sel[vco_optimal_index % 4]; - pd->vco_ratio =3D ratio[vco_optimal_index / 4]; - pd->hsclk_divsel =3D hs_divsel[vco_optimal_index / 4]; - - return 0; - } - - return -EINVAL; -} - -static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk, - struct hdmi_8996_phy_pll_reg_cfg *cfg) -{ - struct hdmi_8996_post_divider pd; - u64 bclk; - u64 tmds_clk; - u64 dec_start; - u64 frac_start; - u64 fdata; - u32 pll_divisor; - u32 rem; - u32 cpctrl; - u32 rctrl; - u32 cctrl; - u32 integloop_gain; - u32 pll_cmp; - int i, ret; - - /* bit clk =3D 10 * pix_clk */ - bclk =3D ((u64)pix_clk) * 10; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) - tmds_clk =3D pix_clk >> 2; - else - tmds_clk =3D pix_clk; - - ret =3D pll_get_post_div(&pd, bclk); - if (ret) - return ret; - - dec_start =3D pd.vco_freq; - pll_divisor =3D 4 * ref_clk; - do_div(dec_start, pll_divisor); - - frac_start =3D pd.vco_freq * (1 << 20); - - rem =3D do_div(frac_start, pll_divisor); - frac_start -=3D dec_start * (1 << 20); - if (rem > (pll_divisor >> 1)) - frac_start++; - - cpctrl =3D pll_get_cpctrl(frac_start, ref_clk, false); - rctrl =3D pll_get_rctrl(frac_start, false); - cctrl =3D pll_get_cctrl(frac_start, false); - integloop_gain =3D pll_get_integloop_gain(frac_start, bclk, - ref_clk, false); - - fdata =3D pd.vco_freq; - do_div(fdata, pd.vco_ratio); - - pll_cmp =3D pll_get_pll_cmp(fdata, ref_clk); - - DBG("VCO freq: %llu", pd.vco_freq); - DBG("fdata: %llu", fdata); - DBG("pix_clk: %lu", pix_clk); - DBG("tmds clk: %llu", tmds_clk); - DBG("HSCLK_SEL: %d", pd.hsclk_divsel); - DBG("DEC_START: %llu", dec_start); - DBG("DIV_FRAC_START: %llu", frac_start); - DBG("PLL_CPCTRL: %u", cpctrl); - DBG("PLL_RCTRL: %u", rctrl); - DBG("PLL_CCTRL: %u", cctrl); - DBG("INTEGLOOP_GAIN: %u", integloop_gain); - DBG("TX_BAND: %d", pd.tx_band_sel); - DBG("PLL_CMP: %u", pll_cmp); - - /* Convert these values to register specific values */ - if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) - cfg->com_svs_mode_clk_sel =3D 1; - else - cfg->com_svs_mode_clk_sel =3D 2; - - cfg->com_hsclk_sel =3D (0x20 | pd.hsclk_divsel); - cfg->com_pll_cctrl_mode0 =3D cctrl; - cfg->com_pll_rctrl_mode0 =3D rctrl; - cfg->com_cp_ctrl_mode0 =3D cpctrl; - cfg->com_dec_start_mode0 =3D dec_start; - cfg->com_div_frac_start1_mode0 =3D (frac_start & 0xff); - cfg->com_div_frac_start2_mode0 =3D ((frac_start & 0xff00) >> 8); - cfg->com_div_frac_start3_mode0 =3D ((frac_start & 0xf0000) >> 16); - cfg->com_integloop_gain0_mode0 =3D (integloop_gain & 0xff); - cfg->com_integloop_gain1_mode0 =3D ((integloop_gain & 0xf00) >> 8); - cfg->com_lock_cmp1_mode0 =3D (pll_cmp & 0xff); - cfg->com_lock_cmp2_mode0 =3D ((pll_cmp & 0xff00) >> 8); - cfg->com_lock_cmp3_mode0 =3D ((pll_cmp & 0x30000) >> 16); - cfg->com_lock_cmp_en =3D 0x0; - cfg->com_core_clk_en =3D 0x2c; - cfg->com_coreclk_div =3D HDMI_CORECLK_DIV; - cfg->phy_mode =3D (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0; - cfg->com_vco_tune_ctrl =3D 0x0; - - cfg->tx_lx_lane_mode[0] =3D - cfg->tx_lx_lane_mode[2] =3D 0x43; - - cfg->tx_lx_hp_pd_enables[0] =3D - cfg->tx_lx_hp_pd_enables[1] =3D - cfg->tx_lx_hp_pd_enables[2] =3D 0x0c; - cfg->tx_lx_hp_pd_enables[3] =3D 0x3; - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) - cfg->tx_lx_tx_band[i] =3D pd.tx_band_sel + 4; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_lx_tx_drv_lvl[0] =3D - cfg->tx_lx_tx_drv_lvl[1] =3D - cfg->tx_lx_tx_drv_lvl[2] =3D 0x25; - cfg->tx_lx_tx_drv_lvl[3] =3D 0x22; - - cfg->tx_lx_tx_emp_post1_lvl[0] =3D - cfg->tx_lx_tx_emp_post1_lvl[1] =3D - cfg->tx_lx_tx_emp_post1_lvl[2] =3D 0x23; - cfg->tx_lx_tx_emp_post1_lvl[3] =3D 0x27; - - cfg->tx_lx_vmode_ctrl1[0] =3D - cfg->tx_lx_vmode_ctrl1[1] =3D - cfg->tx_lx_vmode_ctrl1[2] =3D - cfg->tx_lx_vmode_ctrl1[3] =3D 0x00; - - cfg->tx_lx_vmode_ctrl2[0] =3D - cfg->tx_lx_vmode_ctrl2[1] =3D - cfg->tx_lx_vmode_ctrl2[2] =3D 0x0D; - - cfg->tx_lx_vmode_ctrl2[3] =3D 0x00; - } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - cfg->tx_lx_tx_drv_lvl[i] =3D 0x25; - cfg->tx_lx_tx_emp_post1_lvl[i] =3D 0x23; - cfg->tx_lx_vmode_ctrl1[i] =3D 0x00; - } - - cfg->tx_lx_vmode_ctrl2[0] =3D - cfg->tx_lx_vmode_ctrl2[1] =3D - cfg->tx_lx_vmode_ctrl2[2] =3D 0x0D; - cfg->tx_lx_vmode_ctrl2[3] =3D 0x00; - } else { - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - cfg->tx_lx_tx_drv_lvl[i] =3D 0x20; - cfg->tx_lx_tx_emp_post1_lvl[i] =3D 0x20; - cfg->tx_lx_vmode_ctrl1[i] =3D 0x00; - cfg->tx_lx_vmode_ctrl2[i] =3D 0x0E; - } - } - - DBG("com_svs_mode_clk_sel =3D 0x%x", cfg->com_svs_mode_clk_sel); - DBG("com_hsclk_sel =3D 0x%x", cfg->com_hsclk_sel); - DBG("com_lock_cmp_en =3D 0x%x", cfg->com_lock_cmp_en); - DBG("com_pll_cctrl_mode0 =3D 0x%x", cfg->com_pll_cctrl_mode0); - DBG("com_pll_rctrl_mode0 =3D 0x%x", cfg->com_pll_rctrl_mode0); - DBG("com_cp_ctrl_mode0 =3D 0x%x", cfg->com_cp_ctrl_mode0); - DBG("com_dec_start_mode0 =3D 0x%x", cfg->com_dec_start_mode0); - DBG("com_div_frac_start1_mode0 =3D 0x%x", cfg->com_div_frac_start1_mode0); - DBG("com_div_frac_start2_mode0 =3D 0x%x", cfg->com_div_frac_start2_mode0); - DBG("com_div_frac_start3_mode0 =3D 0x%x", cfg->com_div_frac_start3_mode0); - DBG("com_integloop_gain0_mode0 =3D 0x%x", cfg->com_integloop_gain0_mode0); - DBG("com_integloop_gain1_mode0 =3D 0x%x", cfg->com_integloop_gain1_mode0); - DBG("com_lock_cmp1_mode0 =3D 0x%x", cfg->com_lock_cmp1_mode0); - DBG("com_lock_cmp2_mode0 =3D 0x%x", cfg->com_lock_cmp2_mode0); - DBG("com_lock_cmp3_mode0 =3D 0x%x", cfg->com_lock_cmp3_mode0); - DBG("com_core_clk_en =3D 0x%x", cfg->com_core_clk_en); - DBG("com_coreclk_div =3D 0x%x", cfg->com_coreclk_div); - DBG("phy_mode =3D 0x%x", cfg->phy_mode); - - DBG("tx_l0_lane_mode =3D 0x%x", cfg->tx_lx_lane_mode[0]); - DBG("tx_l2_lane_mode =3D 0x%x", cfg->tx_lx_lane_mode[2]); - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - DBG("tx_l%d_tx_band =3D 0x%x", i, cfg->tx_lx_tx_band[i]); - DBG("tx_l%d_tx_drv_lvl =3D 0x%x", i, cfg->tx_lx_tx_drv_lvl[i]); - DBG("tx_l%d_tx_emp_post1_lvl =3D 0x%x", i, - cfg->tx_lx_tx_emp_post1_lvl[i]); - DBG("tx_l%d_vmode_ctrl1 =3D 0x%x", i, cfg->tx_lx_vmode_ctrl1[i]); - DBG("tx_l%d_vmode_ctrl2 =3D 0x%x", i, cfg->tx_lx_vmode_ctrl2[i]); - } - - return 0; -} - -static int hdmi_8996_pll_set_clk_rate(struct clk_hw *hw, unsigned long rat= e, - unsigned long parent_rate) -{ - struct hdmi_pll_8996 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - struct hdmi_8996_phy_pll_reg_cfg cfg; - int i, ret; - - memset(&cfg, 0x00, sizeof(cfg)); - - ret =3D pll_calculate(rate, parent_rate, &cfg); - if (ret) { - DRM_ERROR("PLL calculation failed\n"); - return ret; - } - - /* Initially shut down PHY */ - DBG("Disabling PHY"); - hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x0); - udelay(500); - - /* Power up sequence */ - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x04); - - hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20); - hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL, 0x0F); - hdmi_phy_write(phy, REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL, 0x0F); - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_CLKBUF_ENABLE, - 0x03); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_TX_BAND, - cfg.tx_lx_tx_band[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_RESET_TSYNC_EN, - 0x03); - } - - hdmi_tx_chan_write(pll, 0, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE, - cfg.tx_lx_lane_mode[0]); - hdmi_tx_chan_write(pll, 2, REG_HDMI_PHY_QSERDES_TX_LX_LANE_MODE, - cfg.tx_lx_lane_mode[2]); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1E); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E); - - /* Bypass VCO calibration */ - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SVS_MODE_CLK_SEL, - cfg.com_svs_mode_clk_sel); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_TRIM, 0x0F); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_IVCO, 0x0F); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_CTRL, - cfg.com_vco_tune_ctrl); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_BG_CTRL, 0x06); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CLK_SELECT, 0x30); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_HSCLK_SEL, - cfg.com_hsclk_sel); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP_EN, - cfg.com_lock_cmp_en); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_CCTRL_MODE0, - cfg.com_pll_cctrl_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_PLL_RCTRL_MODE0, - cfg.com_pll_rctrl_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CP_CTRL_MODE0, - cfg.com_cp_ctrl_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DEC_START_MODE0, - cfg.com_dec_start_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0, - cfg.com_div_frac_start1_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0, - cfg.com_div_frac_start2_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0, - cfg.com_div_frac_start3_mode0); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0, - cfg.com_integloop_gain0_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0, - cfg.com_integloop_gain1_mode0); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0, - cfg.com_lock_cmp1_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0, - cfg.com_lock_cmp2_mode0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0, - cfg.com_lock_cmp3_mode0); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORE_CLK_EN, - cfg.com_core_clk_en); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CORECLK_DIV, - cfg.com_coreclk_div); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_CMN_CONFIG, 0x02); - - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_RESCODE_DIV_NUM, 0x15); - - /* TX lanes setup (TX 0/1/2/3) */ - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL, - cfg.tx_lx_tx_drv_lvl[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_TX_EMP_POST1_LVL, - cfg.tx_lx_tx_emp_post1_lvl[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL1, - cfg.tx_lx_vmode_ctrl1[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_VMODE_CTRL2, - cfg.tx_lx_vmode_ctrl2[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_TX_DRV_LVL_OFFSET, - 0x00); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_RES_CODE_LANE_OFFSET, - 0x00); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_TRAN_DRVR_EMP_EN, - 0x03); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_PARRATE_REC_DETECT_IDLE_EN, - 0x40); - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_HP_PD_ENABLES, - cfg.tx_lx_hp_pd_enables[i]); - } - - hdmi_phy_write(phy, REG_HDMI_8996_PHY_MODE, cfg.phy_mode); - hdmi_phy_write(phy, REG_HDMI_8996_PHY_PD_CTL, 0x1F); - - /* - * Ensure that vco configuration gets flushed to hardware before - * enabling the PLL - */ - wmb(); - - return 0; -} - -static int hdmi_8996_phy_ready_status(struct hdmi_phy *phy) -{ - u32 nb_tries =3D HDMI_PLL_POLL_MAX_READS; - unsigned long timeout =3D HDMI_PLL_POLL_TIMEOUT_US; - u32 status; - int phy_ready =3D 0; - - DBG("Waiting for PHY ready"); - - while (nb_tries--) { - status =3D hdmi_phy_read(phy, REG_HDMI_8996_PHY_STATUS); - phy_ready =3D status & BIT(0); - - if (phy_ready) - break; - - udelay(timeout); - } - - DBG("PHY is %sready", phy_ready ? "" : "*not* "); - - return phy_ready; -} - -static int hdmi_8996_pll_lock_status(struct hdmi_pll_8996 *pll) -{ - u32 status; - int nb_tries =3D HDMI_PLL_POLL_MAX_READS; - unsigned long timeout =3D HDMI_PLL_POLL_TIMEOUT_US; - int pll_locked =3D 0; - - DBG("Waiting for PLL lock"); - - while (nb_tries--) { - status =3D hdmi_pll_read(pll, - REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS); - pll_locked =3D status & BIT(0); - - if (pll_locked) - break; - - udelay(timeout); - } - - DBG("HDMI PLL is %slocked", pll_locked ? "" : "*not* "); - - return pll_locked; -} - -static int hdmi_8996_pll_prepare(struct clk_hw *hw) -{ - struct hdmi_pll_8996 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - int i, ret =3D 0; - - hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x1); - udelay(100); - - hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19); - udelay(100); - - ret =3D hdmi_8996_pll_lock_status(pll); - if (!ret) - return ret; - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) - hdmi_tx_chan_write(pll, i, - REG_HDMI_PHY_QSERDES_TX_LX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, - 0x6F); - - /* Disable SSC */ - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER1, 0x0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_PER2, 0x0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE1, 0x0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_STEP_SIZE2, 0x0); - hdmi_pll_write(pll, REG_HDMI_PHY_QSERDES_COM_SSC_EN_CENTER, 0x2); - - ret =3D hdmi_8996_phy_ready_status(phy); - if (!ret) - return ret; - - /* Restart the retiming buffer */ - hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x18); - udelay(1); - hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x19); - - return 0; -} - -static long hdmi_8996_pll_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *parent_rate) -{ - if (rate < HDMI_PCLK_MIN_FREQ) - return HDMI_PCLK_MIN_FREQ; - else if (rate > HDMI_PCLK_MAX_FREQ) - return HDMI_PCLK_MAX_FREQ; - else - return rate; -} - -static unsigned long hdmi_8996_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct hdmi_pll_8996 *pll =3D hw_clk_to_pll(hw); - u64 fdata; - u32 cmp1, cmp2, cmp3, pll_cmp; - - cmp1 =3D hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0); - cmp2 =3D hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0); - cmp3 =3D hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0); - - pll_cmp =3D cmp1 | (cmp2 << 8) | (cmp3 << 16); - - fdata =3D pll_cmp_to_fdata(pll_cmp + 1, parent_rate); - - do_div(fdata, 10); - - return fdata; -} - -static void hdmi_8996_pll_unprepare(struct clk_hw *hw) -{ - struct hdmi_pll_8996 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - - hdmi_phy_write(phy, REG_HDMI_8996_PHY_CFG, 0x6); - usleep_range(100, 150); -} - -static int hdmi_8996_pll_is_enabled(struct clk_hw *hw) -{ - struct hdmi_pll_8996 *pll =3D hw_clk_to_pll(hw); - u32 status; - int pll_locked; - - status =3D hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS); - pll_locked =3D status & BIT(0); - - return pll_locked; -} - -static const struct clk_ops hdmi_8996_pll_ops =3D { - .set_rate =3D hdmi_8996_pll_set_clk_rate, - .round_rate =3D hdmi_8996_pll_round_rate, - .recalc_rate =3D hdmi_8996_pll_recalc_rate, - .prepare =3D hdmi_8996_pll_prepare, - .unprepare =3D hdmi_8996_pll_unprepare, - .is_enabled =3D hdmi_8996_pll_is_enabled, -}; - -static const struct clk_init_data pll_init =3D { - .name =3D "hdmipll", - .ops =3D &hdmi_8996_pll_ops, - .parent_data =3D (const struct clk_parent_data[]){ - { .fw_name =3D "xo", .name =3D "xo_board" }, - }, - .num_parents =3D 1, - .flags =3D CLK_IGNORE_UNUSED, -}; - -int msm_hdmi_pll_8996_init(struct platform_device *pdev) -{ - struct device *dev =3D &pdev->dev; - struct hdmi_pll_8996 *pll; - int i, ret; - - pll =3D devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); - if (!pll) - return -ENOMEM; - - pll->pdev =3D pdev; - - pll->mmio_qserdes_com =3D msm_ioremap(pdev, "hdmi_pll"); - if (IS_ERR(pll->mmio_qserdes_com)) { - DRM_DEV_ERROR(dev, "failed to map pll base\n"); - return -ENOMEM; - } - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - char name[32]; - - snprintf(name, sizeof(name), "hdmi_tx_l%d", i); - - pll->mmio_qserdes_tx[i] =3D msm_ioremap(pdev, name); - if (IS_ERR(pll->mmio_qserdes_tx[i])) { - DRM_DEV_ERROR(dev, "failed to map pll base\n"); - return -ENOMEM; - } - } - pll->clk_hw.init =3D &pll_init; - - ret =3D devm_clk_hw_register(dev, &pll->clk_hw); - if (ret) { - DRM_DEV_ERROR(dev, "failed to register pll clock\n"); - return ret; - } - - ret =3D devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_= hw); - if (ret) { - DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__= , ret); - return ret; - } - - return 0; -} - -static const char * const hdmi_phy_8996_reg_names[] =3D { - "vddio", - "vcca", -}; - -static const char * const hdmi_phy_8996_clk_names[] =3D { - "iface", "ref", -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg =3D { - .type =3D MSM_HDMI_PHY_8996, - .reg_names =3D hdmi_phy_8996_reg_names, - .num_regs =3D ARRAY_SIZE(hdmi_phy_8996_reg_names), - .clk_names =3D hdmi_phy_8996_clk_names, - .num_clks =3D ARRAY_SIZE(hdmi_phy_8996_clk_names), -}; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c b/drivers/gpu/drm/msm= /hdmi/hdmi_phy_8998.c deleted file mode 100644 index 33bb48ae58a2da13b7e90ff419c6e05fec1466af..000000000000000000000000000= 0000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8998.c +++ /dev/null @@ -1,769 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. - * Copyright (c) 2024 Freebox SAS - */ - -#include -#include - -#include "hdmi.h" - -#define HDMI_VCO_MAX_FREQ 12000000000UL -#define HDMI_VCO_MIN_FREQ 8000000000UL - -#define HDMI_PCLK_MAX_FREQ 600000000 -#define HDMI_PCLK_MIN_FREQ 25000000 - -#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL -#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL -#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000UL -#define HDMI_CORECLK_DIV 5 -#define HDMI_DEFAULT_REF_CLOCK 19200000 -#define HDMI_PLL_CMP_CNT 1024 - -#define HDMI_PLL_POLL_MAX_READS 100 -#define HDMI_PLL_POLL_TIMEOUT_US 150 - -#define HDMI_NUM_TX_CHANNEL 4 - -struct hdmi_pll_8998 { - struct platform_device *pdev; - struct clk_hw clk_hw; - unsigned long rate; - - /* pll mmio base */ - void __iomem *mmio_qserdes_com; - /* tx channel base */ - void __iomem *mmio_qserdes_tx[HDMI_NUM_TX_CHANNEL]; -}; - -#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8998, clk_hw) - -struct hdmi_8998_phy_pll_reg_cfg { - u32 com_svs_mode_clk_sel; - u32 com_hsclk_sel; - u32 com_pll_cctrl_mode0; - u32 com_pll_rctrl_mode0; - u32 com_cp_ctrl_mode0; - u32 com_dec_start_mode0; - u32 com_div_frac_start1_mode0; - u32 com_div_frac_start2_mode0; - u32 com_div_frac_start3_mode0; - u32 com_integloop_gain0_mode0; - u32 com_integloop_gain1_mode0; - u32 com_lock_cmp_en; - u32 com_lock_cmp1_mode0; - u32 com_lock_cmp2_mode0; - u32 com_lock_cmp3_mode0; - u32 com_core_clk_en; - u32 com_coreclk_div_mode0; - - u32 tx_lx_tx_band[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_tx_drv_lvl[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_tx_emp_post1_lvl[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_pre_driver_1[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_pre_driver_2[HDMI_NUM_TX_CHANNEL]; - u32 tx_lx_res_code_offset[HDMI_NUM_TX_CHANNEL]; - - u32 phy_mode; -}; - -struct hdmi_8998_post_divider { - u64 vco_freq; - int hsclk_divsel; - int vco_ratio; - int tx_band_sel; - int half_rate_mode; -}; - -static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8998 *pll) -{ - return platform_get_drvdata(pll->pdev); -} - -static inline void hdmi_pll_write(struct hdmi_pll_8998 *pll, int offset, - u32 data) -{ - writel(data, pll->mmio_qserdes_com + offset); -} - -static inline u32 hdmi_pll_read(struct hdmi_pll_8998 *pll, int offset) -{ - return readl(pll->mmio_qserdes_com + offset); -} - -static inline void hdmi_tx_chan_write(struct hdmi_pll_8998 *pll, int chann= el, - int offset, int data) -{ - writel(data, pll->mmio_qserdes_tx[channel] + offset); -} - -static inline u32 pll_get_cpctrl(u64 frac_start, unsigned long ref_clk, - bool gen_ssc) -{ - if ((frac_start !=3D 0) || gen_ssc) - return 0x8; - - return 0x30; -} - -static inline u32 pll_get_rctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start !=3D 0) || gen_ssc) - return 0x16; - - return 0x18; -} - -static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start !=3D 0) || gen_ssc) - return 0x34; - - return 0x2; -} - -static inline u32 pll_get_integloop_gain(u64 frac_start, u64 bclk, u32 ref= _clk, - bool gen_ssc) -{ - int digclk_divsel =3D bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2; - u64 base; - - if ((frac_start !=3D 0) || gen_ssc) - base =3D 0x3F; - else - base =3D 0xC4; - - base <<=3D (digclk_divsel =3D=3D 2 ? 1 : 0); - - return base; -} - -static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk) -{ - u64 dividend =3D HDMI_PLL_CMP_CNT * fdata; - u32 divisor =3D ref_clk * 10; - u32 rem; - - rem =3D do_div(dividend, divisor); - if (rem > (divisor >> 1)) - dividend++; - - return dividend - 1; -} - -#define HDMI_REF_CLOCK_HZ ((u64)19200000) -#define HDMI_MHZ_TO_HZ ((u64)1000000) -static int pll_get_post_div(struct hdmi_8998_post_divider *pd, u64 bclk) -{ - static const u32 ratio_list[] =3D {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25}; - static const u32 band_list[] =3D {0, 1, 2, 3}; - u32 const sz_ratio =3D ARRAY_SIZE(ratio_list); - u32 const sz_band =3D ARRAY_SIZE(band_list); - u32 const cmp_cnt =3D 1024; - u32 const th_min =3D 500, th_max =3D 1000; - u32 half_rate_mode =3D 0; - u32 list_elements; - int optimal_index; - u32 i, j, k; - u32 found_hsclk_divsel =3D 0, found_vco_ratio; - u32 found_tx_band_sel; - u64 const min_freq =3D HDMI_VCO_MIN_FREQ, max_freq =3D HDMI_VCO_MAX_FREQ; - u64 freq_list[ARRAY_SIZE(ratio_list) * ARRAY_SIZE(band_list)]; - u64 found_vco_freq; - u64 freq_optimal; - -find_optimal_index: - freq_optimal =3D max_freq; - optimal_index =3D -1; - list_elements =3D 0; - - for (i =3D 0; i < sz_ratio; i++) { - for (j =3D 0; j < sz_band; j++) { - u64 freq =3D div_u64(bclk, (1 << half_rate_mode)); - - freq *=3D (ratio_list[i] * (1 << band_list[j])); - freq_list[list_elements++] =3D freq; - } - } - - for (k =3D 0; k < ARRAY_SIZE(freq_list); k++) { - u32 const clks_pll_div =3D 2, core_clk_div =3D 5; - u32 const rng1 =3D 16, rng2 =3D 8; - u32 th1, th2; - u64 core_clk, rvar1, rem; - - core_clk =3D div_u64(freq_list[k], - ratio_list[k / sz_band] * clks_pll_div * - core_clk_div); - - rvar1 =3D HDMI_REF_CLOCK_HZ * rng1 * HDMI_MHZ_TO_HZ; - rvar1 =3D div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem); - if (rem > ((cmp_cnt * core_clk) >> 1)) - rvar1++; - th1 =3D rvar1; - - rvar1 =3D HDMI_REF_CLOCK_HZ * rng2 * HDMI_MHZ_TO_HZ; - rvar1 =3D div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem); - if (rem > ((cmp_cnt * core_clk) >> 1)) - rvar1++; - th2 =3D rvar1; - - if (freq_list[k] >=3D min_freq && - freq_list[k] <=3D max_freq) { - if ((th1 >=3D th_min && th1 <=3D th_max) || - (th2 >=3D th_min && th2 <=3D th_max)) { - if (freq_list[k] <=3D freq_optimal) { - freq_optimal =3D freq_list[k]; - optimal_index =3D k; - } - } - } - } - - if (optimal_index =3D=3D -1) { - if (!half_rate_mode) { - half_rate_mode =3D 1; - goto find_optimal_index; - } else { - return -EINVAL; - } - } else { - found_vco_ratio =3D ratio_list[optimal_index / sz_band]; - found_tx_band_sel =3D band_list[optimal_index % sz_band]; - found_vco_freq =3D freq_optimal; - } - - switch (found_vco_ratio) { - case 1: - found_hsclk_divsel =3D 15; - break; - case 2: - found_hsclk_divsel =3D 0; - break; - case 3: - found_hsclk_divsel =3D 4; - break; - case 4: - found_hsclk_divsel =3D 8; - break; - case 5: - found_hsclk_divsel =3D 12; - break; - case 6: - found_hsclk_divsel =3D 1; - break; - case 9: - found_hsclk_divsel =3D 5; - break; - case 10: - found_hsclk_divsel =3D 2; - break; - case 12: - found_hsclk_divsel =3D 9; - break; - case 15: - found_hsclk_divsel =3D 13; - break; - case 25: - found_hsclk_divsel =3D 14; - break; - } - - pd->vco_freq =3D found_vco_freq; - pd->tx_band_sel =3D found_tx_band_sel; - pd->vco_ratio =3D found_vco_ratio; - pd->hsclk_divsel =3D found_hsclk_divsel; - - return 0; -} - -static int pll_calculate(unsigned long pix_clk, unsigned long ref_clk, - struct hdmi_8998_phy_pll_reg_cfg *cfg) -{ - struct hdmi_8998_post_divider pd; - u64 bclk; - u64 dec_start; - u64 frac_start; - u64 fdata; - u32 pll_divisor; - u32 rem; - u32 cpctrl; - u32 rctrl; - u32 cctrl; - u32 integloop_gain; - u32 pll_cmp; - int i, ret; - - /* bit clk =3D 10 * pix_clk */ - bclk =3D ((u64)pix_clk) * 10; - - ret =3D pll_get_post_div(&pd, bclk); - if (ret) - return ret; - - dec_start =3D pd.vco_freq; - pll_divisor =3D 4 * ref_clk; - do_div(dec_start, pll_divisor); - - frac_start =3D pd.vco_freq * (1 << 20); - - rem =3D do_div(frac_start, pll_divisor); - frac_start -=3D dec_start * (1 << 20); - if (rem > (pll_divisor >> 1)) - frac_start++; - - cpctrl =3D pll_get_cpctrl(frac_start, ref_clk, false); - rctrl =3D pll_get_rctrl(frac_start, false); - cctrl =3D pll_get_cctrl(frac_start, false); - integloop_gain =3D pll_get_integloop_gain(frac_start, bclk, - ref_clk, false); - - fdata =3D pd.vco_freq; - do_div(fdata, pd.vco_ratio); - - pll_cmp =3D pll_get_pll_cmp(fdata, ref_clk); - - /* Convert these values to register specific values */ - if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) - cfg->com_svs_mode_clk_sel =3D 1; - else - cfg->com_svs_mode_clk_sel =3D 2; - - cfg->com_hsclk_sel =3D (0x20 | pd.hsclk_divsel); - cfg->com_pll_cctrl_mode0 =3D cctrl; - cfg->com_pll_rctrl_mode0 =3D rctrl; - cfg->com_cp_ctrl_mode0 =3D cpctrl; - cfg->com_dec_start_mode0 =3D dec_start; - cfg->com_div_frac_start1_mode0 =3D (frac_start & 0xff); - cfg->com_div_frac_start2_mode0 =3D ((frac_start & 0xff00) >> 8); - cfg->com_div_frac_start3_mode0 =3D ((frac_start & 0xf0000) >> 16); - cfg->com_integloop_gain0_mode0 =3D (integloop_gain & 0xff); - cfg->com_integloop_gain1_mode0 =3D ((integloop_gain & 0xf00) >> 8); - cfg->com_lock_cmp1_mode0 =3D (pll_cmp & 0xff); - cfg->com_lock_cmp2_mode0 =3D ((pll_cmp & 0xff00) >> 8); - cfg->com_lock_cmp3_mode0 =3D ((pll_cmp & 0x30000) >> 16); - cfg->com_lock_cmp_en =3D 0x0; - cfg->com_core_clk_en =3D 0x2c; - cfg->com_coreclk_div_mode0 =3D HDMI_CORECLK_DIV; - cfg->phy_mode =3D (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x5 : 0x4; - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) - cfg->tx_lx_tx_band[i] =3D pd.tx_band_sel; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_lx_tx_drv_lvl[0] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[1] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[2] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[3] =3D 0x0f; - cfg->tx_lx_tx_emp_post1_lvl[0] =3D 0x03; - cfg->tx_lx_tx_emp_post1_lvl[1] =3D 0x02; - cfg->tx_lx_tx_emp_post1_lvl[2] =3D 0x03; - cfg->tx_lx_tx_emp_post1_lvl[3] =3D 0x00; - cfg->tx_lx_pre_driver_1[0] =3D 0x00; - cfg->tx_lx_pre_driver_1[1] =3D 0x00; - cfg->tx_lx_pre_driver_1[2] =3D 0x00; - cfg->tx_lx_pre_driver_1[3] =3D 0x00; - cfg->tx_lx_pre_driver_2[0] =3D 0x1C; - cfg->tx_lx_pre_driver_2[1] =3D 0x1C; - cfg->tx_lx_pre_driver_2[2] =3D 0x1C; - cfg->tx_lx_pre_driver_2[3] =3D 0x00; - cfg->tx_lx_res_code_offset[0] =3D 0x03; - cfg->tx_lx_res_code_offset[1] =3D 0x00; - cfg->tx_lx_res_code_offset[2] =3D 0x00; - cfg->tx_lx_res_code_offset[3] =3D 0x03; - } else if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_lx_tx_drv_lvl[0] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[1] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[2] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[3] =3D 0x0f; - cfg->tx_lx_tx_emp_post1_lvl[0] =3D 0x03; - cfg->tx_lx_tx_emp_post1_lvl[1] =3D 0x03; - cfg->tx_lx_tx_emp_post1_lvl[2] =3D 0x03; - cfg->tx_lx_tx_emp_post1_lvl[3] =3D 0x00; - cfg->tx_lx_pre_driver_1[0] =3D 0x00; - cfg->tx_lx_pre_driver_1[1] =3D 0x00; - cfg->tx_lx_pre_driver_1[2] =3D 0x00; - cfg->tx_lx_pre_driver_1[3] =3D 0x00; - cfg->tx_lx_pre_driver_2[0] =3D 0x16; - cfg->tx_lx_pre_driver_2[1] =3D 0x16; - cfg->tx_lx_pre_driver_2[2] =3D 0x16; - cfg->tx_lx_pre_driver_2[3] =3D 0x18; - cfg->tx_lx_res_code_offset[0] =3D 0x03; - cfg->tx_lx_res_code_offset[1] =3D 0x00; - cfg->tx_lx_res_code_offset[2] =3D 0x00; - cfg->tx_lx_res_code_offset[3] =3D 0x00; - } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_lx_tx_drv_lvl[0] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[1] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[2] =3D 0x0f; - cfg->tx_lx_tx_drv_lvl[3] =3D 0x0f; - cfg->tx_lx_tx_emp_post1_lvl[0] =3D 0x05; - cfg->tx_lx_tx_emp_post1_lvl[1] =3D 0x05; - cfg->tx_lx_tx_emp_post1_lvl[2] =3D 0x05; - cfg->tx_lx_tx_emp_post1_lvl[3] =3D 0x00; - cfg->tx_lx_pre_driver_1[0] =3D 0x00; - cfg->tx_lx_pre_driver_1[1] =3D 0x00; - cfg->tx_lx_pre_driver_1[2] =3D 0x00; - cfg->tx_lx_pre_driver_1[3] =3D 0x00; - cfg->tx_lx_pre_driver_2[0] =3D 0x0E; - cfg->tx_lx_pre_driver_2[1] =3D 0x0E; - cfg->tx_lx_pre_driver_2[2] =3D 0x0E; - cfg->tx_lx_pre_driver_2[3] =3D 0x0E; - cfg->tx_lx_res_code_offset[0] =3D 0x00; - cfg->tx_lx_res_code_offset[1] =3D 0x00; - cfg->tx_lx_res_code_offset[2] =3D 0x00; - cfg->tx_lx_res_code_offset[3] =3D 0x00; - } else { - cfg->tx_lx_tx_drv_lvl[0] =3D 0x01; - cfg->tx_lx_tx_drv_lvl[1] =3D 0x01; - cfg->tx_lx_tx_drv_lvl[2] =3D 0x01; - cfg->tx_lx_tx_drv_lvl[3] =3D 0x00; - cfg->tx_lx_tx_emp_post1_lvl[0] =3D 0x00; - cfg->tx_lx_tx_emp_post1_lvl[1] =3D 0x00; - cfg->tx_lx_tx_emp_post1_lvl[2] =3D 0x00; - cfg->tx_lx_tx_emp_post1_lvl[3] =3D 0x00; - cfg->tx_lx_pre_driver_1[0] =3D 0x00; - cfg->tx_lx_pre_driver_1[1] =3D 0x00; - cfg->tx_lx_pre_driver_1[2] =3D 0x00; - cfg->tx_lx_pre_driver_1[3] =3D 0x00; - cfg->tx_lx_pre_driver_2[0] =3D 0x16; - cfg->tx_lx_pre_driver_2[1] =3D 0x16; - cfg->tx_lx_pre_driver_2[2] =3D 0x16; - cfg->tx_lx_pre_driver_2[3] =3D 0x18; - cfg->tx_lx_res_code_offset[0] =3D 0x00; - cfg->tx_lx_res_code_offset[1] =3D 0x00; - cfg->tx_lx_res_code_offset[2] =3D 0x00; - cfg->tx_lx_res_code_offset[3] =3D 0x00; - } - - return 0; -} - -static int hdmi_8998_pll_set_clk_rate(struct clk_hw *hw, unsigned long rat= e, - unsigned long parent_rate) -{ - struct hdmi_pll_8998 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - struct hdmi_8998_phy_pll_reg_cfg cfg =3D {}; - int i, ret; - - ret =3D pll_calculate(rate, parent_rate, &cfg); - if (ret) { - DRM_ERROR("PLL calculation failed\n"); - return ret; - } - - /* Initially shut down PHY */ - hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x0); - udelay(500); - - /* Power up sequence */ - hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0x1); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_RESETSM_CNTRL, 0x20); - hdmi_phy_write(phy, REG_HDMI_8998_PHY_CMN_CTRL, 0x6); - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_INTERFACE_SELECT_TX_BAND, - cfg.tx_lx_tx_band[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_CLKBUF_TERM_ENABLE, - 0x1); - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_LANE_MODE, - 0x20); - } - - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_BUF_ENABLE, 0x02= ); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x= 0B); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYSCLK_EN_SEL, 0x37); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SYS_CLK_CTRL, 0x02); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_ENABLE1, 0x0E); - - /* Bypass VCO calibration */ - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_SVS_MODE_CLK_SEL, - cfg.com_svs_mode_clk_sel); - - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_IVCO, 0x07); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_CTRL, 0x00); - - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CLK_SEL, 0x30); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_HSCLK_SEL, - cfg.com_hsclk_sel); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP_EN, - cfg.com_lock_cmp_en); - - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_CCTRL_MODE0, - cfg.com_pll_cctrl_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_PLL_RCTRL_MODE0, - cfg.com_pll_rctrl_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CP_CTRL_MODE0, - cfg.com_cp_ctrl_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DEC_START_MODE0, - cfg.com_dec_start_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START1_MODE0, - cfg.com_div_frac_start1_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START2_MODE0, - cfg.com_div_frac_start2_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_DIV_FRAC_START3_MODE0, - cfg.com_div_frac_start3_mode0); - - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN0_MODE0, - cfg.com_integloop_gain0_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_INTEGLOOP_GAIN1_MODE0, - cfg.com_integloop_gain1_mode0); - - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP1_MODE0, - cfg.com_lock_cmp1_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP2_MODE0, - cfg.com_lock_cmp2_mode0); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_LOCK_CMP3_MODE0, - cfg.com_lock_cmp3_mode0); - - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_VCO_TUNE_MAP, 0x00); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORE_CLK_EN, - cfg.com_core_clk_en); - hdmi_pll_write(pll, REG_HDMI_8998_PHY_QSERDES_COM_CORECLK_DIV_MODE0, - cfg.com_coreclk_div_mode0); - - /* TX lanes setup (TX 0/1/2/3) */ - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_DRV_LVL, - cfg.tx_lx_tx_drv_lvl[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL, - cfg.tx_lx_tx_emp_post1_lvl[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1, - cfg.tx_lx_pre_driver_1[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2, - cfg.tx_lx_pre_driver_2[i]); - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_OFFSET, - cfg.tx_lx_res_code_offset[i]); - } - - hdmi_phy_write(phy, REG_HDMI_8998_PHY_MODE, cfg.phy_mode); - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_LANE_CONFIG, - 0x10); - } - - /* - * Ensure that vco configuration gets flushed to hardware before - * enabling the PLL - */ - wmb(); - - pll->rate =3D rate; - - return 0; -} - -static int hdmi_8998_phy_ready_status(struct hdmi_phy *phy) -{ - u32 nb_tries =3D HDMI_PLL_POLL_MAX_READS; - unsigned long timeout =3D HDMI_PLL_POLL_TIMEOUT_US; - u32 status; - int phy_ready =3D 0; - - while (nb_tries--) { - status =3D hdmi_phy_read(phy, REG_HDMI_8998_PHY_STATUS); - phy_ready =3D status & BIT(0); - - if (phy_ready) - break; - - udelay(timeout); - } - - return phy_ready; -} - -static int hdmi_8998_pll_lock_status(struct hdmi_pll_8998 *pll) -{ - u32 status; - int nb_tries =3D HDMI_PLL_POLL_MAX_READS; - unsigned long timeout =3D HDMI_PLL_POLL_TIMEOUT_US; - int pll_locked =3D 0; - - while (nb_tries--) { - status =3D hdmi_pll_read(pll, - REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATUS); - pll_locked =3D status & BIT(0); - - if (pll_locked) - break; - - udelay(timeout); - } - - return pll_locked; -} - -static int hdmi_8998_pll_prepare(struct clk_hw *hw) -{ - struct hdmi_pll_8998 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - int i, ret =3D 0; - - hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x1); - udelay(100); - - hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59); - udelay(100); - - ret =3D hdmi_8998_pll_lock_status(pll); - if (!ret) - return ret; - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - hdmi_tx_chan_write(pll, i, - REG_HDMI_8998_PHY_TXn_LANE_CONFIG, 0x1F); - } - - /* Ensure all registers are flushed to hardware */ - wmb(); - - ret =3D hdmi_8998_phy_ready_status(phy); - if (!ret) - return ret; - - /* Restart the retiming buffer */ - hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x58); - udelay(1); - hdmi_phy_write(phy, REG_HDMI_8998_PHY_CFG, 0x59); - - /* Ensure all registers are flushed to hardware */ - wmb(); - - return 0; -} - -static long hdmi_8998_pll_round_rate(struct clk_hw *hw, - unsigned long rate, - unsigned long *parent_rate) -{ - if (rate < HDMI_PCLK_MIN_FREQ) - return HDMI_PCLK_MIN_FREQ; - else if (rate > HDMI_PCLK_MAX_FREQ) - return HDMI_PCLK_MAX_FREQ; - else - return rate; -} - -static unsigned long hdmi_8998_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct hdmi_pll_8998 *pll =3D hw_clk_to_pll(hw); - return pll->rate; -} - -static void hdmi_8998_pll_unprepare(struct clk_hw *hw) -{ - struct hdmi_pll_8998 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - - hdmi_phy_write(phy, REG_HDMI_8998_PHY_PD_CTL, 0); - usleep_range(100, 150); -} - -static int hdmi_8998_pll_is_enabled(struct clk_hw *hw) -{ - struct hdmi_pll_8998 *pll =3D hw_clk_to_pll(hw); - u32 status; - int pll_locked; - - status =3D hdmi_pll_read(pll, REG_HDMI_8998_PHY_QSERDES_COM_C_READY_STATU= S); - pll_locked =3D status & BIT(0); - - return pll_locked; -} - -static const struct clk_ops hdmi_8998_pll_ops =3D { - .set_rate =3D hdmi_8998_pll_set_clk_rate, - .round_rate =3D hdmi_8998_pll_round_rate, - .recalc_rate =3D hdmi_8998_pll_recalc_rate, - .prepare =3D hdmi_8998_pll_prepare, - .unprepare =3D hdmi_8998_pll_unprepare, - .is_enabled =3D hdmi_8998_pll_is_enabled, -}; - -static const struct clk_init_data pll_init =3D { - .name =3D "hdmipll", - .ops =3D &hdmi_8998_pll_ops, - .parent_data =3D (const struct clk_parent_data[]){ - { .fw_name =3D "xo", .name =3D "xo_board" }, - }, - .num_parents =3D 1, - .flags =3D CLK_IGNORE_UNUSED, -}; - -int msm_hdmi_pll_8998_init(struct platform_device *pdev) -{ - struct device *dev =3D &pdev->dev; - struct hdmi_pll_8998 *pll; - int ret, i; - - pll =3D devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); - if (!pll) - return -ENOMEM; - - pll->pdev =3D pdev; - - pll->mmio_qserdes_com =3D msm_ioremap(pdev, "hdmi_pll"); - if (IS_ERR(pll->mmio_qserdes_com)) { - DRM_DEV_ERROR(dev, "failed to map pll base\n"); - return -ENOMEM; - } - - for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { - char name[32]; - - snprintf(name, sizeof(name), "hdmi_tx_l%d", i); - - pll->mmio_qserdes_tx[i] =3D msm_ioremap(pdev, name); - if (IS_ERR(pll->mmio_qserdes_tx[i])) { - DRM_DEV_ERROR(dev, "failed to map pll base\n"); - return -ENOMEM; - } - } - pll->clk_hw.init =3D &pll_init; - - ret =3D devm_clk_hw_register(dev, &pll->clk_hw); - if (ret) { - DRM_DEV_ERROR(dev, "failed to register pll clock\n"); - return ret; - } - - ret =3D devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_= hw); - if (ret) { - DRM_DEV_ERROR(dev, "failed to register clk provider: %d\n", ret); - return ret; - } - - return 0; -} - -static const char * const hdmi_phy_8998_reg_names[] =3D { - "vddio", - "vcca", -}; - -static const char * const hdmi_phy_8998_clk_names[] =3D { - "iface", "ref", "xo", -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8998_cfg =3D { - .type =3D MSM_HDMI_PHY_8998, - .reg_names =3D hdmi_phy_8998_reg_names, - .num_regs =3D ARRAY_SIZE(hdmi_phy_8998_reg_names), - .clk_names =3D hdmi_phy_8998_clk_names, - .num_clks =3D ARRAY_SIZE(hdmi_phy_8998_clk_names), -}; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c b/drivers/gpu/drm/msm= /hdmi/hdmi_phy_8x60.c deleted file mode 100644 index 1d97640d8c24aa62f5f80e58ca6408f51fbfe38f..000000000000000000000000000= 0000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c +++ /dev/null @@ -1,141 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2013 Red Hat - * Author: Rob Clark - */ - -#include - -#include "hdmi.h" - -static void hdmi_phy_8x60_powerup(struct hdmi_phy *phy, - unsigned long int pixclock) -{ - /* De-serializer delay D/C for non-lbk mode: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG0, - HDMI_8x60_PHY_REG0_DESER_DEL_CTRL(3)); - - if (pixclock =3D=3D 27000000) { - /* video_format =3D=3D HDMI_VFRMT_720x480p60_16_9 */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG1, - HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(5) | - HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(3)); - } else { - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG1, - HDMI_8x60_PHY_REG1_DTEST_MUX_SEL(5) | - HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(4)); - } - - /* No matter what, start from the power down mode: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, - HDMI_8x60_PHY_REG2_PD_PWRGEN | - HDMI_8x60_PHY_REG2_PD_PLL | - HDMI_8x60_PHY_REG2_PD_DRIVE_4 | - HDMI_8x60_PHY_REG2_PD_DRIVE_3 | - HDMI_8x60_PHY_REG2_PD_DRIVE_2 | - HDMI_8x60_PHY_REG2_PD_DRIVE_1 | - HDMI_8x60_PHY_REG2_PD_DESER); - - /* Turn PowerGen on: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, - HDMI_8x60_PHY_REG2_PD_PLL | - HDMI_8x60_PHY_REG2_PD_DRIVE_4 | - HDMI_8x60_PHY_REG2_PD_DRIVE_3 | - HDMI_8x60_PHY_REG2_PD_DRIVE_2 | - HDMI_8x60_PHY_REG2_PD_DRIVE_1 | - HDMI_8x60_PHY_REG2_PD_DESER); - - /* Turn PLL power on: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, - HDMI_8x60_PHY_REG2_PD_DRIVE_4 | - HDMI_8x60_PHY_REG2_PD_DRIVE_3 | - HDMI_8x60_PHY_REG2_PD_DRIVE_2 | - HDMI_8x60_PHY_REG2_PD_DRIVE_1 | - HDMI_8x60_PHY_REG2_PD_DESER); - - /* Write to HIGH after PLL power down de-assert: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG3, - HDMI_8x60_PHY_REG3_PLL_ENABLE); - - /* ASIC power on; PHY REG9 =3D 0 */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG9, 0); - - /* Enable PLL lock detect, PLL lock det will go high after lock - * Enable the re-time logic - */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG12, - HDMI_8x60_PHY_REG12_RETIMING_EN | - HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN); - - /* Drivers are on: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, - HDMI_8x60_PHY_REG2_PD_DESER); - - /* If the RX detector is needed: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, - HDMI_8x60_PHY_REG2_RCV_SENSE_EN | - HDMI_8x60_PHY_REG2_PD_DESER); - - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG4, 0); - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG5, 0); - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG6, 0); - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG7, 0); - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG8, 0); - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG9, 0); - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG10, 0); - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG11, 0); - - /* If we want to use lock enable based on counting: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG12, - HDMI_8x60_PHY_REG12_RETIMING_EN | - HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN | - HDMI_8x60_PHY_REG12_FORCE_LOCK); -} - -static void hdmi_phy_8x60_powerdown(struct hdmi_phy *phy) -{ - /* Assert RESET PHY from controller */ - hdmi_phy_write(phy, REG_HDMI_PHY_CTRL, - HDMI_PHY_CTRL_SW_RESET); - udelay(10); - /* De-assert RESET PHY from controller */ - hdmi_phy_write(phy, REG_HDMI_PHY_CTRL, 0); - /* Turn off Driver */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, - HDMI_8x60_PHY_REG2_PD_DRIVE_4 | - HDMI_8x60_PHY_REG2_PD_DRIVE_3 | - HDMI_8x60_PHY_REG2_PD_DRIVE_2 | - HDMI_8x60_PHY_REG2_PD_DRIVE_1 | - HDMI_8x60_PHY_REG2_PD_DESER); - udelay(10); - /* Disable PLL */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG3, 0); - /* Power down PHY, but keep RX-sense: */ - hdmi_phy_write(phy, REG_HDMI_8x60_PHY_REG2, - HDMI_8x60_PHY_REG2_RCV_SENSE_EN | - HDMI_8x60_PHY_REG2_PD_PWRGEN | - HDMI_8x60_PHY_REG2_PD_PLL | - HDMI_8x60_PHY_REG2_PD_DRIVE_4 | - HDMI_8x60_PHY_REG2_PD_DRIVE_3 | - HDMI_8x60_PHY_REG2_PD_DRIVE_2 | - HDMI_8x60_PHY_REG2_PD_DRIVE_1 | - HDMI_8x60_PHY_REG2_PD_DESER); -} - -static const char * const hdmi_phy_8x60_reg_names[] =3D { - "core-vdda", -}; - -static const char * const hdmi_phy_8x60_clk_names[] =3D { - "slave_iface", -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg =3D { - .type =3D MSM_HDMI_PHY_8x60, - .powerup =3D hdmi_phy_8x60_powerup, - .powerdown =3D hdmi_phy_8x60_powerdown, - .reg_names =3D hdmi_phy_8x60_reg_names, - .num_regs =3D ARRAY_SIZE(hdmi_phy_8x60_reg_names), - .clk_names =3D hdmi_phy_8x60_clk_names, - .num_clks =3D ARRAY_SIZE(hdmi_phy_8x60_clk_names), -}; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c b/drivers/gpu/drm/msm= /hdmi/hdmi_phy_8x74.c deleted file mode 100644 index a2a6940e195a0788a3d84de0171565510ef60623..000000000000000000000000000= 0000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) 2013 Red Hat - * Author: Rob Clark - */ - -#include "hdmi.h" - -static void hdmi_phy_8x74_powerup(struct hdmi_phy *phy, - unsigned long int pixclock) -{ - hdmi_phy_write(phy, REG_HDMI_8x74_ANA_CFG0, 0x1b); - hdmi_phy_write(phy, REG_HDMI_8x74_ANA_CFG1, 0xf2); - hdmi_phy_write(phy, REG_HDMI_8x74_BIST_CFG0, 0x0); - hdmi_phy_write(phy, REG_HDMI_8x74_BIST_PATN0, 0x0); - hdmi_phy_write(phy, REG_HDMI_8x74_BIST_PATN1, 0x0); - hdmi_phy_write(phy, REG_HDMI_8x74_BIST_PATN2, 0x0); - hdmi_phy_write(phy, REG_HDMI_8x74_BIST_PATN3, 0x0); - hdmi_phy_write(phy, REG_HDMI_8x74_PD_CTRL1, 0x20); -} - -static void hdmi_phy_8x74_powerdown(struct hdmi_phy *phy) -{ - hdmi_phy_write(phy, REG_HDMI_8x74_PD_CTRL0, 0x7f); -} - -static const char * const hdmi_phy_8x74_reg_names[] =3D { - "core-vdda", - "vddio", -}; - -static const char * const hdmi_phy_8x74_clk_names[] =3D { - "iface", "alt_iface" -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8x74_cfg =3D { - .type =3D MSM_HDMI_PHY_8x74, - .powerup =3D hdmi_phy_8x74_powerup, - .powerdown =3D hdmi_phy_8x74_powerdown, - .reg_names =3D hdmi_phy_8x74_reg_names, - .num_regs =3D ARRAY_SIZE(hdmi_phy_8x74_reg_names), - .clk_names =3D hdmi_phy_8x74_clk_names, - .num_clks =3D ARRAY_SIZE(hdmi_phy_8x74_clk_names), -}; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c b/drivers/gpu/drm/msm= /hdmi/hdmi_pll_8960.c deleted file mode 100644 index 83c8781fcc3f6e1db99cfec64055ee5f359e49e5..000000000000000000000000000= 0000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c +++ /dev/null @@ -1,458 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (c) 2016, The Linux Foundation. All rights reserved. - * Copyright (C) 2013 Red Hat - * Author: Rob Clark - */ - -#include -#include - -#include "hdmi.h" - -struct hdmi_pll_8960 { - struct platform_device *pdev; - struct clk_hw clk_hw; - void __iomem *mmio; - - unsigned long pixclk; -}; - -#define hw_clk_to_pll(x) container_of(x, struct hdmi_pll_8960, clk_hw) - -/* - * HDMI PLL: - * - * To get the parent clock setup properly, we need to plug in hdmi pll - * configuration into common-clock-framework. - */ - -struct pll_rate { - unsigned long rate; - int num_reg; - struct { - u32 val; - u32 reg; - } conf[32]; -}; - -/* NOTE: keep sorted highest freq to lowest: */ -static const struct pll_rate freqtbl[] =3D { - { 154000000, 14, { - { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x0d, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x4d, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0x5e, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0x42, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - } - }, - /* 1080p60/1080p50 case */ - { 148500000, 27, { - { 0x02, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG }, - { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG }, - { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG }, - { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B }, - { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 }, - { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 }, - { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 }, - { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 }, - { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 }, - } - }, - { 108000000, 13, { - { 0x08, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x21, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x1c, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x49, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - } - }, - /* 720p60/720p50/1080i60/1080i50/1080p24/1080p30/1080p25 */ - { 74250000, 8, { - { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B }, - { 0x12, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x76, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0xe6, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - } - }, - { 74176000, 14, { - { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0xe5, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x0c, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0x7d, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0xbc, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - } - }, - { 65000000, 14, { - { 0x18, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0xf9, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x8a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x0b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x4b, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0x09, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - } - }, - /* 480p60/480i60 */ - { 27030000, 18, { - { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B }, - { 0x38, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG }, - { 0x20, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0xff, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x4e, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0xd7, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0x03, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 }, - } - }, - /* 576p50/576i50 */ - { 27000000, 27, { - { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG }, - { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG }, - { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG }, - { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B }, - { 0x7b, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x01, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG3 }, - { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 }, - { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 }, - { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 }, - { 0x2a, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x03, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 }, - } - }, - /* 640x480p60 */ - { 25200000, 27, { - { 0x32, REG_HDMI_8960_PHY_PLL_REFCLK_CFG }, - { 0x02, REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG }, - { 0x01, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 }, - { 0x33, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 }, - { 0x2c, REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG }, - { 0x06, REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG }, - { 0x0a, REG_HDMI_8960_PHY_PLL_PWRDN_B }, - { 0x77, REG_HDMI_8960_PHY_PLL_SDM_CFG0 }, - { 0x4c, REG_HDMI_8960_PHY_PLL_SDM_CFG1 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG2 }, - { 0xc0, REG_HDMI_8960_PHY_PLL_SDM_CFG3 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SDM_CFG4 }, - { 0x9a, REG_HDMI_8960_PHY_PLL_SSC_CFG0 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG1 }, - { 0x00, REG_HDMI_8960_PHY_PLL_SSC_CFG2 }, - { 0x20, REG_HDMI_8960_PHY_PLL_SSC_CFG3 }, - { 0x10, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 }, - { 0x1a, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 }, - { 0x0d, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 }, - { 0xf4, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 }, - { 0x02, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 }, - { 0x3b, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 }, - { 0x86, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 }, - { 0x33, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 }, - { 0x00, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 }, - } - }, -}; - -static inline void pll_write(struct hdmi_pll_8960 *pll, u32 reg, u32 data) -{ - writel(data, pll->mmio + reg); -} - -static inline u32 pll_read(struct hdmi_pll_8960 *pll, u32 reg) -{ - return readl(pll->mmio + reg); -} - -static inline struct hdmi_phy *pll_get_phy(struct hdmi_pll_8960 *pll) -{ - return platform_get_drvdata(pll->pdev); -} - -static int hdmi_pll_enable(struct clk_hw *hw) -{ - struct hdmi_pll_8960 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - int timeout_count, pll_lock_retry =3D 10; - unsigned int val; - - DBG(""); - - /* Assert PLL S/W reset */ - pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d); - pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10); - pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a); - - /* Wait for a short time before de-asserting - * to allow the hardware to complete its job. - * This much of delay should be fine for hardware - * to assert and de-assert. - */ - udelay(10); - - /* De-assert PLL S/W reset */ - pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d); - - val =3D hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); - val |=3D HDMI_8960_PHY_REG12_SW_RESET; - /* Assert PHY S/W reset */ - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); - val &=3D ~HDMI_8960_PHY_REG12_SW_RESET; - /* - * Wait for a short time before de-asserting to allow the hardware to - * complete its job. This much of delay should be fine for hardware to - * assert and de-assert. - */ - udelay(10); - /* De-assert PHY S/W reset */ - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x3f); - - val =3D hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); - val |=3D HDMI_8960_PHY_REG12_PWRDN_B; - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); - /* Wait 10 us for enabling global power for PHY */ - mb(); - udelay(10); - - val =3D pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B); - val |=3D HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B; - val &=3D ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL; - pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val); - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x80); - - timeout_count =3D 1000; - while (--pll_lock_retry > 0) { - /* are we there yet? */ - val =3D pll_read(pll, REG_HDMI_8960_PHY_PLL_STATUS0); - if (val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK) - break; - - udelay(1); - - if (--timeout_count > 0) - continue; - - /* - * PLL has still not locked. - * Do a software reset and try again - * Assert PLL S/W reset first - */ - pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d); - udelay(10); - pll_write(pll, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d); - - /* - * Wait for a short duration for the PLL calibration - * before checking if the PLL gets locked - */ - udelay(350); - - timeout_count =3D 1000; - } - - return 0; -} - -static void hdmi_pll_disable(struct clk_hw *hw) -{ - struct hdmi_pll_8960 *pll =3D hw_clk_to_pll(hw); - struct hdmi_phy *phy =3D pll_get_phy(pll); - unsigned int val; - - DBG(""); - - val =3D hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); - val &=3D ~HDMI_8960_PHY_REG12_PWRDN_B; - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); - - val =3D pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B); - val |=3D HDMI_8960_PHY_REG12_SW_RESET; - val &=3D ~HDMI_8960_PHY_REG12_PWRDN_B; - pll_write(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B, val); - /* Make sure HDMI PHY/PLL are powered down */ - mb(); -} - -static const struct pll_rate *find_rate(unsigned long rate) -{ - int i; - - for (i =3D 1; i < ARRAY_SIZE(freqtbl); i++) - if (rate > freqtbl[i].rate) - return &freqtbl[i - 1]; - - return &freqtbl[i - 1]; -} - -static unsigned long hdmi_pll_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct hdmi_pll_8960 *pll =3D hw_clk_to_pll(hw); - - return pll->pixclk; -} - -static long hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *parent_rate) -{ - const struct pll_rate *pll_rate =3D find_rate(rate); - - return pll_rate->rate; -} - -static int hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - struct hdmi_pll_8960 *pll =3D hw_clk_to_pll(hw); - const struct pll_rate *pll_rate =3D find_rate(rate); - int i; - - DBG("rate=3D%lu", rate); - - for (i =3D 0; i < pll_rate->num_reg; i++) - pll_write(pll, pll_rate->conf[i].reg, pll_rate->conf[i].val); - - pll->pixclk =3D rate; - - return 0; -} - -static const struct clk_ops hdmi_pll_ops =3D { - .enable =3D hdmi_pll_enable, - .disable =3D hdmi_pll_disable, - .recalc_rate =3D hdmi_pll_recalc_rate, - .round_rate =3D hdmi_pll_round_rate, - .set_rate =3D hdmi_pll_set_rate, -}; - -static const struct clk_parent_data hdmi_pll_parents[] =3D { - { .fw_name =3D "pxo", .name =3D "pxo_board" }, -}; - -static struct clk_init_data pll_init =3D { - .name =3D "hdmi_pll", - .ops =3D &hdmi_pll_ops, - .parent_data =3D hdmi_pll_parents, - .num_parents =3D ARRAY_SIZE(hdmi_pll_parents), - .flags =3D CLK_IGNORE_UNUSED, -}; - -int msm_hdmi_pll_8960_init(struct platform_device *pdev) -{ - struct device *dev =3D &pdev->dev; - struct hdmi_pll_8960 *pll; - int i, ret; - - /* sanity check: */ - for (i =3D 0; i < (ARRAY_SIZE(freqtbl) - 1); i++) - if (WARN_ON(freqtbl[i].rate < freqtbl[i + 1].rate)) - return -EINVAL; - - pll =3D devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); - if (!pll) - return -ENOMEM; - - pll->mmio =3D msm_ioremap(pdev, "hdmi_pll"); - if (IS_ERR(pll->mmio)) { - DRM_DEV_ERROR(dev, "failed to map pll base\n"); - return -ENOMEM; - } - - pll->pdev =3D pdev; - pll->clk_hw.init =3D &pll_init; - - ret =3D devm_clk_hw_register(dev, &pll->clk_hw); - if (ret < 0) { - DRM_DEV_ERROR(dev, "failed to register pll clock\n"); - return ret; - } - - ret =3D devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &pll->clk_= hw); - if (ret) { - DRM_DEV_ERROR(dev, "%s: failed to register clk provider: %d\n", __func__= , ret); - return ret; - } - - return 0; -} diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index ef14f4e33973cff4103d8ea3b07cfd62d344e450..4e3636ee53efc5691307e7c21d1= f5caf5d7d71ff 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -42,6 +42,20 @@ config PHY_QCOM_IPQ806X_SATA depends on OF select GENERIC_PHY =20 +config PHY_QCOM_HDMI + tristate "Qualcomm MSM8x60/MSM8960/MSM8974 HDMI PHY driver" + depends on ARCH_QCOM || COMPILE_TEST + depends on OF + depends on COMMON_CLK + default DRM_MSM_HDMI && ARCH_QCOM && ARM + select GENERIC_PHY + help + Enable this to support the Qualcomm HDMI PHY presend on 32-bit platform= s: + MSM8260, MSM8660, MSM8960, MSM8974, APQ8060, APQ8064, APQ8074 and APQ80= 84. + + Note, this driver is not used on MSM899x platforms, which use + PHY_QCOM_QMP_HDMI instead. + config PHY_QCOM_PCIE2 tristate "Qualcomm PCIe Gen2 PHY Driver" depends on OF && COMMON_CLK && (ARCH_QCOM || COMPILE_TEST) @@ -68,6 +82,13 @@ config PHY_QCOM_QMP_COMBO Enable this to support the QMP Combo PHY transceiver that is used with USB3 and DisplayPort controllers on Qualcomm chips. =20 +config PHY_QCOM_QMP_HDMI + tristate "Qualcomm QMP HDMI PHY Driver" + default PHY_QCOM_QMP && DRM_MSM_HDMI + help + Enable this to support the QMP HDMI PHY transceiver that is used + with HDMI output on Qualcomm MSM8996 chips. + config PHY_QCOM_QMP_PCIE tristate "Qualcomm QMP PCIe PHY Driver" depends on PCI || COMPILE_TEST diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index 3851e28a212d4a677a5b41805868f38b9ab49841..351b9ff5aa9dad74c454c461e88= 3a83cd098e6fc 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -4,16 +4,30 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) +=3D phy-qcom-apq8064= -sata.o obj-$(CONFIG_PHY_QCOM_EDP) +=3D phy-qcom-edp.o obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) +=3D phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) +=3D phy-qcom-ipq806x-sata.o +obj-$(CONFIG_PHY_QCOM_HDMI) +=3D phy-qcom-hdmi.o + +phy-qcom-hdmi-y :=3D \ + phy-qcom-hdmi-preqmp.o \ + phy-qcom-hdmi-28hpm.o \ + phy-qcom-hdmi-28lpm.o \ + phy-qcom-hdmi-45nm.o \ + obj-$(CONFIG_PHY_QCOM_M31_USB) +=3D phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_PCIE2) +=3D phy-qcom-pcie2.o =20 obj-$(CONFIG_PHY_QCOM_QMP_COMBO) +=3D phy-qcom-qmp-combo.o phy-qcom-qmp-us= bc.o +obj-$(CONFIG_PHY_QCOM_QMP_HDMI) +=3D phy-qcom-qmp-hdmi.o obj-$(CONFIG_PHY_QCOM_QMP_PCIE) +=3D phy-qcom-qmp-pcie.o obj-$(CONFIG_PHY_QCOM_QMP_PCIE_8996) +=3D phy-qcom-qmp-pcie-msm8996.o obj-$(CONFIG_PHY_QCOM_QMP_UFS) +=3D phy-qcom-qmp-ufs.o obj-$(CONFIG_PHY_QCOM_QMP_USB) +=3D phy-qcom-qmp-usb.o obj-$(CONFIG_PHY_QCOM_QMP_USB_LEGACY) +=3D phy-qcom-qmp-usb-legacy.o =20 +phy-qcom-qmp-hdmi-y :=3D \ + phy-qcom-qmp-hdmi-base.o \ + phy-qcom-qmp-hdmi-msm8996.o \ + phy-qcom-qmp-hdmi-msm8998.o \ + obj-$(CONFIG_PHY_QCOM_QUSB2) +=3D phy-qcom-qusb2.o obj-$(CONFIG_PHY_QCOM_EUSB2_REPEATER) +=3D phy-qcom-eusb2-repeater.o obj-$(CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP) +=3D phy-qcom-uniphy-pcie-28lp.o diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c b/drivers/phy/qualc= omm/phy-qcom-hdmi-28hpm.c new file mode 100644 index 0000000000000000000000000000000000000000..db7fa2df1a369d3889daab922c2= 1ed8b71d733be --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + * Author: Rob Clark + */ + +#include +#include + +#include "phy-qcom-hdmi-preqmp.h" + +#define REG_HDMI_8x74_ANA_CFG0 0x00000000 +#define REG_HDMI_8x74_ANA_CFG1 0x00000004 +#define REG_HDMI_8x74_ANA_CFG2 0x00000008 +#define REG_HDMI_8x74_ANA_CFG3 0x0000000c +#define REG_HDMI_8x74_PD_CTRL0 0x00000010 +#define REG_HDMI_8x74_PD_CTRL1 0x00000014 +#define REG_HDMI_8x74_GLB_CFG 0x00000018 +#define REG_HDMI_8x74_DCC_CFG0 0x0000001c +#define REG_HDMI_8x74_DCC_CFG1 0x00000020 +#define REG_HDMI_8x74_TXCAL_CFG0 0x00000024 +#define REG_HDMI_8x74_TXCAL_CFG1 0x00000028 +#define REG_HDMI_8x74_TXCAL_CFG2 0x0000002c +#define REG_HDMI_8x74_TXCAL_CFG3 0x00000030 +#define REG_HDMI_8x74_BIST_CFG0 0x00000034 +#define REG_HDMI_8x74_BIST_PATN0 0x0000003c +#define REG_HDMI_8x74_BIST_PATN1 0x00000040 +#define REG_HDMI_8x74_BIST_PATN2 0x00000044 +#define REG_HDMI_8x74_BIST_PATN3 0x00000048 +#define REG_HDMI_8x74_STATUS 0x0000005c + +static int qcom_hdmi_msm8974_phy_power_on(struct qcom_hdmi_preqmp_phy *hdm= i_phy) +{ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG0, 0x1b); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG1, 0xf2); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_BIST_CFG0, 0x0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_BIST_PATN0, 0x0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_BIST_PATN1, 0x0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_BIST_PATN2, 0x0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_BIST_PATN3, 0x0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_PD_CTRL1, 0x20); + + return 0; +} + +static int qcom_hdmi_msm8974_phy_power_off(struct qcom_hdmi_preqmp_phy *hd= mi_phy) +{ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_PD_CTRL0, 0x7f); + + return 0; +} + +const struct clk_parent_data msm8974_hdmi_pll_parent =3D { + .fw_name =3D "xo", .name =3D "xo_board", +}; + +const struct qcom_hdmi_preqmp_cfg msm8974_hdmi_phy_cfg =3D { + .clk_names =3D { "iface", "alt_iface" }, + .num_clks =3D 2, + + .reg_names =3D { "vddio", "core-vdda" }, + .reg_init_load =3D { 100000, 10000 }, + .num_regs =3D 2, + + .power_on =3D qcom_hdmi_msm8974_phy_power_on, + .power_off =3D qcom_hdmi_msm8974_phy_power_off, + + .pll_parent =3D &msm8974_hdmi_pll_parent, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c b/drivers/phy/qualc= omm/phy-qcom-hdmi-28lpm.c new file mode 100644 index 0000000000000000000000000000000000000000..61e29c65395cd0a92ace1ee3769= 5ed449138aa41 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + * Author: Rob Clark + */ + +#include +#include + +#include "phy-qcom-hdmi-preqmp.h" + +#define REG_HDMI_8960_PHY_REG0 0x00000000 + +#define REG_HDMI_8960_PHY_REG1 0x00000004 + +#define REG_HDMI_8960_PHY_REG2 0x00000008 + +#define REG_HDMI_8960_PHY_REG3 0x0000000c + +#define REG_HDMI_8960_PHY_REG4 0x00000010 + +#define REG_HDMI_8960_PHY_REG5 0x00000014 + +#define REG_HDMI_8960_PHY_REG6 0x00000018 + +#define REG_HDMI_8960_PHY_REG7 0x0000001c + +#define REG_HDMI_8960_PHY_REG8 0x00000020 + +#define REG_HDMI_8960_PHY_REG9 0x00000024 + +#define REG_HDMI_8960_PHY_REG10 0x00000028 + +#define REG_HDMI_8960_PHY_REG11 0x0000002c + +#define REG_HDMI_8960_PHY_REG12 0x00000030 +#define HDMI_8960_PHY_REG12_SW_RESET 0x00000020 +#define HDMI_8960_PHY_REG12_PWRDN_B 0x00000080 + +#define REG_HDMI_8960_PHY_REG_BIST_CFG 0x00000034 + +#define REG_HDMI_8960_PHY_DEBUG_BUS_SEL 0x00000038 + +#define REG_HDMI_8960_PHY_REG_MISC0 0x0000003c + +#define REG_HDMI_8960_PHY_REG13 0x00000040 + +#define REG_HDMI_8960_PHY_REG14 0x00000044 + +#define REG_HDMI_8960_PHY_REG15 0x00000048 + +#define REG_HDMI_8960_PHY_PLL_REFCLK_CFG 0x00000000 + +#define REG_HDMI_8960_PHY_PLL_CHRG_PUMP_CFG 0x00000004 + +#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0 0x00000008 + +#define REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1 0x0000000c + +#define REG_HDMI_8960_PHY_PLL_IDAC_ADJ_CFG 0x00000010 + +#define REG_HDMI_8960_PHY_PLL_I_VI_KVCO_CFG 0x00000014 + +#define REG_HDMI_8960_PHY_PLL_PWRDN_B 0x00000018 +#define HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL 0x00000002 +#define HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B 0x00000008 + +#define REG_HDMI_8960_PHY_PLL_SDM_CFG0 0x0000001c + +#define REG_HDMI_8960_PHY_PLL_SDM_CFG1 0x00000020 + +#define REG_HDMI_8960_PHY_PLL_SDM_CFG2 0x00000024 + +#define REG_HDMI_8960_PHY_PLL_SDM_CFG3 0x00000028 + +#define REG_HDMI_8960_PHY_PLL_SDM_CFG4 0x0000002c + +#define REG_HDMI_8960_PHY_PLL_SSC_CFG0 0x00000030 + +#define REG_HDMI_8960_PHY_PLL_SSC_CFG1 0x00000034 + +#define REG_HDMI_8960_PHY_PLL_SSC_CFG2 0x00000038 + +#define REG_HDMI_8960_PHY_PLL_SSC_CFG3 0x0000003c + +#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0 0x00000040 + +#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1 0x00000044 + +#define REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2 0x00000048 + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0 0x0000004c + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1 0x00000050 + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2 0x00000054 + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG3 0x00000058 + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG4 0x0000005c + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG5 0x00000060 + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG6 0x00000064 + +#define REG_HDMI_8960_PHY_PLL_VCOCAL_CFG7 0x00000068 + +#define REG_HDMI_8960_PHY_PLL_DEBUG_SEL 0x0000006c + +#define REG_HDMI_8960_PHY_PLL_MISC0 0x00000070 + +#define REG_HDMI_8960_PHY_PLL_MISC1 0x00000074 + +#define REG_HDMI_8960_PHY_PLL_MISC2 0x00000078 + +#define REG_HDMI_8960_PHY_PLL_MISC3 0x0000007c + +#define REG_HDMI_8960_PHY_PLL_MISC4 0x00000080 + +#define REG_HDMI_8960_PHY_PLL_MISC5 0x00000084 + +#define REG_HDMI_8960_PHY_PLL_MISC6 0x00000088 + +#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS0 0x0000008c + +#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS1 0x00000090 + +#define REG_HDMI_8960_PHY_PLL_DEBUG_BUS2 0x00000094 + +#define REG_HDMI_8960_PHY_PLL_STATUS0 0x00000098 +#define HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK 0x00000001 + +#define REG_HDMI_8960_PHY_PLL_STATUS1 0x0000009c + +#define HDMI_8974_VCO_MAX_FREQ 1125000000UL +#define HDMI_8974_VCO_MIN_FREQ 540000000UL + +#define HDMI_8974_COMMON_DIV 5 + +static unsigned long qcom_28lpm_recalc(struct qcom_hdmi_preqmp_phy *hdmi_p= hy, + unsigned long parent_rate) +{ + unsigned long rate; + u32 refclk_cfg; + u32 dc_offset; + u64 fraq_n; + u32 val; + + refclk_cfg =3D hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_REFCLK_CFG); + if (refclk_cfg & BIT(1)) + parent_rate /=3D 2; + if (refclk_cfg & BIT(3)) + parent_rate *=3D 2; + + val =3D hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG0); + if (val & 0x40) { + dc_offset =3D val & 0x3f; + fraq_n =3D 0; + } else { + dc_offset =3D hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG1) & = 0x3f; + fraq_n =3D hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG2) | + (hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG3) << 8); + } + + rate =3D (dc_offset + 1) * parent_rate; + rate +=3D mult_frac(fraq_n, parent_rate, 0x10000); + + return rate; +} + +static int qcom_28lpm_set_rate(struct qcom_hdmi_preqmp_phy *hdmi_phy, unsi= gned long parent_rate, + unsigned long vco_freq, u32 div_idx) +{ + unsigned int pixclk =3D hdmi_phy->hdmi_opts.tmds_char_rate; + unsigned int int_ref_freq; + unsigned int div; + unsigned int dc_offset; + unsigned int sdm_freq_seed; + unsigned int val; + bool sdm_mode =3D false; + u32 refclk_cfg; + u32 lf_cfg0; + u32 lf_cfg1; + + dev_dbg(hdmi_phy->dev, "rate=3D%u, div =3D %d, vco =3D %lu", pixclk, div,= vco_freq); + + if (vco_freq % (parent_rate / 2) =3D=3D 0) { + refclk_cfg =3D 0x2; + int_ref_freq =3D parent_rate / 2; + } else { + refclk_cfg =3D 0x8; + int_ref_freq =3D parent_rate * 2; + sdm_mode =3D true; + } + + dc_offset =3D vco_freq / int_ref_freq - 1; + sdm_freq_seed =3D vco_freq - (dc_offset + 1) * int_ref_freq; + sdm_freq_seed =3D mult_frac(sdm_freq_seed, 0x10000, int_ref_freq); + + val =3D (div_idx << 4) | refclk_cfg; + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_REFCLK_CFG, val); + + lf_cfg0 =3D dc_offset >=3D 30 ? 0 : (dc_offset >=3D 16 ? 0x10 : 0x20); + lf_cfg0 +=3D sdm_mode ? 0 : 1; + + /* XXX: 0xc3 instead of 0x33 for qcs404 */ + lf_cfg1 =3D dc_offset >=3D 30 ? 0x33 : (dc_offset >=3D 16 ? 0xbb : 0xf9); + + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG0, lf_cfg0); + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_LOOP_FLT_CFG1, lf_cfg1); + + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG0, + (sdm_mode ? 0 : 0x40) | dc_offset); + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG1, + 0x40 | dc_offset); + + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG2, + sdm_freq_seed & 0xff); + + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG3, + (sdm_freq_seed >> 8) & 0xff); + + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG4, + sdm_freq_seed >> 16); + + vco_freq /=3D 1000; + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0, vco_freq & 0x= ff); + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG1, vco_freq >> 8= ); + + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG2, 0x3b); + + return 0; +} + +static const unsigned int qcom_hdmi_8974_divs[] =3D {1, 2, 4, 6}; + +static unsigned long qcom_hdmi_8960_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D hw_clk_to_phy(hw); + u32 div_idx =3D hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_REFCLK_CFG); + unsigned long rate =3D qcom_28lpm_recalc(hdmi_phy, parent_rate); + + return rate / HDMI_8974_COMMON_DIV / qcom_hdmi_8974_divs[div_idx >> 4]; +} + +static long qcom_hdmi_8960_pll_round_rate(struct clk_hw *hw, unsigned long= rate, + unsigned long *parent_rate) +{ + return clamp(rate, + HDMI_8974_VCO_MIN_FREQ / HDMI_8974_COMMON_DIV / 6, + HDMI_8974_VCO_MAX_FREQ / HDMI_8974_COMMON_DIV / 1); +} + +static const struct clk_ops qcom_hdmi_8960_pll_ops =3D { + .recalc_rate =3D qcom_hdmi_8960_pll_recalc_rate, + .round_rate =3D qcom_hdmi_8960_pll_round_rate, +}; + +static int qcom_hdmi_msm8960_phy_pll_enable(struct qcom_hdmi_preqmp_phy *p= hy) +{ + int pll_lock_retry =3D 10; + unsigned int val; + int ret; + + /* Assert PLL S/W reset */ + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d); + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG0, 0x10); + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG1, 0x1a); + + /* Wait for a short time before de-asserting + * to allow the hardware to complete its job. + * This much of delay should be fine for hardware + * to assert and de-assert. + */ + udelay(10); + + /* De-assert PLL S/W reset */ + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d); + + val =3D hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); + val |=3D HDMI_8960_PHY_REG12_SW_RESET; + /* Assert PHY S/W reset */ + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); + val &=3D ~HDMI_8960_PHY_REG12_SW_RESET; + /* + * Wait for a short time before de-asserting to allow the hardware to + * complete its job. This much of delay should be fine for hardware to + * assert and de-assert. + */ + udelay(10); + /* De-assert PHY S/W reset */ + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x3f); + + val =3D hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); + val |=3D HDMI_8960_PHY_REG12_PWRDN_B; + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); + /* Wait 10 us for enabling global power for PHY */ + mb(); + udelay(10); + + val =3D hdmi_pll_read(phy, REG_HDMI_8960_PHY_PLL_PWRDN_B); + val |=3D HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B; + val &=3D ~HDMI_8960_PHY_PLL_PWRDN_B_PD_PLL; + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_PWRDN_B, val); + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG2, 0x80); + + while (--pll_lock_retry > 0) { + ret =3D readl_poll_timeout(phy->pll_reg + REG_HDMI_8960_PHY_PLL_STATUS0, + val, val & HDMI_8960_PHY_PLL_STATUS0_PLL_LOCK, + 1, 1000); + if (!ret) + break; + + /* + * PLL has still not locked. + * Do a software reset and try again + * Assert PLL S/W reset first + */ + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x8d); + udelay(10); + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_LOCKDET_CFG2, 0x0d); + + /* + * Wait for a short duration for the PLL calibration + * before checking if the PLL gets locked + */ + udelay(350); + } + + return ret; +} + +static int qcom_hdmi_msm8974_phy_find_div(unsigned long long pixclk) +{ + int i; + unsigned long long min_freq =3D HDMI_8974_VCO_MIN_FREQ / HDMI_8974_COMMON= _DIV; + + if (pixclk > HDMI_8974_VCO_MAX_FREQ / HDMI_8974_COMMON_DIV) + return -E2BIG; + + for (i =3D 0; i < ARRAY_SIZE(qcom_hdmi_8974_divs); i++) { + if (pixclk >=3D min_freq / qcom_hdmi_8974_divs[i]) + return i; + } + + return -EINVAL; +} + +static int qcom_hdmi_msm8960_phy_set_rate(struct qcom_hdmi_preqmp_phy *hdm= i_phy) +{ + unsigned long long pixclk =3D hdmi_phy->hdmi_opts.tmds_char_rate; + /* XXX: 19.2 for qcs404 */ + unsigned long parent_rate =3D 27000000; + unsigned long vco_freq; + int div_idx; + u32 div; + + div_idx =3D qcom_hdmi_msm8974_phy_find_div(pixclk); + if (WARN_ON(div_idx < 0)) + return div_idx; + + div =3D qcom_hdmi_8974_divs[div_idx]; + vco_freq =3D pixclk * HDMI_8974_COMMON_DIV * div; + + return qcom_28lpm_set_rate(hdmi_phy, parent_rate, vco_freq, div_idx); +} + +static void qcom_hdmi_msm8960_phy_pll_disable(struct qcom_hdmi_preqmp_phy = *phy) +{ + unsigned int val; + + val =3D hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); + val &=3D ~HDMI_8960_PHY_REG12_PWRDN_B; + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); + + val =3D hdmi_pll_read(phy, REG_HDMI_8960_PHY_PLL_PWRDN_B); + val |=3D HDMI_8960_PHY_REG12_SW_RESET; + val &=3D ~HDMI_8960_PHY_REG12_PWRDN_B; + hdmi_pll_write(phy, REG_HDMI_8960_PHY_PLL_PWRDN_B, val); + /* Make sure HDMI PHY/PLL are powered down */ + mb(); +} + +static int qcom_hdmi_msm8960_phy_power_on(struct qcom_hdmi_preqmp_phy *hdm= i_phy) +{ + int ret; + + ret =3D qcom_hdmi_msm8960_phy_set_rate(hdmi_phy); + if (ret) + return ret; + + ret =3D qcom_hdmi_msm8960_phy_pll_enable(hdmi_phy); + if (ret) + return ret; + + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG2, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG0, 0x1b); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG1, 0xf2); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG4, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG5, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG6, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG7, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG8, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG9, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG10, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG11, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG3, 0x20); + + return 0; +} + +static int qcom_hdmi_msm8960_phy_power_off(struct qcom_hdmi_preqmp_phy *hd= mi_phy) +{ + hdmi_phy_write(hdmi_phy, REG_HDMI_8960_PHY_REG2, 0x7f); + + qcom_hdmi_msm8960_phy_pll_disable(hdmi_phy); + + return 0; +} + +const struct clk_parent_data msm8960_hdmi_pll_parent =3D { + .fw_name =3D "pxo", .name =3D "pxo_board", +}; + +const struct qcom_hdmi_preqmp_cfg msm8960_hdmi_phy_cfg =3D { + .clk_names =3D { "slave_iface" }, + .num_clks =3D 1, + + .reg_names =3D { "core-vdda" }, + .num_regs =3D 1, + + .power_on =3D qcom_hdmi_msm8960_phy_power_on, + .power_off =3D qcom_hdmi_msm8960_phy_power_off, + + .pll_ops =3D &qcom_hdmi_8960_pll_ops, + .pll_parent =3D &msm8960_hdmi_pll_parent, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c b/drivers/phy/qualco= mm/phy-qcom-hdmi-45nm.c new file mode 100644 index 0000000000000000000000000000000000000000..ae834f0827fa67cbcbb9c00d547= 7c2f70b9e9f8d --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c @@ -0,0 +1,186 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + * Author: Rob Clark + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "phy-qcom-hdmi-preqmp.h" + +#define REG_HDMI_8x60_PHY_REG0 0x00000000 +#define HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__MASK 0x0000001c + +#define REG_HDMI_8x60_PHY_REG1 0x00000004 +#define HDMI_8x60_PHY_REG1_DTEST_MUX_SEL__MASK 0x000000f0 +#define HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL__MASK 0x0000000f + +#define REG_HDMI_8x60_PHY_REG2 0x00000008 +#define HDMI_8x60_PHY_REG2_PD_DESER 0x00000001 +#define HDMI_8x60_PHY_REG2_PD_DRIVE_1 0x00000002 +#define HDMI_8x60_PHY_REG2_PD_DRIVE_2 0x00000004 +#define HDMI_8x60_PHY_REG2_PD_DRIVE_3 0x00000008 +#define HDMI_8x60_PHY_REG2_PD_DRIVE_4 0x00000010 +#define HDMI_8x60_PHY_REG2_PD_PLL 0x00000020 +#define HDMI_8x60_PHY_REG2_PD_PWRGEN 0x00000040 +#define HDMI_8x60_PHY_REG2_RCV_SENSE_EN 0x00000080 + +#define REG_HDMI_8x60_PHY_REG3 0x0000000c +#define HDMI_8x60_PHY_REG3_PLL_ENABLE 0x00000001 + +#define REG_HDMI_8x60_PHY_REG4 0x00000010 + +#define REG_HDMI_8x60_PHY_REG5 0x00000014 + +#define REG_HDMI_8x60_PHY_REG6 0x00000018 + +#define REG_HDMI_8x60_PHY_REG7 0x0000001c + +#define REG_HDMI_8x60_PHY_REG8 0x00000020 + +#define REG_HDMI_8x60_PHY_REG9 0x00000024 + +#define REG_HDMI_8x60_PHY_REG10 0x00000028 + +#define REG_HDMI_8x60_PHY_REG11 0x0000002c + +#define REG_HDMI_8x60_PHY_REG12 0x00000030 +#define HDMI_8x60_PHY_REG12_RETIMING_EN 0x00000001 +#define HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN 0x00000002 +#define HDMI_8x60_PHY_REG12_FORCE_LOCK 0x00000010 + +static int qcom_hdmi_msm8x60_phy_power_on(struct qcom_hdmi_preqmp_phy *hdm= i_phy) +{ + unsigned long pixclock =3D hdmi_phy->hdmi_opts.tmds_char_rate; + + /* De-serializer delay D/C for non-lbk mode: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG0, + FIELD_PREP(HDMI_8x60_PHY_REG0_DESER_DEL_CTRL__MASK, 3)); + + if (pixclock =3D=3D 27 * HZ_PER_MHZ) { + /* video_format =3D=3D HDMI_VFRMT_720x480p60_16_9 */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG1, + FIELD_PREP(HDMI_8x60_PHY_REG1_DTEST_MUX_SEL__MASK, 5) | + FIELD_PREP(HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL__MASK, 3)); + } else { + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG1, + FIELD_PREP(HDMI_8x60_PHY_REG1_DTEST_MUX_SEL__MASK, 5) | + FIELD_PREP(HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL__MASK, 4)); + } + + /* No matter what, start from the power down mode: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG2, + HDMI_8x60_PHY_REG2_PD_PWRGEN | + HDMI_8x60_PHY_REG2_PD_PLL | + HDMI_8x60_PHY_REG2_PD_DRIVE_4 | + HDMI_8x60_PHY_REG2_PD_DRIVE_3 | + HDMI_8x60_PHY_REG2_PD_DRIVE_2 | + HDMI_8x60_PHY_REG2_PD_DRIVE_1 | + HDMI_8x60_PHY_REG2_PD_DESER); + + /* Turn PowerGen on: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG2, + HDMI_8x60_PHY_REG2_PD_PLL | + HDMI_8x60_PHY_REG2_PD_DRIVE_4 | + HDMI_8x60_PHY_REG2_PD_DRIVE_3 | + HDMI_8x60_PHY_REG2_PD_DRIVE_2 | + HDMI_8x60_PHY_REG2_PD_DRIVE_1 | + HDMI_8x60_PHY_REG2_PD_DESER); + + /* Turn PLL power on: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG2, + HDMI_8x60_PHY_REG2_PD_DRIVE_4 | + HDMI_8x60_PHY_REG2_PD_DRIVE_3 | + HDMI_8x60_PHY_REG2_PD_DRIVE_2 | + HDMI_8x60_PHY_REG2_PD_DRIVE_1 | + HDMI_8x60_PHY_REG2_PD_DESER); + + /* Write to HIGH after PLL power down de-assert: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG3, + HDMI_8x60_PHY_REG3_PLL_ENABLE); + + /* ASIC power on; PHY REG9 =3D 0 */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG9, 0); + + /* Enable PLL lock detect, PLL lock det will go high after lock + * Enable the re-time logic + */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG12, + HDMI_8x60_PHY_REG12_RETIMING_EN | + HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN); + + /* Drivers are on: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG2, + HDMI_8x60_PHY_REG2_PD_DESER); + + /* If the RX detector is needed: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG2, + HDMI_8x60_PHY_REG2_RCV_SENSE_EN | + HDMI_8x60_PHY_REG2_PD_DESER); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG4, 0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG5, 0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG6, 0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG7, 0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG8, 0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG9, 0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG10, 0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG11, 0); + + /* If we want to use lock enable based on counting: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG12, + HDMI_8x60_PHY_REG12_RETIMING_EN | + HDMI_8x60_PHY_REG12_PLL_LOCK_DETECT_EN | + HDMI_8x60_PHY_REG12_FORCE_LOCK); + + return 0; +} + +static int qcom_hdmi_msm8x60_phy_power_off(struct qcom_hdmi_preqmp_phy *hd= mi_phy) +{ + /* Turn off Driver */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG2, + HDMI_8x60_PHY_REG2_PD_DRIVE_4 | + HDMI_8x60_PHY_REG2_PD_DRIVE_3 | + HDMI_8x60_PHY_REG2_PD_DRIVE_2 | + HDMI_8x60_PHY_REG2_PD_DRIVE_1 | + HDMI_8x60_PHY_REG2_PD_DESER); + udelay(10); + /* Disable PLL */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG3, 0); + /* Power down PHY, but keep RX-sense: */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x60_PHY_REG2, + HDMI_8x60_PHY_REG2_RCV_SENSE_EN | + HDMI_8x60_PHY_REG2_PD_PWRGEN | + HDMI_8x60_PHY_REG2_PD_PLL | + HDMI_8x60_PHY_REG2_PD_DRIVE_4 | + HDMI_8x60_PHY_REG2_PD_DRIVE_3 | + HDMI_8x60_PHY_REG2_PD_DRIVE_2 | + HDMI_8x60_PHY_REG2_PD_DRIVE_1 | + HDMI_8x60_PHY_REG2_PD_DESER); + + return 0; +} + +const struct qcom_hdmi_preqmp_cfg msm8x60_hdmi_phy_cfg =3D { + .clk_names =3D { "slave_iface" }, + .num_clks =3D 1, + + .reg_names =3D { "core-vdda" }, + .num_regs =3D 1, + + .power_on =3D qcom_hdmi_msm8x60_phy_power_on, + .power_off =3D qcom_hdmi_msm8x60_phy_power_off, + + /* FIXME: no PLL support */ +}; diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c b/drivers/phy/qual= comm/phy-qcom-hdmi-preqmp.c new file mode 100644 index 0000000000000000000000000000000000000000..de188f660da76d45079916277b3= 1f3b014374f1d --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c @@ -0,0 +1,212 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + */ + +#include +#include + +#include "phy-qcom-hdmi-preqmp.h" + +static int qcom_hdmi_preqmp_phy_init(struct phy *phy) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D phy_get_drvdata(phy); + + return pm_runtime_resume_and_get(hdmi_phy->dev); +} + +static int qcom_hdmi_preqmp_phy_exit(struct phy *phy) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D phy_get_drvdata(phy); + + pm_runtime_put_noidle(hdmi_phy->dev); + + return 0; +} + +static int qcom_hdmi_preqmp_phy_power_on(struct phy *phy) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D phy_get_drvdata(phy); + + return hdmi_phy->power_on(hdmi_phy); +}; + +static int qcom_hdmi_preqmp_phy_power_off(struct phy *phy) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D phy_get_drvdata(phy); + + return hdmi_phy->power_off(hdmi_phy); +}; + +static int qcom_hdmi_preqmp_phy_configure(struct phy *phy, union phy_confi= gure_opts *opts) +{ + const struct phy_configure_opts_hdmi *hdmi_opts =3D &opts->hdmi; + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D phy_get_drvdata(phy); + int ret =3D 0; + + memcpy(&hdmi_phy->hdmi_opts, hdmi_opts, sizeof(*hdmi_opts)); + + return ret; +} + +static int __maybe_unused qcom_hdmi_preqmp_runtime_resume(struct device *d= ev) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D dev_get_drvdata(dev); + int ret; + + ret =3D regulator_bulk_enable(hdmi_phy->num_regs, hdmi_phy->regs); + if (ret) + return ret; + + ret =3D clk_bulk_prepare_enable(hdmi_phy->num_clks, hdmi_phy->clks); + if (ret) + goto out_disable_supplies; + + return 0; + +out_disable_supplies: + regulator_bulk_disable(hdmi_phy->num_regs, hdmi_phy->regs); + + return ret; +} + +static int __maybe_unused qcom_hdmi_preqmp_runtime_suspend(struct device *= dev) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(hdmi_phy->num_clks, hdmi_phy->clks); + regulator_bulk_disable(hdmi_phy->num_regs, hdmi_phy->regs); + + return 0; +} + +static const struct phy_ops qcom_hdmi_preqmp_phy_ops =3D { + .init =3D qcom_hdmi_preqmp_phy_init, + .configure =3D qcom_hdmi_preqmp_phy_configure, + .power_on =3D qcom_hdmi_preqmp_phy_power_on, + .power_off =3D qcom_hdmi_preqmp_phy_power_off, + .exit =3D qcom_hdmi_preqmp_phy_exit, + .owner =3D THIS_MODULE, +}; + +static int qcom_hdmi_preqmp_probe(struct platform_device *pdev) +{ + struct clk_init_data init; + struct phy_provider *phy_provider; + struct device *dev =3D &pdev->dev; + struct qcom_hdmi_preqmp_phy *hdmi_phy; + const struct qcom_hdmi_preqmp_cfg *cfg; + int i, ret; + + cfg =3D of_device_get_match_data(dev); + if (!cfg) + return -EINVAL; + + hdmi_phy =3D devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL); + if (!hdmi_phy) + return -ENOMEM; + + hdmi_phy->dev =3D dev; + + hdmi_phy->phy_reg =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hdmi_phy->phy_reg)) + return PTR_ERR(hdmi_phy->phy_reg); + + hdmi_phy->pll_reg =3D devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(hdmi_phy->pll_reg)) + return PTR_ERR(hdmi_phy->pll_reg); + + hdmi_phy->num_clks =3D cfg->num_clks; + for (i =3D 0; i < cfg->num_clks; i++) + hdmi_phy->clks[i].id =3D cfg->clk_names[i]; + ret =3D devm_clk_bulk_get(dev, hdmi_phy->num_clks, hdmi_phy->clks); + if (ret) + return ret; + + hdmi_phy->num_regs =3D cfg->num_regs; + for (i =3D 0; i < cfg->num_regs; i++) { + hdmi_phy->regs[i].supply =3D cfg->reg_names[i]; + hdmi_phy->regs[i].init_load_uA =3D cfg->reg_init_load[i]; + } + ret =3D devm_regulator_bulk_get(dev, hdmi_phy->num_regs, hdmi_phy->regs); + if (ret) + return ret; + + hdmi_phy->power_on =3D cfg->power_on; + hdmi_phy->power_off =3D cfg->power_off; + + platform_set_drvdata(pdev, hdmi_phy); + + ret =3D devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret =3D pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + /* FIXME: msm8x60 doesn't yet have PLL ops */ + if (cfg->pll_ops) { + init.name =3D "hdmipll"; + init.ops =3D cfg->pll_ops; + init.flags =3D CLK_GET_RATE_NOCACHE; + init.parent_data =3D cfg->pll_parent; + init.num_parents =3D 1; + + hdmi_phy->pll_hw.init =3D &init; + ret =3D devm_clk_hw_register(hdmi_phy->dev, &hdmi_phy->pll_hw); + if (ret) + goto err; + + ret =3D devm_of_clk_add_hw_provider(hdmi_phy->dev, of_clk_hw_simple_get, + &hdmi_phy->pll_hw); + if (ret) + goto err; + } + + hdmi_phy->phy =3D devm_phy_create(dev, pdev->dev.of_node, &qcom_hdmi_preq= mp_phy_ops); + if (IS_ERR(hdmi_phy->phy)) { + ret =3D PTR_ERR(hdmi_phy->phy); + goto err; + } + + phy_set_drvdata(hdmi_phy->phy, hdmi_phy); + + phy_provider =3D devm_of_phy_provider_register(dev, of_phy_simple_xlate); + pm_runtime_put_noidle(&pdev->dev); + return PTR_ERR_OR_ZERO(phy_provider); + +err: + pm_runtime_put_noidle(&pdev->dev); + return ret; +} + +static const struct of_device_id qcom_hdmi_preqmp_of_match_table[] =3D { + { .compatible =3D "qcom,hdmi-phy-8660", .data =3D &msm8x60_hdmi_phy_cfg, = }, + { .compatible =3D "qcom,hdmi-phy-8960", .data =3D &msm8960_hdmi_phy_cfg, = }, + { .compatible =3D "qcom,hdmi-phy-8974", .data =3D &msm8974_hdmi_phy_cfg, = }, + { }, +}; +MODULE_DEVICE_TABLE(of, qcom_hdmi_preqmp_of_match_table); + +DEFINE_RUNTIME_DEV_PM_OPS(qcom_hdmi_preqmp_pm_ops, + qcom_hdmi_preqmp_runtime_suspend, + qcom_hdmi_preqmp_runtime_resume, + NULL); + +static struct platform_driver qcom_hdmi_preqmp_driver =3D { + .probe =3D qcom_hdmi_preqmp_probe, + .driver =3D { + .name =3D "qcom-preqmp-hdmi-phy", + .of_match_table =3D qcom_hdmi_preqmp_of_match_table, + .pm =3D &qcom_hdmi_preqmp_pm_ops, + }, +}; + +module_platform_driver(qcom_hdmi_preqmp_driver); + +MODULE_AUTHOR("Dmitry Baryshkov "); +MODULE_DESCRIPTION("Qualcomm MSMpreqmp HDMI PHY driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h b/drivers/phy/qual= comm/phy-qcom-hdmi-preqmp.h new file mode 100644 index 0000000000000000000000000000000000000000..5562a3ac4840f7a76d7c76f6f80= f1f9c1c7852e1 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h @@ -0,0 +1,81 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2013 Red Hat + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + */ + +#ifndef PHY_QCOM_HDMI_PREQMP_H +#define PHY_QCOM_HDMI_PREQMP_H + +#include +#include +#include +#include + +#define MAX_CLKS 2 +#define MAX_SUPPLIES 2 + +struct qcom_hdmi_preqmp_phy { + struct device *dev; + struct phy *phy; + void __iomem *pll_reg; + void __iomem *phy_reg; + + struct phy_configure_opts_hdmi hdmi_opts; + + struct clk_hw pll_hw; + struct clk_bulk_data clks[MAX_CLKS]; + int num_clks; + + struct regulator_bulk_data regs[MAX_SUPPLIES]; + int num_regs; + + int (*power_on)(struct qcom_hdmi_preqmp_phy *phy); + int (*power_off)(struct qcom_hdmi_preqmp_phy *phy); +}; + +#define hw_clk_to_phy(x) container_of(x, struct qcom_hdmi_preqmp_phy, pll_= hw) + +struct qcom_hdmi_preqmp_cfg { + const char * const clk_names[MAX_CLKS]; + int num_clks; + + const char * const reg_names[MAX_SUPPLIES]; + int reg_init_load[MAX_SUPPLIES]; + int num_regs; + + int (*power_on)(struct qcom_hdmi_preqmp_phy *phy); + int (*power_off)(struct qcom_hdmi_preqmp_phy *phy); + + const struct clk_ops *pll_ops; + const struct clk_parent_data *pll_parent; +}; + +static inline void hdmi_phy_write(struct qcom_hdmi_preqmp_phy *phy, int of= fset, + u32 data) +{ + writel(data, phy->phy_reg + offset); +} + +static inline u32 hdmi_phy_read(struct qcom_hdmi_preqmp_phy *phy, int offs= et) +{ + return readl(phy->phy_reg + offset); +} + +static inline void hdmi_pll_write(struct qcom_hdmi_preqmp_phy *phy, int of= fset, + u32 data) +{ + writel(data, phy->pll_reg + offset); +} + +static inline u32 hdmi_pll_read(struct qcom_hdmi_preqmp_phy *phy, int offs= et) +{ + return readl(phy->pll_reg + offset); +} + +extern const struct qcom_hdmi_preqmp_cfg msm8x60_hdmi_phy_cfg; +extern const struct qcom_hdmi_preqmp_cfg msm8960_hdmi_phy_cfg; +extern const struct qcom_hdmi_preqmp_cfg msm8974_hdmi_phy_cfg; + +#endif diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c b/drivers/phy/qu= alcomm/phy-qcom-qmp-hdmi-base.c new file mode 100644 index 0000000000000000000000000000000000000000..caca753d50e423a831fa9ba3346= 4b713b093e0ff --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + */ + +#include +#include +#include + +#include "phy-qcom-qmp-hdmi.h" + +int qmp_hdmi_phy_init(struct phy *phy) +{ + struct qmp_hdmi_phy *hdmi_phy =3D phy_get_drvdata(phy); + + return pm_runtime_resume_and_get(hdmi_phy->dev); +} + +int qmp_hdmi_phy_configure(struct phy *phy, union phy_configure_opts *opts) +{ + const struct phy_configure_opts_hdmi *hdmi_opts =3D &opts->hdmi; + struct qmp_hdmi_phy *hdmi_phy =3D phy_get_drvdata(phy); + int ret =3D 0; + + memcpy(&hdmi_phy->hdmi_opts, hdmi_opts, sizeof(*hdmi_opts)); + + return ret; +} + +int qmp_hdmi_phy_exit(struct phy *phy) +{ + struct qmp_hdmi_phy *hdmi_phy =3D phy_get_drvdata(phy); + + pm_runtime_put_noidle(hdmi_phy->dev); + + return 0; +} + +static int __maybe_unused qmp_hdmi_runtime_resume(struct device *dev) +{ + struct qmp_hdmi_phy *hdmi_phy =3D dev_get_drvdata(dev); + int ret; + + ret =3D regulator_bulk_enable(ARRAY_SIZE(hdmi_phy->supplies), hdmi_phy->s= upplies); + if (ret) + return ret; + + ret =3D clk_bulk_prepare_enable(ARRAY_SIZE(hdmi_phy->clks), hdmi_phy->clk= s); + if (ret) + goto out_disable_supplies; + + return 0; + +out_disable_supplies: + regulator_bulk_disable(ARRAY_SIZE(hdmi_phy->supplies), hdmi_phy->supplies= ); + + return ret; +} + +static int __maybe_unused qmp_hdmi_runtime_suspend(struct device *dev) +{ + struct qmp_hdmi_phy *hdmi_phy =3D dev_get_drvdata(dev); + + clk_bulk_disable_unprepare(ARRAY_SIZE(hdmi_phy->clks), hdmi_phy->clks); + regulator_bulk_disable(ARRAY_SIZE(hdmi_phy->supplies), hdmi_phy->supplies= ); + + return 0; +} + +static int qmp_hdmi_probe(struct platform_device *pdev) +{ + struct clk_init_data init =3D { + .name =3D "hdmipll", + .parent_data =3D (const struct clk_parent_data[]) { + { .fw_name =3D "xo", .name =3D "xo_board" }, + }, + .flags =3D CLK_GET_RATE_NOCACHE, + .num_parents =3D 1, + }; + const struct qmp_hdmi_cfg *cfg =3D of_device_get_match_data(&pdev->dev); + struct phy_provider *phy_provider; + struct device *dev =3D &pdev->dev; + struct qmp_hdmi_phy *hdmi_phy; + int ret, i; + + hdmi_phy =3D devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL); + if (!hdmi_phy) + return -ENOMEM; + + hdmi_phy->dev =3D dev; + + hdmi_phy->serdes =3D devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hdmi_phy->serdes)) + return PTR_ERR(hdmi_phy->serdes); + + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_phy->tx[i] =3D devm_platform_ioremap_resource(pdev, 1 + i); + if (IS_ERR(hdmi_phy->tx[i])) + return PTR_ERR(hdmi_phy->tx[i]); + } + + hdmi_phy->phy_reg =3D devm_platform_ioremap_resource(pdev, 5); + if (IS_ERR(hdmi_phy->phy_reg)) + return PTR_ERR(hdmi_phy->phy_reg); + + hdmi_phy->clks[0].id =3D "iface"; + hdmi_phy->clks[1].id =3D "ref"; + ret =3D devm_clk_bulk_get(dev, ARRAY_SIZE(hdmi_phy->clks), hdmi_phy->clks= ); + if (ret) + return ret; + + hdmi_phy->supplies[0].supply =3D "vddio"; + hdmi_phy->supplies[0].init_load_uA =3D 100000; + hdmi_phy->supplies[1].supply =3D "vcca"; + hdmi_phy->supplies[1].init_load_uA =3D 10000; + ret =3D devm_regulator_bulk_get(dev, ARRAY_SIZE(hdmi_phy->supplies), hdmi= _phy->supplies); + if (ret) + return ret; + + platform_set_drvdata(pdev, hdmi_phy); + + ret =3D devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret =3D pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + init.ops =3D cfg->pll_ops; + hdmi_phy->pll_hw.init =3D &init; + ret =3D devm_clk_hw_register(hdmi_phy->dev, &hdmi_phy->pll_hw); + if (ret) + goto err; + + ret =3D devm_of_clk_add_hw_provider(hdmi_phy->dev, of_clk_hw_simple_get, = &hdmi_phy->pll_hw); + if (ret) + goto err; + + hdmi_phy->phy =3D devm_phy_create(dev, pdev->dev.of_node, cfg->phy_ops); + if (IS_ERR(hdmi_phy->phy)) { + ret =3D PTR_ERR(hdmi_phy->phy); + goto err; + } + + phy_set_drvdata(hdmi_phy->phy, hdmi_phy); + + phy_provider =3D devm_of_phy_provider_register(dev, of_phy_simple_xlate); + pm_runtime_put_noidle(&pdev->dev); + return PTR_ERR_OR_ZERO(phy_provider); + +err: + pm_runtime_put_noidle(&pdev->dev); + return ret; +} + +static const struct of_device_id qmp_hdmi_of_match_table[] =3D { + { + .compatible =3D "qcom,hdmi-phy-8996", .data =3D &qmp_hdmi_8996_cfg, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, qmp_hdmi_of_match_table); + +DEFINE_RUNTIME_DEV_PM_OPS(qmp_hdmi_pm_ops, + qmp_hdmi_runtime_suspend, + qmp_hdmi_runtime_resume, + NULL); + +static struct platform_driver qmp_hdmi_driver =3D { + .probe =3D qmp_hdmi_probe, + .driver =3D { + .name =3D "qcom-qmp-hdmi-phy", + .of_match_table =3D qmp_hdmi_of_match_table, + .pm =3D &qmp_hdmi_pm_ops, + }, +}; + +module_platform_driver(qmp_hdmi_driver); + +MODULE_AUTHOR("Dmitry Baryshkov "); +MODULE_DESCRIPTION("Qualcomm QMP HDMI PHY driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c b/drivers/phy= /qualcomm/phy-qcom-qmp-hdmi-msm8996.c new file mode 100644 index 0000000000000000000000000000000000000000..2eb1064046f289dacb58b5242c2= a388122561b13 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c @@ -0,0 +1,442 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + */ + +#include +#include +#include + +#include "phy-qcom-qmp-hdmi.h" +#include "phy-qcom-qmp-qserdes-com.h" +#include "phy-qcom-qmp-qserdes-txrx.h" + +#define HDMI_VCO_MAX_FREQ 12000000000UL +#define HDMI_VCO_MIN_FREQ 8000000000UL + +#define HDMI_PCLK_MAX_FREQ 600000000UL +#define HDMI_PCLK_MIN_FREQ 25000000UL + +#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL +#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL +#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000UL +#define HDMI_DEFAULT_REF_CLOCK 19200000 +#define HDMI_PLL_CMP_CNT 1024 + +#define HDMI_PLL_POLL_MAX_READS 100 +#define HDMI_PLL_POLL_TIMEOUT_US 150 + +#define REG_HDMI_8996_PHY_CFG 0x00000000 +#define REG_HDMI_8996_PHY_PD_CTL 0x00000004 +#define REG_HDMI_8996_PHY_MODE 0x00000008 +#define REG_HDMI_8996_PHY_MISR_CLEAR 0x0000000c +#define REG_HDMI_8996_PHY_TX0_TX1_BIST_CFG0 0x00000010 +#define REG_HDMI_8996_PHY_TX0_TX1_BIST_CFG1 0x00000014 +#define REG_HDMI_8996_PHY_TX0_TX1_PRBS_SEED_BYTE0 0x00000018 +#define REG_HDMI_8996_PHY_TX0_TX1_PRBS_SEED_BYTE1 0x0000001c +#define REG_HDMI_8996_PHY_TX0_TX1_BIST_PATTERN0 0x00000020 +#define REG_HDMI_8996_PHY_TX0_TX1_BIST_PATTERN1 0x00000024 +#define REG_HDMI_8996_PHY_TX2_TX3_BIST_CFG0 0x00000028 +#define REG_HDMI_8996_PHY_TX2_TX3_BIST_CFG1 0x0000002c +#define REG_HDMI_8996_PHY_TX2_TX3_PRBS_SEED_BYTE0 0x00000030 +#define REG_HDMI_8996_PHY_TX2_TX3_PRBS_SEED_BYTE1 0x00000034 +#define REG_HDMI_8996_PHY_TX2_TX3_BIST_PATTERN0 0x00000038 +#define REG_HDMI_8996_PHY_TX2_TX3_BIST_PATTERN1 0x0000003c +#define REG_HDMI_8996_PHY_DEBUG_BUS_SEL 0x00000040 +#define REG_HDMI_8996_PHY_TXCAL_CFG0 0x00000044 +#define REG_HDMI_8996_PHY_TXCAL_CFG1 0x00000048 +#define REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL 0x0000004c +#define REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL 0x00000050 +#define REG_HDMI_8996_PHY_LANE_BIST_CONFIG 0x00000054 +#define REG_HDMI_8996_PHY_CLOCK 0x00000058 +#define REG_HDMI_8996_PHY_MISC1 0x0000005c +#define REG_HDMI_8996_PHY_MISC2 0x00000060 +#define REG_HDMI_8996_PHY_TX0_TX1_BIST_STATUS0 0x00000064 +#define REG_HDMI_8996_PHY_TX0_TX1_BIST_STATUS1 0x00000068 +#define REG_HDMI_8996_PHY_TX0_TX1_BIST_STATUS2 0x0000006c +#define REG_HDMI_8996_PHY_TX2_TX3_BIST_STATUS0 0x00000070 +#define REG_HDMI_8996_PHY_TX2_TX3_BIST_STATUS1 0x00000074 +#define REG_HDMI_8996_PHY_TX2_TX3_BIST_STATUS2 0x00000078 +#define REG_HDMI_8996_PHY_PRE_MISR_STATUS0 0x0000007c +#define REG_HDMI_8996_PHY_PRE_MISR_STATUS1 0x00000080 +#define REG_HDMI_8996_PHY_PRE_MISR_STATUS2 0x00000084 +#define REG_HDMI_8996_PHY_PRE_MISR_STATUS3 0x00000088 +#define REG_HDMI_8996_PHY_POST_MISR_STATUS0 0x0000008c +#define REG_HDMI_8996_PHY_POST_MISR_STATUS1 0x00000090 +#define REG_HDMI_8996_PHY_POST_MISR_STATUS2 0x00000094 +#define REG_HDMI_8996_PHY_POST_MISR_STATUS3 0x00000098 +#define REG_HDMI_8996_PHY_STATUS 0x0000009c +#define REG_HDMI_8996_PHY_MISC3_STATUS 0x000000a0 +#define REG_HDMI_8996_PHY_MISC4_STATUS 0x000000a4 +#define REG_HDMI_8996_PHY_DEBUG_BUS0 0x000000a8 +#define REG_HDMI_8996_PHY_DEBUG_BUS1 0x000000ac +#define REG_HDMI_8996_PHY_DEBUG_BUS2 0x000000b0 +#define REG_HDMI_8996_PHY_DEBUG_BUS3 0x000000b4 +#define REG_HDMI_8996_PHY_PHY_REVISION_ID0 0x000000b8 +#define REG_HDMI_8996_PHY_PHY_REVISION_ID1 0x000000bc +#define REG_HDMI_8996_PHY_PHY_REVISION_ID2 0x000000c0 +#define REG_HDMI_8996_PHY_PHY_REVISION_ID3 0x000000c4 + +struct qmp_hdmi_8996_post_divider { + u64 vco_freq; + int hsclk_divsel; + int vco_ratio; + int tx_band_sel; +}; + +static inline u32 qmp_hdmi_8996_pll_get_pll_cmp(u64 fdata, unsigned long r= ef_clk) +{ + u64 dividend =3D HDMI_PLL_CMP_CNT * fdata; + u32 divisor =3D ref_clk * 10; + u32 rem; + + rem =3D do_div(dividend, divisor); + if (rem > (divisor >> 1)) + dividend++; + + return dividend - 1; +} + +static int qmp_hdmi_8996_pll_get_post_div(struct qmp_hdmi_8996_post_divide= r *pd, u64 bclk) +{ + int ratio[] =3D { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 }; + int hs_divsel[] =3D { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 }; + int tx_band_sel[] =3D { 0, 1, 2, 3 }; + u64 vco_freq[60]; + u64 vco, vco_optimal; + int half_rate_mode =3D 0; + int vco_optimal_index, vco_freq_index; + int i, j; + +retry: + vco_optimal =3D HDMI_VCO_MAX_FREQ; + vco_optimal_index =3D -1; + vco_freq_index =3D 0; + for (i =3D 0; i < 15; i++) { + for (j =3D 0; j < 4; j++) { + u32 ratio_mult =3D ratio[i] << tx_band_sel[j]; + + vco =3D bclk >> half_rate_mode; + vco *=3D ratio_mult; + vco_freq[vco_freq_index++] =3D vco; + } + } + + for (i =3D 0; i < 60; i++) { + u64 vco_tmp =3D vco_freq[i]; + + if ((vco_tmp >=3D HDMI_VCO_MIN_FREQ) && + (vco_tmp <=3D vco_optimal)) { + vco_optimal =3D vco_tmp; + vco_optimal_index =3D i; + } + } + + if (vco_optimal_index =3D=3D -1) { + if (!half_rate_mode) { + half_rate_mode =3D 1; + goto retry; + } + + return -EINVAL; + } + + pd->vco_freq =3D vco_optimal; + pd->tx_band_sel =3D tx_band_sel[vco_optimal_index % 4]; + pd->vco_ratio =3D ratio[vco_optimal_index / 4]; + pd->hsclk_divsel =3D hs_divsel[vco_optimal_index / 4]; + + return 0; +} + +static int qmp_hdmi_8996_phy_set_rate(struct qmp_hdmi_phy *hdmi_phy) +{ + unsigned long parent_rate =3D HDMI_DEFAULT_REF_CLOCK; + unsigned long rate =3D hdmi_phy->hdmi_opts.tmds_char_rate; + struct qmp_hdmi_8996_post_divider pd; + bool gen_ssc =3D false; + u64 bclk; + u64 dec_start; + u64 frac_start; + u64 fdata; + u32 pll_divisor; + u32 rem; + u32 integloop_gain; + u32 pll_cmp; + int i, ret; + + bclk =3D ((u64)rate) * 10; + ret =3D qmp_hdmi_8996_pll_get_post_div(&pd, bclk); + if (ret) { + dev_err(hdmi_phy->dev, "PLL calculation failed\n"); + return ret; + } + + dec_start =3D pd.vco_freq; + pll_divisor =3D 4 * parent_rate; + do_div(dec_start, pll_divisor); + + frac_start =3D pd.vco_freq * (1 << 20); + + rem =3D do_div(frac_start, pll_divisor); + frac_start -=3D dec_start * (1 << 20); + if (rem > (pll_divisor >> 1)) + frac_start++; + + fdata =3D pd.vco_freq; + do_div(fdata, pd.vco_ratio); + + pll_cmp =3D qmp_hdmi_8996_pll_get_pll_cmp(fdata, parent_rate); + + /* Initially shut down PHY */ + dev_dbg(hdmi_phy->dev, "Disabling PHY"); + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_PD_CTL, 0x0); + udelay(500); + + /* Power up sequence */ + hdmi_pll_write(hdmi_phy, QSERDES_COM_BG_CTRL, 0x04); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_PD_CTL, 0x1); + hdmi_pll_write(hdmi_phy, QSERDES_COM_RESETSM_CNTRL, 0x20); + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_TX0_TX1_LANE_CTL, 0x0f); + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_TX2_TX3_LANE_CTL, 0x0f); + + hdmi_tx_chan_write(hdmi_phy, 0, QSERDES_TX_LANE_MODE, 0x43); + hdmi_tx_chan_write(hdmi_phy, 2, QSERDES_TX_LANE_MODE, 0x43); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_SYSCLK_BUF_ENABLE, 0x1e); + hdmi_pll_write(hdmi_phy, QSERDES_COM_BIAS_EN_CLKBUFLR_EN, 0x07); + hdmi_pll_write(hdmi_phy, QSERDES_COM_SYSCLK_EN_SEL, 0x37); + hdmi_pll_write(hdmi_phy, QSERDES_COM_SYS_CLK_CTRL, 0x02); + hdmi_pll_write(hdmi_phy, QSERDES_COM_CLK_ENABLE1, 0x0e); + + if (frac_start !=3D 0 || gen_ssc) { + hdmi_pll_write(hdmi_phy, QSERDES_COM_PLL_CCTRL_MODE0, 0x28); + hdmi_pll_write(hdmi_phy, QSERDES_COM_PLL_RCTRL_MODE0, 0x16); + hdmi_pll_write(hdmi_phy, QSERDES_COM_CP_CTRL_MODE0, + 11000000 / (parent_rate / 20)); + integloop_gain =3D (64 * parent_rate) / HDMI_DEFAULT_REF_CLOCK; + } else { + hdmi_pll_write(hdmi_phy, QSERDES_COM_PLL_CCTRL_MODE0, 0x01); + hdmi_pll_write(hdmi_phy, QSERDES_COM_PLL_RCTRL_MODE0, 0x10); + hdmi_pll_write(hdmi_phy, QSERDES_COM_CP_CTRL_MODE0, 0x23); + integloop_gain =3D (1022 * parent_rate) / (100 * 1000 * 1000); + } + + /* Bypass VCO calibration */ + if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) { + hdmi_pll_write(hdmi_phy, QSERDES_COM_SVS_MODE_CLK_SEL, 1); + integloop_gain <<=3D 1; + } else { + hdmi_pll_write(hdmi_phy, QSERDES_COM_SVS_MODE_CLK_SEL, 2); + integloop_gain <<=3D 2; + } + + integloop_gain =3D min_t(u32, integloop_gain, 2046); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_BG_TRIM, 0x0f); + hdmi_pll_write(hdmi_phy, QSERDES_COM_PLL_IVCO, 0x0f); + hdmi_pll_write(hdmi_phy, QSERDES_COM_VCO_TUNE_CTRL, 0); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_BG_CTRL, 0x06); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_CLK_SELECT, 0x30); + hdmi_pll_write(hdmi_phy, QSERDES_COM_HSCLK_SEL, 0x20 | pd.hsclk_divsel); + hdmi_pll_write(hdmi_phy, QSERDES_COM_LOCK_CMP_EN, 0x0); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_DEC_START_MODE0, dec_start); + hdmi_pll_write(hdmi_phy, QSERDES_COM_DIV_FRAC_START1_MODE0, + frac_start & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_COM_DIV_FRAC_START2_MODE0, + (frac_start >> 8) & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_COM_DIV_FRAC_START3_MODE0, + (frac_start >> 16) & 0xf); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_INTEGLOOP_GAIN0_MODE0, + integloop_gain & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_COM_INTEGLOOP_GAIN1_MODE0, + (integloop_gain >> 8) & 0xff); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_LOCK_CMP1_MODE0, + pll_cmp & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_COM_LOCK_CMP2_MODE0, + (pll_cmp >> 8) & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_COM_LOCK_CMP3_MODE0, + (pll_cmp >> 16) & 0x3); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_VCO_TUNE_MAP, 0x00); + hdmi_pll_write(hdmi_phy, QSERDES_COM_CORE_CLK_EN, 0x2c); + hdmi_pll_write(hdmi_phy, QSERDES_COM_CORECLK_DIV, 5); + hdmi_pll_write(hdmi_phy, QSERDES_COM_CMN_CONFIG, 0x02); + + hdmi_pll_write(hdmi_phy, QSERDES_COM_RESCODE_DIV_NUM, 0x15); + + /* TX lanes setup (TX 0/1/2/3) */ + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_CLKBUF_ENABLE, 0x03); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_BAND, pd.tx_band_sel + 4); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_RESET_TSYNC_EN, 0x03); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_VMODE_CTRL1, 0x00); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_DRV_LVL_OFFSET, 0x00); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_RES_CODE_LANE_OFFSET, 0x00); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TRAN_DRVR_EMP_EN, 0x03); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_PARRATE_REC_DETECT_IDLE_EN, 0= x40); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_HP_PD_ENABLES, + i !=3D 3 ? 0xc : 0x3); + } + + if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_DRV_LVL, + i !=3D 3 ? 0x25 : 0x22); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_EMP_POST1_LVL, + i !=3D 3 ? 0x23 : 0x27); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_VMODE_CTRL2, + i !=3D 3 ? 0x0d : 0x00); + } + } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_DRV_LVL, 0x25); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_EMP_POST1_LVL, 0x23); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_VMODE_CTRL2, + i !=3D 3 ? 0x0d : 0x00); + } + } else { + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_DRV_LVL, 0x20); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_EMP_POST1_LVL, 0x20); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_VMODE_CTRL2, 0x0e); + } + } + + if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_MODE, 0x10); + else + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_MODE, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_PD_CTL, 0x1f); + + return 0; +} + +static int qmp_hdmi_8996_phy_power_on(struct phy *phy) +{ + struct qmp_hdmi_phy *hdmi_phy =3D phy_get_drvdata(phy); + u32 status; + int i, ret =3D 0; + + ret =3D qmp_hdmi_8996_phy_set_rate(hdmi_phy); + if (ret) { + dev_err(hdmi_phy->dev, "Setting pixel clock rate failed\n"); + return ret; + } + + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_CFG, 0x1); + udelay(100); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_CFG, 0x19); + udelay(100); + + ret =3D readl_poll_timeout(hdmi_phy->serdes + QSERDES_COM_C_READY_STATUS, + status, status & BIT(0), + HDMI_PLL_POLL_TIMEOUT_US, + HDMI_PLL_POLL_MAX_READS * HDMI_PLL_POLL_TIMEOUT_US); + + if (ret) { + dev_warn(hdmi_phy->dev, "HDMI PLL is not locked\n"); + return ret; + } + + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) + hdmi_tx_chan_write(hdmi_phy, i, + QSERDES_TX_HIGHZ_TRANSCEIVEREN_BIAS_DRVR_EN, + 0x6f); + + /* Disable SSC */ + hdmi_pll_write(hdmi_phy, QSERDES_COM_SSC_PER1, 0x0); + hdmi_pll_write(hdmi_phy, QSERDES_COM_SSC_PER2, 0x0); + hdmi_pll_write(hdmi_phy, QSERDES_COM_SSC_STEP_SIZE1, 0x0); + hdmi_pll_write(hdmi_phy, QSERDES_COM_SSC_STEP_SIZE2, 0x0); + hdmi_pll_write(hdmi_phy, QSERDES_COM_SSC_EN_CENTER, 0x2); + + ret =3D readl_poll_timeout(hdmi_phy->phy_reg + REG_HDMI_8996_PHY_STATUS, + status, status & BIT(0), + HDMI_PLL_POLL_TIMEOUT_US, + HDMI_PLL_POLL_MAX_READS * HDMI_PLL_POLL_TIMEOUT_US); + if (ret) { + dev_warn(hdmi_phy->dev, "HDMI PLL is not locked\n"); + return ret; + } + + /* Restart the retiming buffer */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_CFG, 0x18); + udelay(1); + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_CFG, 0x19); + + return 0; +} + +static int qmp_hdmi_8996_phy_power_off(struct phy *phy) +{ + struct qmp_hdmi_phy *hdmi_phy =3D phy_get_drvdata(phy); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8996_PHY_CFG, 0x6); + usleep_range(100, 150); + + return 0; +} + +static long qmp_hdmi_8996_pll_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + return clamp(rate, HDMI_PCLK_MIN_FREQ, HDMI_PCLK_MAX_FREQ); +} + +static unsigned long qmp_hdmi_8996_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct qmp_hdmi_phy *phy =3D hw_clk_to_pll(hw); + u32 cmp1, cmp2, cmp3, pll_cmp; + + cmp1 =3D hdmi_pll_read(phy, QSERDES_COM_LOCK_CMP1_MODE0); + cmp2 =3D hdmi_pll_read(phy, QSERDES_COM_LOCK_CMP2_MODE0); + cmp3 =3D hdmi_pll_read(phy, QSERDES_COM_LOCK_CMP3_MODE0); + + pll_cmp =3D cmp1 | (cmp2 << 8) | (cmp3 << 16); + + return mult_frac(pll_cmp + 1, parent_rate, HDMI_PLL_CMP_CNT); +} + +static int qmp_hdmi_8996_pll_is_enabled(struct clk_hw *hw) +{ + struct qmp_hdmi_phy *phy =3D hw_clk_to_pll(hw); + u32 status; + int pll_locked; + + status =3D hdmi_pll_read(phy, QSERDES_COM_C_READY_STATUS); + pll_locked =3D status & BIT(0); + + return pll_locked; +} + +static const struct clk_ops qmp_hdmi_8996_pll_ops =3D { + .recalc_rate =3D qmp_hdmi_8996_pll_recalc_rate, + .round_rate =3D qmp_hdmi_8996_pll_round_rate, + .is_enabled =3D qmp_hdmi_8996_pll_is_enabled, +}; + +static const struct phy_ops qmp_hdmi_8996_phy_ops =3D { + .init =3D qmp_hdmi_phy_init, + .configure =3D qmp_hdmi_phy_configure, + .power_on =3D qmp_hdmi_8996_phy_power_on, + .power_off =3D qmp_hdmi_8996_phy_power_off, + .exit =3D qmp_hdmi_phy_exit, + .owner =3D THIS_MODULE, +}; + +const struct qmp_hdmi_cfg qmp_hdmi_8996_cfg =3D { + .pll_ops =3D &qmp_hdmi_8996_pll_ops, + .phy_ops =3D &qmp_hdmi_8996_phy_ops, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8998.c b/drivers/phy= /qualcomm/phy-qcom-qmp-hdmi-msm8998.c new file mode 100644 index 0000000000000000000000000000000000000000..b0ff96f7168a9dd3433a523098c= c7978ad46be49 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8998.c @@ -0,0 +1,495 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2024 Freebox SAS + * Copyright (c) 2025, Qualcomm Incorporated + */ + +#include +#include +#include +#include + +#include "phy-qcom-qmp-hdmi.h" +#include "phy-qcom-qmp-qserdes-com-v3.h" +#include "phy-qcom-qmp-qserdes-txrx.h" + +#define HDMI_VCO_MAX_FREQ 12000000000UL +#define HDMI_VCO_MIN_FREQ 8000000000UL + +#define HDMI_PCLK_MAX_FREQ 600000000UL +#define HDMI_PCLK_MIN_FREQ 25000000UL + +#define HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD 3400000000UL +#define HDMI_DIG_FREQ_BIT_CLK_THRESHOLD 1500000000UL +#define HDMI_MID_FREQ_BIT_CLK_THRESHOLD 750000000UL +#define HDMI_DEFAULT_REF_CLOCK 19200000 +#define HDMI_PLL_CMP_CNT 1024 + +#define HDMI_PLL_POLL_MAX_READS 100 +#define HDMI_PLL_POLL_TIMEOUT_US 150 + +#define REG_HDMI_8998_PHY_CFG 0x00000000 +#define REG_HDMI_8998_PHY_PD_CTL 0x00000004 +#define REG_HDMI_8998_PHY_MODE 0x00000010 +#define REG_HDMI_8998_PHY_CLOCK 0x0000005c +#define REG_HDMI_8998_PHY_CMN_CTRL 0x00000068 +#define REG_HDMI_8998_PHY_STATUS 0x000000b4 + +#define REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL 0x00000000 +#define REG_HDMI_8998_PHY_TXn_INTERFACE_SELECT_TX_BAND 0x00000008 +#define REG_HDMI_8998_PHY_TXn_CLKBUF_TERM_ENABLE 0x0000000c +#define REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_OFFSET 0x00000014 +#define REG_HDMI_8998_PHY_TXn_DRV_LVL 0x00000018 +#define REG_HDMI_8998_PHY_TXn_LANE_CONFIG 0x0000001c +#define REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1 0x00000024 +#define REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2 0x00000028 +#define REG_HDMI_8998_PHY_TXn_LANE_MODE 0x0000002c + +struct qmp_hdmi_8998_post_divider { + u64 vco_freq; + int hsclk_divsel; + int vco_ratio; + int tx_band_sel; + int half_rate_mode; +}; + +static inline u32 qmp_hdmi_8998_pll_get_pll_cmp(u64 fdata, unsigned long r= ef_clk) +{ + u64 dividend =3D HDMI_PLL_CMP_CNT * fdata; + u32 divisor =3D ref_clk * 10; + u32 rem; + + rem =3D do_div(dividend, divisor); + if (rem > (divisor >> 1)) + dividend++; + + return dividend - 1; +} + +static int qmp_hdmi_8998_pll_get_post_div(struct qmp_hdmi_8998_post_divide= r *pd, u64 bclk) +{ + u32 const ratio_list[] =3D {1, 2, 3, 4, 5, 6, 9, 10, 12, 15, 25}; + u32 const band_list[] =3D {0, 1, 2, 3}; + u32 const sz_ratio =3D ARRAY_SIZE(ratio_list); + u32 const sz_band =3D ARRAY_SIZE(band_list); + u32 const cmp_cnt =3D 1024; + u32 const th_min =3D 500, th_max =3D 1000; + u32 half_rate_mode =3D 0; + u32 list_elements; + int optimal_index; + u32 i, j, k; + u32 found_hsclk_divsel =3D 0, found_vco_ratio; + u32 found_tx_band_sel; + u64 const min_freq =3D HDMI_VCO_MIN_FREQ, max_freq =3D HDMI_VCO_MAX_FREQ; + u64 freq_list[ARRAY_SIZE(ratio_list) * ARRAY_SIZE(band_list)]; + u64 found_vco_freq; + u64 freq_optimal; + +find_optimal_index: + freq_optimal =3D max_freq; + optimal_index =3D -1; + list_elements =3D 0; + + for (i =3D 0; i < sz_ratio; i++) { + for (j =3D 0; j < sz_band; j++) { + u64 freq =3D div_u64(bclk, (1 << half_rate_mode)); + + freq *=3D (ratio_list[i] * (1 << band_list[j])); + freq_list[list_elements++] =3D freq; + } + } + + for (k =3D 0; k < ARRAY_SIZE(freq_list); k++) { + u32 const clks_pll_div =3D 2, core_clk_div =3D 5; + u32 const rng1 =3D 16, rng2 =3D 8; + u32 th1, th2; + u64 core_clk, rvar1, rem; + + core_clk =3D div_u64(freq_list[k], + ratio_list[k / sz_band] * clks_pll_div * + core_clk_div); + + rvar1 =3D HDMI_DEFAULT_REF_CLOCK * rng1 * HZ_PER_MHZ; + rvar1 =3D div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem); + if (rem > ((cmp_cnt * core_clk) >> 1)) + rvar1++; + th1 =3D rvar1; + + rvar1 =3D HDMI_DEFAULT_REF_CLOCK * rng2 * HZ_PER_MHZ; + rvar1 =3D div64_u64_rem(rvar1, (cmp_cnt * core_clk), &rem); + if (rem > ((cmp_cnt * core_clk) >> 1)) + rvar1++; + th2 =3D rvar1; + + if (freq_list[k] >=3D min_freq && + freq_list[k] <=3D max_freq) { + if ((th1 >=3D th_min && th1 <=3D th_max) || + (th2 >=3D th_min && th2 <=3D th_max)) { + if (freq_list[k] <=3D freq_optimal) { + freq_optimal =3D freq_list[k]; + optimal_index =3D k; + } + } + } + } + + if (optimal_index =3D=3D -1) { + if (!half_rate_mode) { + half_rate_mode =3D 1; + goto find_optimal_index; + } else { + return -EINVAL; + } + } else { + found_vco_ratio =3D ratio_list[optimal_index / sz_band]; + found_tx_band_sel =3D band_list[optimal_index % sz_band]; + found_vco_freq =3D freq_optimal; + } + + switch (found_vco_ratio) { + case 1: + found_hsclk_divsel =3D 15; + break; + case 2: + found_hsclk_divsel =3D 0; + break; + case 3: + found_hsclk_divsel =3D 4; + break; + case 4: + found_hsclk_divsel =3D 8; + break; + case 5: + found_hsclk_divsel =3D 12; + break; + case 6: + found_hsclk_divsel =3D 1; + break; + case 9: + found_hsclk_divsel =3D 5; + break; + case 10: + found_hsclk_divsel =3D 2; + break; + case 12: + found_hsclk_divsel =3D 9; + break; + case 15: + found_hsclk_divsel =3D 13; + break; + case 25: + found_hsclk_divsel =3D 14; + break; + } + + pd->vco_freq =3D found_vco_freq; + pd->tx_band_sel =3D found_tx_band_sel; + pd->vco_ratio =3D found_vco_ratio; + pd->hsclk_divsel =3D found_hsclk_divsel; + + return 0; +} + +static int qmp_hdmi_8998_phy_set_rate(struct qmp_hdmi_phy *hdmi_phy) +{ + unsigned long parent_rate =3D HDMI_DEFAULT_REF_CLOCK; + unsigned long rate =3D hdmi_phy->hdmi_opts.tmds_char_rate; + struct qmp_hdmi_8998_post_divider pd; + bool gen_ssc =3D false; + u64 bclk; + u64 dec_start; + u64 frac_start; + u64 fdata; + u32 pll_divisor; + u32 rem; + u32 integloop_gain; + u32 pll_cmp; + int i, ret; + + bclk =3D ((u64)rate) * 10; + ret =3D qmp_hdmi_8998_pll_get_post_div(&pd, bclk); + if (ret) { + dev_err(hdmi_phy->dev, "PLL calculation failed\n"); + return ret; + } + + dec_start =3D pd.vco_freq; + pll_divisor =3D 4 * parent_rate; + do_div(dec_start, pll_divisor); + + frac_start =3D pd.vco_freq * (1 << 20); + + rem =3D do_div(frac_start, pll_divisor); + frac_start -=3D dec_start * (1 << 20); + if (rem > (pll_divisor >> 1)) + frac_start++; + + fdata =3D pd.vco_freq; + do_div(fdata, pd.vco_ratio); + + pll_cmp =3D qmp_hdmi_8998_pll_get_pll_cmp(fdata, parent_rate); + + /* Initially shut down PHY */ + dev_dbg(hdmi_phy->dev, "Disabling PHY"); + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_PD_CTL, 0x0); + udelay(500); + + /* Power up sequence */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_PD_CTL, 0x1); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_RESETSM_CNTRL, 0x20); + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_CMN_CTRL, 0x6); + + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, + REG_HDMI_8998_PHY_TXn_INTERFACE_SELECT_TX_BAND, + pd.tx_band_sel); + hdmi_tx_chan_write(hdmi_phy, i, + REG_HDMI_8998_PHY_TXn_CLKBUF_TERM_ENABLE, + 0x1); + hdmi_tx_chan_write(hdmi_phy, i, + REG_HDMI_8998_PHY_TXn_LANE_MODE, + 0x20); + } + + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_SYSCLK_BUF_ENABLE, 0x02); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_BIAS_EN_CLKBUFLR_EN, 0x0B); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_SYSCLK_EN_SEL, 0x37); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_SYS_CLK_CTRL, 0x02); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_CLK_ENABLE1, 0x0E); + + if (frac_start !=3D 0 || gen_ssc) { + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x34); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x16); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_CP_CTRL_MODE0, 0x08); + integloop_gain =3D 0x3f; + } else { + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_PLL_CCTRL_MODE0, 0x02); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_PLL_RCTRL_MODE0, 0x18); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_CP_CTRL_MODE0, 0x30); + integloop_gain =3D 0xc4; + } + + /* Bypass VCO calibration */ + if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) { + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_SVS_MODE_CLK_SEL, 1); + integloop_gain <<=3D 1; + } else { + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_SVS_MODE_CLK_SEL, 2); + integloop_gain <<=3D 2; + } + + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_PLL_IVCO, 0x07); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_VCO_TUNE_CTRL, 0x00); + + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_CLK_SELECT, 0x30); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_HSCLK_SEL, 0x20 | pd.hsclk_divsel= ); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_LOCK_CMP_EN, 0x0); + + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_DEC_START_MODE0, dec_start); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_DIV_FRAC_START1_MODE0, + frac_start & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_DIV_FRAC_START2_MODE0, + (frac_start >> 8) & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_DIV_FRAC_START3_MODE0, + (frac_start >> 16) & 0xf); + + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_INTEGLOOP_GAIN0_MODE0, + integloop_gain & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_INTEGLOOP_GAIN1_MODE0, + (integloop_gain >> 8) & 0xff); + + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_LOCK_CMP1_MODE0, + pll_cmp & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_LOCK_CMP2_MODE0, + (pll_cmp >> 8) & 0xff); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_LOCK_CMP3_MODE0, + (pll_cmp >> 16) & 0x3); + + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_VCO_TUNE_MAP, 0x00); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_CORE_CLK_EN, 0x2c); + hdmi_pll_write(hdmi_phy, QSERDES_V3_COM_CORECLK_DIV_MODE0, 5); + + /* TX lanes setup (TX 0/1/2/3) */ + if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL, + 0xf); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL, + i =3D=3D 3 ? 0x00 : + i =3D=3D 1 ? 0x02 : 0x03); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1, + 0x00); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2, + i =3D=3D 3 ? 0x00 : 0x1c); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_= OFFSET, + (i =3D=3D 0 || i =3D=3D 3) ? 0x03 : 0x00); + } + } else if (bclk > HDMI_DIG_FREQ_BIT_CLK_THRESHOLD) { + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL, + 0x0f); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL, + i =3D=3D 3 ? 0x00 : 0x03); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1, + 0x00); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2, + i =3D=3D 3 ? 0x18 : 0x16); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_= OFFSET, + i =3D=3D 0 ? 0x03 : 0x00); + } + } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL, + 0x0f); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL, + i =3D=3D 3 ? 0x00 : 0x05); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1, + 0x00); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2, + 0x0e); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_= OFFSET, + 0x00); + } + } else { + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL, + i =3D=3D 3 ? 0x00 : 0x01); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_EMP_POST1_LVL, + 0x00); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_1, + 0x00); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_PRE_DRIVER_2, + i =3D=3D 3 ? 0x18 : 0x16); + hdmi_tx_chan_write(hdmi_phy, i, REG_HDMI_8998_PHY_TXn_DRV_LVL_RES_CODE_= OFFSET, + 0x00); + } + } + + if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_MODE, 0x5); + else + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_MODE, 0x4); + + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, + REG_HDMI_8998_PHY_TXn_LANE_CONFIG, + 0x10); + } + + return 0; +} + +static int qmp_hdmi_8998_phy_power_on(struct phy *phy) +{ + struct qmp_hdmi_phy *hdmi_phy =3D phy_get_drvdata(phy); + u32 status; + int i, ret =3D 0; + + ret =3D qmp_hdmi_8998_phy_set_rate(hdmi_phy); + if (ret) { + dev_err(hdmi_phy->dev, "Setting pixel clock rate failed\n"); + return ret; + } + + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_CFG, 0x1); + udelay(100); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_CFG, 0x59); + udelay(100); + + ret =3D readl_poll_timeout(hdmi_phy->serdes + QSERDES_V3_COM_C_READY_STAT= US, + status, status & BIT(0), + HDMI_PLL_POLL_TIMEOUT_US, + HDMI_PLL_POLL_MAX_READS * HDMI_PLL_POLL_TIMEOUT_US); + + if (ret) { + dev_warn(hdmi_phy->dev, "HDMI PLL is not locked\n"); + return ret; + } + + for (i =3D 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, + REG_HDMI_8998_PHY_TXn_LANE_CONFIG, 0x1f); + } + + ret =3D readl_poll_timeout(hdmi_phy->phy_reg + REG_HDMI_8998_PHY_STATUS, + status, status & BIT(0), + HDMI_PLL_POLL_TIMEOUT_US, + HDMI_PLL_POLL_MAX_READS * HDMI_PLL_POLL_TIMEOUT_US); + if (ret) { + dev_warn(hdmi_phy->dev, "HDMI PLL is not locked\n"); + return ret; + } + + /* Restart the retiming buffer */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_CFG, 0x58); + udelay(1); + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_CFG, 0x59); + + return 0; +} + +static int qmp_hdmi_8998_phy_power_off(struct phy *phy) +{ + struct qmp_hdmi_phy *hdmi_phy =3D phy_get_drvdata(phy); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8998_PHY_PD_CTL, 0); + usleep_range(100, 150); + + return 0; +} + +static long qmp_hdmi_8998_pll_round_rate(struct clk_hw *hw, + unsigned long rate, + unsigned long *parent_rate) +{ + return clamp(rate, HDMI_PCLK_MIN_FREQ, HDMI_PCLK_MAX_FREQ); +} + +static unsigned long qmp_hdmi_8998_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct qmp_hdmi_phy *phy =3D hw_clk_to_pll(hw); + u32 cmp1, cmp2, cmp3, pll_cmp; + + cmp1 =3D hdmi_pll_read(phy, QSERDES_V3_COM_LOCK_CMP1_MODE0); + cmp2 =3D hdmi_pll_read(phy, QSERDES_V3_COM_LOCK_CMP2_MODE0); + cmp3 =3D hdmi_pll_read(phy, QSERDES_V3_COM_LOCK_CMP3_MODE0); + + pll_cmp =3D cmp1 | (cmp2 << 8) | (cmp3 << 16); + + return mult_frac(pll_cmp + 1, parent_rate, HDMI_PLL_CMP_CNT); +} + +static int qmp_hdmi_8998_pll_is_enabled(struct clk_hw *hw) +{ + struct qmp_hdmi_phy *phy =3D hw_clk_to_pll(hw); + u32 status; + int pll_locked; + + status =3D hdmi_pll_read(phy, QSERDES_V3_COM_C_READY_STATUS); + pll_locked =3D status & BIT(0); + + return pll_locked; +} + +static const struct clk_ops qmp_hdmi_8998_pll_ops =3D { + .recalc_rate =3D qmp_hdmi_8998_pll_recalc_rate, + .round_rate =3D qmp_hdmi_8998_pll_round_rate, + .is_enabled =3D qmp_hdmi_8998_pll_is_enabled, +}; + +static const struct phy_ops qmp_hdmi_8998_phy_ops =3D { + .init =3D qmp_hdmi_phy_init, + .configure =3D qmp_hdmi_phy_configure, + .power_on =3D qmp_hdmi_8998_phy_power_on, + .power_off =3D qmp_hdmi_8998_phy_power_off, + .exit =3D qmp_hdmi_phy_exit, + .owner =3D THIS_MODULE, +}; + +const struct qmp_hdmi_cfg qmp_hdmi_8998_cfg =3D { + .pll_ops =3D &qmp_hdmi_8998_pll_ops, + .phy_ops =3D &qmp_hdmi_8998_phy_ops, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h b/drivers/phy/qualcom= m/phy-qcom-qmp-hdmi.h new file mode 100644 index 0000000000000000000000000000000000000000..cac28bff396400eb05794daec70= 5104defbcb796 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h @@ -0,0 +1,77 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. + * Copyright (c) 2025, Qualcomm Incorporated + */ + +#ifndef PHY_QCOM_QMP_HDMI_H +#define PHY_QCOM_QMP_HDMI_H + +#include +#include +#include +#include + +#define MAX_CLKS 2 +#define MAX_SUPPLIES 2 + +#define HDMI_NUM_TX_CHANNEL 4 + +struct qmp_hdmi_phy { + struct device *dev; + struct phy *phy; + void __iomem *serdes; + void __iomem *tx[HDMI_NUM_TX_CHANNEL]; + void __iomem *phy_reg; + + struct phy_configure_opts_hdmi hdmi_opts; + + struct clk_hw pll_hw; + struct clk_bulk_data clks[MAX_CLKS]; + struct regulator_bulk_data supplies[MAX_SUPPLIES]; +}; + +struct qmp_hdmi_cfg { + const struct clk_ops *pll_ops; + const struct phy_ops *phy_ops; +}; + +#define hw_clk_to_pll(x) container_of(x, struct qmp_hdmi_phy, pll_hw) + +static inline void hdmi_phy_write(struct qmp_hdmi_phy *phy, int offset, + u32 data) +{ + writel(data, phy->phy_reg + offset); +} + +static inline u32 hdmi_phy_read(struct qmp_hdmi_phy *phy, int offset) +{ + return readl(phy->phy_reg + offset); +} + +static inline void hdmi_pll_write(struct qmp_hdmi_phy *phy, int offset, + u32 data) +{ + writel(data, phy->serdes + offset); +} + +static inline u32 hdmi_pll_read(struct qmp_hdmi_phy *phy, int offset) +{ + return readl(phy->serdes + offset); +} + +static inline void hdmi_tx_chan_write(struct qmp_hdmi_phy *phy, int channe= l, + int offset, int data) +{ + writel(data, phy->tx[channel] + offset); +} + +int qmp_hdmi_phy_init(struct phy *phy); +int qmp_hdmi_phy_configure(struct phy *phy, union phy_configure_opts *opts= ); +int qmp_hdmi_phy_exit(struct phy *phy); + +extern const struct qmp_hdmi_cfg qmp_hdmi_8996_cfg; +extern const struct qmp_hdmi_cfg qmp_hdmi_8998_cfg; + +#endif --=20 2.39.5 From nobody Fri Dec 19 11:32:35 2025 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AD00F28C841 for ; Tue, 20 May 2025 20:44:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773900; cv=none; b=fmoq4PUsx3oTiyVyEkClx2vya2K983dB/fLZ6g9uIJmYU9UeRSj8u+3o2JxFRmRtSewLyVhbJRjoc1HPL7ZIEL0XvLWggbg7sHrib+TUfG0D7kuLGLDzgnz/f0KnrRYS5gG5/ZHSedn17B6aM1DFOux5ujSmhkSQ+0tr2Halgfw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773900; c=relaxed/simple; bh=fX3LnzT2rmBafYy+QSdGUQeHRA967rMH44ZJQ5KxcQo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=AgMkxtaXC/CcRhHv6sJIXeJJnhFLzPxNUKfkPzukqwRA+S7SydxxhULRYjRjAk4nM3Lxel9ljojxQGjKCCrEyI62XIjAqhwndp7pM1dHawQX7igp/7TlQ6KCAcmP1dxq9SUbHVCf4uWV246XuEjQHL5DEsANcFjl+9Vi/nfbqI0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=bqeIfzI6; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="bqeIfzI6" Received: from pps.filterd (m0279863.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 54KGdb4A031948 for ; Tue, 20 May 2025 20:44:58 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= ykPlUua1WYJOj8gRH4+W8xOqCf2Wt8uktxwJQmda3VQ=; b=bqeIfzI6O775RuX9 XEgANszm+qJzkfQrZA3KYborl8uhrcVVj7Eg/e4CGQ9prJkt+SjWbhrrBrwCLGuW /p7FkazLnkV5ThJYB4slpamVeZF/RIxhAVbmbW492wt34VyrPi/jh8dUL1kA6HYc DXmx3mwqFIyhbxCkwYb/KeeHS1mnt1/ibX2JsumDUXgzvYoD42Q0XFfoNssuEJdA yn4K5nxeESVgo8zQqBMiy9VQqrkjpkjhynxrHFB4gDgwF63uaetFniueJekZ5OTj ZdPul4yoexnADtMLaS7A8A/rsNTFOyXkE6Vncq8eeME/A87MWQZPWz6YiDzUygMb sDdbAA== Received: from mail-qv1-f70.google.com (mail-qv1-f70.google.com [209.85.219.70]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf18kq3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 20 May 2025 20:44:57 +0000 (GMT) Received: by mail-qv1-f70.google.com with SMTP id 6a1803df08f44-6f8c2ad9cf2so71160156d6.3 for ; Tue, 20 May 2025 13:44:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747773896; x=1748378696; 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=ykPlUua1WYJOj8gRH4+W8xOqCf2Wt8uktxwJQmda3VQ=; b=hvRlgnBCdYMba4YmdrUWV4n3U4ERZvijefuCe9ukJhVxCc8f0FfIge1puQjIORI/DS 1akogmHJQNd08rqI7EW1Rv6YR9sVeci63MfefAi7myauflEuE/+3NOKCOKEqvYlQs/Hu ui/B3wA/g+BBe4v5EAbsjoY6mugLA2jtCWUFqokWIxsST1P56387sRT1LcgORaJi0Zl4 G77QVzAGW83a8YLWWgM95OhvHtsy8KuU42BAuFdQfumaaIHECWv1vjTXn4XfCgcXYd++ LGC2ffKaMKlFtGAIQMSnzjJxJosj+vibUc5/Zr1Uf3EoEb7CKT9+pHJMfHYAGCJyzoSO z0GA== X-Gm-Message-State: AOJu0Yw3WdCDSQpq3DWKa0kMPfsZ4dwI3I5R2X0F/P2JtGk6kD0H4/rf R3DLMQB2O+8xcXiBgTv+wU9jL5M58oEBYl1x9wg3yOSa2C80Gr8RpXedM4a0WuVaBRSZEL0pJD1 MCKNN4+z+g0Lp6IMPzE13fk7UTrInZSyZzqEx6tnZbFcDoD2cL5tgd6ytiSSErSTJwGg= X-Gm-Gg: ASbGnct1RZQ67lXixhMbyc4NQeM0+fqQExNF7sayhAEhxFNtwZjBx2EGhKtn64xg20l Xz7YW0GV70yIfuof9gZ1C+DYGs819vtk0H/oXECTJCWBKRaxDmasHIvxnyNtFz9JHIpqw/0djUy XjIHwKbKHBx2cctfwBLzs+ZitMif0j5q1SC3De1s/rW0Kbhpk9FMbhWVJYRDEjN4vRWSILhmWJM kcGZK8RpTJEdLibav1CPPPFMtjWlWru0F0Dg+giPPvZPILk3u8i+rixSnkQXP1iX7ngeno1GkQq fLSIzVxI+yId2D+VYFg+QeIY2M0YF92uDLTh20WgbrFbvo7P3CStEVgbXxKc5/SgQ9hZcafqonk /ZBtDDojtJdr0qxklEoOxpg+/ X-Received: by 2002:a05:6214:1cce:b0:6e8:f4e2:26ef with SMTP id 6a1803df08f44-6f8b2d853a5mr303605746d6.31.1747773896228; Tue, 20 May 2025 13:44:56 -0700 (PDT) X-Google-Smtp-Source: AGHT+IExse+TXH1VriLP4f0U2rBvd0pIcWTRd0DsJ4Y79tLbGTK08qfgjRloMVmoV33Gc93nL2+Brw== X-Received: by 2002:a05:6214:1cce:b0:6e8:f4e2:26ef with SMTP id 6a1803df08f44-6f8b2d853a5mr303605316d6.31.1747773895791; Tue, 20 May 2025 13:44:55 -0700 (PDT) Received: from umbar.lan (2001-14ba-a0c3-3a00-264b-feff-fe8b-be8a.rev.dnainternet.fi. [2001:14ba:a0c3:3a00:264b:feff:fe8b:be8a]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-550e6f163ccsm2497950e87.39.2025.05.20.13.44.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 13:44:54 -0700 (PDT) From: Dmitry Baryshkov Date: Tue, 20 May 2025 23:44:44 +0300 Subject: [PATCH v4 2/5] phy: qcom: apq8064-sata: extract UNI PLL register defines 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: <20250520-fd-hdmi-phy-v4-2-fcbaa652ad75@oss.qualcomm.com> References: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> In-Reply-To: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Vinod Koul , Kishon Vijay Abraham I Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org, Dmitry Baryshkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=3088; i=dmitry.baryshkov@oss.qualcomm.com; h=from:subject:message-id; bh=2R5NhT4/9vDNb/+f8UkhB7hzE5bEH/Asz87X2bNQLwQ=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBoLOnAdDwo49oDYbS1+t5ukVG1d9uFbRIxpBN+H Tz8Z0JgZ+iJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCaCzpwAAKCRCLPIo+Aiko 1XhcCACv+if9OWNeFEos1mVk7rlmiEnK1NhPAIrFf8t3Q2zI+I/VveqtxklSEp1Q8Iq0ggj3NFw junUhBnk6cLbZa06b6uxSaIwKd9GbYwSX1ysiZjwHunNJy3T3mW4YXRPF1HLVYirwIgJNGhumoN Gm1pWzwUWCVhYUEGkxtbJMQeQERwFdmvMBSa1gfgqNjWrVNHGio+VS7egsjwgC3QJiyqZkTA9tU yVA3DWtsoEhmOuU4AiBK295kU1jCA47DWuKhSwU3EO612CPAsAhtM6C3qT1xK59vNtPrbYoxN8X ZTEF4T5Y3rAJ4VY90TbNdqxK2m1mY59Ar+P5ymM2uzFl7+wu X-Developer-Key: i=dmitry.baryshkov@oss.qualcomm.com; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-Proofpoint-GUID: CbVe9G9piSFayTHr1QjejqswxqAfIzyb X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIwMDE2OCBTYWx0ZWRfX5s7Q3n1lwAGv biN1pDR3owN0suDoSKmHt0dDsVlWC3k7lAax7y0CqD/ts5SJXhB3UOcvQ2tYa3m3fPNRSm5+5x8 xxhS/xYRg3z4XpOV/BRrxTK7IUGpR26NwPqf1WAjzNJwY/6ZETjRj9jo/Kr707g71k+XDhxdRl0 EhjwLRbT7tUljnAQ/JebE+6cK7BaAH2CzRLvXFhxYXwq5fJ1+dMfPKpZkvDdjQEMf8+5+neG/jA J/EVerYc90RL5LWWVniwdzA8ylOFlFMPSEUSSoTtlkRRuqv9N21U0T/5d/TybWoAPNmpNX7uu1/ qxNxYZaHXcm7zFn3Y4cp+8qy+LNJIU7e2Yu94TLW9Pjj3VjavtsX+HSB4XuDrmC9eTsboqVT84U oM1ftXU1JiMdfv2SLI1mCoG0HTSFtDbbhPDIhlxnxX2cocl/BiXDvl0BdPtHXjJ8VRfM1ZR9 X-Authority-Analysis: v=2.4 cv=F6JXdrhN c=1 sm=1 tr=0 ts=682ce9c9 cx=c_pps a=oc9J++0uMp73DTRD5QyR2A==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=dt9VzEwgFbYA:10 a=KKAkSRfTAAAA:8 a=EUspDBNiAAAA:8 a=O3Nj34nO-tYaQW5E_hgA:9 a=QEXdDO2ut3YA:10 a=iYH6xdkBrDN1Jqds4HTS:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-ORIG-GUID: CbVe9G9piSFayTHr1QjejqswxqAfIzyb X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 definitions=2025-05-20_09,2025-05-20_03,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 mlxscore=0 lowpriorityscore=0 malwarescore=0 priorityscore=1501 suspectscore=0 spamscore=0 phishscore=0 bulkscore=0 clxscore=1015 adultscore=0 mlxlogscore=806 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 definitions=main-2505200168 From: Dmitry Baryshkov The "uni" PLL is shared between several PHYS: APQ8064's SATA, MSM8974/APQ8084 HDMI, MSM8916 DSI, MSM8974/APQ8084 DSI. Signed-off-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong --- drivers/phy/qualcomm/phy-qcom-apq8064-sata.c | 23 +------------------- drivers/phy/qualcomm/phy-qcom-uniphy.h | 32 ++++++++++++++++++++++++= ++++ 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qua= lcomm/phy-qcom-apq8064-sata.c index cae290a6e19fcb7fd68fe6cd0229b9b00d47131c..dd9929429f9a0e2f265180e8d3f= 390451d91adde 100644 --- a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c +++ b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c @@ -15,28 +15,7 @@ #include #include =20 -/* PHY registers */ -#define UNIPHY_PLL_REFCLK_CFG 0x000 -#define UNIPHY_PLL_PWRGEN_CFG 0x014 -#define UNIPHY_PLL_GLB_CFG 0x020 -#define UNIPHY_PLL_SDM_CFG0 0x038 -#define UNIPHY_PLL_SDM_CFG1 0x03C -#define UNIPHY_PLL_SDM_CFG2 0x040 -#define UNIPHY_PLL_SDM_CFG3 0x044 -#define UNIPHY_PLL_SDM_CFG4 0x048 -#define UNIPHY_PLL_SSC_CFG0 0x04C -#define UNIPHY_PLL_SSC_CFG1 0x050 -#define UNIPHY_PLL_SSC_CFG2 0x054 -#define UNIPHY_PLL_SSC_CFG3 0x058 -#define UNIPHY_PLL_LKDET_CFG0 0x05C -#define UNIPHY_PLL_LKDET_CFG1 0x060 -#define UNIPHY_PLL_LKDET_CFG2 0x064 -#define UNIPHY_PLL_CAL_CFG0 0x06C -#define UNIPHY_PLL_CAL_CFG8 0x08C -#define UNIPHY_PLL_CAL_CFG9 0x090 -#define UNIPHY_PLL_CAL_CFG10 0x094 -#define UNIPHY_PLL_CAL_CFG11 0x098 -#define UNIPHY_PLL_STATUS 0x0C0 +#include "phy-qcom-uniphy.h" =20 #define SATA_PHY_SER_CTRL 0x100 #define SATA_PHY_TX_DRIV_CTRL0 0x104 diff --git a/drivers/phy/qualcomm/phy-qcom-uniphy.h b/drivers/phy/qualcomm/= phy-qcom-uniphy.h new file mode 100644 index 0000000000000000000000000000000000000000..e5b79a4dc270f25d8979f51bf4a= cd6c76998032e --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-uniphy.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2014, The Linux Foundation. All rights reserved. + */ + +#ifndef PHY_QCOM_UNIPHY_H +#define PHY_QCOM_UNIPHY_H + +/* PHY registers */ +#define UNIPHY_PLL_REFCLK_CFG 0x000 +#define UNIPHY_PLL_PWRGEN_CFG 0x014 +#define UNIPHY_PLL_GLB_CFG 0x020 +#define UNIPHY_PLL_SDM_CFG0 0x038 +#define UNIPHY_PLL_SDM_CFG1 0x03c +#define UNIPHY_PLL_SDM_CFG2 0x040 +#define UNIPHY_PLL_SDM_CFG3 0x044 +#define UNIPHY_PLL_SDM_CFG4 0x048 +#define UNIPHY_PLL_SSC_CFG0 0x04c +#define UNIPHY_PLL_SSC_CFG1 0x050 +#define UNIPHY_PLL_SSC_CFG2 0x054 +#define UNIPHY_PLL_SSC_CFG3 0x058 +#define UNIPHY_PLL_LKDET_CFG0 0x05c +#define UNIPHY_PLL_LKDET_CFG1 0x060 +#define UNIPHY_PLL_LKDET_CFG2 0x064 +#define UNIPHY_PLL_CAL_CFG0 0x06c +#define UNIPHY_PLL_CAL_CFG8 0x08c +#define UNIPHY_PLL_CAL_CFG9 0x090 +#define UNIPHY_PLL_CAL_CFG10 0x094 +#define UNIPHY_PLL_CAL_CFG11 0x098 +#define UNIPHY_PLL_STATUS 0x0c0 + +#endif --=20 2.39.5 From nobody Fri Dec 19 11:32:35 2025 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E598E288C3B for ; Tue, 20 May 2025 20:45:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773902; cv=none; b=Vu13xkXPiWOo9J7zF1rjlUBurIywjUeuuilLWAeyGdp9qMkWnDP6Uf6ZKYp61yuBd+l8fhaiiLuhmtRmdQHzDCgboOj6EYC1dvi0hawRpeeFYkwyvEbHdOqaly+FcoDMYFAQALWnbn+3hpEWk1WySAoxSz3tPCowZS/7Ir/CnwY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773902; c=relaxed/simple; bh=Xmg1LtYxJaJI2EQ0Va4Q2f9jN887//vucqiSmZrGx6E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=G5QMI8SehuGoYA6QIomEoq8SxYxzX5z3s5qFWULoPzvkmd304Pu8vRueIKcC8KhxzNXpGrpnkWz3sYqRmvaekPyZvt5ngeSCk8TWEk8B1nbckvEDz0YXcMNnPoiosacblk4AHX6WXCRGfENBjREAw1BNYBLfmDBI1lZgtslgfvs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=YYhnnGI/; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="YYhnnGI/" Received: from pps.filterd (m0279864.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 54KGdm3O024656 for ; Tue, 20 May 2025 20:45:00 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= tanQOqYw0Cihj8lfa4clmi+xNJuQzns3UjTESaZfuxI=; b=YYhnnGI/6urAaUJt SIQ1bUssucmm9QNEHgHjq2IDhtaxgRuCNEtwhRGFy4mfaZ7n0b6qo4/RgQmxqj3T H/N5w3OcP44YEtf+GFyFkQzHiHYiXDx+h+SIFCfTEhKR7ja7rgKWPcZRMGCCvqAw rpZl9HjVPm5/25bh0d+e5CaQPpkq0ctlgffAIaO1a0Ht4+fhuhpYN5X29PA5bFIP mvgTnar1Xf4UK+65i1kxxZEN5G4bQl69K1ZpOGmRzk49RGTXvQROtWCnC6tSnn2H M/TKLER9Ja9cGB179eP96RSUYic+9Kx5CWstt2zW+3nqXKPvM4b7SgsAlszEzwUO gsWNbw== Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf30k2v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 20 May 2025 20:44:59 +0000 (GMT) Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-6f8bdefcb39so74176586d6.0 for ; Tue, 20 May 2025 13:44:59 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747773898; x=1748378698; 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=tanQOqYw0Cihj8lfa4clmi+xNJuQzns3UjTESaZfuxI=; b=NNiQw5DYCa8mVHXLL140Bfn43x1e1xGLDhSDRVgIvFbej7ntk1aE3X7ug/7akQOGXt Amo1hQNHLI3Yky4u9buUlcwxepoxD022XBsNsKxJO1Dy6qKM/njSWWUrFFWkSHC6mExB CRNFOETrL+Y14VxHKjGD7Ayg14Z5esESmsSilQI/gGKJMuqDfcZvBznPhmIFrJva/SmZ w/ilK/yk7pOB84LnHfh2mW9JpxCgNzz/nBV6+gICQLT7oaxZWwMqrm7XwOeupt68o1uB gVmunD9Jm2nCHN0e4QQDShsDJogrMj0eWk9lrvi28AfswJ/aR4zjEMasdvkM+X1SVo1x 7+8Q== X-Gm-Message-State: AOJu0YxHonhLxG/TEoBQ6mGhg3PMqMrr12aPr19+j2E9klGPaAhp0476 WlYn2RaEXlS9xInNbaA0ROb9rLMgdJJnQCZuid9pVge3vZolLJJiV1wCiFNE7SxcftG6+q5Bsgz AyDT/9EiExD8gVPWCbwEs01tafI+4rIxnBTXKOG47q8RLbyYmT3y79xKCTpvBqg8RKjA= X-Gm-Gg: ASbGncufcAOJ1yWqhN+65PxQ7nUsnlvMGxI43rQKfGlTynUvYVum7pg6aoWrrp1d3Un niXOMJ+juL0OnxNPruBZGKNxx3RcZhEBDHpetjbytkC6WEuLB9qb0GqO/OI2aXIYEjNYB6BjaEU AvQRvm+cto+9NNKM6tWxtuJNJH7qXU1hqt/AfeAzSJ6J22Xr2SfFa5w7Oo58+oWme9ebks37RRT pc93y3ynNe1x96L/jGlhLIWMWsAoYUXPxuGpld/sbdKNl7lulu++r9tr6Y5Dz94WjU2PZgBJFtr 5mbLrTRjqFbUiRuzwsyy9m6u6uim5v0kB1i5f/sL7QarzttZd8r8hsUQmDzyP/P0weuJfy3bbsP nn6YQPhE+oesN21xX6AVm8pS5 X-Received: by 2002:a05:6214:2481:b0:6f8:e208:2ff3 with SMTP id 6a1803df08f44-6f8e2083315mr84783866d6.3.1747773898573; Tue, 20 May 2025 13:44:58 -0700 (PDT) X-Google-Smtp-Source: AGHT+IHsmwNxdG/HYMxqSROppvUBzj8rzZOT8nKj3cJAd2Y9WI6WTWrLs2D6LA3ZQ5SDaLunJEwAYQ== X-Received: by 2002:a05:6214:2481:b0:6f8:e208:2ff3 with SMTP id 6a1803df08f44-6f8e2083315mr84783476d6.3.1747773898221; Tue, 20 May 2025 13:44:58 -0700 (PDT) Received: from umbar.lan (2001-14ba-a0c3-3a00-264b-feff-fe8b-be8a.rev.dnainternet.fi. [2001:14ba:a0c3:3a00:264b:feff:fe8b:be8a]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-550e6f163ccsm2497950e87.39.2025.05.20.13.44.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 13:44:56 -0700 (PDT) From: Dmitry Baryshkov Date: Tue, 20 May 2025 23:44:45 +0300 Subject: [PATCH v4 3/5] phy: qcom-uniphy: add more registers from display PHYs 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: <20250520-fd-hdmi-phy-v4-3-fcbaa652ad75@oss.qualcomm.com> References: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> In-Reply-To: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Vinod Koul , Kishon Vijay Abraham I Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org, Dmitry Baryshkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=2529; i=dmitry.baryshkov@oss.qualcomm.com; h=from:subject:message-id; bh=Dgc1ExVnp711AdXhWA9ncnFbHeGjGDWinEG7f2MOuNE=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBoLOnAVhF+aEhT/5ZT81bqALxrU41/0xO1XWmyf RZ0clayhAuJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCaCzpwAAKCRCLPIo+Aiko 1aqlB/wP43HCfQCLGS9i7ddYdAIIbjlSbr5UDLEkG3+Kk3jWOsbmMt3q5BY/ALb3NaTatSpTklk T6FqUtNTOP8ZBbL6ls1eecOO03aY9Q+bA085G1Z0KsRTxGLsjWvluDGqzvpogHCDV7fB1hBukoP 9ZYARb32vhuLXccFhoGMWJxfeR6+luUc0rGeQqDaj3tKV1Q7s2FcWRiRHpmEWvSxEzIlY51sqbw fPhYxUYKHlYziwUryEzNZsRStghA2Z91DbHB/u5N7QSyzeF21RGPeEqJjbwbarP2bwVEH4mrG4M ClWUCoxcZrWDEf8ObBzsu515WhCClUqzM2jB+cR/yu0N2jd9 X-Developer-Key: i=dmitry.baryshkov@oss.qualcomm.com; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-Proofpoint-ORIG-GUID: ZaL_kRrf2LrtEaQVnuuX1J6OqknLpal1 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIwMDE2OCBTYWx0ZWRfX4Jcau33TrflY MgFsLbVWFBBdOn9ybzKG4/SLm3GHHT5LZzVZYjv79S1pSV17UuvY03hIkCtuVMzG6pfCO+j/IT6 qet4JCsM6VMYAn9VrM0swETSwMjdaIlAOojAZcqoAjPpuGb5gFR3hpcI5/kyWS++QdRfH7iTTEr MXqp2kK24VpZqDSN21jqAdu1ozNltNDZPkva2R3puAAkGjHO8M/rfi8uQj2KmKldm3JZUlK8kzf bVud/aTWOSZsuQdFaaqKHmcpbVPjc56pcpCKStwbVn2hT9PpQMPnwEvdrfPaDyukRe5BUtgiVP5 TkdGNusNylGRAn+MftaL1RZTW9ZCZlfwsoEB+gO6mZWZl2yOydWU5ANQCzlokbId72mM55yIcbj PvsXCZ3kSmMf6iaOkcis1t+J30/rPyowuTIrinOEDgV55MS6XaqFwoki9uLT7J3mREJN+Pl5 X-Proofpoint-GUID: ZaL_kRrf2LrtEaQVnuuX1J6OqknLpal1 X-Authority-Analysis: v=2.4 cv=a9kw9VSF c=1 sm=1 tr=0 ts=682ce9cb cx=c_pps a=UgVkIMxJMSkC9lv97toC5g==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=dt9VzEwgFbYA:10 a=KKAkSRfTAAAA:8 a=EUspDBNiAAAA:8 a=UZIV0CQzuhujAGWTQQkA:9 a=QEXdDO2ut3YA:10 a=1HOtulTD9v-eNWfpl4qZ:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 definitions=2025-05-20_09,2025-05-20_03,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 clxscore=1015 priorityscore=1501 phishscore=0 mlxscore=0 lowpriorityscore=0 mlxlogscore=849 bulkscore=0 spamscore=0 adultscore=0 malwarescore=0 suspectscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 definitions=main-2505200168 From: Dmitry Baryshkov Import register definitions from 28nm DSI and HDMI PHYs, adding more UNI PHY registers. Signed-off-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov Reviewed-by: Neil Armstrong --- drivers/phy/qualcomm/phy-qcom-uniphy.h | 33 ++++++++++++++++++++++++++++++= +++ 1 file changed, 33 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-uniphy.h b/drivers/phy/qualcomm/= phy-qcom-uniphy.h index e5b79a4dc270f25d8979f51bf4acd6c76998032e..ce782018124b5431ee647575289= c963d8fd0de1f 100644 --- a/drivers/phy/qualcomm/phy-qcom-uniphy.h +++ b/drivers/phy/qualcomm/phy-qcom-uniphy.h @@ -8,8 +8,19 @@ =20 /* PHY registers */ #define UNIPHY_PLL_REFCLK_CFG 0x000 +#define UNIPHY_PLL_POSTDIV1_CFG 0x004 +#define UNIPHY_PLL_CHGPUMP_CFG 0x008 +#define UNIPHY_PLL_VCOLPF_CFG 0x00c +#define UNIPHY_PLL_VREG_CFG 0x010 #define UNIPHY_PLL_PWRGEN_CFG 0x014 +#define UNIPHY_PLL_DMUX_CFG 0x018 +#define UNIPHY_PLL_AMUX_CFG 0x01c #define UNIPHY_PLL_GLB_CFG 0x020 +#define UNIPHY_PLL_POSTDIV2_CFG 0x024 +#define UNIPHY_PLL_POSTDIV3_CFG 0x028 +#define UNIPHY_PLL_LPFR_CFG 0x02c +#define UNIPHY_PLL_LPFC1_CFG 0x030 +#define UNIPHY_PLL_LPFC2_CFG 0x034 #define UNIPHY_PLL_SDM_CFG0 0x038 #define UNIPHY_PLL_SDM_CFG1 0x03c #define UNIPHY_PLL_SDM_CFG2 0x040 @@ -22,11 +33,33 @@ #define UNIPHY_PLL_LKDET_CFG0 0x05c #define UNIPHY_PLL_LKDET_CFG1 0x060 #define UNIPHY_PLL_LKDET_CFG2 0x064 +#define UNIPHY_PLL_TEST_CFG 0x068 #define UNIPHY_PLL_CAL_CFG0 0x06c +#define UNIPHY_PLL_CAL_CFG1 0x070 +#define UNIPHY_PLL_CAL_CFG2 0x074 +#define UNIPHY_PLL_CAL_CFG3 0x078 +#define UNIPHY_PLL_CAL_CFG4 0x07c +#define UNIPHY_PLL_CAL_CFG5 0x080 +#define UNIPHY_PLL_CAL_CFG6 0x084 +#define UNIPHY_PLL_CAL_CFG7 0x088 #define UNIPHY_PLL_CAL_CFG8 0x08c #define UNIPHY_PLL_CAL_CFG9 0x090 #define UNIPHY_PLL_CAL_CFG10 0x094 #define UNIPHY_PLL_CAL_CFG11 0x098 +#define UNIPHY_PLL_EFUSE_CFG 0x09c +#define UNIPHY_PLL_DEBUG_BUS_SEL 0x0a0 +#define UNIPHY_PLL_CTRL_42 0x0a4 +#define UNIPHY_PLL_CTRL_43 0x0a8 +#define UNIPHY_PLL_CTRL_44 0x0ac +#define UNIPHY_PLL_CTRL_45 0x0b0 +#define UNIPHY_PLL_CTRL_46 0x0b4 +#define UNIPHY_PLL_CTRL_47 0x0b8 +#define UNIPHY_PLL_CTRL_48 0x0bc #define UNIPHY_PLL_STATUS 0x0c0 +#define UNIPHY_PLL_DEBUG_BUS0 0x0c4 +#define UNIPHY_PLL_DEBUG_BUS1 0x0c8 +#define UNIPHY_PLL_DEBUG_BUS2 0x0cc +#define UNIPHY_PLL_DEBUG_BUS3 0x0d0 +#define UNIPHY_PLL_CTRL_54 0x0d4 =20 #endif --=20 2.39.5 From nobody Fri Dec 19 11:32:35 2025 Received: from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com [205.220.168.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A34282135CB for ; Tue, 20 May 2025 20:45:02 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.168.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773904; cv=none; b=iX1N6vh+xT/nun359MV6Oo4Vhky5QhiKiw6NtBN1Sw7ISef0BLFE4db9Ytfhq1xr/Vond+7SMsJvljREmYh5thDJ+0WLk8REIe4kCvhLN45Ydx2lbFKkWYMARQ3JXiW0vAaR3mk8NMYTS6WY+GQXagdrMbYpTIivjSjXjy3udXM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773904; c=relaxed/simple; bh=Q3oxit2uXVirUmlDpxNZ/SA2JUKyyiPgFNu/v/Mfmpg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=XZNXEDxF4xjxLsrdASQIc6Pqbl1Mwc0cpURc2ZfkNzndP7dLoGIBygFuyyH0z/vBqtvSUU46ZmHw87welR7ornJ3c6baL+oXJT9wVaEbWP55tvfG+9mPyJt+/kGoPL1B9ZlZMnoe0qZNLArL4oRiQnMFyYsgO5KrFjcPCft39e4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=C3dJNNAR; arc=none smtp.client-ip=205.220.168.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="C3dJNNAR" Received: from pps.filterd (m0279866.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 54KGiveu020361 for ; Tue, 20 May 2025 20:45:02 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= /Sf2sU8QXkUGxm3P0AkiZVGagcMsU33MoJLUJ+ohpOA=; b=C3dJNNARlXSOF45i H5f1Pc01AsAAyW9FnJBGQaa+Up3p+aBetbxEkgSKJDGrsyURtLg/4gB4qkSGoByC 4dMaZWPNNMWc2mOw3sRPfbgiBIqJW4tehq2WT0U4crMb73sllQSp1jKJTCFEh/hD SgL2uvb+TpLv0SEBirrFnW7F2Lp1lVDm7sXThNAP20lRw3T3+cuSON9bAYceGGRn Gi4AZ4GWrSxUiWT/1hX3a3o7MFpr+wxPV6zBBOOQvEUyARhJN59gTcDU6rMwFlHm pmExE9Mh/h/LdJGyuMwlJ7K9hj5ZDs3vp6G0uH5ZGnf+0E2lx6RZX/1vnd/X2tkf 8bFqYw== Received: from mail-qv1-f69.google.com (mail-qv1-f69.google.com [209.85.219.69]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwh58kha-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 20 May 2025 20:45:01 +0000 (GMT) Received: by mail-qv1-f69.google.com with SMTP id 6a1803df08f44-6f8e1d900e5so31639386d6.2 for ; Tue, 20 May 2025 13:45:01 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747773900; x=1748378700; 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=/Sf2sU8QXkUGxm3P0AkiZVGagcMsU33MoJLUJ+ohpOA=; b=T08V65G2i2ek3x0GBrk8yeqoA2bB2km5noWkOHfb2bEMxl0ckQTWkl4yLAt6sVtFk6 1zYZ70rhFMj/RYSAtQV4gWcPrATIcXQoQaKWUtxBdUuFdoeBfObMeYkCU1ZCtJzdqsls K3kANWxRHhpjUWZ0t0qiyPd0+qJLpdwkZMTYGssxTtF322mnYFw1y344Uhr1Xvs5bQO8 9J0MXr5i0s+4XsIJN0TkPkvHZaxMflqnddJbeDOMicErvBq0xq9Nd5pYOnYndScbZL/+ UZ3kmXbSANChVvUQuJsEcE79lUioFiRRDWFWPKtsN+Y3+BSLZR0a19KlI+h51j6eXr70 OwjA== X-Gm-Message-State: AOJu0YwNlLHB/Ai9gZGb2k61B9rI/nf8tFyoiLNBNAkSovGzuIxWBNK8 uSmcGMQQMPnbNc2k5zlmr7S8Ro4wcIgn1WIYmopF2Dz9bGLH+Jgro5lKpl+lHLuydSpM03DuBED xZ8UJ2JQhDTAMw4VrZrrr9HemgpXZxXfUVfIclADZYs1GJ7qHkpLycgEOr+yDBEv0kFc= X-Gm-Gg: ASbGncuqcCFaE0rrP15RztihVNhbv+J+M6rSaa1f74sVqsCthn8/QUT5HR5d1hlEXjX iBO4wTq5AvSOOxZ6gtZoLvQhLY9GM4fh6wYSRWgYy/gBn9HwN5R3Us9a0JfCEyGWgfTSVdAk5D8 CLb23O0JzYwuNhiEhzrFrwpV2MpPlJZTd/YaO8d1zpwldDSXcMgRIFhokT/l7B0QCeZsJsj647N hZ1P5ns+En5B0TQ7emgVz8zCelbQ3Ja9juRE20acKgK68NMuu2mwvqGrr6TJwPOZ4tw0TiqOZOO U+AfBlUEMG0hH+jmuI/Mn92cVaIvkUPrwrskBSP5mRAQceayLsyuQPxj15iTAMBu+aToRTPHIZH VLPjEaqynnv75EtXslAsgBXzl X-Received: by 2002:a05:6214:c44:b0:6f4:cbcf:5d46 with SMTP id 6a1803df08f44-6f8b08abafamr270835876d6.20.1747773900276; Tue, 20 May 2025 13:45:00 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEkl3tYdKo+pWUTiMv0OZy1z1/H2i6Pu6K1fr3RwR2mOhW5QPjQAgjsg8qK75X0E913s7m2+A== X-Received: by 2002:a05:6214:c44:b0:6f4:cbcf:5d46 with SMTP id 6a1803df08f44-6f8b08abafamr270835476d6.20.1747773899749; Tue, 20 May 2025 13:44:59 -0700 (PDT) Received: from umbar.lan (2001-14ba-a0c3-3a00-264b-feff-fe8b-be8a.rev.dnainternet.fi. [2001:14ba:a0c3:3a00:264b:feff:fe8b:be8a]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-550e6f163ccsm2497950e87.39.2025.05.20.13.44.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 13:44:58 -0700 (PDT) From: Dmitry Baryshkov Date: Tue, 20 May 2025 23:44:46 +0300 Subject: [PATCH v4 4/5] phy: qualcomm: add MSM8974 HDMI PHY support 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: <20250520-fd-hdmi-phy-v4-4-fcbaa652ad75@oss.qualcomm.com> References: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> In-Reply-To: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Vinod Koul , Kishon Vijay Abraham I Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org, Dmitry Baryshkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=9501; i=dmitry.baryshkov@oss.qualcomm.com; h=from:subject:message-id; bh=OLeHIuWSpgzTAy71HK+ckC1M4XfY8GW2xAOao+NEl5g=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBoLOnADZDprVDGwWXUwTqicXYzKiBiMS6cMbgwJ 0tObEbYNeaJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCaCzpwAAKCRCLPIo+Aiko 1VvnCACIHW4tm/rezTFxV5k0KC6tY8sIjJ7QP1EMNHSIUVA+jtHmBlgKw3r9wH5v5e02UVI+/ai SqiBYVgiFNbA3ntKgZAaT9VH8zB0mXG/VGhzGyLn6zjSQkxtggwlj7Z5VRV6XrTOCGUZXDri1vX wIkOC9Mq4QWADyueq0S0PN6i0DiaEDO5276irvv9z92cm4c5rEf/meJU1nZF1N2IMMdBjpCMsup jJ8299G1xEom+XFhhCQHYTxPTE+dW5E7v6sY8oJ8QAgBu20vR+O6OSLR1EI4IUAEbVm9szcGwyt dI+B3+gyYpCcbwhEuinCGbARHJCh0Qjdls1o08l1Rh0GJXPT X-Developer-Key: i=dmitry.baryshkov@oss.qualcomm.com; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIwMDE2OCBTYWx0ZWRfX9lVn3BvnWSkm kJRNFimcEc9S3E3W1z/4SZj8NRt/YZ8shGzkhyJyxXk7Gy2eWnSdlVyW4dUd51U0TK+hpN+8v+U 8x6U2KeW9EjcQHulR9RQWF3/DOxuXQZ9fWV1KQ1QyP5d/NTGbnsNO1ggtcrJn1eFKzyUsV/H0W9 TbvFBmKI30fBaT/BQbbZbtT4u7DJq43JoQ5PwdtAa6mCpGwxnH7cjWH9fEYsYzEP7joUDMLZp7V ZqKPrOrCVU1ehdHT+XR7yhdB2dJjOpuXBoPvoR1PEL+jd4oYGPI8jJZMXRAay+yzVTK0Az+eKrx +WUwYc1gdxH0Zn/nobjNgWZAUbcPRg0XRHt/OljlbYwaPGjNLHyiunKBSrK+XNGt5sXXmaIzEJQ 0XPjp24hFma+D4F9/KsYuHMyFAZfR0r3pjnT8Ez3Zbc9yX5JP0XRTGzp+NW4vvYryFNX7y0Q X-Authority-Analysis: v=2.4 cv=XeWJzJ55 c=1 sm=1 tr=0 ts=682ce9cd cx=c_pps a=wEM5vcRIz55oU/E2lInRtA==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=dt9VzEwgFbYA:10 a=KKAkSRfTAAAA:8 a=EUspDBNiAAAA:8 a=wq9x00DRF7jIeu_RijoA:9 a=QEXdDO2ut3YA:10 a=OIgjcC2v60KrkQgK7BGD:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-GUID: IzsS4YbDb6hCAn5AVLRgTV5pcG4Ki4YA X-Proofpoint-ORIG-GUID: IzsS4YbDb6hCAn5AVLRgTV5pcG4Ki4YA X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 definitions=2025-05-20_09,2025-05-20_03,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 clxscore=1015 mlxlogscore=840 mlxscore=0 bulkscore=0 spamscore=0 suspectscore=0 impostorscore=0 adultscore=0 malwarescore=0 lowpriorityscore=0 priorityscore=1501 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 definitions=main-2505200168 From: Dmitry Baryshkov Add support for HDMI PHY on Qualcomm MSM8974 / APQ8074 platforms. Signed-off-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov --- drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c | 259 +++++++++++++++++++++++++= ++++ 1 file changed, 259 insertions(+) diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c b/drivers/phy/qualc= omm/phy-qcom-hdmi-28hpm.c index db7fa2df1a369d3889daab922c21ed8b71d733be..059afe5504639e65ef4e0c5f09e= ee9615f1413c1 100644 --- a/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c @@ -10,6 +10,7 @@ #include =20 #include "phy-qcom-hdmi-preqmp.h" +#include "phy-qcom-uniphy.h" =20 #define REG_HDMI_8x74_ANA_CFG0 0x00000000 #define REG_HDMI_8x74_ANA_CFG1 0x00000004 @@ -31,8 +32,261 @@ #define REG_HDMI_8x74_BIST_PATN3 0x00000048 #define REG_HDMI_8x74_STATUS 0x0000005c =20 +#define HDMI_8974_VCO_MAX_FREQ 1800000000UL +#define HDMI_8974_VCO_MIN_FREQ 600000000UL + +#define HDMI_8974_COMMON_DIV 5 + +static void qcom_uniphy_setup(void __iomem *base, unsigned int ref_freq, + bool sdm_mode, + bool ref_freq_mult_2, + bool dither, + unsigned int refclk_div, + unsigned int vco_freq) +{ + unsigned int int_ref_freq =3D ref_freq * (ref_freq_mult_2 ? 2 : 1); + unsigned int div_in_freq =3D vco_freq / refclk_div; + unsigned int dc_offset =3D div_in_freq / int_ref_freq - 1; + unsigned int sdm_freq_seed; + unsigned int val; + unsigned int remain =3D div_in_freq - (dc_offset + 1) * int_ref_freq; + + sdm_freq_seed =3D mult_frac(remain, 0x10000, int_ref_freq); + + val =3D (ref_freq_mult_2 ? BIT(0) : 0) | + ((refclk_div - 1) << 2); + writel(val, base + UNIPHY_PLL_REFCLK_CFG); + + writel(sdm_mode ? 0 : 0x40 + dc_offset, base + UNIPHY_PLL_SDM_CFG0); + + writel(dither ? 0x40 + dc_offset : 0, base + UNIPHY_PLL_SDM_CFG1); + + writel(sdm_freq_seed & 0xff, base + UNIPHY_PLL_SDM_CFG2); + + writel((sdm_freq_seed >> 8) & 0xff, base + UNIPHY_PLL_SDM_CFG3); + + writel(sdm_freq_seed >> 16, base + UNIPHY_PLL_SDM_CFG4); + + ref_freq =3D ref_freq * 5 / 1000; + writel(ref_freq & 0xff, base + UNIPHY_PLL_CAL_CFG8); + + writel(ref_freq >> 8, base + UNIPHY_PLL_CAL_CFG9); + + vco_freq /=3D 1000; + writel(vco_freq & 0xff, base + UNIPHY_PLL_CAL_CFG10); + + writel(vco_freq >> 8, base + UNIPHY_PLL_CAL_CFG11); +} + +static unsigned long qcom_uniphy_recalc(void __iomem *base, unsigned long = parent_rate) +{ + unsigned long rate; + u32 refclk_cfg; + u32 dc_offset; + u64 fraq_n; + u32 val; + + refclk_cfg =3D readl(base + UNIPHY_PLL_REFCLK_CFG); + if (refclk_cfg & BIT(0)) + parent_rate *=3D 2; + + val =3D readl(base + UNIPHY_PLL_SDM_CFG0); + if (val & 0x40) { + dc_offset =3D val & 0x3f; + fraq_n =3D 0; + } else { + dc_offset =3D readl(base + UNIPHY_PLL_SDM_CFG1) & 0x3f; + fraq_n =3D readl(base + UNIPHY_PLL_SDM_CFG2) | + (readl(base + UNIPHY_PLL_SDM_CFG3) << 8); + } + + rate =3D (dc_offset + 1) * parent_rate; + rate +=3D mult_frac(fraq_n, parent_rate, 0x10000); + + rate *=3D (refclk_cfg >> 2) * 0x3 + 1; + + return rate; +} + +static const unsigned int qcom_hdmi_8974_divs[] =3D {1, 2, 4, 6}; + +static unsigned long qcom_hdmi_8974_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy =3D hw_clk_to_phy(hw); + u32 div_idx =3D hdmi_pll_read(hdmi_phy, UNIPHY_PLL_POSTDIV1_CFG); + unsigned long rate =3D qcom_uniphy_recalc(hdmi_phy->pll_reg, parent_rate); + + return rate / HDMI_8974_COMMON_DIV / qcom_hdmi_8974_divs[div_idx & 0x3]; +} + +static long qcom_hdmi_8974_pll_round_rate(struct clk_hw *hw, unsigned long= rate, + unsigned long *parent_rate) +{ + return clamp(rate, + HDMI_8974_VCO_MIN_FREQ / HDMI_8974_COMMON_DIV / 6, + HDMI_8974_VCO_MAX_FREQ / HDMI_8974_COMMON_DIV / 1); +} + +static const struct clk_ops qcom_hdmi_8974_pll_ops =3D { + .recalc_rate =3D qcom_hdmi_8974_pll_recalc_rate, + .round_rate =3D qcom_hdmi_8974_pll_round_rate, +}; + +static int qcom_hdmi_msm8974_phy_find_div(unsigned long long pixclk) +{ + int i; + unsigned long long min_freq =3D HDMI_8974_VCO_MIN_FREQ / HDMI_8974_COMMON= _DIV; + + if (pixclk > HDMI_8974_VCO_MAX_FREQ / HDMI_8974_COMMON_DIV) + return -E2BIG; + + for (i =3D 0; i < ARRAY_SIZE(qcom_hdmi_8974_divs); i++) { + if (pixclk >=3D min_freq / qcom_hdmi_8974_divs[i]) + return i; + } + + return -EINVAL; +} + +static int qcom_hdmi_msm8974_phy_pll_set_rate(struct qcom_hdmi_preqmp_phy = *hdmi_phy) +{ + unsigned long long pixclk =3D hdmi_phy->hdmi_opts.tmds_char_rate; + unsigned long vco_rate; + unsigned int div; + int div_idx =3D 0; + + div_idx =3D qcom_hdmi_msm8974_phy_find_div(pixclk); + if (WARN_ON(div_idx < 0)) + return div_idx; + + div =3D qcom_hdmi_8974_divs[div_idx]; + vco_rate =3D pixclk * HDMI_8974_COMMON_DIV * div; + + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_GLB_CFG, 0x81); + + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_GLB_CFG, 0x01); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_VCOLPF_CFG, 0x19); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_LPFR_CFG, 0x0e); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_LPFC1_CFG, 0x20); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_LPFC2_CFG, 0x0d); + + qcom_uniphy_setup(hdmi_phy->pll_reg, 19200000, true, true, true, 1, vco_r= ate); + + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_LKDET_CFG0, 0x10); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_LKDET_CFG1, 0x1a); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_LKDET_CFG2, 0x05); + + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_POSTDIV1_CFG, div_idx); + + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_POSTDIV2_CFG, 0x00); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_POSTDIV3_CFG, 0x00); + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_CAL_CFG2, 0x01); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_PD_CTRL0, 0x1f); + udelay(50); + + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_GLB_CFG, 0x0f); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_PD_CTRL1, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG2, 0x10); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG0, 0xdb); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG1, 0x43); + if (pixclk =3D=3D 297000) { + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG2, 0x06); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG3, 0x03); + } else if (pixclk =3D=3D 268500) { + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG2, 0x05); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG3, 0x00); + } else { + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG2, 0x02); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG3, 0x00); + } + + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_VREG_CFG, 0x04); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_DCC_CFG0, 0xd0); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_DCC_CFG1, 0x1a); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_TXCAL_CFG0, 0x00); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_TXCAL_CFG1, 0x00); + + if (pixclk =3D=3D 268500) + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_TXCAL_CFG2, 0x11); + else + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_TXCAL_CFG2, 0x02); + + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_TXCAL_CFG3, 0x05); + udelay(200); + + return 0; +} + +static int qcom_hdmi_msm8974_phy_pll_enable(struct qcom_hdmi_preqmp_phy *h= dmi_phy) +{ + int ret; + unsigned long status; + + /* Global enable */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_GLB_CFG, 0x81); + + /* Power up power gen */ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_PD_CTRL0, 0x00); + udelay(350); + + /* PLL power up */ + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_GLB_CFG, 0x01); + udelay(5); + + /* Power up PLL LDO */ + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_GLB_CFG, 0x03); + udelay(350); + + /* PLL power up */ + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_GLB_CFG, 0x0f); + udelay(350); + + /* Poll for PLL ready status */ + ret =3D readl_poll_timeout(hdmi_phy->pll_reg + UNIPHY_PLL_STATUS, + status, status & BIT(0), + 100, 2000); + if (ret) { + dev_warn(hdmi_phy->dev, "HDMI PLL not ready\n"); + goto err; + } + + udelay(350); + + /* Poll for PHY ready status */ + ret =3D readl_poll_timeout(hdmi_phy->phy_reg + REG_HDMI_8x74_STATUS, + status, status & BIT(0), + 100, 2000); + if (ret) { + dev_warn(hdmi_phy->dev, "HDMI PHY not ready\n"); + goto err; + } + + return 0; + +err: + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_GLB_CFG, 0); + udelay(5); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_GLB_CFG, 0); + + return ret; +} + static int qcom_hdmi_msm8974_phy_power_on(struct qcom_hdmi_preqmp_phy *hdm= i_phy) { + int ret; + + ret =3D qcom_hdmi_msm8974_phy_pll_set_rate(hdmi_phy); + if (ret) + return ret; + + ret =3D qcom_hdmi_msm8974_phy_pll_enable(hdmi_phy); + if (ret) + return ret; + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG0, 0x1b); hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_ANA_CFG1, 0xf2); hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_BIST_CFG0, 0x0); @@ -49,6 +303,10 @@ static int qcom_hdmi_msm8974_phy_power_off(struct qcom_= hdmi_preqmp_phy *hdmi_phy { hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_PD_CTRL0, 0x7f); =20 + hdmi_pll_write(hdmi_phy, UNIPHY_PLL_GLB_CFG, 0); + udelay(5); + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_GLB_CFG, 0); + return 0; } =20 @@ -67,5 +325,6 @@ const struct qcom_hdmi_preqmp_cfg msm8974_hdmi_phy_cfg = =3D { .power_on =3D qcom_hdmi_msm8974_phy_power_on, .power_off =3D qcom_hdmi_msm8974_phy_power_off, =20 + .pll_ops =3D &qcom_hdmi_8974_pll_ops, .pll_parent =3D &msm8974_hdmi_pll_parent, }; --=20 2.39.5 From nobody Fri Dec 19 11:32:35 2025 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27DB325392A for ; Tue, 20 May 2025 20:45:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773907; cv=none; b=j6gutIYWmHZkJtCnbD1iEj1PQeFqpzyCHOv6uTkNG8+SXZQn2Dg1du/DEuhUPEMuKTCRzn7IpuSgYv2YdCUsyUTcvMhE1CVuCGq9Om9/e6CaaXfguFSKlvV2SSoX9h7SkpsCmuqbLPkdGPd6503f8uE54nIeYe/8e5DbetVIAvM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1747773907; c=relaxed/simple; bh=2rkm+Wp7Nl4ACvy6m/jS4aFH9nSpfuEADUOy2QXan5E=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gV99m8mzaLL7Akv8FoDmU1X+Akfc4ROXGTMpIILCJ25Lwag40JhOpf4WgVvnBdfjaCBDKHpciNeimThW/8oVao8LDN1EpGnwxA0PNhoICEMukEFAt1eYS+hCwOgW9U/0xzohD1Fw4VmP7BCeSXPss3s53q4S1a9IMnO0ebgFbLA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=SOAPUelp; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="SOAPUelp" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.2/8.18.1.2) with ESMTP id 54KGe0s4000729 for ; Tue, 20 May 2025 20:45:04 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:in-reply-to :message-id:mime-version:references:subject:to; s=qcppdkim1; bh= Y/rh0R9tpWXVkxE39YDI+lWvwLBDn4zQLtiVh5brNaE=; b=SOAPUelpGbGtypJB hPxO58k2OGOH+FEK4nk/NuyXQZySNnMMptQyMHZQRQSutNp/Az8yqf8cKCSxTCfl Nw7C0sjhRLYswNc5K4wLpknUUwWCMwNYjexmqYuPi8GaWYQYrk1ERsQ4QQqUiJmN +6Q1wEKc3OZ+0jso5a8cpwpJgTbW5gDjo64qEVffQyD3RnHIL7+50xR52CO8OIel 8TUyyX0ibxFcB6bT5q8EqXHe9woyW/cDceVTQEdz3qArQypIU3v4/rUm8Oi7LG/l NkxCRbuQqu8MvZe1q9jcVkKKuRol2oHiCQjkXG6AAwh/8uIkKWgXd1aw6lOvJrby oC4TZQ== Received: from mail-qv1-f71.google.com (mail-qv1-f71.google.com [209.85.219.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 46rwf4rjgn-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=NOT) for ; Tue, 20 May 2025 20:45:03 +0000 (GMT) Received: by mail-qv1-f71.google.com with SMTP id 6a1803df08f44-6f8dbab898cso53399926d6.3 for ; Tue, 20 May 2025 13:45:03 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1747773902; x=1748378702; 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=Y/rh0R9tpWXVkxE39YDI+lWvwLBDn4zQLtiVh5brNaE=; b=UmzW2Uu8oQfZB1BJoGjQdv+cYLC4vfKIeVa8Gw2hiCTRXa6LpWhyhfZyivAFbiKhBm SD+sbfXpmxxJRgfq+cRgQGNKcsJitM/6QaVoE7e1WdfeLiz8iOTHeFwmRV8G76HHKQN8 Nutp9qnchWXUNabFeTob03F+Klmfoo5DuQYk1ovVD8YLCqK9hqytU9SpFTQYoLTdR4f+ rD4jOorwLM+jAsGPzYQcUctM6aebY2kuGoXv8PLoNMUk9dohsNHPW71y9c5Ed283Z3sv 7COLvbSpl7Ysx93Eg2cO5RokvX4x21VhCyenBBCl7KoZPuBiBtWv3XQ61nxuKII6nEH6 4voQ== X-Gm-Message-State: AOJu0YyGV7Wvc+W022K6rttdX7TKh+77hL+YGBv1E5lIFueE4fllPzEs kEIBWBRIrgdrhv2h+cwjmrGvomUiTLY/8GHRSbgISNUPdjtGfCPABYNviJWReNjP5ShuzLr3NkM AbpKAWGK1L6Y74sYESFxZMU4lq10ZnKx72cAMYhJaVM+GqrcMHV0+K/N6htas7wVSxVCGXMjcYu huPA== X-Gm-Gg: ASbGncu0gxzKL8YmpPTtRnDPyDFwjarJiI+FqmIZC0dOnLnooQcLGoIeon9ZMx2THXT qI/VkihR+P8363mCIky+XqNaPgVp2sw90vqQcjRiXLTyJaKwWUe2cB44+UIyyGGN7YiBJConbku rMRYZ0hqPG1E8mNIQQfOMOVNtyvPvmlqbymk1yPxdfxNGO/tPmpkj4X4+9Pkc0GIKwY+YX1guhh 7d5+X5kSsT65UwuaXD9kDk0Ua0n7t6OGoR7I7WGTrV1LOkGZK3RPh680VgQ+/bTikoiZCYB6iSS 8Dm14K0PLiyu7hRsBor95dtB/OxeZne/Mkg2XZ5sL/BGambM2YoOpvdoU7z9PMPXMHIoF4WHxHR 4p3u9SuRLahdiQZ2OCJoe3Lbm X-Received: by 2002:ad4:5aa3:0:b0:6f5:108b:d857 with SMTP id 6a1803df08f44-6f8b2d15707mr299977796d6.36.1747773902115; Tue, 20 May 2025 13:45:02 -0700 (PDT) X-Google-Smtp-Source: AGHT+IEkMvApU27Xi4DNOxe5crEMOlpgPH/pnPyGO4WWWAxbN7fBy9SXWfkDLDONqPA4GCt5J3jrnQ== X-Received: by 2002:ad4:5aa3:0:b0:6f5:108b:d857 with SMTP id 6a1803df08f44-6f8b2d15707mr299977326d6.36.1747773901654; Tue, 20 May 2025 13:45:01 -0700 (PDT) Received: from umbar.lan (2001-14ba-a0c3-3a00-264b-feff-fe8b-be8a.rev.dnainternet.fi. [2001:14ba:a0c3:3a00:264b:feff:fe8b:be8a]) by smtp.gmail.com with ESMTPSA id 2adb3069b0e04-550e6f163ccsm2497950e87.39.2025.05.20.13.44.59 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 May 2025 13:45:00 -0700 (PDT) From: Dmitry Baryshkov Date: Tue, 20 May 2025 23:44:47 +0300 Subject: [PATCH v4 5/5] drm/msm/registers: drop HDMI PHY register definitions 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: <20250520-fd-hdmi-phy-v4-5-fcbaa652ad75@oss.qualcomm.com> References: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> In-Reply-To: <20250520-fd-hdmi-phy-v4-0-fcbaa652ad75@oss.qualcomm.com> To: Rob Clark , Abhinav Kumar , Dmitry Baryshkov , Sean Paul , Marijn Suijten , David Airlie , Simona Vetter , Vinod Koul , Kishon Vijay Abraham I Cc: linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org, Dmitry Baryshkov X-Mailer: b4 0.14.2 X-Developer-Signature: v=1; a=openpgp-sha256; l=26257; i=dmitry.baryshkov@oss.qualcomm.com; h=from:subject:message-id; bh=y0P+Hi9CyYTcC6PcuG/EtvjloSg7WanVzhX7D03Rjfg=; b=owEBbQGS/pANAwAKAYs8ij4CKSjVAcsmYgBoLOnAQ7no4d2pdpxIEt/nWMMfhRF+26sn5U0kY son5RY97zuJATMEAAEKAB0WIQRMcISVXLJjVvC4lX+LPIo+Aiko1QUCaCzpwAAKCRCLPIo+Aiko 1Y4YB/sEc+uBNhgUOOp+kWd4YLVj4tVbFb0zxXYOctedArsaUxwgqAjXDSsWbekceFYhLAZUR8l Ttp5El861o3iEIJg5Pfm3QEQ/8BvI/nZarP8qASI2rYEF2EsZiReiOIooatgL62GR5GTCceAqsV WySI0vtQEdDob3vN/ph+T889W0qH4Mz7v+7Yze/RxSp9lF27uMytauA6XoNSVxCmgpGD3hZEx/j mHysIV0jSgQ34P6iwl62rWdWBWFNQmbRiFuzf14DtCQrM2CFsIE+WdB8n4M/CQ5pUm7j8FAnMK3 5nqE/4V8y1MXizBp/7WYd7CBNMMxWWJiTMnZvAb2KakW6kEi X-Developer-Key: i=dmitry.baryshkov@oss.qualcomm.com; a=openpgp; fpr=8F88381DD5C873E4AE487DA5199BF1243632046A X-Proofpoint-GUID: 20F2dWtUAJTtwgyOU-P5LsaZ3C578CRv X-Proofpoint-ORIG-GUID: 20F2dWtUAJTtwgyOU-P5LsaZ3C578CRv X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwNTIwMDE2NyBTYWx0ZWRfX0Th3O/9Fongi mFPTHptUm7hCCJX4rwMBw1gOKkX4MEM78b3nzeYhT4Myi/wRKnzJgpIjk25W1KEPkVrv6Z39YYL 0fsAaSdclxsZrsX/YpfDKSHTe1yfaQoz57qt2EB19xx0Dc5hvr2J/FMM721pHqgzqVlZ5DQGjLM DzVw8YGRe5bgDyx4QRAALtj5ArVzP2b26oVxLHkKFpvs3yNYun4rM/BYJ4zUnnOBoHYuUk5pnUl mUFX0CG4BHkghmx9cLD8bL+JH+IRxEZRSbUTrnTrUUPpKmq8uYLfeSBoz8DCtEqxn6IWhtx4VP5 JGAhx9lJrPpLyhEW8tCoEZD8N1p42iZGjoJ6syS3a3a5is5w/a0MohZDG0WLLCxefMblFVkmJIi +pGtpE5XeBTsE73FGZBiaajycEZg9XFSIGloBmlW1kiw5dIykMO+X4DYTRAaBJJ+ueIvNAgX X-Authority-Analysis: v=2.4 cv=R7UDGcRX c=1 sm=1 tr=0 ts=682ce9cf cx=c_pps a=UgVkIMxJMSkC9lv97toC5g==:117 a=xqWC_Br6kY4A:10 a=IkcTkHD0fZMA:10 a=dt9VzEwgFbYA:10 a=e5mUnYsNAAAA:8 a=KKAkSRfTAAAA:8 a=EUspDBNiAAAA:8 a=BGUQ00EFi6mp_B5OqyUA:9 a=QEXdDO2ut3YA:10 a=1HOtulTD9v-eNWfpl4qZ:22 a=Vxmtnl_E_bksehYqCbjh:22 a=cvBusfyB2V15izCimMoJ:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.0.736,FMLib:17.12.80.40 definitions=2025-05-20_09,2025-05-20_03,2025-03-28_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 phishscore=0 clxscore=1015 mlxlogscore=999 priorityscore=1501 spamscore=0 bulkscore=0 lowpriorityscore=0 malwarescore=0 suspectscore=0 mlxscore=0 impostorscore=0 adultscore=0 classifier=spam authscore=0 authtc=n/a authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.19.0-2505160000 definitions=main-2505200167 From: Dmitry Baryshkov With the HDMI PHYs migrated to the generic PHY subsystem and to a separate drivers there is no point in keeping HDMI PHY registers in the drm/msm database, drop them. Signed-off-by: Dmitry Baryshkov Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/registers/display/hdmi.xml | 537 ---------------------= ---- 1 file changed, 537 deletions(-) diff --git a/drivers/gpu/drm/msm/registers/display/hdmi.xml b/drivers/gpu/d= rm/msm/registers/display/hdmi.xml index 0ebb96297dae80940dc8a918d26cd58ff2e6f81a..1d44aa26c833708ee910e3bf4c2= 9fd52ec5f6d0c 100644 --- a/drivers/gpu/drm/msm/registers/display/hdmi.xml +++ b/drivers/gpu/drm/msm/registers/display/hdmi.xml @@ -564,541 +564,4 @@ xsi:schemaLocation=3D"https://gitlab.freedesktop.org/= freedreno/ rules-fd.xsd"> =20 =20 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --=20 2.39.5