From patchwork Thu Sep 28 11:16:15 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402742 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5EC30E732C4 for ; Thu, 28 Sep 2023 11:18:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232152AbjI1LSi (ORCPT ); Thu, 28 Sep 2023 07:18:38 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39128 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232165AbjI1LS1 (ORCPT ); Thu, 28 Sep 2023 07:18:27 -0400 Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B79A37EEA for ; Thu, 28 Sep 2023 04:16:33 -0700 (PDT) Received: by mail-lf1-x134.google.com with SMTP id 2adb3069b0e04-50482ba2b20so3134555e87.1 for ; Thu, 28 Sep 2023 04:16:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899792; x=1696504592; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=+rAzb42lEaywWSTeyGfFqSgOOBaQCtyh9GaKNsjXvNc=; b=hUI3HaiZ4V5YNtEG4QpmBn3Jcym92VvL6jiFcPV6jKdy1baaFy7mzpVx/BGa+SIFTP /CGVtnW12FOBDCWpMdIFVxrbjSVBX05ecKOKTPhKmwStHlrGOdcMNskdaeaA9rSMGRBy lVr3mPsaTPoZaKp8F64h+oFQq/2YaiiaPAL0VqZmMTqZ1vjRjCBjh6HBHfmTP6De/ZgW 0MBTu2l3+lWPoXl44Vsi3R3fVKYNSo19F0U2+iF4lSp8KFJCdz1+dmoKikmQXi5TSCzf 3EWr8dXCd6y949poKVDhbYXG1BkEvr/rBcAYmBG4vV2EFDQ2C+ylootdEnclPwjHv4VS Iwjw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899792; x=1696504592; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=+rAzb42lEaywWSTeyGfFqSgOOBaQCtyh9GaKNsjXvNc=; b=kNbR3BVuQuArWlYRp926fOqCFY1blpYjfGa1yqfoYiTemiPCUqR9SzVH/hs44wA0Ns IX/QmO3UW+GAWbrZF/cR9GqaAHm2LxnKf6xa0u+Fbl+6HcacPlqxSFWQYsKDFzTE2aXK LST3/Ey/hMcgPFWfhwFqzLtT0qjQvdSKJg+oeARXiFEfkLqDv86rQbA4Gz2oNi8NV3Y0 OOY7wtMRWFqU/R1yrZkVMPqd7yamVbf952dzHyt7KdbGGcFCmWGNhQ7E8gb0YSr1zIxs Sc1arWADtLpq9Q903XjOSfE4axq7uTIhB0sSHHx8H2HyYqNisjA+F21lnBkZyaAKEuHs iwvg== X-Gm-Message-State: AOJu0Yx7uwxWPxpbchW03T8U+dwf0SqUqbhalJZF0OMtZUZCBUxhyELn bo2psC8GnyShhIfiKkh9Wecsbw== X-Google-Smtp-Source: AGHT+IGcjUHlLCx60PubBWC2qag96N6Bg3aeeKUItjtSZFizOGfELXbcnLll0+B3oNQkBsV8BKWQ3w== X-Received: by 2002:a05:6512:1192:b0:501:bf37:262a with SMTP id g18-20020a056512119200b00501bf37262amr736122lfr.32.1695899792013; Thu, 28 Sep 2023 04:16:32 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:31 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org, Sandor Yu Subject: [PATCH v3 01/15] phy: Add HDMI configuration options Date: Thu, 28 Sep 2023 14:16:15 +0300 Message-Id: <20230928111630.1217419-2-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org From: Sandor Yu Allow HDMI PHYs to be configured through the generic functions through a custom structure added to the generic union. The parameters added here are based on HDMI PHY implementation practices. The current set of parameters should cover the potential users. Signed-off-by: Sandor Yu Reviewed-by: Dmitry Baryshkov --- include/linux/phy/phy-hdmi.h | 24 ++++++++++++++++++++++++ include/linux/phy/phy.h | 7 ++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 include/linux/phy/phy-hdmi.h diff --git a/include/linux/phy/phy-hdmi.h b/include/linux/phy/phy-hdmi.h new file mode 100644 index 000000000000..b7de88e9090f --- /dev/null +++ b/include/linux/phy/phy-hdmi.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2022 NXP + */ + +#ifndef __PHY_HDMI_H_ +#define __PHY_HDMI_H_ + +#include +/** + * struct phy_configure_opts_hdmi - HDMI configuration set + * @pixel_clk_rate: Pixel clock of video modes in KHz. + * @bpc: Maximum bits per color channel. + * @color_space: Colorspace in enum hdmi_colorspace. + * + * This structure is used to represent the configuration state of a HDMI phy. + */ +struct phy_configure_opts_hdmi { + unsigned int pixel_clk_rate; + unsigned int bpc; + enum hdmi_colorspace color_space; +}; + +#endif /* __PHY_HDMI_H_ */ diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index f6d607ef0e80..94d489a8a163 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -42,7 +43,8 @@ enum phy_mode { PHY_MODE_MIPI_DPHY, PHY_MODE_SATA, PHY_MODE_LVDS, - PHY_MODE_DP + PHY_MODE_DP, + PHY_MODE_HDMI, }; enum phy_media { @@ -60,11 +62,14 @@ enum phy_media { * the DisplayPort protocol. * @lvds: Configuration set applicable for phys supporting * the LVDS phy mode. + * @hdmi: Configuration set applicable for phys supporting + * the HDMI phy mode. */ union phy_configure_opts { struct phy_configure_opts_mipi_dphy mipi_dphy; struct phy_configure_opts_dp dp; struct phy_configure_opts_lvds lvds; + struct phy_configure_opts_hdmi hdmi; }; /** From patchwork Thu Sep 28 11:16:16 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402746 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B4E2FE732C5 for ; Thu, 28 Sep 2023 11:18:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232080AbjI1LSk (ORCPT ); Thu, 28 Sep 2023 07:18:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39258 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232058AbjI1LS2 (ORCPT ); Thu, 28 Sep 2023 07:18:28 -0400 Received: from mail-lf1-x133.google.com (mail-lf1-x133.google.com [IPv6:2a00:1450:4864:20::133]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id EF5897EEF for ; Thu, 28 Sep 2023 04:16:34 -0700 (PDT) Received: by mail-lf1-x133.google.com with SMTP id 2adb3069b0e04-50336768615so21756099e87.0 for ; Thu, 28 Sep 2023 04:16:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899793; x=1696504593; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FpKdF8Qb8AWN6GLwYn2vjDdAak/Nn9GdqYJddmG7YNI=; b=UOaql8BYqOmzxpGrIAx6pgkPjIXY3QiY8wBCYUmDTNT4HuNnEKWAvPXskyDU/w8EgM UjQleXAEZWS5PZpoN54RwGTYNn8FVnaMHDM91jbHRMK3cPL9tbfOKyXwvXFLxTQqjtcn VnfXoq7nfRteVo63+hZGdqQ1jh8Hs4F0aWtgJpUeJpQr+Zj6rtp0Ps0K4u2XaEcce0Pj 40Kn6YMfnNEzkW11GjVaZ8znQK9Jlu29xTv7QKb7FXx5Otg+wNSxm/PZT1Ze94f51Ev4 7Y9Ze+1fcR+ydMNBLupgbZOJC05QpoEqp0wvu4Lgj9rW+VAAl5TZ4Oim/up5HgIhYhgQ NcVw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899793; x=1696504593; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FpKdF8Qb8AWN6GLwYn2vjDdAak/Nn9GdqYJddmG7YNI=; b=Q/OO8XZnPubKRSIZbRWaXsna9MgwZhsXtpqVZX/zRcxHJgatk8OI3n5mspLW4YHK4M IX1QgnO2+eaYMOYVYaeTAtT6ir5XTAif3qKkIy0+ee9tp8vKBpTpdlNbFx0SqIIMW6Yc ljVPiMkzPSn+dQEb8mK8h5+94Y0UDHSkSPDKsHou0alzcLYLHn3RXfD4j6KUqCsr8pCU EZXgBy8+fbYM0u3ScQP+knRkXqOrIF9IMVUhqUUFALvuCH3q7KtC4P7KDDNqPz0YMJRs DUDDACZPvA3biN56vpVUJbQ1BJZ5Q7l5V3Xxtoh84fZNaCqLkj72o+pOWYE/hmj5jREa n/1w== X-Gm-Message-State: AOJu0YycHOZ2ORnLtdsBF1kbCoYHW9RaBzh97llZtlxUz1tBMMOGVtG4 hxLcbVVjtgPRZ2x8TD6hw1FN1A== X-Google-Smtp-Source: AGHT+IGthG94nbO1o5pwORkjCOKSqwl3hj5m+CvwnlZCyRD7oA1L3U/7d6ytUMKI+9FfhSZkt9+KDQ== X-Received: by 2002:a05:6512:55c:b0:4ff:7f7f:22e7 with SMTP id h28-20020a056512055c00b004ff7f7f22e7mr757117lfl.17.1695899793030; Thu, 28 Sep 2023 04:16:33 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:32 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 02/15] phy: qualcomm: add QMP HDMI PHY driver Date: Thu, 28 Sep 2023 14:16:16 +0300 Message-Id: <20230928111630.1217419-3-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Port Qualcomm QMP HDMI PHY to the generic PHY framework. Split the generic part and the msm8996 part. When adding support for msm8992/4 and msm8998 (which also employ QMP for HDMI PHY), one will have to provide the PLL programming part only. Signed-off-by: Dmitry Baryshkov --- drivers/phy/qualcomm/Kconfig | 7 + drivers/phy/qualcomm/Makefile | 5 + drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c | 184 ++++++++ .../phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c | 441 ++++++++++++++++++ drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h | 75 +++ 5 files changed, 712 insertions(+) create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c create mode 100644 drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index d891058b7c39..127fb2f59a57 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -68,6 +68,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. +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 ffd609ac6233..c09828eccc89 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -8,12 +8,17 @@ obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o obj-$(CONFIG_PHY_QCOM_QMP_COMBO) += phy-qcom-qmp-combo.o +obj-$(CONFIG_PHY_QCOM_QMP_HDMI) += phy-qcom-qmp-hdmi.o obj-$(CONFIG_PHY_QCOM_QMP_PCIE) += phy-qcom-qmp-pcie.o obj-$(CONFIG_PHY_QCOM_QMP_PCIE_8996) += phy-qcom-qmp-pcie-msm8996.o obj-$(CONFIG_PHY_QCOM_QMP_UFS) += phy-qcom-qmp-ufs.o obj-$(CONFIG_PHY_QCOM_QMP_USB) += phy-qcom-qmp-usb.o obj-$(CONFIG_PHY_QCOM_QMP_USB_LEGACY) += phy-qcom-qmp-usb-legacy.o +phy-qcom-qmp-hdmi-y := \ + phy-qcom-qmp-hdmi-base.o \ + phy-qcom-qmp-hdmi-msm8996.o \ + obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o obj-$(CONFIG_PHY_QCOM_SNPS_EUSB2) += phy-qcom-snps-eusb2.o obj-$(CONFIG_PHY_QCOM_EUSB2_REPEATER) += phy-qcom-eusb2-repeater.o diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c new file mode 100644 index 000000000000..08132b3f82af --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-base.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. + */ + +#include +#include +#include + +#include "phy-qcom-qmp-hdmi.h" + +int qmp_hdmi_phy_init(struct phy *phy) +{ + struct qmp_hdmi_phy *hdmi_phy = 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 = &opts->hdmi; + struct qmp_hdmi_phy *hdmi_phy = phy_get_drvdata(phy); + int ret = 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 = 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 = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(ARRAY_SIZE(hdmi_phy->supplies), hdmi_phy->supplies); + if (ret) + return ret; + + ret = clk_bulk_prepare_enable(ARRAY_SIZE(hdmi_phy->clks), hdmi_phy->clks); + 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 = 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 = { + .name = "hdmipll", + .parent_data = (const struct clk_parent_data[]) { + { .fw_name = "xo", .name = "xo_board" }, + }, + .flags = CLK_GET_RATE_NOCACHE, + .num_parents = 1, + }; + const struct qmp_hdmi_cfg *cfg = of_device_get_match_data(&pdev->dev); + struct phy_provider *phy_provider; + struct device *dev = &pdev->dev; + struct qmp_hdmi_phy *hdmi_phy; + int ret, i; + + hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL); + if (!hdmi_phy) + return -ENOMEM; + + hdmi_phy->dev = dev; + + hdmi_phy->serdes = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hdmi_phy->serdes)) + return PTR_ERR(hdmi_phy->serdes); + + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_phy->tx[i] = 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 = 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 = "iface"; + hdmi_phy->clks[1].id = "ref"; + ret = devm_clk_bulk_get(dev, ARRAY_SIZE(hdmi_phy->clks), hdmi_phy->clks); + if (ret) + return ret; + + hdmi_phy->supplies[0].supply = "vddio"; + hdmi_phy->supplies[0].init_load_uA = 100000; + hdmi_phy->supplies[1].supply = "vcca"; + hdmi_phy->supplies[1].init_load_uA = 10000; + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(hdmi_phy->supplies), hdmi_phy->supplies); + if (ret) + return ret; + + platform_set_drvdata(pdev, hdmi_phy); + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + init.ops = cfg->pll_ops; + hdmi_phy->pll_hw.init = &init; + ret = devm_clk_hw_register(hdmi_phy->dev, &hdmi_phy->pll_hw); + if (ret) + goto err; + + ret = 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 = devm_phy_create(dev, pdev->dev.of_node, cfg->phy_ops); + if (IS_ERR(hdmi_phy->phy)) { + ret = PTR_ERR(hdmi_phy->phy); + goto err; + } + + phy_set_drvdata(hdmi_phy->phy, hdmi_phy); + + phy_provider = 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[] = { + { + .compatible = "qcom,hdmi-phy-8996", .data = &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 = { + .probe = qmp_hdmi_probe, + .driver = { + .name = "qcom-qmp-hdmi-phy", + .of_match_table = qmp_hdmi_of_match_table, + .pm = &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 000000000000..27ffa70d0faa --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi-msm8996.c @@ -0,0 +1,441 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. + */ + +#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 ref_clk) +{ + u64 dividend = HDMI_PLL_CMP_CNT * fdata; + u32 divisor = ref_clk * 10; + u32 rem; + + rem = 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_divider *pd, u64 bclk) +{ + int ratio[] = { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 }; + int hs_divsel[] = { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 }; + int tx_band_sel[] = { 0, 1, 2, 3 }; + u64 vco_freq[60]; + u64 vco, vco_optimal; + int half_rate_mode = 0; + int vco_optimal_index, vco_freq_index; + int i, j; + +retry: + vco_optimal = HDMI_VCO_MAX_FREQ; + vco_optimal_index = -1; + vco_freq_index = 0; + for (i = 0; i < 15; i++) { + for (j = 0; j < 4; j++) { + u32 ratio_mult = ratio[i] << tx_band_sel[j]; + + vco = bclk >> half_rate_mode; + vco *= ratio_mult; + vco_freq[vco_freq_index++] = vco; + } + } + + for (i = 0; i < 60; i++) { + u64 vco_tmp = vco_freq[i]; + + if ((vco_tmp >= HDMI_VCO_MIN_FREQ) && + (vco_tmp <= vco_optimal)) { + vco_optimal = vco_tmp; + vco_optimal_index = i; + } + } + + if (vco_optimal_index == -1) { + if (!half_rate_mode) { + half_rate_mode = 1; + goto retry; + } + + return -EINVAL; + } + + pd->vco_freq = vco_optimal; + pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4]; + pd->vco_ratio = ratio[vco_optimal_index / 4]; + pd->hsclk_divsel = 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 = HDMI_DEFAULT_REF_CLOCK; + unsigned long rate = hdmi_phy->hdmi_opts.pixel_clk_rate * 1000; + struct qmp_hdmi_8996_post_divider pd; + bool gen_ssc = 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 = ((u64)rate) * 10; + ret = qmp_hdmi_8996_pll_get_post_div(&pd, bclk); + if (ret) { + dev_err(hdmi_phy->dev, "PLL calculation failed\n"); + return ret; + } + + dec_start = pd.vco_freq; + pll_divisor = 4 * parent_rate; + do_div(dec_start, pll_divisor); + + frac_start = pd.vco_freq * (1 << 20); + + rem = do_div(frac_start, pll_divisor); + frac_start -= dec_start * (1 << 20); + if (rem > (pll_divisor >> 1)) + frac_start++; + + fdata = pd.vco_freq; + do_div(fdata, pd.vco_ratio); + + pll_cmp = 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 != 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 = (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 = (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 <<= 1; + } else { + hdmi_pll_write(hdmi_phy, QSERDES_COM_SVS_MODE_CLK_SEL, 2); + integloop_gain <<= 2; + } + + integloop_gain = 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 = 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, 0x40); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_HP_PD_ENABLES, + i != 3 ? 0xc : 0x3); + } + + if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { + for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_DRV_LVL, + i != 3 ? 0x25 : 0x22); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_TX_EMP_POST1_LVL, + i != 3 ? 0x23 : 0x27); + hdmi_tx_chan_write(hdmi_phy, i, QSERDES_TX_VMODE_CTRL2, + i != 3 ? 0x0d : 0x00); + } + } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { + for (i = 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 != 3 ? 0x0d : 0x00); + } + } else { + for (i = 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 = phy_get_drvdata(phy); + u32 status; + int i, ret = 0; + + ret = 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 = 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 = 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 = 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 = 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 = hw_clk_to_pll(hw); + u32 cmp1, cmp2, cmp3, pll_cmp; + + cmp1 = hdmi_pll_read(phy, QSERDES_COM_LOCK_CMP1_MODE0); + cmp2 = hdmi_pll_read(phy, QSERDES_COM_LOCK_CMP2_MODE0); + cmp3 = hdmi_pll_read(phy, QSERDES_COM_LOCK_CMP3_MODE0); + + pll_cmp = 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 = hw_clk_to_pll(hw); + u32 status; + int pll_locked; + + status = hdmi_pll_read(phy, QSERDES_COM_C_READY_STATUS); + pll_locked = status & BIT(0); + + return pll_locked; +} + +static const struct clk_ops qmp_hdmi_8996_pll_ops = { + .recalc_rate = qmp_hdmi_8996_pll_recalc_rate, + .round_rate = qmp_hdmi_8996_pll_round_rate, + .is_enabled = qmp_hdmi_8996_pll_is_enabled, +}; + +static const struct phy_ops qmp_hdmi_8996_phy_ops = { + .init = qmp_hdmi_phy_init, + .configure = qmp_hdmi_phy_configure, + .power_on = qmp_hdmi_8996_phy_power_on, + .power_off = qmp_hdmi_8996_phy_power_off, + .exit = qmp_hdmi_phy_exit, + .owner = THIS_MODULE, +}; + +const struct qmp_hdmi_cfg qmp_hdmi_8996_cfg = { + .pll_ops = &qmp_hdmi_8996_pll_ops, + .phy_ops = &qmp_hdmi_8996_phy_ops, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h new file mode 100644 index 000000000000..25d307a8f287 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-qmp-hdmi.h @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2016, The Linux Foundation. All rights reserved. + * Copyright (c) 2023, Linaro Ltd. + */ + +#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 channel, + 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; + +#endif From patchwork Thu Sep 28 11:16:17 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402744 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 45AEAE732C6 for ; Thu, 28 Sep 2023 11:18:40 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232009AbjI1LSj (ORCPT ); Thu, 28 Sep 2023 07:18:39 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39224 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231822AbjI1LS1 (ORCPT ); Thu, 28 Sep 2023 07:18:27 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 74B707EF0 for ; Thu, 28 Sep 2023 04:16:35 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id 2adb3069b0e04-50307759b65so20730534e87.0 for ; Thu, 28 Sep 2023 04:16:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899794; x=1696504594; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=S7fKi5WIxwX5ZmNAvm8rVeCk+5FnbCELjzvHYUfJmkU=; b=o9OJsR4zQXPS8ULXvRPlcfQxoGyqQ5nmPVzVEgK8zRPDLAnSrpokVtHfcLxvY8hIXw GXJKc3RhH9VyXJSWuaxu12nYl0quSDo55WzlyvI/t8z3BIoDoKZjFrsHC9AQbHtXU82A qUcboyl5Gke4BcWUAhOZUUumlpEo0PoU8BQNO4ZBDmpwGduRepnlSNASSlr9K2uST2yv 8p/C1rTedxpv9PXhy0H8W8RNYlRzir4zhNWXJRuG5nKqNpges03v9EVL4OxDjTKPf6qM V45L+4IT2WqD/iEBa+OXLz95rl4l1+5TwDGDeOimwzGNs1iXniEySMEHMBdvLbKGkLPw rhtg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899794; x=1696504594; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=S7fKi5WIxwX5ZmNAvm8rVeCk+5FnbCELjzvHYUfJmkU=; b=BHCM2n5GzIt536GCN9xUgc8Bm2L4dnhVnEG8B6fm/DtSXJQXu0CAnCzMb7J9GKmSbb xhKCrJc+ITIklrmrCE+f4FUJ+mXgjRFGu5kOVnw+yX1+LD8ID+amStSWC0c7InDv8yuD QSLBw2kkRHOV34Jc9GpyG9soH7LkNWjJnRGc1MAw8GixdIc24y2/KpyGfhYx8TMovYlm obfjAEnu/QMfEuRP08MqGqtNciFGCOLrojjZhLz+/umhsd7Yfl4Zia2hUvgnSTYwUWRV dsuqXEVNjEUy6iy/tjjFIwkrsbSX5eKY2RqdGLYKrhqOcCNxx8bpubWnql3gosp1Lwgy rDkA== X-Gm-Message-State: AOJu0Yxgzwyw9/YonQV3XOch3kpcqEYTKcFoz29lw2ULATdlX1xZde0a Ey9kwOvCxwn/qnVVBnZEra3oZA== X-Google-Smtp-Source: AGHT+IE90kxoRUpzk/sWNgYNbmcNadcNWLeaqvjzXrliCW2jT2RJ3Qlabv65kQhxmrcR4pGuzcr3sA== X-Received: by 2002:a05:6512:32cb:b0:500:9a67:d40e with SMTP id f11-20020a05651232cb00b005009a67d40emr1118908lfg.60.1695899793707; Thu, 28 Sep 2023 04:16:33 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:33 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 03/15] phy: qcom: apq8064-sata: extract UNI PLL register defines Date: Thu, 28 Sep 2023 14:16:17 +0300 Message-Id: <20230928111630.1217419-4-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org The "uni" PLL is shared between several PHYS: APQ8064's SATA, MSM8974/APQ8084 HDMI, MSM8916 DSI, MSM8974/APQ8084 DSI. Signed-off-by: Dmitry Baryshkov --- drivers/phy/qualcomm/phy-qcom-apq8064-sata.c | 23 +------------- drivers/phy/qualcomm/phy-qcom-uniphy.h | 32 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 22 deletions(-) create mode 100644 drivers/phy/qualcomm/phy-qcom-uniphy.h diff --git a/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c b/drivers/phy/qualcomm/phy-qcom-apq8064-sata.c index 3642a5d4f2f3..e29836d7b734 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 -/* 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" #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 000000000000..d8be32b5317c --- /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 From patchwork Thu Sep 28 11:16:18 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402745 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 37CC7E732C4 for ; Thu, 28 Sep 2023 11:18:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232171AbjI1LSk (ORCPT ); Thu, 28 Sep 2023 07:18:40 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39180 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232067AbjI1LS2 (ORCPT ); Thu, 28 Sep 2023 07:18:28 -0400 Received: from mail-lf1-x12c.google.com (mail-lf1-x12c.google.com [IPv6:2a00:1450:4864:20::12c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 32CCF7EF3 for ; Thu, 28 Sep 2023 04:16:36 -0700 (PDT) Received: by mail-lf1-x12c.google.com with SMTP id 2adb3069b0e04-50433d8385cso20033323e87.0 for ; Thu, 28 Sep 2023 04:16:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899794; x=1696504594; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=S0sobRIk6tCMFCwXhjjdodtZDMDOffBV8iCIEpNnHQY=; b=rgKtHP9untNMCcUttgTLel0oqKcbT3GVrYLS5quevawSvq6jC8PnAgExahUT6NdSle WiMD6jde9PKnY8hzU+MAZANWdBQ3l10IThmCeoXdDkh0eXLh2+XZNfDOb/GW3ksKpwgk zcGCL7aANi7b/4C2rD1YvEo4G++LNuUmmdtu5h+VWUyN+VBBiSdnTt5hXUhYVdRKPcYz qD/gFVT1Oc240LifFt8jTqic7DswtNbHurgN7oP5jXJx05YR+LYbnsLfW1JAiEvNKvTq d+dGa4N0CVcqo3R18kv7jmu+hCq4bdUpoLszik1yywHfoZMYrVWyfJps7YSmDZb+bSX6 K1Nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899794; x=1696504594; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=S0sobRIk6tCMFCwXhjjdodtZDMDOffBV8iCIEpNnHQY=; b=Tpi4JcvcONGOg9kn3CqivWYlgfL9y2nIDOtOCT3k14+S1+xHiZAGC7PxUZEfvqVMxz jBwRFJr/UfvgqjTC7RC3wBgskboKTHpRybeRWbCgPB8xRVGt8zLha7Ic70NasOGuaCXP 5fvAiJTNucW4nGZFZQSKPWWax19tGoW815Nt/BaowWsyP3dcUDxXPpOapga/4sZX9Lcw DmvZ7oz5ZJjhUIs+NfbFlxjHO9FNhIVtXZkaRlFbbYrXuXSbazpjQfUX6eEzEGuXqaGV FHqXTg9bt25BtSF2PjyfaojRs6k5rZq2k0VtzkEvh1DdN98Ca+WFKR2feKTlApRRhVsw GKqw== X-Gm-Message-State: AOJu0Yw+ecJTiSI2+XnuIal+HwSjd3ApMINjnJj95PxBCnNg+D+z0I4P gnGJlySIzjD94ekbZc2WrornRg== X-Google-Smtp-Source: AGHT+IELBQgqiQMXyEz+Jj67Dbbj28IvmoG/+EaZfha/Kn6VWR3rko8850416JFr1fP0E4QmCuvhRw== X-Received: by 2002:a19:4f15:0:b0:503:ed9:58e3 with SMTP id d21-20020a194f15000000b005030ed958e3mr843358lfb.8.1695899794437; Thu, 28 Sep 2023 04:16:34 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:34 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 04/15] phy: qcom-uniphy: add more registers from display PHYs Date: Thu, 28 Sep 2023 14:16:18 +0300 Message-Id: <20230928111630.1217419-5-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Import register definitions from 28nm DSI and HDMI PHYs, adding more UNI PHY registers. Signed-off-by: Dmitry Baryshkov --- 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 d8be32b5317c..4be9bda37fa3 100644 --- a/drivers/phy/qualcomm/phy-qcom-uniphy.h +++ b/drivers/phy/qualcomm/phy-qcom-uniphy.h @@ -8,8 +8,19 @@ /* 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 #endif From patchwork Thu Sep 28 11:16:19 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402749 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4E369E732C8 for ; Thu, 28 Sep 2023 11:18:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232145AbjI1LSm (ORCPT ); Thu, 28 Sep 2023 07:18:42 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39206 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232176AbjI1LS3 (ORCPT ); Thu, 28 Sep 2023 07:18:29 -0400 Received: from mail-lf1-x12d.google.com (mail-lf1-x12d.google.com [IPv6:2a00:1450:4864:20::12d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C2997EF7 for ; Thu, 28 Sep 2023 04:16:37 -0700 (PDT) Received: by mail-lf1-x12d.google.com with SMTP id 2adb3069b0e04-50433d8385cso20033341e87.0 for ; Thu, 28 Sep 2023 04:16:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899795; x=1696504595; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7F0auU/NfLH897WAbs3SpPYlKGk03JtqCenx0/lvKaI=; b=nDqckwKiLL/fQZStI/2GWcZmnlfVOhCRFFzRHp8YLeZJkKZ5Gkp5cQBfXdiD+BmyOE 7amhY8kqb2DhU1nhnBhil+Pu0Lyv8lhsnCBZKHOfInSe31X2T4QpQMFc6j9FJ47kTu6G jAPHWBlTyhROj4LPMLrKLnVZprRx+l0H/ZJJyv446HP6pwM92vbL5MhBfJOba6wxhhVN IjAnhImIXlUz75ZwzoG4gfc2xk5q5r/tMGqg84wdoFzdAmGbdG8AVbVNh+cBWnQO9yIx o2gDjiIwd1+SxzhyFr7txoVJzSbwTLaRSvMSc4WewUZeksditW1rLO+ycvejMBIn5Q19 HTOg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899795; x=1696504595; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7F0auU/NfLH897WAbs3SpPYlKGk03JtqCenx0/lvKaI=; b=OOYcoFAsI53XyuwmtHUmWNaQsND9hlc+afiMBL6HnPjvlLP6dbiQIN8OENMhcWPTt7 vbK2AIkVxcLs9qIkNZZHTQtw38aG+46GEtqF1DhEsymsmX7Vr2/XjvVFdDZI7yALthUV Xk7/UFbn7c0P9P5pVQypzE54GgdGO6oramygYlqWvHtBi6VfbhZFAAXq1lhjgVEZMTFO yL1KuyvHD5yZszN71HvZ0SkL5vP4SiLBFLbmMaaUEMdEpRFMoC+ziWm6ach/A5SMpdNA ACK+goE1Oo29KwPyKF8dKcPKz0PBwTwk4wZZglm9r+W1P3VjzLo2wr3h5wftMHDHnq5u 5Z1g== X-Gm-Message-State: AOJu0YztZN5KwaKsUrwnQbWV707QoONlk7+gpncFV5N++eA7AQSlKpvV JFXk7c9nQ5r0NMNhOB4xtXTzvw== X-Google-Smtp-Source: AGHT+IE563x0bqnEEcgzITHgBRkZ30puIo3c/M3QmhqftwSbO5kcCe3+TbMHZrat/Y0vhJIEafn0DA== X-Received: by 2002:a05:6512:708:b0:503:2dce:4544 with SMTP id b8-20020a056512070800b005032dce4544mr768391lfs.59.1695899795325; Thu, 28 Sep 2023 04:16:35 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:34 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 05/15] phy: qualcomm: add legacy HDMI PHY driver Date: Thu, 28 Sep 2023 14:16:19 +0300 Message-Id: <20230928111630.1217419-6-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Add the driver for pre-QMP Qualcomm HDMI PHYs. Currently it suppports Qualcomm MSM8960 / APQ8064 platforms, other platforms will come later. Signed-off-by: Dmitry Baryshkov --- drivers/phy/qualcomm/Kconfig | 14 + drivers/phy/qualcomm/Makefile | 6 + drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c | 439 ++++++++++++++++++++ drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c | 206 +++++++++ drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h | 79 ++++ 5 files changed, 744 insertions(+) create mode 100644 drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c create mode 100644 drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c create mode 100644 drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index 127fb2f59a57..f31b575a6832 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 +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 platforms: + MSM8260, MSM8660, MSM8960, APQ8060 and APQ8064. + + 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) diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index c09828eccc89..de9bbaf45c74 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -4,6 +4,12 @@ obj-$(CONFIG_PHY_QCOM_APQ8064_SATA) += phy-qcom-apq8064-sata.o obj-$(CONFIG_PHY_QCOM_EDP) += phy-qcom-edp.o obj-$(CONFIG_PHY_QCOM_IPQ4019_USB) += phy-qcom-ipq4019-usb.o obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o +obj-$(CONFIG_PHY_QCOM_HDMI) += phy-qcom-hdmi.o + +phy-qcom-hdmi-y := \ + phy-qcom-hdmi-preqmp.o \ + phy-qcom-hdmi-28lpm.o \ + obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c b/drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c new file mode 100644 index 000000000000..64e043f3f0e2 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-28lpm.c @@ -0,0 +1,439 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + * Copyright (c) 2023, Linaro Ltd. + */ + +#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_phy, unsigned long parent_rate) +{ + unsigned long rate; + u32 refclk_cfg; + u32 dc_offset; + u64 fraq_n; + u32 val; + + refclk_cfg = hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_REFCLK_CFG); + if (refclk_cfg & BIT(1)) + parent_rate /= 2; + if (refclk_cfg & BIT(3)) + parent_rate *= 2; + + val = hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG0); + if (val & 0x40) { + dc_offset = val & 0x3f; + fraq_n = 0; + } else { + dc_offset = hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_SDM_CFG1) & 0x3f; + fraq_n = 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 = (dc_offset + 1) * parent_rate; + rate += mult_frac(fraq_n, parent_rate, 0x10000); + + return rate; +} + +static int qcom_28lpm_set_rate(struct qcom_hdmi_preqmp_phy *hdmi_phy, unsigned long parent_rate, + unsigned long vco_freq, u32 div_idx) +{ + unsigned int pixclk = hdmi_phy->hdmi_opts.pixel_clk_rate; + unsigned int int_ref_freq; + unsigned int div; + unsigned int dc_offset; + unsigned int sdm_freq_seed; + unsigned int val; + bool sdm_mode = false; + u32 refclk_cfg; + u32 lf_cfg0; + u32 lf_cfg1; + + dev_dbg(hdmi_phy->dev, "rate=%u, div = %d, vco = %lu", pixclk, div, vco_freq); + + if (vco_freq % (parent_rate / 2) == 0) { + refclk_cfg = 0x2; + int_ref_freq = parent_rate / 2; + } else { + refclk_cfg = 0x8; + int_ref_freq = parent_rate * 2; + sdm_mode = true; + } + + dc_offset = vco_freq / int_ref_freq - 1; + sdm_freq_seed = vco_freq - (dc_offset + 1) * int_ref_freq; + sdm_freq_seed = mult_frac(sdm_freq_seed, 0x10000, int_ref_freq); + + val = (div_idx << 4) | refclk_cfg; + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_REFCLK_CFG, val); + + lf_cfg0 = dc_offset >= 30 ? 0 : (dc_offset >= 16 ? 0x10 : 0x20); + lf_cfg0 += sdm_mode ? 0 : 1; + + /* XXX: 0xc3 instead of 0x33 for qcs404 */ + lf_cfg1 = dc_offset >= 30 ? 0x33 : (dc_offset >= 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 /= 1000; + hdmi_pll_write(hdmi_phy, REG_HDMI_8960_PHY_PLL_VCOCAL_CFG0, vco_freq & 0xff); + 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[] = {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 = hw_clk_to_phy(hw); + u32 div_idx = hdmi_pll_read(hdmi_phy, REG_HDMI_8960_PHY_PLL_REFCLK_CFG); + unsigned long rate = 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 = { + .recalc_rate = qcom_hdmi_8960_pll_recalc_rate, + .round_rate = qcom_hdmi_8960_pll_round_rate, +}; + +static int qcom_hdmi_msm8960_phy_pll_enable(struct qcom_hdmi_preqmp_phy *phy) +{ + int pll_lock_retry = 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 = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); + val |= HDMI_8960_PHY_REG12_SW_RESET; + /* Assert PHY S/W reset */ + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); + val &= ~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 = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); + val |= 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 = hdmi_pll_read(phy, REG_HDMI_8960_PHY_PLL_PWRDN_B); + val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B; + val &= ~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 = 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 int pixclk) +{ + int i; + unsigned int min_freq = HDMI_8974_VCO_MIN_FREQ / HDMI_8974_COMMON_DIV / 1000; + + if (pixclk > HDMI_8974_VCO_MAX_FREQ / HDMI_8974_COMMON_DIV / 1000) + return -E2BIG; + + for (i = 0; i < ARRAY_SIZE(qcom_hdmi_8974_divs); i++) { + if (pixclk >= min_freq / qcom_hdmi_8974_divs[i]) + return i; + } + + return -EINVAL; +} + +static int qcom_hdmi_msm8960_phy_set_rate(struct qcom_hdmi_preqmp_phy *hdmi_phy) +{ + unsigned int pixclk = hdmi_phy->hdmi_opts.pixel_clk_rate; + /* XXX: 19.2 for qcs404 */ + unsigned long parent_rate = 27000; + unsigned long vco_freq; + int div_idx; + u32 div; + + div_idx = qcom_hdmi_msm8974_phy_find_div(pixclk); + if (WARN_ON(div_idx < 0)) + return div_idx; + + div = qcom_hdmi_8974_divs[div_idx]; + vco_freq = 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 = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); + val &= ~HDMI_8960_PHY_REG12_PWRDN_B; + hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); + + val = hdmi_pll_read(phy, REG_HDMI_8960_PHY_PLL_PWRDN_B); + val |= HDMI_8960_PHY_REG12_SW_RESET; + val &= ~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 *hdmi_phy) +{ + int ret; + + ret = qcom_hdmi_msm8960_phy_set_rate(hdmi_phy); + if (ret) + return ret; + + ret = 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 *hdmi_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 = { + .fw_name = "pxo", .name = "pxo_board", +}; + +const struct qcom_hdmi_preqmp_cfg msm8960_hdmi_phy_cfg = { + .clk_names = { "slave_iface" }, + .num_clks = 1, + + .reg_names = { "core-vdda" }, + .num_regs = 1, + + .power_on = qcom_hdmi_msm8960_phy_power_on, + .power_off = qcom_hdmi_msm8960_phy_power_off, + + .pll_ops = &qcom_hdmi_8960_pll_ops, + .pll_parent = &msm8960_hdmi_pll_parent, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c new file mode 100644 index 000000000000..6885f587d7b4 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + * Copyright (c) 2023, Linaro Ltd. + */ + +#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 = 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 = 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 = 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 = phy_get_drvdata(phy); + + return hdmi_phy->power_off(hdmi_phy); +}; + +static int qcom_hdmi_preqmp_phy_configure(struct phy *phy, union phy_configure_opts *opts) +{ + const struct phy_configure_opts_hdmi *hdmi_opts = &opts->hdmi; + struct qcom_hdmi_preqmp_phy *hdmi_phy = phy_get_drvdata(phy); + int ret = 0; + + memcpy(&hdmi_phy->hdmi_opts, hdmi_opts, sizeof(*hdmi_opts)); + + return ret; +} + +static int __maybe_unused qcom_hdmi_preqmp_runtime_resume(struct device *dev) +{ + struct qcom_hdmi_preqmp_phy *hdmi_phy = dev_get_drvdata(dev); + int ret; + + ret = regulator_bulk_enable(hdmi_phy->num_regs, hdmi_phy->regs); + if (ret) + return ret; + + ret = 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 = 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 = { + .init = qcom_hdmi_preqmp_phy_init, + .configure = qcom_hdmi_preqmp_phy_configure, + .power_on = qcom_hdmi_preqmp_phy_power_on, + .power_off = qcom_hdmi_preqmp_phy_power_off, + .exit = qcom_hdmi_preqmp_phy_exit, + .owner = 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 = &pdev->dev; + struct qcom_hdmi_preqmp_phy *hdmi_phy; + const struct qcom_hdmi_preqmp_cfg *cfg; + int i, ret; + + cfg = of_device_get_match_data(dev); + if (!cfg) + return -EINVAL; + + hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL); + if (!hdmi_phy) + return -ENOMEM; + + hdmi_phy->dev = dev; + + hdmi_phy->phy_reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(hdmi_phy->phy_reg)) + return PTR_ERR(hdmi_phy->phy_reg); + + hdmi_phy->pll_reg = devm_platform_ioremap_resource(pdev, 1); + if (IS_ERR(hdmi_phy->pll_reg)) + return PTR_ERR(hdmi_phy->pll_reg); + + hdmi_phy->num_clks = cfg->num_clks; + for (i = 0; i < cfg->num_clks; i++) + hdmi_phy->clks[i].id = cfg->clk_names[i]; + ret = devm_clk_bulk_get(dev, hdmi_phy->num_clks, hdmi_phy->clks); + if (ret) + return ret; + + hdmi_phy->num_regs = cfg->num_regs; + for (i = 0; i < cfg->num_regs; i++) { + hdmi_phy->regs[i].supply = cfg->reg_names[i]; + hdmi_phy->regs[i].init_load_uA = cfg->reg_init_load[i]; + } + ret = devm_regulator_bulk_get(dev, hdmi_phy->num_regs, hdmi_phy->regs); + if (ret) + return ret; + + hdmi_phy->power_on = cfg->power_on; + hdmi_phy->power_off = cfg->power_off; + + platform_set_drvdata(pdev, hdmi_phy); + + ret = devm_pm_runtime_enable(&pdev->dev); + if (ret) + return ret; + + ret = pm_runtime_resume_and_get(&pdev->dev); + if (ret) + return ret; + + init.name = "hdmipll"; + init.ops = cfg->pll_ops; + init.flags = CLK_GET_RATE_NOCACHE; + init.parent_data = cfg->pll_parent; + init.num_parents = 1; + + hdmi_phy->pll_hw.init = &init; + ret = devm_clk_hw_register(hdmi_phy->dev, &hdmi_phy->pll_hw); + if (ret) + goto err; + + ret = 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 = devm_phy_create(dev, pdev->dev.of_node, &qcom_hdmi_preqmp_phy_ops); + if (IS_ERR(hdmi_phy->phy)) { + ret = PTR_ERR(hdmi_phy->phy); + goto err; + } + + phy_set_drvdata(hdmi_phy->phy, hdmi_phy); + + phy_provider = 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[] = { + { .compatible = "qcom,hdmi-phy-8960", .data = &msm8960_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 = { + .probe = qcom_hdmi_preqmp_probe, + .driver = { + .name = "qcom-preqmp-hdmi-phy", + .of_match_table = qcom_hdmi_preqmp_of_match_table, + .pm = &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/qualcomm/phy-qcom-hdmi-preqmp.h new file mode 100644 index 000000000000..dca9be78d8fc --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h @@ -0,0 +1,79 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + * Copyright (c) 2023, Linaro Ltd. + */ + +#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 offset, + u32 data) +{ + writel(data, phy->phy_reg + offset); +} + +static inline u32 hdmi_phy_read(struct qcom_hdmi_preqmp_phy *phy, int offset) +{ + return readl(phy->phy_reg + offset); +} + +static inline void hdmi_pll_write(struct qcom_hdmi_preqmp_phy *phy, int offset, + u32 data) +{ + writel(data, phy->pll_reg + offset); +} + +static inline u32 hdmi_pll_read(struct qcom_hdmi_preqmp_phy *phy, int offset) +{ + return readl(phy->pll_reg + offset); +} + +extern const struct qcom_hdmi_preqmp_cfg msm8960_hdmi_phy_cfg; + +#endif From patchwork Thu Sep 28 11:16:20 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402747 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B028DE732C0 for ; Thu, 28 Sep 2023 11:18:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232198AbjI1LSl (ORCPT ); Thu, 28 Sep 2023 07:18:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39280 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232145AbjI1LS3 (ORCPT ); Thu, 28 Sep 2023 07:18:29 -0400 Received: from mail-lf1-x135.google.com (mail-lf1-x135.google.com [IPv6:2a00:1450:4864:20::135]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DB6165248 for ; Thu, 28 Sep 2023 04:16:37 -0700 (PDT) Received: by mail-lf1-x135.google.com with SMTP id 2adb3069b0e04-5041d6d8b10so21171612e87.2 for ; Thu, 28 Sep 2023 04:16:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899796; x=1696504596; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=FKxj0arPUviJ2iyzbqVJuwkdIDz3zRmvjljfAcCpENE=; b=k81YYb/HBasnmzw7RAyKPjz4dgAKyQSelslNMuKp+k8/bAOr/L3DnDF7ljOfZcVbMX LiQcwK7lDJjCXgrrDnMPFs/z+TVtLXQROEwYJYGDWtFw5G+JRvDZQf7no3Lr1qvtdNjd u5Gor/K0jFVxEhNXcjKK8jSQfN84/JsV80R6fhyBSosrnZE+kU6Ftzcn5Wc2IMUS2NyL XxYXfwBI1ErwCDcVexkf4oG0HgF4ykVBKZnoTIESQgn43EUxaybfCSv7NVRYLHMCyo+i CpmVO91uR3MXCPRIJxHHePzFp2qMqb//4RFvMpQ445rtDIokjhVnOPq0v04UiN4pU8Cy kZUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899796; x=1696504596; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FKxj0arPUviJ2iyzbqVJuwkdIDz3zRmvjljfAcCpENE=; b=BSFBchBnzHv/9mV4wWbOWwy4CvyLS8w4iJ4yruyBIw6ekXzianOvVf0VtOQOWOKsg0 5P3ipT3Ti6EGAxhdhUQeqjCcHlSxb9RP3c6VsM/irf6lvRIpFTHNErtHDl5N5psQ5ZPy U2jGxCrp0Jwpwr3qnnzecgO8fDl064OzQZ8kgIPTv0lTgitEZszw9FT43eHagxpolSeu x06wDyWJbmOQW7+y8rMO4k0JWDmx0JYoEoAJH6bRpxQHZxCO0E0Hlv7QlHt03dGIm5p+ XCxwcHhIyt86NenMmNvGnTV3W2J02QBAxV1/bPWLmOL4PdLTsxzpcD/9L583OGWECZjs OoEA== X-Gm-Message-State: AOJu0Yx8oomMxoTzXtrVJVtei+bGiXOtOXTT9m6K9O/5NF2bTcMlFgmp KVy+5ft/I6JqDzjgR1WRjRsI2A== X-Google-Smtp-Source: AGHT+IEXTNyzRJ0604k8PtlLNmcr46WQuauQ/xCc4YbXLkw4RuVO/IL+vK7Vckfv2fOxrz+iaaX2dA== X-Received: by 2002:a05:6512:1391:b0:500:9a45:63b with SMTP id fc17-20020a056512139100b005009a45063bmr1011434lfb.13.1695899796104; Thu, 28 Sep 2023 04:16:36 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:35 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 06/15] phy: qualcomm: add MSM8974 HDMI PHY support Date: Thu, 28 Sep 2023 14:16:20 +0300 Message-Id: <20230928111630.1217419-7-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Add support for HDMI PHY on Qualcomm MSM8974 / APQ8074 platforms. Signed-off-by: Dmitry Baryshkov --- drivers/phy/qualcomm/Kconfig | 2 +- drivers/phy/qualcomm/Makefile | 1 + drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c | 327 ++++++++++++++++++++ drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c | 1 + drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h | 1 + 5 files changed, 331 insertions(+), 1 deletion(-) create mode 100644 drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c diff --git a/drivers/phy/qualcomm/Kconfig b/drivers/phy/qualcomm/Kconfig index f31b575a6832..36f78fd06b06 100644 --- a/drivers/phy/qualcomm/Kconfig +++ b/drivers/phy/qualcomm/Kconfig @@ -51,7 +51,7 @@ config PHY_QCOM_HDMI select GENERIC_PHY help Enable this to support the Qualcomm HDMI PHY presend on 32-bit platforms: - MSM8260, MSM8660, MSM8960, APQ8060 and APQ8064. + MSM8260, MSM8660, MSM8960, MSM8974, APQ8060, APQ8064, APQ8074 and APQ8084. Note, this driver is not used on MSM899x platforms, which use PHY_QCOM_QMP_HDMI instead. diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index de9bbaf45c74..082020af7fc1 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_PHY_QCOM_HDMI) += phy-qcom-hdmi.o phy-qcom-hdmi-y := \ phy-qcom-hdmi-preqmp.o \ + phy-qcom-hdmi-28hpm.o \ phy-qcom-hdmi-28lpm.o \ obj-$(CONFIG_PHY_QCOM_M31_USB) += phy-qcom-m31.o diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c b/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c new file mode 100644 index 000000000000..d3bf67e743aa --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-28hpm.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + * Copyright (c) 2023, Linaro Ltd. + */ + +#include +#include + +#include "phy-qcom-hdmi-preqmp.h" +#include "phy-qcom-uniphy.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 + +#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 = ref_freq * (ref_freq_mult_2 ? 2 : 1); + unsigned int div_in_freq = vco_freq / refclk_div; + unsigned int dc_offset = div_in_freq / int_ref_freq - 1; + unsigned int sdm_freq_seed; + unsigned int val; + unsigned int remain = div_in_freq - (dc_offset + 1) * int_ref_freq; + sdm_freq_seed = mult_frac(remain, 0x10000, int_ref_freq); + + val = (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 = ref_freq * 5 / 1000; + writel(ref_freq & 0xff, base + UNIPHY_PLL_CAL_CFG8); + + writel(ref_freq >> 8, base + UNIPHY_PLL_CAL_CFG9); + + vco_freq /= 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 = readl(base + UNIPHY_PLL_REFCLK_CFG); + if (refclk_cfg & BIT(0)) + parent_rate *= 2; + + val = readl(base + UNIPHY_PLL_SDM_CFG0); + if (val & 0x40) { + dc_offset = val & 0x3f; + fraq_n = 0; + } else { + dc_offset = readl(base + UNIPHY_PLL_SDM_CFG1) & 0x3f; + fraq_n = readl(base + UNIPHY_PLL_SDM_CFG2) | + (readl(base + UNIPHY_PLL_SDM_CFG3) << 8); + } + + rate = (dc_offset + 1) * parent_rate; + rate += mult_frac(fraq_n, parent_rate, 0x10000); + + rate *= (refclk_cfg >> 2) * 0x3 + 1; + + return rate; +} + +static const unsigned int qcom_hdmi_8974_divs[] = {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 = hw_clk_to_phy(hw); + u32 div_idx = hdmi_pll_read(hdmi_phy, UNIPHY_PLL_POSTDIV1_CFG); + unsigned long rate = 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 = { + .recalc_rate = qcom_hdmi_8974_pll_recalc_rate, + .round_rate = qcom_hdmi_8974_pll_round_rate, +}; + +static int qcom_hdmi_msm8974_phy_find_div(unsigned int pixclk) +{ + int i; + unsigned int min_freq = HDMI_8974_VCO_MIN_FREQ / HDMI_8974_COMMON_DIV / 1000; + + if (pixclk > HDMI_8974_VCO_MAX_FREQ / HDMI_8974_COMMON_DIV / 1000) + return -E2BIG; + + for (i = 0; i < ARRAY_SIZE(qcom_hdmi_8974_divs); i++) { + if (pixclk >= 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 int pixclk = hdmi_phy->hdmi_opts.pixel_clk_rate; + unsigned long vco_rate; + unsigned int div; + int div_idx = 0; + + div_idx = qcom_hdmi_msm8974_phy_find_div(pixclk); + if (WARN_ON(div_idx < 0)) + return div_idx; + + div = qcom_hdmi_8974_divs[div_idx]; + vco_rate = 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, 19200, true, true, true, 1, vco_rate); + + 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 == 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 == 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 == 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 *hdmi_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 = 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 = 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 *hdmi_phy) +{ + int ret; + + ret = qcom_hdmi_msm8974_phy_pll_set_rate(hdmi_phy); + if (ret) + return ret; + + ret = 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); + 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 *hdmi_phy) +{ + hdmi_phy_write(hdmi_phy, REG_HDMI_8x74_PD_CTRL0, 0x7f); + + 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; +} + +const struct clk_parent_data msm8974_hdmi_pll_parent = { + .fw_name = "xo", .name = "xo_board", +}; + +const struct qcom_hdmi_preqmp_cfg msm8974_hdmi_phy_cfg = { + .clk_names = { "iface", "alt_iface" }, + .num_clks = 2, + + .reg_names = { "vddio", "core-vdda" }, + .reg_init_load = { 100000, 10000 }, + .num_regs = 2, + + .power_on = qcom_hdmi_msm8974_phy_power_on, + .power_off = qcom_hdmi_msm8974_phy_power_off, + + .pll_ops = &qcom_hdmi_8974_pll_ops, + .pll_parent = &msm8974_hdmi_pll_parent, +}; diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c index 6885f587d7b4..e181a45df2dc 100644 --- a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c @@ -181,6 +181,7 @@ static int qcom_hdmi_preqmp_probe(struct platform_device *pdev) static const struct of_device_id qcom_hdmi_preqmp_of_match_table[] = { { .compatible = "qcom,hdmi-phy-8960", .data = &msm8960_hdmi_phy_cfg, }, + { .compatible = "qcom,hdmi-phy-8974", .data = &msm8974_hdmi_phy_cfg, }, { }, }; MODULE_DEVICE_TABLE(of, qcom_hdmi_preqmp_of_match_table); diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h index dca9be78d8fc..bc81d68463ec 100644 --- a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h @@ -75,5 +75,6 @@ static inline u32 hdmi_pll_read(struct qcom_hdmi_preqmp_phy *phy, int offset) } extern const struct qcom_hdmi_preqmp_cfg msm8960_hdmi_phy_cfg; +extern const struct qcom_hdmi_preqmp_cfg msm8974_hdmi_phy_cfg; #endif From patchwork Thu Sep 28 11:16:21 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402750 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3DF9DE732C0 for ; Thu, 28 Sep 2023 11:18:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231808AbjI1LSn (ORCPT ); Thu, 28 Sep 2023 07:18:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39338 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232186AbjI1LS3 (ORCPT ); Thu, 28 Sep 2023 07:18:29 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D51737EFD for ; Thu, 28 Sep 2023 04:16:38 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-50325ce89e9so21213552e87.0 for ; Thu, 28 Sep 2023 04:16:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899797; x=1696504597; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=WaqYa1p7vqN61Nnmz1mMsVu16pc4A060DpWFBkQ5zwA=; b=eghbFeGCOvcFUBGdFu4a8ihouIBpG2DtPjBfEvv25B4+mVOBjwwrLWxzJbkn4lm//z fIbvCrOQIQOPiuCs7Av0Rx01HvCgvjVfX31rTj4nfWpMOByoO+ODWn3g4S/CsWvjqc4+ YvmBX9u9JnTIRPkvsvP3S1ZGMd1OLdwnwZbuuAOk6CytSWjkQI0zGYjZbHEzsK2mYv3o vf8gQdY1eLY5egGrPs4/OS+EmVTZf3zSfk91rgC7yrjrGuA9JEbnfnZx164ixChAC5+T yHXsIo4XmKZKHdWrRj4u4fDWdAsKLjxnFJ/Z2axGrz5uPJ5Vbf5n8XsPr6xkbdNYGB41 Ul6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899797; x=1696504597; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=WaqYa1p7vqN61Nnmz1mMsVu16pc4A060DpWFBkQ5zwA=; b=uhPuIoxxwgfYKb9vUoBH3dLoVIi8rbGLqbiddLK2B599AFy/HpzFS4T68Djc0qazQs MBbJCXmwkqnftlUkU6J1qZyKlpN4Zn9m/qhr7HmLYeqUC2Krfc2vdrE9jyABRFqyBKgo irKQBoRwU8OvC9km+TSfEWZNiTmPaKrkbWJi9y+mEyVRLMuGOnsTTO+M8lIekGAXmG0H CRaTCV2UhUM6ANr+jxNleARpO/XcWgIOc52Do2+n+vYb0Z2KmtQIo4LQRZClnC8TdZyJ PWQLr5nV1vcUU0NvlUCyuejb88XQ48TdyBCgrUM4FaXKPnbQCIBP7+avR8gdtRWEIfSX cMZA== X-Gm-Message-State: AOJu0YwZLFeXlpyB/QUIv/PyuxX4s23zXeawD3njr6rFv7Ldv1UwMFfs LRb/DvubI0MWc+eGFvFgyKRI1g== X-Google-Smtp-Source: AGHT+IELwAXbwNWKBM1QMtP91xkOdmLsDx0Ktv/JYhcUeyUVfQBYJWS7Wq0baHGU6E4lXOEPSArOwg== X-Received: by 2002:a05:6512:3c8b:b0:502:ab7b:e480 with SMTP id h11-20020a0565123c8b00b00502ab7be480mr1068705lfv.36.1695899796850; Thu, 28 Sep 2023 04:16:36 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:36 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 07/15] phy: qualcomm: add MSM8x60 HDMI PHY support Date: Thu, 28 Sep 2023 14:16:21 +0300 Message-Id: <20230928111630.1217419-8-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Add support for HDMI PHY on Qualcomm MSM8x60 / APQ8060 platforms. Signed-off-by: Dmitry Baryshkov --- drivers/phy/qualcomm/Makefile | 1 + drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c | 184 ++++++++++++++++++++ drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c | 32 ++-- drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h | 1 + 4 files changed, 204 insertions(+), 14 deletions(-) create mode 100644 drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c diff --git a/drivers/phy/qualcomm/Makefile b/drivers/phy/qualcomm/Makefile index 082020af7fc1..79df2f1e9bc8 100644 --- a/drivers/phy/qualcomm/Makefile +++ b/drivers/phy/qualcomm/Makefile @@ -10,6 +10,7 @@ phy-qcom-hdmi-y := \ 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) += phy-qcom-m31.o obj-$(CONFIG_PHY_QCOM_PCIE2) += phy-qcom-pcie2.o diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c b/drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c new file mode 100644 index 000000000000..31e1e9f2d037 --- /dev/null +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-45nm.c @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (C) 2013 Red Hat + * Author: Rob Clark + * Copyright (c) 2023, Linaro Ltd. + */ + +#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 *hdmi_phy) +{ + unsigned long pixclock = hdmi_phy->hdmi_opts.pixel_clk_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 == 27000) { + /* video_format == 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 = 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 *hdmi_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 = { + .clk_names = { "slave_iface" }, + .num_clks = 1, + + .reg_names = { "core-vdda" }, + .num_regs = 1, + + .power_on = qcom_hdmi_msm8x60_phy_power_on, + .power_off = qcom_hdmi_msm8x60_phy_power_off, + + /* FIXME: no PLL support */ +}; diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c index e181a45df2dc..66aa199424b8 100644 --- a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.c @@ -147,20 +147,23 @@ static int qcom_hdmi_preqmp_probe(struct platform_device *pdev) if (ret) return ret; - init.name = "hdmipll"; - init.ops = cfg->pll_ops; - init.flags = CLK_GET_RATE_NOCACHE; - init.parent_data = cfg->pll_parent; - init.num_parents = 1; - - hdmi_phy->pll_hw.init = &init; - ret = devm_clk_hw_register(hdmi_phy->dev, &hdmi_phy->pll_hw); - if (ret) - goto err; - - ret = devm_of_clk_add_hw_provider(hdmi_phy->dev, of_clk_hw_simple_get, &hdmi_phy->pll_hw); - if (ret) - goto err; + /* FIXME: msm8x60 doesn't yet have PLL ops */ + if (cfg->pll_ops) { + init.name = "hdmipll"; + init.ops = cfg->pll_ops; + init.flags = CLK_GET_RATE_NOCACHE; + init.parent_data = cfg->pll_parent; + init.num_parents = 1; + + hdmi_phy->pll_hw.init = &init; + ret = devm_clk_hw_register(hdmi_phy->dev, &hdmi_phy->pll_hw); + if (ret) + goto err; + + ret = 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 = devm_phy_create(dev, pdev->dev.of_node, &qcom_hdmi_preqmp_phy_ops); if (IS_ERR(hdmi_phy->phy)) { @@ -180,6 +183,7 @@ static int qcom_hdmi_preqmp_probe(struct platform_device *pdev) } static const struct of_device_id qcom_hdmi_preqmp_of_match_table[] = { + { .compatible = "qcom,hdmi-phy-8x60", .data = &msm8x60_hdmi_phy_cfg, }, { .compatible = "qcom,hdmi-phy-8960", .data = &msm8960_hdmi_phy_cfg, }, { .compatible = "qcom,hdmi-phy-8974", .data = &msm8974_hdmi_phy_cfg, }, { }, diff --git a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h index bc81d68463ec..66fb9235520a 100644 --- a/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h +++ b/drivers/phy/qualcomm/phy-qcom-hdmi-preqmp.h @@ -74,6 +74,7 @@ static inline u32 hdmi_pll_read(struct qcom_hdmi_preqmp_phy *phy, int offset) 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; From patchwork Thu Sep 28 11:16:22 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402748 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id D72CEE732C7 for ; Thu, 28 Sep 2023 11:18:43 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231843AbjI1LSn (ORCPT ); Thu, 28 Sep 2023 07:18:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39352 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231808AbjI1LSa (ORCPT ); Thu, 28 Sep 2023 07:18:30 -0400 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AAEE7EFF for ; Thu, 28 Sep 2023 04:16:39 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id 2adb3069b0e04-503397ee920so20315438e87.1 for ; Thu, 28 Sep 2023 04:16:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899797; x=1696504597; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ZUcCOVu6ZaxzHiAf2no1lacr8/uO1deQMwqsfTD0Nwk=; b=Ryf+KYOzF8pv+Md0byv9Ai9wy17ExdSUdkMQ8Klf0wKDDulXnUjkiqKEwdWdZCiq8z nFSd5LhLwbIOoqptGgUkIukXHobBNxvGdLRkK71rwRHaCtHL7ILE0eDtLs+RrHzkf+0Z xUIaIq/YSLQelpbOcNmI/hioBtqOEpmSTuo1pWGgoRtAxIhOCTTUKR1y9yvt11HUjQ2D Vi65gIeKgKvR7gKAGsdfX5dhYcWIvmtcX4jTul5q6ofzV1wo8ECUCMmxoaDuEeoPVVm4 vdJ/hQZ6gLZTFt9xENkiPEVhkk78ZwewUUp5ck6+s2twCHqKiflDQeThS9eW2j2zsste cWvg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899797; x=1696504597; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZUcCOVu6ZaxzHiAf2no1lacr8/uO1deQMwqsfTD0Nwk=; b=nVzxPIsVrspupIDYVFe81yqI6hCl5o6jlxeumt0Zb6CgbAJLhxcI2U8+AfSC2UF38e Jk9RnnjpBLY/fR8MC3KiaQZMkZUV4TCkP5P4zBThMdWhYR3Tmc0zc0N14LmVUyDu8ndL bXfJ0aw7YLWMKEpKnva4WuOlmW5KIzereDUMR9Yk5kAnIqW+A1sAtk6ArMwNaVJlAWhT /RFDVm438KSCUgb/xn/NiODEqRHmGs8Sp87z/vypKz7x0ZgAKodKce4/g0taPv3o+Odq deO+Zi0tORXyVI3rBzB056DjNYwovZEjtyv348CDws6q0gpMvTl8g5HHaNRol68sWrvt e23w== X-Gm-Message-State: AOJu0YwaS4dp4OEEBiGe/JeD3UOaHTkJaVbmCOJYK1aZzJEOnD+8dMfI pBseKPJ/yjkGYJxRnL+v2oUd9Q== X-Google-Smtp-Source: AGHT+IGayXiNU18owRcbSjsnuEvUZI+a5/Tg0pK7lvyHa0cMWTUPF+pJZOcVu6K1HD5AKpwp7dZ+ww== X-Received: by 2002:a05:6512:447:b0:503:9a4:26f7 with SMTP id y7-20020a056512044700b0050309a426f7mr844038lfk.40.1695899797684; Thu, 28 Sep 2023 04:16:37 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:37 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 08/15] drm/msm/hdmi: move the alt_iface clock to the hpd list Date: Thu, 28 Sep 2023 14:16:22 +0300 Message-Id: <20230928111630.1217419-9-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org According to the vendor kernel [1] , the alt_iface clock should be enabled together with the rest of HPD clocks, to make HPD to work properly. [1] https://git.codelinaro.org/clo/la/kernel/msm-3.18/-/commit/e07a5487e521e57f76083c0a6e2f995414ac6d03 Reviewed-by: Konrad Dybcio Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index b6bcb9f675fe..75644efe23cb 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -250,9 +250,9 @@ static const struct hdmi_platform_config hdmi_tx_8960_config = { }; static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; -static const char *pwr_clk_names_8x74[] = {"extp", "alt_iface"}; -static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core"}; -static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0}; +static const char *pwr_clk_names_8x74[] = {"extp"}; +static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; +static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0, 0}; static const struct hdmi_platform_config hdmi_tx_8974_config = { HDMI_CFG(pwr_reg, 8x74), From patchwork Thu Sep 28 11:16:23 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402751 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 93EC2E732C6 for ; Thu, 28 Sep 2023 11:18:46 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231167AbjI1LSo (ORCPT ); Thu, 28 Sep 2023 07:18:44 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39326 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232194AbjI1LSa (ORCPT ); Thu, 28 Sep 2023 07:18:30 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3A60283C5 for ; Thu, 28 Sep 2023 04:16:40 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-5045cb9c091so14405499e87.3 for ; Thu, 28 Sep 2023 04:16:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899798; x=1696504598; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=SukUA3fI1tQGNVMdH0ei4U7VI2eWRat+KEt6+0rkX5I=; b=irnWVVbYOoubFdSxeTIXgQCQese9MeV4gXhDOGsY704WHoe33CRyuMjBl/El4p3Gja nsWHSJhQvYySSBR6s2ROq23XkQcfIwkqL6tEd1xJSVoXngi0V9J0HSRpttnAiOIOdqsm JswSy3T2gIg+xI195Z2ZUB3kozxhzq2Ui9btyMHKElAJvDEaRc2PAymLg6q5ayHz/6d8 fxvMKfNiNbsN1ejeI2H43keoHGf+bDNc+UMaMV6ixq58O46ujdgsvXgQXJ+UQgudNU87 O06AV4GKAGC+BqNPqAW54/Za5uXT5RljQBSuRlF7U8PKxl0jxaz+B1tP+wxtOBz4xy8w bKHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899798; x=1696504598; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=SukUA3fI1tQGNVMdH0ei4U7VI2eWRat+KEt6+0rkX5I=; b=R+jIDnaIpqY04PsxolgQ1kwVtXDkv6BTifdzA5O4C+cfxlz2Lumlr1R9imWJLNOurm lpop+FFWVJe45cTxQ/1WrrUpKOyBfG3TEMzjLAzLIKaD/Je4Oki/MjkZC/SKuToTnEBR XKsIMWEBcQJy7RRwipEboD9M5jDW3X/vN8JONypqvfMWjUiwZ4Qi0rkITOQcEka7l2mV zUDSa/1WegGlPDnLqaGGjL3F93ww2xuQgda1iPRJ1PsGZBRjHBOU7cOT8BTQ0+u6Z+lm WUDRwDJ/mAbU9v0A6yfY/qysPu07Dd6sgoL/1Au6wn8ID56TKe3B1pWGr5lL8xKeZiIG f+RA== X-Gm-Message-State: AOJu0Yy6A/EkD6TXtmZlWtUeKvkFaYY8opUi6pVbFMY7HiFdbN8wmMp/ NWjNf30FQ7q4Cs7iRskt+fgvlQ== X-Google-Smtp-Source: AGHT+IFjwHd7NRfnkgGxquMfyXL0IyBGS1TLvEgHewzxNs8qcrQ6uYoRWWPfq5Q1ub1FrAopMDmunA== X-Received: by 2002:a05:6512:485b:b0:503:3707:66ed with SMTP id ep27-20020a056512485b00b00503370766edmr864245lfb.34.1695899798526; Thu, 28 Sep 2023 04:16:38 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:38 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 09/15] drm/msm/hdmi: simplify extp clock handling Date: Thu, 28 Sep 2023 14:16:23 +0300 Message-Id: <20230928111630.1217419-10-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org With the extp being the only "power" clock left, remove the surrounding loops and handle the extp clock directly. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.c | 24 ++++--------------- drivers/gpu/drm/msm/hdmi/hdmi.h | 6 +---- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 33 ++++++++++---------------- 3 files changed, 18 insertions(+), 45 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 75644efe23cb..0425f7560ec5 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -250,13 +250,11 @@ static const struct hdmi_platform_config hdmi_tx_8960_config = { }; static const char *pwr_reg_names_8x74[] = {"core-vdda", "core-vcc"}; -static const char *pwr_clk_names_8x74[] = {"extp"}; static const char *hpd_clk_names_8x74[] = {"iface", "core", "mdp_core", "alt_iface"}; static unsigned long hpd_clk_freq_8x74[] = {0, 19200000, 0, 0}; static const struct hdmi_platform_config hdmi_tx_8974_config = { HDMI_CFG(pwr_reg, 8x74), - HDMI_CFG(pwr_clk, 8x74), HDMI_CFG(hpd_clk, 8x74), .hpd_freq = hpd_clk_freq_8x74, }; @@ -497,24 +495,10 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) hdmi->hpd_clks[i] = clk; } - hdmi->pwr_clks = devm_kcalloc(&pdev->dev, - config->pwr_clk_cnt, - sizeof(hdmi->pwr_clks[0]), - GFP_KERNEL); - if (!hdmi->pwr_clks) - return -ENOMEM; - - for (i = 0; i < config->pwr_clk_cnt; i++) { - struct clk *clk; - - clk = msm_clk_get(pdev, config->pwr_clk_names[i]); - if (IS_ERR(clk)) - return dev_err_probe(dev, PTR_ERR(clk), - "failed to get pwr clk: %s\n", - config->pwr_clk_names[i]); - - hdmi->pwr_clks[i] = clk; - } + hdmi->extp_clk = devm_clk_get_optional(&pdev->dev, "extp"); + if (IS_ERR(hdmi->extp_clk)) + return dev_err_probe(dev, PTR_ERR(hdmi->extp_clk), + "failed to get extp clock\n"); hdmi->hpd_gpiod = devm_gpiod_get_optional(&pdev->dev, "hpd", GPIOD_IN); /* This will catch e.g. -EPROBE_DEFER */ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index e8dbee50637f..2d405da63bd0 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -51,7 +51,7 @@ struct hdmi { struct regulator_bulk_data *hpd_regs; struct regulator_bulk_data *pwr_regs; struct clk **hpd_clks; - struct clk **pwr_clks; + struct clk *extp_clk; struct gpio_desc *hpd_gpiod; @@ -98,10 +98,6 @@ struct hdmi_platform_config { const char **hpd_clk_names; const long unsigned *hpd_freq; int hpd_clk_cnt; - - /* clks that need to be on for screen pwr (ie pixel clk): */ - const char **pwr_clk_names; - int pwr_clk_cnt; }; struct hdmi_bridge { diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 9b1391d27ed3..62ce1455f974 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -25,7 +25,7 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; const struct hdmi_platform_config *config = hdmi->config; - int i, ret; + int ret; pm_runtime_get_sync(&hdmi->pdev->dev); @@ -33,21 +33,15 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); - if (config->pwr_clk_cnt > 0) { + if (hdmi->extp_clk) { DBG("pixclock: %lu", hdmi->pixclock); - ret = clk_set_rate(hdmi->pwr_clks[0], hdmi->pixclock); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to set pixel clk: %s (%d)\n", - config->pwr_clk_names[0], ret); - } - } + ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret); - for (i = 0; i < config->pwr_clk_cnt; i++) { - ret = clk_prepare_enable(hdmi->pwr_clks[i]); - if (ret) { - DRM_DEV_ERROR(dev->dev, "failed to enable pwr clk: %s (%d)\n", - config->pwr_clk_names[i], ret); - } + ret = clk_prepare_enable(hdmi->extp_clk); + if (ret) + DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret); } } @@ -57,15 +51,15 @@ static void power_off(struct drm_bridge *bridge) struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; const struct hdmi_platform_config *config = hdmi->config; - int i, ret; + int ret; /* TODO do we need to wait for final vblank somewhere before * cutting the clocks? */ mdelay(16 + 4); - for (i = 0; i < config->pwr_clk_cnt; i++) - clk_disable_unprepare(hdmi->pwr_clks[i]); + if (hdmi->extp_clk) + clk_disable_unprepare(hdmi->extp_clk); ret = regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); if (ret) @@ -270,7 +264,6 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - const struct hdmi_platform_config *config = hdmi->config; struct msm_drm_private *priv = bridge->dev->dev_private; struct msm_kms *kms = priv->kms; long actual, requested; @@ -284,8 +277,8 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge if (kms->funcs->round_pixclk) actual = kms->funcs->round_pixclk(kms, requested, hdmi_bridge->hdmi->encoder); - else if (config->pwr_clk_cnt > 0) - actual = clk_round_rate(hdmi->pwr_clks[0], requested); + else if (hdmi->extp_clk) + actual = clk_round_rate(hdmi->extp_clk, requested); else actual = requested; From patchwork Thu Sep 28 11:16:24 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402752 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC861E732C5 for ; Thu, 28 Sep 2023 11:18:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231181AbjI1LSq (ORCPT ); Thu, 28 Sep 2023 07:18:46 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39212 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232253AbjI1LSa (ORCPT ); Thu, 28 Sep 2023 07:18:30 -0400 Received: from mail-lf1-x12b.google.com (mail-lf1-x12b.google.com [IPv6:2a00:1450:4864:20::12b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 0E07083C8 for ; Thu, 28 Sep 2023 04:16:41 -0700 (PDT) Received: by mail-lf1-x12b.google.com with SMTP id 2adb3069b0e04-50307759b65so20730627e87.0 for ; Thu, 28 Sep 2023 04:16:40 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899799; x=1696504599; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=HlnLygFYYtSxoKEaC5DFXDBhNuXumh16hVtzEXEvSec=; b=IZ9UD6Hp5lp4A5sU5mSeXMtj3VfmWJVVGifMjsmseGhOGfidhBNQt8haKW1IlAjpiQ mIY/+/M47EKKWrs4r1p73erKw80ZUUw4/gdQ5/JF0yeGQW+QLmeJtxAKE6iu2mCujMNv 6aP70eTYY3NGJpMQai6uKXIjcu9P65keNfiPPHXNRB4F4xoVRWxFJPyN8vakjzAh6oP2 6ypLAXPsA2AhtOgkiBUIrw4Vu0wcG6gytpTjqQS2KU+5O23xbOz58bFlxZumLda2Wmzx 7rF93xyA6whpDUpw1VfqtiMBBROqnoKCO3jlzLWckSz6bQaFEWd+RLt0FVrir37a85AX xavw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899799; x=1696504599; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=HlnLygFYYtSxoKEaC5DFXDBhNuXumh16hVtzEXEvSec=; b=OBv2rYriPkue50mXHfuGkKOFSXtkgjs9iRLQ8QV1BeksGyM6NdgJdbybXYzvksEgQm 8pQGyxekmIGvvSHXld4DJy1C3Y98RD8gdADTfUkf7BSRiXwvVbGDpw0bSrtLIuZwXmab d/oPKHwp7Pk61d++hs6vRq8Iqg5NfvoafRSDdsx6AcaCbJBFFw6GntE3FazyHWaZTZa2 Nc641Um1SZLAW2cPxdx3EYKbxkjzRw9BCB39LPnPygixkStPOgpisMYZ4noq8B/Xv1qe Ck1IUkF+MMsB8X6MnRUg7h8sH494k4Cz0moUXC4RYtGBqoWpulZ+P0UAhAGfvIrsm5pc JFmQ== X-Gm-Message-State: AOJu0YxKPwncVL3F0iEgrPrp9jeZmEOV9qJOy0f77EVf2gDEYHay8SW5 NcqC6WWWE7vE+Sx68Ywcimeg/g== X-Google-Smtp-Source: AGHT+IHs4BEIb3K6wYvwHxL4p5CqDe1+YQl/dXfmh3TBE8urT/HY3ABoF5hl90DcpvKbMm8Y9pmZ2Q== X-Received: by 2002:a19:790c:0:b0:500:8fcd:c3b5 with SMTP id u12-20020a19790c000000b005008fcdc3b5mr772169lfc.12.1695899799367; Thu, 28 Sep 2023 04:16:39 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.38 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:38 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 10/15] drm/msm/hdmi: correct indentation of HDMI bridge functions Date: Thu, 28 Sep 2023 14:16:24 +0300 Message-Id: <20230928111630.1217419-11-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Signed-off-by: Dmitry Baryshkov Reviewed-by: Konrad Dybcio --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 62ce1455f974..fbcf4dd91cd9 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -291,12 +291,12 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge } static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { - .pre_enable = msm_hdmi_bridge_pre_enable, - .post_disable = msm_hdmi_bridge_post_disable, - .mode_set = msm_hdmi_bridge_mode_set, - .mode_valid = msm_hdmi_bridge_mode_valid, - .get_edid = msm_hdmi_bridge_get_edid, - .detect = msm_hdmi_bridge_detect, + .pre_enable = msm_hdmi_bridge_pre_enable, + .post_disable = msm_hdmi_bridge_post_disable, + .mode_set = msm_hdmi_bridge_mode_set, + .mode_valid = msm_hdmi_bridge_mode_valid, + .get_edid = msm_hdmi_bridge_get_edid, + .detect = msm_hdmi_bridge_detect, }; static void From patchwork Thu Sep 28 11:16:25 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402753 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DB248E732C4 for ; Thu, 28 Sep 2023 11:18:47 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231874AbjI1LSr (ORCPT ); Thu, 28 Sep 2023 07:18:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39420 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231849AbjI1LSb (ORCPT ); Thu, 28 Sep 2023 07:18:31 -0400 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 2C92C83CA for ; Thu, 28 Sep 2023 04:16:42 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id 2adb3069b0e04-5048156976cso4645353e87.2 for ; Thu, 28 Sep 2023 04:16:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899800; x=1696504600; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JRCcVx5yqkWjx+j8HRIisuUziAvNRbEhBQXvfMXuZd8=; b=WFK5J1zSwNBNSwETVxoizEI4AruTWQt/f6GdK/l/z+/fYOyDSonbX2GJOZPuyjMJ67 L3EZM8I8CbRqeeUJSGxQ1tz2tplgdABd0w9ifytLKrl1+JT7CH5Qyxtli3/2mXVEGpAf 8PoSdl3RKIZYEfAbiq8OXaiI4fBWUMNQgeJ471qmzzdJ9fgtixwu94rQjQ2WjYxLBsjS bsUP7RcGel70QaQP47EMrPsGEYm5NXreoNLE81kN1gVSKRCJGzIKR+SdeR/d6ZpVLESS VMZex6ctIy8ufqHwrVdrUUnKiP4EJ4OfendkYA0bxf/5qG29M8kzZraYwPMw0rPm66qK UxYQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899800; x=1696504600; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JRCcVx5yqkWjx+j8HRIisuUziAvNRbEhBQXvfMXuZd8=; b=mxpGAhthu2/U4B5kPmfQgtxaya+xRBtFN/yVVWouDUSfq3aUCSCc/jd0MPLLNd56W7 EMRueOSa7677Xx5x4IRBRCToXS0uqU2EYT9GIXtgIU1F+cJio/JTZ9BsqCi9bS7PAeIz V+VOOZ9Ps/VIeJ73PjTfdf9WezKXMoeVyhAH50Kq84RKPFGgsNpq7hFygeqQNHhRCgry 8SDsOV6cY/m5JHHDwWdELhjbcwc8QTxIGQtjMwYtbIve4n8CUvesreas3SzGbgF3aFxH G8o6xPM/CmFbYkUlAjNsQnuuoa7B3sKUCBo48e9SOJvGpaOiXu41QtU2vuq+S1P+W3AW AOQA== X-Gm-Message-State: AOJu0YxrrSTMEKN9juWvasIVsK60uCQaHPcJ0wjZ2RaA8EIyGE6atX/R pXUxFzZwNfQKB/FWXiynAYLWPg== X-Google-Smtp-Source: AGHT+IHLwo684MahSmAYShlLDvoSRmHtO8mYnv5mhthJNX/V/OPt/lEcKL7/YqjqaMYb1p94sDMhnA== X-Received: by 2002:a19:791c:0:b0:4fe:8ba8:16a9 with SMTP id u28-20020a19791c000000b004fe8ba816a9mr737263lfc.55.1695899800332; Thu, 28 Sep 2023 04:16:40 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.39 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:39 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 11/15] drm/msm/hdmi: switch to atomic_pre_enable/post_disable Date: Thu, 28 Sep 2023 14:16:25 +0300 Message-Id: <20230928111630.1217419-12-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org In preparation of reworking the HDMI mode setting, switch pre_enable and post_disable callbacks to their atomic variants. Signed-off-by: Dmitry Baryshkov Acked-by: Konrad Dybcio --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index fbcf4dd91cd9..f9293f7d8f34 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -128,7 +128,8 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL1, val); } -static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) +static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; @@ -154,7 +155,8 @@ static void msm_hdmi_bridge_pre_enable(struct drm_bridge *bridge) msm_hdmi_hdcp_on(hdmi->hdcp_ctrl); } -static void msm_hdmi_bridge_post_disable(struct drm_bridge *bridge) +static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_bridge_state *old_bridge_state) { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; @@ -291,8 +293,13 @@ static enum drm_mode_status msm_hdmi_bridge_mode_valid(struct drm_bridge *bridge } static const struct drm_bridge_funcs msm_hdmi_bridge_funcs = { - .pre_enable = msm_hdmi_bridge_pre_enable, - .post_disable = msm_hdmi_bridge_post_disable, + .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state, + .atomic_reset = drm_atomic_helper_bridge_reset, + + .atomic_pre_enable = msm_hdmi_bridge_atomic_pre_enable, + .atomic_post_disable = msm_hdmi_bridge_atomic_post_disable, + .mode_set = msm_hdmi_bridge_mode_set, .mode_valid = msm_hdmi_bridge_mode_valid, .get_edid = msm_hdmi_bridge_get_edid, From patchwork Thu Sep 28 11:16:26 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402754 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 762A0E732C6 for ; Thu, 28 Sep 2023 11:18:49 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231849AbjI1LSs (ORCPT ); Thu, 28 Sep 2023 07:18:48 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39312 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232261AbjI1LSb (ORCPT ); Thu, 28 Sep 2023 07:18:31 -0400 Received: from mail-lf1-x136.google.com (mail-lf1-x136.google.com [IPv6:2a00:1450:4864:20::136]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 09F3E83CB for ; Thu, 28 Sep 2023 04:16:43 -0700 (PDT) Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-503f39d3236so20724407e87.0 for ; Thu, 28 Sep 2023 04:16:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899801; x=1696504601; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=kMftiAUxeR8BPoZkZvXeNvb1WLgqdhL6DsPjfLjpExg=; b=zSWFCzVM4492+iV9eM7FJbsIoO/58pSMn15jq6BUwaln8uo2W2TzkBGY28SkUgaHbW zauZExgAZYL9as5IKOGC/qOM1MB0xOprZd8sELrnYsucQDKCQMj44P7q9NbknehTgeL4 DxljqCdwKdoQWJfV6Rdghbmm9FXWBnmR0PIeuwgfZx3fwsHsHkh0KvrGvb+JBQ1LFZ00 mSMv8ffd4Flw0S5VnPuG2ywDgaI8hJ3/M0NZirV2UHn3qJVzHXks4ggD/+Ik6GiD9Mc8 +KRpMHzT2h1yYLAZiEYZP9k63FN6y2z0bHt5vz49kD505+9G1lja98JvAx+JOuAZTdFr IEIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899801; x=1696504601; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=kMftiAUxeR8BPoZkZvXeNvb1WLgqdhL6DsPjfLjpExg=; b=Kg0Ferzw2YWePRJBRU4C4C5OaC+B539mYCjjBFmFfC00GY2P66PVXe2oEBnKlGycu4 66W6aEysoUcmj4an5zCB0eQO9YcpHfekK5Gk1uKANHxviMeBqHazDFo/qkdH8mTszp2k s70nqKkcCQxeyt4bQLaytwjv+BQmSyaIR+UN5l9JZGSPtdUaGl4ladEBVjckufFw4xly cPiSLdcSkMg2RiB+I8klQ7UDK57QMhkLxuWpmjSFOQucnKBx7XDiipjzIUUYosYaEN/H aTjNAR8jksA/jWMy7xISoMyjKBeo7EPu+xYCmI7Nf0EtYjGp+ACjgrOzFy7E/7H5KcxT 4GuQ== X-Gm-Message-State: AOJu0YxtjGw8/Ufa8udfKmdWrKL/znhYOV/QuO6CV0sB8HjgU1Sj5YAQ LASQRzqUxGqcMdY2QnL3rLgQzQ== X-Google-Smtp-Source: AGHT+IGJuLOW0z+nyXsjDWy/AhORRPbvfkWB2Dltrt556qDZ0CEwO2DNjEzeGytc0iYjtCSew21T2A== X-Received: by 2002:a19:4304:0:b0:4ff:7046:984a with SMTP id q4-20020a194304000000b004ff7046984amr733375lfa.7.1695899801373; Thu, 28 Sep 2023 04:16:41 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:40 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 12/15] drm/msm/hdmi: set infoframes on all pre_enable calls Date: Thu, 28 Sep 2023 14:16:26 +0300 Message-Id: <20230928111630.1217419-13-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org In consequent modeset calls, the atomic_pre_enable() will be called several times without calling atomic_post_disable() inbetween. Thus iframes will not be updated for the next mode. Fix this by setting the iframe outside of the !power_on check. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index f9293f7d8f34..bb10b35194ff 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -141,10 +141,11 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, msm_hdmi_phy_resource_enable(phy); msm_hdmi_power_on(bridge); hdmi->power_on = true; - if (hdmi->hdmi_mode) { - msm_hdmi_config_avi_infoframe(hdmi); - msm_hdmi_audio_update(hdmi); - } + } + + if (hdmi->hdmi_mode) { + msm_hdmi_config_avi_infoframe(hdmi); + msm_hdmi_audio_update(hdmi); } msm_hdmi_phy_powerup(phy, hdmi->pixclock); From patchwork Thu Sep 28 11:16:27 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402756 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 63DE1E732C4 for ; Thu, 28 Sep 2023 11:18:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231963AbjI1LSt (ORCPT ); Thu, 28 Sep 2023 07:18:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39536 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232266AbjI1LSb (ORCPT ); Thu, 28 Sep 2023 07:18:31 -0400 Received: from mail-lf1-x12e.google.com (mail-lf1-x12e.google.com [IPv6:2a00:1450:4864:20::12e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 20C5E83CC for ; Thu, 28 Sep 2023 04:16:44 -0700 (PDT) Received: by mail-lf1-x12e.google.com with SMTP id 2adb3069b0e04-50336768615so21756268e87.0 for ; Thu, 28 Sep 2023 04:16:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899802; x=1696504602; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=enSUc5wVEHF7eZy9e0DAWbElAzfosEhYHkkqQR9evEU=; b=YCkKHz3rrGGC1VSdDkvj2/K0Yc0KhKzNNsTR+9k//LgvRnpeWLNIw24iRkFajWm+rt HxlBlrxf933j+Mz0Acz5MvVkBmCYoJA555yrNxEQzICQKrcyMx2/C96v5+IQkUMvAPCg ok+KLoovk86jjHLgVRm0M+LHHShkJQHX4jGsHQM7dBe4hSDPTJp5AbJf/jb7KgPj7hJp hW7Y1pVwPMAotJIVbQ39W8DfU9Xm6kyIEB1CGvis0zJLQTx+bolfFIVGkYSmJgtRK/KE reUScKWwFXhlpPAq7ks6yx173wncccBRjvJ9pg6+WR9j8b0iANcAJSTRym1Rny35nUwa M4pw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899802; x=1696504602; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=enSUc5wVEHF7eZy9e0DAWbElAzfosEhYHkkqQR9evEU=; b=WqPMf+a49PkZHNVekKef9MlduPYLVtn1LK3QQT8i6PwPoMbTEfV3nAUoOEPYm4Y9BG bgRpLtH8E0hoIxZRlNGZtyezBknRUk0QMZmXJxiR/2+ZpAjR2nTkUZGHRbRERDab//Fl XpT2u5smB5zaEfu6Mh/sGQnWa/O5hxTcVi71fYM7SFjcnVVyAkr4I750b1c7dbkfteC0 LkPZqolgFnsi7L1KpfxMOryO4tEAvtx/2Ts8UVNtAAKn0abmrI5cWH1UVJIRB1cjx/LB ogSh+s3m8EmmuocTefWdHzBYnG/6EY392jQMEwdGeSCb0lhuO3gkwP250dRQ30rkAy73 pMpg== X-Gm-Message-State: AOJu0YwnFZyC38h3ie8PqvNw3kOetaI/QqS80CBEHe4Vu+qfMuPYxrzf mYHEF9r9VnLdeibkA29lZ0Ddebw3Cpr+BqfWj0pKkw== X-Google-Smtp-Source: AGHT+IGwCeckW7pWu4XX3/cIFXJn7uNwvwln041/BMgKyIZsfbVBTMcODI67KjHZ8k4db5jC4PvYXA== X-Received: by 2002:a05:6512:2148:b0:500:9bbf:da17 with SMTP id s8-20020a056512214800b005009bbfda17mr689312lfr.51.1695899802188; Thu, 28 Sep 2023 04:16:42 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.41 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:41 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 13/15] drm/msm/hdmi: pair msm_hdmi_phy_powerup with msm_hdmi_phy_powerdown Date: Thu, 28 Sep 2023 14:16:27 +0300 Message-Id: <20230928111630.1217419-14-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org In preparation to converting MSM HDMI driver to use PHY framework, which requires phy_power_on() calls to be paired with phy_power_off(), add a conditional call to msm_hdmi_phy_powerdown() before the call to msm_hdmi_phy_powerup(). Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi.h | 1 + drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.h b/drivers/gpu/drm/msm/hdmi/hdmi.h index 2d405da63bd0..46ae7ef9bc98 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.h +++ b/drivers/gpu/drm/msm/hdmi/hdmi.h @@ -42,6 +42,7 @@ struct hdmi { /* video state: */ bool power_on; + bool phy_power_on; unsigned long int pixclock; void __iomem *mmio; diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index bb10b35194ff..1bbd76e595af 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -148,7 +148,11 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, msm_hdmi_audio_update(hdmi); } + if (hdmi->phy_power_on) + msm_hdmi_phy_powerdown(phy); + msm_hdmi_phy_powerup(phy, hdmi->pixclock); + hdmi->phy_power_on = true; msm_hdmi_set_mode(hdmi, true); @@ -170,6 +174,7 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, msm_hdmi_set_mode(hdmi, false); msm_hdmi_phy_powerdown(phy); + hdmi->phy_power_on = false; if (hdmi->power_on) { power_off(bridge); From patchwork Thu Sep 28 11:16:28 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402755 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id A21B9E732C7 for ; Thu, 28 Sep 2023 11:18:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231788AbjI1LSr (ORCPT ); Thu, 28 Sep 2023 07:18:47 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39484 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232259AbjI1LSb (ORCPT ); Thu, 28 Sep 2023 07:18:31 -0400 Received: from mail-lj1-x229.google.com (mail-lj1-x229.google.com [IPv6:2a00:1450:4864:20::229]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9782083CD for ; Thu, 28 Sep 2023 04:16:44 -0700 (PDT) Received: by mail-lj1-x229.google.com with SMTP id 38308e7fff4ca-2c007d6159aso207108341fa.3 for ; Thu, 28 Sep 2023 04:16:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899803; x=1696504603; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=JB7b//YXpSyikV68jb2A2pRpIR9zRWpK7Dv7qSPSg7I=; b=c0E8mpsIeoM/0N6m0a6OE18W/LLuJ7rr8FsPoMZjrxVZtb1cW5N4ghhs3nTBu9+K7Q xJ0RaREFUEPO4OiUABtWETk+lq78+FBmFi9tuY2+RRKODo3sDpBlvAgtCtmSBfoM2TFN 3EJokSJ6wuIT7rz8P+v/I/kUralfcqJEwPg0xjc8jgrVX5Ydn/rP9UtpnKzR2KOzpC7W aL93JeDa5d40Tj0hezM+hpUj4t/w8+t414AxRa38sokj0sSqqSjp+kZ+29DE6U+mpIPr VPLzdtw+jD8K9LUogjvCh8CY612rYHBGugiOcy+ypFmZlRotHCEtaRAK8byro+Od89U9 P3vA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899803; x=1696504603; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JB7b//YXpSyikV68jb2A2pRpIR9zRWpK7Dv7qSPSg7I=; b=o2VuEua6migQzuiJq1DaKBQFU8CMzFd+8OZ4A+lMKYTCZwy5LlYn1dqCpCY6txvdLi mmCyZlarV+YbpYO/pWqdu4QVFurHuBCYdZrA4PxojBc+tatFtfgHaZokTKPoTu5LTWJi 2Xc36MOnHNaNbqvNCxB3KCiJP47EhkCfgf2gRRdeKH+Wzc+RkVz7ZHj13Tsz2DHNaT/9 FdmUom1C42lJE1hHMlRNIEN/AIz1jpfjvsZceQus8bvel23xKDWBILoecvdapQ6dAUVB UUsDHOZkSKF7Wx7sx1bmE/L3Di6CfaejJVZODaWbGtb7y4d6lJaz9+P/Qdy1NF3/fjx7 +CHw== X-Gm-Message-State: AOJu0YyrhuPKNZba8HpjLT6j4PBvjKKqlYlTmXZPA8bQk+c1vanaXLel crXaj3GHwQ2Z8iQWAEw1CVEiLA== X-Google-Smtp-Source: AGHT+IEOxhc7jkAT6TrYvdH9fjQRB0rsH9dMnTZ6/Lhw2rJK1RTZk1t/wC7wrjf97lssYKd8L8A46Q== X-Received: by 2002:a05:6512:2808:b0:503:2623:7cfa with SMTP id cf8-20020a056512280800b0050326237cfamr1037001lfb.35.1695899802871; Thu, 28 Sep 2023 04:16:42 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:42 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 14/15] drm/msm/hdmi: switch to generic PHY subsystem Date: Thu, 28 Sep 2023 14:16:28 +0300 Message-Id: <20230928111630.1217419-15-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org 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 Acked-by: Konrad Dybcio --- drivers/gpu/drm/msm/Makefile | 6 --- drivers/gpu/drm/msm/hdmi/hdmi.c | 60 +++------------------ drivers/gpu/drm/msm/hdmi/hdmi.h | 72 +------------------------- drivers/gpu/drm/msm/hdmi/hdmi_bridge.c | 58 +++++++++++++-------- 4 files changed, 45 insertions(+), 151 deletions(-) diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile index 8d02d8c33069..908c79702864 100644 --- a/drivers/gpu/drm/msm/Makefile +++ b/drivers/gpu/drm/msm/Makefile @@ -23,12 +23,6 @@ msm-$(CONFIG_DRM_MSM_HDMI) += \ 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_8x60.o \ - hdmi/hdmi_phy_8x74.o \ - hdmi/hdmi_pll_8960.o \ msm-$(CONFIG_DRM_MSM_MDP4) += \ disp/mdp4/mdp4_crtc.o \ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c index 0425f7560ec5..d1ab282fec44 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi.c @@ -7,8 +7,7 @@ #include #include -#include -#include +#include #include #include @@ -74,44 +73,6 @@ static void msm_hdmi_destroy(struct hdmi *hdmi) msm_hdmi_i2c_destroy(hdmi->i2c); } -static void msm_hdmi_put_phy(struct hdmi *hdmi) -{ - if (hdmi->phy_dev) { - put_device(hdmi->phy_dev); - hdmi->phy = NULL; - hdmi->phy_dev = NULL; - } -} - -static int msm_hdmi_get_phy(struct hdmi *hdmi) -{ - struct platform_device *pdev = hdmi->pdev; - struct platform_device *phy_pdev; - struct device_node *phy_node; - - phy_node = 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 = 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 = 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 = &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 @@ -512,36 +473,31 @@ static int msm_hdmi_dev_probe(struct platform_device *pdev) if (hdmi->hpd_gpiod) gpiod_set_consumer_name(hdmi->hpd_gpiod, "HDMI_HPD"); - ret = msm_hdmi_get_phy(hdmi); - if (ret) { + hdmi->phy = 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); } ret = devm_pm_runtime_enable(&pdev->dev); if (ret) - goto err_put_phy; + goto err; platform_set_drvdata(pdev, hdmi); ret = component_add(&pdev->dev, &msm_hdmi_ops); if (ret) - goto err_put_phy; + goto err; return 0; -err_put_phy: - msm_hdmi_put_phy(hdmi); +err: return ret; } static void msm_hdmi_dev_remove(struct platform_device *pdev) { - struct hdmi *hdmi = dev_get_drvdata(&pdev->dev); - component_del(&pdev->dev, &msm_hdmi_ops); - - msm_hdmi_put_phy(hdmi); } static const struct of_device_id msm_hdmi_dt_match[] = { @@ -565,12 +521,10 @@ static struct platform_driver msm_hdmi_driver = { void __init msm_hdmi_register(void) { - msm_hdmi_phy_driver_register(); platform_driver_register(&msm_hdmi_driver); } 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/hdmi.h index 46ae7ef9bc98..d68ac7aaf1f2 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" -struct hdmi_phy; struct hdmi_platform_config; struct hdmi_audio { @@ -56,8 +55,7 @@ struct hdmi { struct gpio_desc *hpd_gpiod; - struct hdmi_phy *phy; - struct device *phy_dev; + struct phy *phy; struct i2c_adapter *i2c; struct drm_connector *connector; @@ -125,74 +123,6 @@ static inline u32 hdmi_qfprom_read(struct hdmi *hdmi, u32 reg) return msm_readl(hdmi->qfprom_mmio + reg); } -/* - * 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_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; - -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) -{ - msm_writel(data, phy->mmio + reg); -} - -static inline u32 hdmi_phy_read(struct hdmi_phy *phy, u32 reg) -{ - return msm_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); -#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; -} -#endif - /* * audio: */ diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c index 1bbd76e595af..345ca892988d 100644 --- a/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c +++ b/drivers/gpu/drm/msm/hdmi/hdmi_bridge.c @@ -5,6 +5,7 @@ */ #include +#include #include #include @@ -32,17 +33,6 @@ static void msm_hdmi_power_on(struct drm_bridge *bridge) ret = regulator_bulk_enable(config->pwr_reg_cnt, hdmi->pwr_regs); if (ret) DRM_DEV_ERROR(dev->dev, "failed to enable pwr regulator: %d\n", ret); - - if (hdmi->extp_clk) { - DBG("pixclock: %lu", hdmi->pixclock); - ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to set extp clk rate: %d\n", ret); - - ret = clk_prepare_enable(hdmi->extp_clk); - if (ret) - DRM_DEV_ERROR(dev->dev, "failed to enable extp clk: %d\n", ret); - } } static void power_off(struct drm_bridge *bridge) @@ -58,9 +48,6 @@ static void power_off(struct drm_bridge *bridge) */ mdelay(16 + 4); - if (hdmi->extp_clk) - clk_disable_unprepare(hdmi->extp_clk); - ret = regulator_bulk_disable(config->pwr_reg_cnt, hdmi->pwr_regs); if (ret) DRM_DEV_ERROR(dev->dev, "failed to disable pwr regulator: %d\n", ret); @@ -131,14 +118,21 @@ static void msm_hdmi_config_avi_infoframe(struct hdmi *hdmi) static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state) { + struct drm_atomic_state *state = old_bridge_state->base.state; struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - struct hdmi_phy *phy = hdmi->phy; + struct drm_connector *connector; + union phy_configure_opts phy_opts; + int ret; DBG("power up"); + connector = drm_atomic_get_new_connector_for_encoder(state, bridge->encoder); + if (WARN_ON(!connector)) + return; + if (!hdmi->power_on) { - msm_hdmi_phy_resource_enable(phy); + phy_init(hdmi->phy); msm_hdmi_power_on(bridge); hdmi->power_on = true; } @@ -149,9 +143,27 @@ static void msm_hdmi_bridge_atomic_pre_enable(struct drm_bridge *bridge, } if (hdmi->phy_power_on) - msm_hdmi_phy_powerdown(phy); + phy_power_off(hdmi->phy); + + phy_opts.hdmi.pixel_clk_rate = hdmi->pixclock / 1000; + phy_opts.hdmi.bpc = connector->display_info.bpc; + phy_opts.hdmi.color_space = HDMI_COLORSPACE_RGB; + phy_configure(hdmi->phy, &phy_opts); + + ret = phy_power_on(hdmi->phy); + if (WARN_ON(ret)) + return; + + if (hdmi->extp_clk) { + ret = clk_set_rate(hdmi->extp_clk, hdmi->pixclock); + if (ret) + DRM_DEV_ERROR(bridge->dev->dev, "failed to set extp clk rate: %d\n", ret); + + ret = clk_prepare_enable(hdmi->extp_clk); + if (ret) + DRM_DEV_ERROR(bridge->dev->dev, "failed to enable extp clk: %d\n", ret); + } - msm_hdmi_phy_powerup(phy, hdmi->pixclock); hdmi->phy_power_on = true; msm_hdmi_set_mode(hdmi, true); @@ -165,7 +177,6 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, { struct hdmi_bridge *hdmi_bridge = to_hdmi_bridge(bridge); struct hdmi *hdmi = hdmi_bridge->hdmi; - struct hdmi_phy *phy = hdmi->phy; if (hdmi->hdcp_ctrl) msm_hdmi_hdcp_off(hdmi->hdcp_ctrl); @@ -173,7 +184,12 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, DBG("power down"); msm_hdmi_set_mode(hdmi, false); - msm_hdmi_phy_powerdown(phy); + if (hdmi->phy_power_on) { + if (hdmi->extp_clk) + clk_disable_unprepare(hdmi->extp_clk); + + phy_power_off(hdmi->phy); + } hdmi->phy_power_on = false; if (hdmi->power_on) { @@ -181,7 +197,7 @@ static void msm_hdmi_bridge_atomic_post_disable(struct drm_bridge *bridge, hdmi->power_on = false; if (hdmi->hdmi_mode) msm_hdmi_audio_update(hdmi); - msm_hdmi_phy_resource_disable(phy); + phy_exit(hdmi->phy); } } From patchwork Thu Sep 28 11:16:29 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dmitry Baryshkov X-Patchwork-Id: 13402757 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C3292E732C5 for ; Thu, 28 Sep 2023 11:18:52 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232002AbjI1LSu (ORCPT ); Thu, 28 Sep 2023 07:18:50 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39520 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231869AbjI1LSb (ORCPT ); Thu, 28 Sep 2023 07:18:31 -0400 Received: from mail-lf1-x132.google.com (mail-lf1-x132.google.com [IPv6:2a00:1450:4864:20::132]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9775583CE for ; Thu, 28 Sep 2023 04:16:45 -0700 (PDT) Received: by mail-lf1-x132.google.com with SMTP id 2adb3069b0e04-5041bb9ce51so20500508e87.1 for ; Thu, 28 Sep 2023 04:16:45 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; t=1695899804; x=1696504604; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Dfc4m5ONh+/VOFcNRm2XefgcSK0PxRNUjlUnClEoS4c=; b=cRawQy1gzB7CElyWtSOHMtc7rQSBT6TxsaupX6W8Hhe7O9WT4kHjt3qr6H9crX/Ns8 VZimygXQH8PX+CSE6aPov3qqLwtWQz+VtM0iSy/faJT45PY4h4/Z2pnS6ycCBJjgBD5j 5o4vwlMCMmn8h46m0HqSJ1ItevXUYSLsEySSJiliuAdFR8Ri1v0zbtEQZZCSapDSgCZR fHHqqa2R2IrXxH7hzqw/NsGV4EMU7J722hiG6uc0WGpriM7hkbuiADa3xcQFwmyz9fbT HNLXQ7EZkbwbjvXKUKzl/k3vrlTxzyjD11IjfZGa2eQvR1uH6ii6XjuDkc20eXMh5A/r 16HQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1695899804; x=1696504604; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Dfc4m5ONh+/VOFcNRm2XefgcSK0PxRNUjlUnClEoS4c=; b=KpnmXbl//6k9Jk3Mmc7miL/z96EmKjQ4vwv5inUpKhDEp/KvfHhF+Xe1lfk3hy5UVU 5z8qvlue9NTNHHkF6aaZOOGjfzEomnmDkwAGGz7IlzT0o8bO9XJbzqX4pGsxFn53N3UB QbUjCbzKyM/R/o+5h+ytaxthDjlP8qax/lR05k0BpDYdOTko8YpIKAIkSvFKqXpsN1pm Bjvm/YOF85ZVSzmG9wn4TUxrTPyKnHzxbvsc7u1kTvpHzx1xhGZ30zLgjkYYvNZ2F5IN XE+Wzj0Eb3m0q6yCIrdW06ohxH6xfwJ01haDkcQaq0n9K9lVmalt0/Ha1QOl7lDa+Cbw gfjA== X-Gm-Message-State: AOJu0Yx3YJb+yunQkHfVNI8WYoEZ7pEHnJkgQFiCgL9yy3ze4QWfgYmW Mbzxenwv9fUYSdTS1K8cL8euZcgkCwohuDam0HTCgw== X-Google-Smtp-Source: AGHT+IHqq4Gz83oBemgXZ5/2v1o+GPUuRXzKPAeKVV8Qyb6wT8p5q0L7gFWxCQJwQTozMtm2sM8aYA== X-Received: by 2002:a05:6512:1246:b0:502:cc8d:f1fc with SMTP id fb6-20020a056512124600b00502cc8df1fcmr1133259lfb.37.1695899803629; Thu, 28 Sep 2023 04:16:43 -0700 (PDT) Received: from umbar.unikie.fi ([192.130.178.91]) by smtp.gmail.com with ESMTPSA id j18-20020ac253b2000000b004fb738796casm3086623lfh.40.2023.09.28.04.16.43 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 28 Sep 2023 04:16:43 -0700 (PDT) From: Dmitry Baryshkov To: Rob Clark , Sean Paul , Abhinav Kumar , Marijn Suijten , Vinod Koul , Kishon Vijay Abraham I Cc: Philipp Zabel , Stephen Boyd , David Airlie , Daniel Vetter , Bjorn Andersson , Konrad Dybcio , linux-arm-msm@vger.kernel.org, dri-devel@lists.freedesktop.org, freedreno@lists.freedesktop.org, linux-phy@lists.infradead.org Subject: [PATCH v3 15/15] drm/msm/hdmi: drop old HDMI PHY code Date: Thu, 28 Sep 2023 14:16:29 +0300 Message-Id: <20230928111630.1217419-16-dmitry.baryshkov@linaro.org> X-Mailer: git-send-email 2.39.2 In-Reply-To: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> References: <20230928111630.1217419-1-dmitry.baryshkov@linaro.org> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Drop source files used by old HDMI PHY and HDMI PLL drivers. Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/msm/hdmi/hdmi_phy.c | 216 ------- 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_8x60.c | 141 ----- drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c | 44 -- drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c | 458 -------------- 6 files changed, 1675 deletions(-) delete mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_phy.c delete mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_phy_8960.c delete mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_phy_8996.c delete mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_phy_8x60.c delete mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_phy_8x74.c delete mode 100644 drivers/gpu/drm/msm/hdmi/hdmi_pll_8960.c 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 88a3423b7f24..000000000000 --- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c +++ /dev/null @@ -1,216 +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 = phy->cfg; - struct device *dev = &phy->pdev->dev; - int i, ret; - - phy->regs = devm_kcalloc(dev, cfg->num_regs, sizeof(phy->regs[0]), - GFP_KERNEL); - if (!phy->regs) - return -ENOMEM; - - phy->clks = devm_kcalloc(dev, cfg->num_clks, sizeof(phy->clks[0]), - GFP_KERNEL); - if (!phy->clks) - return -ENOMEM; - - for (i = 0; i < cfg->num_regs; i++) - phy->regs[i].supply = cfg->reg_names[i]; - - ret = devm_regulator_bulk_get(dev, cfg->num_regs, phy->regs); - if (ret) { - if (ret != -EPROBE_DEFER) - DRM_DEV_ERROR(dev, "failed to get phy regulators: %d\n", ret); - - return ret; - } - - for (i = 0; i < cfg->num_clks; i++) { - struct clk *clk; - - clk = msm_clk_get(phy->pdev, cfg->clk_names[i]); - if (IS_ERR(clk)) { - ret = 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] = clk; - } - - return 0; -} - -int msm_hdmi_phy_resource_enable(struct hdmi_phy *phy) -{ - struct hdmi_phy_cfg *cfg = phy->cfg; - struct device *dev = &phy->pdev->dev; - int i, ret = 0; - - pm_runtime_get_sync(dev); - - ret = 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 = 0; i < cfg->num_clks; i++) { - ret = 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 = phy->cfg; - struct device *dev = &phy->pdev->dev; - int i; - - for (i = cfg->num_clks - 1; i >= 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 = msm_hdmi_pll_8960_init(pdev); - break; - case MSM_HDMI_PHY_8996: - ret = msm_hdmi_pll_8996_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 = 0; - break; - } - - return ret; -} - -static int msm_hdmi_phy_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct hdmi_phy *phy; - int ret; - - phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); - if (!phy) - return -ENODEV; - - phy->cfg = (struct hdmi_phy_cfg *)of_device_get_match_data(dev); - if (!phy->cfg) - return -ENODEV; - - phy->mmio = 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 = pdev; - - ret = msm_hdmi_phy_resource_init(phy); - if (ret) - return ret; - - pm_runtime_enable(&pdev->dev); - - ret = msm_hdmi_phy_resource_enable(phy); - if (ret) - return ret; - - ret = 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[] = { - { .compatible = "qcom,hdmi-phy-8660", - .data = &msm_hdmi_phy_8x60_cfg }, - { .compatible = "qcom,hdmi-phy-8960", - .data = &msm_hdmi_phy_8960_cfg }, - { .compatible = "qcom,hdmi-phy-8974", - .data = &msm_hdmi_phy_8x74_cfg }, - { .compatible = "qcom,hdmi-phy-8084", - .data = &msm_hdmi_phy_8x74_cfg }, - { .compatible = "qcom,hdmi-phy-8996", - .data = &msm_hdmi_phy_8996_cfg }, - {} -}; - -static struct platform_driver msm_hdmi_phy_platform_driver = { - .probe = msm_hdmi_phy_probe, - .remove_new = msm_hdmi_phy_remove, - .driver = { - .name = "msm_hdmi_phy", - .of_match_table = 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 cf90a0c1f822..000000000000 --- 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[] = { - "core-vdda", -}; - -static const char * const hdmi_phy_8960_clk_names[] = { - "slave_iface", -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8960_cfg = { - .type = MSM_HDMI_PHY_8960, - .powerup = hdmi_phy_8960_powerup, - .powerdown = hdmi_phy_8960_powerdown, - .reg_names = hdmi_phy_8960_reg_names, - .num_regs = ARRAY_SIZE(hdmi_phy_8960_reg_names), - .clk_names = hdmi_phy_8960_clk_names, - .num_clks = 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 4dd055416620..000000000000 --- 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) -{ - msm_writel(data, pll->mmio_qserdes_com + offset); -} - -static inline u32 hdmi_pll_read(struct hdmi_pll_8996 *pll, int offset) -{ - return msm_readl(pll->mmio_qserdes_com + offset); -} - -static inline void hdmi_tx_chan_write(struct hdmi_pll_8996 *pll, int channel, - int offset, int data) -{ - msm_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 != 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 != 0) || gen_ssc) - return 0x16; - - return 0x10; -} - -static inline u32 pll_get_cctrl(u64 frac_start, bool gen_ssc) -{ - if ((frac_start != 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 = bclk >= HDMI_DIG_FREQ_BIT_CLK_THRESHOLD ? 1 : 2; - u64 base; - - if ((frac_start != 0) || gen_ssc) - base = (64 * ref_clk) / HDMI_DEFAULT_REF_CLOCK; - else - base = (1022 * ref_clk) / 100; - - base <<= digclk_divsel; - - return (base <= 2046 ? base : 2046); -} - -static inline u32 pll_get_pll_cmp(u64 fdata, unsigned long ref_clk) -{ - u64 dividend = HDMI_PLL_CMP_CNT * fdata; - u32 divisor = ref_clk * 10; - u32 rem; - - rem = 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 = ((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[] = { 2, 3, 4, 5, 6, 9, 10, 12, 14, 15, 20, 21, 25, 28, 35 }; - int hs_divsel[] = { 0, 4, 8, 12, 1, 5, 2, 9, 3, 13, 10, 7, 14, 11, 15 }; - int tx_band_sel[] = { 0, 1, 2, 3 }; - u64 vco_freq[60]; - u64 vco, vco_optimal; - int half_rate_mode = 0; - int vco_optimal_index, vco_freq_index; - int i, j; - -retry: - vco_optimal = HDMI_VCO_MAX_FREQ; - vco_optimal_index = -1; - vco_freq_index = 0; - for (i = 0; i < 15; i++) { - for (j = 0; j < 4; j++) { - u32 ratio_mult = ratio[i] << tx_band_sel[j]; - - vco = bclk >> half_rate_mode; - vco *= ratio_mult; - vco_freq[vco_freq_index++] = vco; - } - } - - for (i = 0; i < 60; i++) { - u64 vco_tmp = vco_freq[i]; - - if ((vco_tmp >= HDMI_VCO_MIN_FREQ) && - (vco_tmp <= vco_optimal)) { - vco_optimal = vco_tmp; - vco_optimal_index = i; - } - } - - if (vco_optimal_index == -1) { - if (!half_rate_mode) { - half_rate_mode = 1; - goto retry; - } - } else { - pd->vco_freq = vco_optimal; - pd->tx_band_sel = tx_band_sel[vco_optimal_index % 4]; - pd->vco_ratio = ratio[vco_optimal_index / 4]; - pd->hsclk_divsel = 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 = 10 * pix_clk */ - bclk = ((u64)pix_clk) * 10; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) - tmds_clk = pix_clk >> 2; - else - tmds_clk = pix_clk; - - ret = pll_get_post_div(&pd, bclk); - if (ret) - return ret; - - dec_start = pd.vco_freq; - pll_divisor = 4 * ref_clk; - do_div(dec_start, pll_divisor); - - frac_start = pd.vco_freq * (1 << 20); - - rem = do_div(frac_start, pll_divisor); - frac_start -= dec_start * (1 << 20); - if (rem > (pll_divisor >> 1)) - frac_start++; - - cpctrl = pll_get_cpctrl(frac_start, ref_clk, false); - rctrl = pll_get_rctrl(frac_start, false); - cctrl = pll_get_cctrl(frac_start, false); - integloop_gain = pll_get_integloop_gain(frac_start, bclk, - ref_clk, false); - - fdata = pd.vco_freq; - do_div(fdata, pd.vco_ratio); - - pll_cmp = 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 = 1; - else - cfg->com_svs_mode_clk_sel = 2; - - cfg->com_hsclk_sel = (0x20 | pd.hsclk_divsel); - cfg->com_pll_cctrl_mode0 = cctrl; - cfg->com_pll_rctrl_mode0 = rctrl; - cfg->com_cp_ctrl_mode0 = cpctrl; - cfg->com_dec_start_mode0 = dec_start; - cfg->com_div_frac_start1_mode0 = (frac_start & 0xff); - cfg->com_div_frac_start2_mode0 = ((frac_start & 0xff00) >> 8); - cfg->com_div_frac_start3_mode0 = ((frac_start & 0xf0000) >> 16); - cfg->com_integloop_gain0_mode0 = (integloop_gain & 0xff); - cfg->com_integloop_gain1_mode0 = ((integloop_gain & 0xf00) >> 8); - cfg->com_lock_cmp1_mode0 = (pll_cmp & 0xff); - cfg->com_lock_cmp2_mode0 = ((pll_cmp & 0xff00) >> 8); - cfg->com_lock_cmp3_mode0 = ((pll_cmp & 0x30000) >> 16); - cfg->com_lock_cmp_en = 0x0; - cfg->com_core_clk_en = 0x2c; - cfg->com_coreclk_div = HDMI_CORECLK_DIV; - cfg->phy_mode = (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) ? 0x10 : 0x0; - cfg->com_vco_tune_ctrl = 0x0; - - cfg->tx_lx_lane_mode[0] = - cfg->tx_lx_lane_mode[2] = 0x43; - - cfg->tx_lx_hp_pd_enables[0] = - cfg->tx_lx_hp_pd_enables[1] = - cfg->tx_lx_hp_pd_enables[2] = 0x0c; - cfg->tx_lx_hp_pd_enables[3] = 0x3; - - for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) - cfg->tx_lx_tx_band[i] = pd.tx_band_sel + 4; - - if (bclk > HDMI_HIGH_FREQ_BIT_CLK_THRESHOLD) { - cfg->tx_lx_tx_drv_lvl[0] = - cfg->tx_lx_tx_drv_lvl[1] = - cfg->tx_lx_tx_drv_lvl[2] = 0x25; - cfg->tx_lx_tx_drv_lvl[3] = 0x22; - - cfg->tx_lx_tx_emp_post1_lvl[0] = - cfg->tx_lx_tx_emp_post1_lvl[1] = - cfg->tx_lx_tx_emp_post1_lvl[2] = 0x23; - cfg->tx_lx_tx_emp_post1_lvl[3] = 0x27; - - cfg->tx_lx_vmode_ctrl1[0] = - cfg->tx_lx_vmode_ctrl1[1] = - cfg->tx_lx_vmode_ctrl1[2] = - cfg->tx_lx_vmode_ctrl1[3] = 0x00; - - cfg->tx_lx_vmode_ctrl2[0] = - cfg->tx_lx_vmode_ctrl2[1] = - cfg->tx_lx_vmode_ctrl2[2] = 0x0D; - - cfg->tx_lx_vmode_ctrl2[3] = 0x00; - } else if (bclk > HDMI_MID_FREQ_BIT_CLK_THRESHOLD) { - for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { - cfg->tx_lx_tx_drv_lvl[i] = 0x25; - cfg->tx_lx_tx_emp_post1_lvl[i] = 0x23; - cfg->tx_lx_vmode_ctrl1[i] = 0x00; - } - - cfg->tx_lx_vmode_ctrl2[0] = - cfg->tx_lx_vmode_ctrl2[1] = - cfg->tx_lx_vmode_ctrl2[2] = 0x0D; - cfg->tx_lx_vmode_ctrl2[3] = 0x00; - } else { - for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { - cfg->tx_lx_tx_drv_lvl[i] = 0x20; - cfg->tx_lx_tx_emp_post1_lvl[i] = 0x20; - cfg->tx_lx_vmode_ctrl1[i] = 0x00; - cfg->tx_lx_vmode_ctrl2[i] = 0x0E; - } - } - - DBG("com_svs_mode_clk_sel = 0x%x", cfg->com_svs_mode_clk_sel); - DBG("com_hsclk_sel = 0x%x", cfg->com_hsclk_sel); - DBG("com_lock_cmp_en = 0x%x", cfg->com_lock_cmp_en); - DBG("com_pll_cctrl_mode0 = 0x%x", cfg->com_pll_cctrl_mode0); - DBG("com_pll_rctrl_mode0 = 0x%x", cfg->com_pll_rctrl_mode0); - DBG("com_cp_ctrl_mode0 = 0x%x", cfg->com_cp_ctrl_mode0); - DBG("com_dec_start_mode0 = 0x%x", cfg->com_dec_start_mode0); - DBG("com_div_frac_start1_mode0 = 0x%x", cfg->com_div_frac_start1_mode0); - DBG("com_div_frac_start2_mode0 = 0x%x", cfg->com_div_frac_start2_mode0); - DBG("com_div_frac_start3_mode0 = 0x%x", cfg->com_div_frac_start3_mode0); - DBG("com_integloop_gain0_mode0 = 0x%x", cfg->com_integloop_gain0_mode0); - DBG("com_integloop_gain1_mode0 = 0x%x", cfg->com_integloop_gain1_mode0); - DBG("com_lock_cmp1_mode0 = 0x%x", cfg->com_lock_cmp1_mode0); - DBG("com_lock_cmp2_mode0 = 0x%x", cfg->com_lock_cmp2_mode0); - DBG("com_lock_cmp3_mode0 = 0x%x", cfg->com_lock_cmp3_mode0); - DBG("com_core_clk_en = 0x%x", cfg->com_core_clk_en); - DBG("com_coreclk_div = 0x%x", cfg->com_coreclk_div); - DBG("phy_mode = 0x%x", cfg->phy_mode); - - DBG("tx_l0_lane_mode = 0x%x", cfg->tx_lx_lane_mode[0]); - DBG("tx_l2_lane_mode = 0x%x", cfg->tx_lx_lane_mode[2]); - - for (i = 0; i < HDMI_NUM_TX_CHANNEL; i++) { - DBG("tx_l%d_tx_band = 0x%x", i, cfg->tx_lx_tx_band[i]); - DBG("tx_l%d_tx_drv_lvl = 0x%x", i, cfg->tx_lx_tx_drv_lvl[i]); - DBG("tx_l%d_tx_emp_post1_lvl = 0x%x", i, - cfg->tx_lx_tx_emp_post1_lvl[i]); - DBG("tx_l%d_vmode_ctrl1 = 0x%x", i, cfg->tx_lx_vmode_ctrl1[i]); - DBG("tx_l%d_vmode_ctrl2 = 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 rate, - unsigned long parent_rate) -{ - struct hdmi_pll_8996 *pll = hw_clk_to_pll(hw); - struct hdmi_phy *phy = pll_get_phy(pll); - struct hdmi_8996_phy_pll_reg_cfg cfg; - int i, ret; - - memset(&cfg, 0x00, sizeof(cfg)); - - ret = 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 = 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 = 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 = HDMI_PLL_POLL_MAX_READS; - unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US; - u32 status; - int phy_ready = 0; - - DBG("Waiting for PHY ready"); - - while (nb_tries--) { - status = hdmi_phy_read(phy, REG_HDMI_8996_PHY_STATUS); - phy_ready = 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 = HDMI_PLL_POLL_MAX_READS; - unsigned long timeout = HDMI_PLL_POLL_TIMEOUT_US; - int pll_locked = 0; - - DBG("Waiting for PLL lock"); - - while (nb_tries--) { - status = hdmi_pll_read(pll, - REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS); - pll_locked = 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 = hw_clk_to_pll(hw); - struct hdmi_phy *phy = pll_get_phy(pll); - int i, ret = 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 = hdmi_8996_pll_lock_status(pll); - if (!ret) - return ret; - - for (i = 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 = 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 = hw_clk_to_pll(hw); - u64 fdata; - u32 cmp1, cmp2, cmp3, pll_cmp; - - cmp1 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP1_MODE0); - cmp2 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP2_MODE0); - cmp3 = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_LOCK_CMP3_MODE0); - - pll_cmp = cmp1 | (cmp2 << 8) | (cmp3 << 16); - - fdata = 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 = hw_clk_to_pll(hw); - struct hdmi_phy *phy = 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 = hw_clk_to_pll(hw); - u32 status; - int pll_locked; - - status = hdmi_pll_read(pll, REG_HDMI_PHY_QSERDES_COM_C_READY_STATUS); - pll_locked = status & BIT(0); - - return pll_locked; -} - -static const struct clk_ops hdmi_8996_pll_ops = { - .set_rate = hdmi_8996_pll_set_clk_rate, - .round_rate = hdmi_8996_pll_round_rate, - .recalc_rate = hdmi_8996_pll_recalc_rate, - .prepare = hdmi_8996_pll_prepare, - .unprepare = hdmi_8996_pll_unprepare, - .is_enabled = hdmi_8996_pll_is_enabled, -}; - -static const struct clk_init_data pll_init = { - .name = "hdmipll", - .ops = &hdmi_8996_pll_ops, - .parent_data = (const struct clk_parent_data[]){ - { .fw_name = "xo", .name = "xo_board" }, - }, - .num_parents = 1, - .flags = CLK_IGNORE_UNUSED, -}; - -int msm_hdmi_pll_8996_init(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct hdmi_pll_8996 *pll; - int i, ret; - - pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); - if (!pll) - return -ENOMEM; - - pll->pdev = pdev; - - pll->mmio_qserdes_com = 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 = 0; i < HDMI_NUM_TX_CHANNEL; i++) { - char name[32]; - - snprintf(name, sizeof(name), "hdmi_tx_l%d", i); - - pll->mmio_qserdes_tx[i] = 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 = &pll_init; - - ret = devm_clk_hw_register(dev, &pll->clk_hw); - if (ret) { - DRM_DEV_ERROR(dev, "failed to register pll clock\n"); - return ret; - } - - ret = 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[] = { - "vddio", - "vcca", -}; - -static const char * const hdmi_phy_8996_clk_names[] = { - "iface", "ref", -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8996_cfg = { - .type = MSM_HDMI_PHY_8996, - .reg_names = hdmi_phy_8996_reg_names, - .num_regs = ARRAY_SIZE(hdmi_phy_8996_reg_names), - .clk_names = hdmi_phy_8996_clk_names, - .num_clks = ARRAY_SIZE(hdmi_phy_8996_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 1d97640d8c24..000000000000 --- 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 == 27000000) { - /* video_format == 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 = 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[] = { - "core-vdda", -}; - -static const char * const hdmi_phy_8x60_clk_names[] = { - "slave_iface", -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8x60_cfg = { - .type = MSM_HDMI_PHY_8x60, - .powerup = hdmi_phy_8x60_powerup, - .powerdown = hdmi_phy_8x60_powerdown, - .reg_names = hdmi_phy_8x60_reg_names, - .num_regs = ARRAY_SIZE(hdmi_phy_8x60_reg_names), - .clk_names = hdmi_phy_8x60_clk_names, - .num_clks = 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 a2a6940e195a..000000000000 --- 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[] = { - "core-vdda", - "vddio", -}; - -static const char * const hdmi_phy_8x74_clk_names[] = { - "iface", "alt_iface" -}; - -const struct hdmi_phy_cfg msm_hdmi_phy_8x74_cfg = { - .type = MSM_HDMI_PHY_8x74, - .powerup = hdmi_phy_8x74_powerup, - .powerdown = hdmi_phy_8x74_powerdown, - .reg_names = hdmi_phy_8x74_reg_names, - .num_regs = ARRAY_SIZE(hdmi_phy_8x74_reg_names), - .clk_names = hdmi_phy_8x74_clk_names, - .num_clks = 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 cb35a297afbd..000000000000 --- 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[] = { - { 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) -{ - msm_writel(data, pll->mmio + reg); -} - -static inline u32 pll_read(struct hdmi_pll_8960 *pll, u32 reg) -{ - return msm_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 = hw_clk_to_pll(hw); - struct hdmi_phy *phy = pll_get_phy(pll); - int timeout_count, pll_lock_retry = 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 = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); - val |= HDMI_8960_PHY_REG12_SW_RESET; - /* Assert PHY S/W reset */ - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); - val &= ~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 = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); - val |= 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 = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B); - val |= HDMI_8960_PHY_PLL_PWRDN_B_PLL_PWRDN_B; - val &= ~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 = 1000; - while (--pll_lock_retry > 0) { - /* are we there yet? */ - val = 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 = 1000; - } - - return 0; -} - -static void hdmi_pll_disable(struct clk_hw *hw) -{ - struct hdmi_pll_8960 *pll = hw_clk_to_pll(hw); - struct hdmi_phy *phy = pll_get_phy(pll); - unsigned int val; - - DBG(""); - - val = hdmi_phy_read(phy, REG_HDMI_8960_PHY_REG12); - val &= ~HDMI_8960_PHY_REG12_PWRDN_B; - hdmi_phy_write(phy, REG_HDMI_8960_PHY_REG12, val); - - val = pll_read(pll, REG_HDMI_8960_PHY_PLL_PWRDN_B); - val |= HDMI_8960_PHY_REG12_SW_RESET; - val &= ~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 = 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 = 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 = 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 = hw_clk_to_pll(hw); - const struct pll_rate *pll_rate = find_rate(rate); - int i; - - DBG("rate=%lu", rate); - - for (i = 0; i < pll_rate->num_reg; i++) - pll_write(pll, pll_rate->conf[i].reg, pll_rate->conf[i].val); - - pll->pixclk = rate; - - return 0; -} - -static const struct clk_ops hdmi_pll_ops = { - .enable = hdmi_pll_enable, - .disable = hdmi_pll_disable, - .recalc_rate = hdmi_pll_recalc_rate, - .round_rate = hdmi_pll_round_rate, - .set_rate = hdmi_pll_set_rate, -}; - -static const struct clk_parent_data hdmi_pll_parents[] = { - { .fw_name = "pxo", .name = "pxo_board" }, -}; - -static struct clk_init_data pll_init = { - .name = "hdmi_pll", - .ops = &hdmi_pll_ops, - .parent_data = hdmi_pll_parents, - .num_parents = ARRAY_SIZE(hdmi_pll_parents), - .flags = CLK_IGNORE_UNUSED, -}; - -int msm_hdmi_pll_8960_init(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct hdmi_pll_8960 *pll; - int i, ret; - - /* sanity check: */ - for (i = 0; i < (ARRAY_SIZE(freqtbl) - 1); i++) - if (WARN_ON(freqtbl[i].rate < freqtbl[i + 1].rate)) - return -EINVAL; - - pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); - if (!pll) - return -ENOMEM; - - pll->mmio = msm_ioremap(pdev, "hdmi_pll"); - if (IS_ERR(pll->mmio)) { - DRM_DEV_ERROR(dev, "failed to map pll base\n"); - return -ENOMEM; - } - - pll->pdev = pdev; - pll->clk_hw.init = &pll_init; - - ret = devm_clk_hw_register(dev, &pll->clk_hw); - if (ret < 0) { - DRM_DEV_ERROR(dev, "failed to register pll clock\n"); - return ret; - } - - ret = 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; -}