disp: msm: dsi: move dsi pll as subnode to dsi PHY
DSI PLL is tightly coupled with DSI PHY. This change removes separate DSI pll driver and makes DSI pll as a subnode to DSI PHY which is an accurate way of representation. In addition, this change adds support for 5nm DSI ctrl and PHY revisions and adds DSI pll support for 5nm. Remove support for older DSI pll revisions such as 7nm, 10nm, 14nm, 20nm, 28nm. Change-Id: Ic8b886a9fe24b906e4ec5130720600efa1e59b68 Signed-off-by: Satya Rama Aditya Pinapala <psraditya30@codeaurora.org>
Šī revīzija ir iekļauta:
@@ -2,6 +2,7 @@
|
||||
ccflags-y := -I$(srctree)/include/drm -I$(srctree)/techpack/display/msm -I$(srctree)/techpack/display/msm/dsi -I$(srctree)/techpack/display/msm/dp
|
||||
ccflags-y += -I$(srctree)/techpack/display/msm/sde
|
||||
ccflags-y += -I$(srctree)/techpack/display/rotator
|
||||
ccflags-y += -I$(srctree)/drivers/clk/qcom/
|
||||
|
||||
msm_drm-$(CONFIG_DRM_MSM_DP) += dp/dp_usbpd.o \
|
||||
dp/dp_parser.o \
|
||||
@@ -88,6 +89,8 @@ msm_drm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi_phy.o \
|
||||
dsi/dsi_phy_timing_v2_0.o \
|
||||
dsi/dsi_phy_timing_v3_0.o \
|
||||
dsi/dsi_phy_timing_v4_0.o \
|
||||
dsi/dsi_pll.o \
|
||||
dsi/dsi_pll_5nm.o \
|
||||
dsi/dsi_ctrl_hw_cmn.o \
|
||||
dsi/dsi_ctrl_hw_1_4.o \
|
||||
dsi/dsi_ctrl_hw_2_0.o \
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/errno.h>
|
||||
@@ -100,6 +100,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
|
||||
case DSI_CTRL_VERSION_2_2:
|
||||
case DSI_CTRL_VERSION_2_3:
|
||||
case DSI_CTRL_VERSION_2_4:
|
||||
case DSI_CTRL_VERSION_2_5:
|
||||
ctrl->ops.phy_reset_config = dsi_ctrl_hw_22_phy_reset_config;
|
||||
ctrl->ops.config_clk_gating = dsi_ctrl_hw_22_config_clk_gating;
|
||||
ctrl->ops.setup_lane_map = dsi_ctrl_hw_20_setup_lane_map;
|
||||
@@ -163,6 +164,7 @@ int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
|
||||
case DSI_CTRL_VERSION_2_2:
|
||||
case DSI_CTRL_VERSION_2_3:
|
||||
case DSI_CTRL_VERSION_2_4:
|
||||
case DSI_CTRL_VERSION_2_5:
|
||||
ctrl->phy_isolation_enabled = phy_isolation_enabled;
|
||||
dsi_catalog_cmn_init(ctrl, version);
|
||||
break;
|
||||
@@ -302,6 +304,7 @@ int dsi_catalog_phy_setup(struct dsi_phy_hw *phy,
|
||||
break;
|
||||
case DSI_PHY_VERSION_4_0:
|
||||
case DSI_PHY_VERSION_4_1:
|
||||
case DSI_PHY_VERSION_4_2:
|
||||
dsi_catalog_phy_4_0_init(phy);
|
||||
break;
|
||||
case DSI_PHY_VERSION_0_0_HPM:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of_device.h>
|
||||
@@ -53,6 +53,7 @@ static const enum dsi_ctrl_version dsi_ctrl_v2_0 = DSI_CTRL_VERSION_2_0;
|
||||
static const enum dsi_ctrl_version dsi_ctrl_v2_2 = DSI_CTRL_VERSION_2_2;
|
||||
static const enum dsi_ctrl_version dsi_ctrl_v2_3 = DSI_CTRL_VERSION_2_3;
|
||||
static const enum dsi_ctrl_version dsi_ctrl_v2_4 = DSI_CTRL_VERSION_2_4;
|
||||
static const enum dsi_ctrl_version dsi_ctrl_v2_5 = DSI_CTRL_VERSION_2_5;
|
||||
|
||||
static const struct of_device_id msm_dsi_of_match[] = {
|
||||
{
|
||||
@@ -75,6 +76,10 @@ static const struct of_device_id msm_dsi_of_match[] = {
|
||||
.compatible = "qcom,dsi-ctrl-hw-v2.4",
|
||||
.data = &dsi_ctrl_v2_4,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,dsi-ctrl-hw-v2.5",
|
||||
.data = &dsi_ctrl_v2_5,
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -559,6 +564,7 @@ static int dsi_ctrl_init_regmap(struct platform_device *pdev,
|
||||
case DSI_CTRL_VERSION_2_2:
|
||||
case DSI_CTRL_VERSION_2_3:
|
||||
case DSI_CTRL_VERSION_2_4:
|
||||
case DSI_CTRL_VERSION_2_5:
|
||||
ptr = msm_ioremap(pdev, "disp_cc_base", ctrl->name);
|
||||
if (IS_ERR(ptr)) {
|
||||
DSI_CTRL_ERR(ctrl, "disp_cc base address not found for\n");
|
||||
@@ -1867,18 +1873,18 @@ static int dsi_ctrl_dev_probe(struct platform_device *pdev)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = dsi_ctrl_clocks_init(pdev, dsi_ctrl);
|
||||
if (rc) {
|
||||
DSI_CTRL_ERR(dsi_ctrl, "Failed to parse clock information, rc = %d\n",
|
||||
rc);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = dsi_ctrl_supplies_init(pdev, dsi_ctrl);
|
||||
if (rc) {
|
||||
DSI_CTRL_ERR(dsi_ctrl, "Failed to parse voltage supplies, rc = %d\n",
|
||||
rc);
|
||||
goto fail_clks;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rc = dsi_ctrl_clocks_init(pdev, dsi_ctrl);
|
||||
if (rc) {
|
||||
DSI_CTRL_ERR(dsi_ctrl, "Failed to parse clock information, rc = %d\n",
|
||||
rc);
|
||||
goto fail_supplies;
|
||||
}
|
||||
|
||||
rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
|
||||
@@ -1887,7 +1893,7 @@ static int dsi_ctrl_dev_probe(struct platform_device *pdev)
|
||||
if (rc) {
|
||||
DSI_CTRL_ERR(dsi_ctrl, "Catalog does not support version (%d)\n",
|
||||
dsi_ctrl->version);
|
||||
goto fail_supplies;
|
||||
goto fail_clks;
|
||||
}
|
||||
|
||||
item->ctrl = dsi_ctrl;
|
||||
@@ -1905,10 +1911,10 @@ static int dsi_ctrl_dev_probe(struct platform_device *pdev)
|
||||
|
||||
return 0;
|
||||
|
||||
fail_supplies:
|
||||
(void)dsi_ctrl_supplies_deinit(dsi_ctrl);
|
||||
fail_clks:
|
||||
(void)dsi_ctrl_clocks_deinit(dsi_ctrl);
|
||||
fail_supplies:
|
||||
(void)dsi_ctrl_supplies_deinit(dsi_ctrl);
|
||||
fail:
|
||||
return rc;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DSI_CTRL_HW_H_
|
||||
@@ -36,6 +36,7 @@
|
||||
* @DSI_CTRL_VERSION_2_2: DSI host v2.2 controller
|
||||
* @DSI_CTRL_VERSION_2_3: DSI host v2.3 controller
|
||||
* @DSI_CTRL_VERSION_2_4: DSI host v2.4 controller
|
||||
* @DSI_CTRL_VERSION_2_5: DSI host v2.5 controller
|
||||
* @DSI_CTRL_VERSION_MAX: max version
|
||||
*/
|
||||
enum dsi_ctrl_version {
|
||||
@@ -45,6 +46,7 @@ enum dsi_ctrl_version {
|
||||
DSI_CTRL_VERSION_2_2,
|
||||
DSI_CTRL_VERSION_2_3,
|
||||
DSI_CTRL_VERSION_2_4,
|
||||
DSI_CTRL_VERSION_2_5,
|
||||
DSI_CTRL_VERSION_MAX
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/of_device.h>
|
||||
@@ -83,6 +83,14 @@ static const struct dsi_ver_spec_info dsi_phy_v4_1 = {
|
||||
.timing_cfg_count = 14,
|
||||
};
|
||||
|
||||
static const struct dsi_ver_spec_info dsi_phy_v4_2 = {
|
||||
.version = DSI_PHY_VERSION_4_2,
|
||||
.lane_cfg_count = 4,
|
||||
.strength_cfg_count = 2,
|
||||
.regulator_cfg_count = 0,
|
||||
.timing_cfg_count = 14,
|
||||
};
|
||||
|
||||
static const struct of_device_id msm_dsi_phy_of_match[] = {
|
||||
{ .compatible = "qcom,dsi-phy-v0.0-hpm",
|
||||
.data = &dsi_phy_v0_0_hpm,},
|
||||
@@ -98,6 +106,8 @@ static const struct of_device_id msm_dsi_phy_of_match[] = {
|
||||
.data = &dsi_phy_v4_0,},
|
||||
{ .compatible = "qcom,dsi-phy-v4.1",
|
||||
.data = &dsi_phy_v4_1,},
|
||||
{ .compatible = "qcom,dsi-phy-v4.2",
|
||||
.data = &dsi_phy_v4_2,},
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -422,6 +432,12 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
|
||||
goto fail_supplies;
|
||||
}
|
||||
|
||||
rc = dsi_pll_init(pdev, &dsi_phy->pll);
|
||||
if (rc) {
|
||||
DSI_PHY_ERR(dsi_phy, "Failed to initialize DSI PLL, rc=%d\n", rc);
|
||||
goto fail_settings;
|
||||
}
|
||||
|
||||
item->phy = dsi_phy;
|
||||
|
||||
mutex_lock(&dsi_phy_list_lock);
|
||||
@@ -435,6 +451,8 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
|
||||
DSI_PHY_INFO(dsi_phy, "Probe successful\n");
|
||||
return 0;
|
||||
|
||||
fail_settings:
|
||||
(void)dsi_phy_settings_deinit(dsi_phy);
|
||||
fail_supplies:
|
||||
(void)dsi_phy_supplies_deinit(dsi_phy);
|
||||
fail_regmap:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DSI_PHY_H_
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "dsi_clk.h"
|
||||
#include "dsi_pwr.h"
|
||||
#include "dsi_phy_hw.h"
|
||||
#include "dsi_pll.h"
|
||||
|
||||
struct dsi_ver_spec_info {
|
||||
enum dsi_phy_version version;
|
||||
@@ -70,6 +71,7 @@ enum phy_ulps_return_type {
|
||||
* @mode: Current mode.
|
||||
* @data_lanes: Number of data lanes used.
|
||||
* @dst_format: Destination format.
|
||||
* @pll: Pointer to PLL resource.
|
||||
* @allow_phy_power_off: True if PHY is allowed to power off when idle
|
||||
* @regulator_min_datarate_bps: Minimum per lane data rate to turn on regulator
|
||||
* @regulator_required: True if phy regulator is required
|
||||
@@ -95,6 +97,8 @@ struct msm_dsi_phy {
|
||||
enum dsi_data_lanes data_lanes;
|
||||
enum dsi_pixel_format dst_format;
|
||||
|
||||
struct dsi_pll_resource *pll;
|
||||
|
||||
bool allow_phy_power_off;
|
||||
u32 regulator_min_datarate_bps;
|
||||
bool regulator_required;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2015-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _DSI_PHY_HW_H_
|
||||
@@ -31,6 +31,7 @@
|
||||
* @DSI_PHY_VERSION_3_0: 10nm
|
||||
* @DSI_PHY_VERSION_4_0: 7nm
|
||||
* @DSI_PHY_VERSION_4_1: 7nm
|
||||
* @DSI_PHY_VERSION_4_2: 5nm
|
||||
* @DSI_PHY_VERSION_MAX:
|
||||
*/
|
||||
enum dsi_phy_version {
|
||||
@@ -42,6 +43,7 @@ enum dsi_phy_version {
|
||||
DSI_PHY_VERSION_3_0, /* 10nm */
|
||||
DSI_PHY_VERSION_4_0, /* 7nm */
|
||||
DSI_PHY_VERSION_4_1, /* 7nm */
|
||||
DSI_PHY_VERSION_4_2, /* 5nm */
|
||||
DSI_PHY_VERSION_MAX
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/math64.h>
|
||||
@@ -156,7 +156,8 @@ static void dsi_phy_hw_v4_0_lane_settings(struct dsi_phy_hw *phy,
|
||||
u8 tx_dctrl_v4_1[] = {0x40, 0x40, 0x40, 0x46, 0x41};
|
||||
u8 *tx_dctrl;
|
||||
|
||||
if (phy->version == DSI_PHY_VERSION_4_1)
|
||||
if ((phy->version == DSI_PHY_VERSION_4_1) ||
|
||||
(phy->version == DSI_PHY_VERSION_4_2))
|
||||
tx_dctrl = &tx_dctrl_v4_1[0];
|
||||
else
|
||||
tx_dctrl = &tx_dctrl_v4[0];
|
||||
@@ -241,7 +242,13 @@ void dsi_phy_hw_v4_0_enable(struct dsi_phy_hw *phy,
|
||||
if (cfg->bit_clk_rate_hz <= 1500000000)
|
||||
less_than_1500_mhz = true;
|
||||
|
||||
if (phy->version == DSI_PHY_VERSION_4_1) {
|
||||
if (phy->version == DSI_PHY_VERSION_4_2) {
|
||||
vreg_ctrl_0 = 0x58;
|
||||
glbl_rescode_top_ctrl = 0x03;
|
||||
glbl_rescode_bot_ctrl = 0x3c;
|
||||
glbl_str_swi_cal_sel_ctrl = 0x00;
|
||||
glbl_hstx_str_ctrl_0 = 0x88;
|
||||
} else if (phy->version == DSI_PHY_VERSION_4_1) {
|
||||
vreg_ctrl_0 = less_than_1500_mhz ? 0x53 : 0x52;
|
||||
glbl_rescode_top_ctrl = less_than_1500_mhz ? 0x3d : 0x00;
|
||||
glbl_rescode_bot_ctrl = less_than_1500_mhz ? 0x39 : 0x3c;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "dsi_phy_timing_calc.h"
|
||||
@@ -788,6 +788,7 @@ int dsi_phy_timing_calc_init(struct dsi_phy_hw *phy,
|
||||
break;
|
||||
case DSI_PHY_VERSION_4_0:
|
||||
case DSI_PHY_VERSION_4_1:
|
||||
case DSI_PHY_VERSION_4_2:
|
||||
ops->get_default_phy_params =
|
||||
dsi_phy_hw_v4_0_get_default_phy_params;
|
||||
ops->calc_clk_zero =
|
||||
|
148
msm/dsi/dsi_pll.c
Parasts fails
148
msm/dsi/dsi_pll.c
Parasts fails
@@ -0,0 +1,148 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define pr_fmt(fmt) "%s: " fmt, __func__
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include "dsi_pll.h"
|
||||
|
||||
static int dsi_pll_clock_register(struct platform_device *pdev,
|
||||
struct dsi_pll_resource *pll_res)
|
||||
{
|
||||
int rc;
|
||||
|
||||
switch (pll_res->pll_revision) {
|
||||
case DSI_PLL_5NM:
|
||||
rc = dsi_pll_clock_register_5nm(pdev, pll_res);
|
||||
break;
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (rc)
|
||||
DSI_PLL_ERR(pll_res, "clock register failed rc=%d\n", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline int dsi_pll_get_ioresources(struct platform_device *pdev,
|
||||
void __iomem **regmap, char *resource_name)
|
||||
{
|
||||
int rc = 0;
|
||||
struct resource *rsc = platform_get_resource_byname(pdev,
|
||||
IORESOURCE_MEM, resource_name);
|
||||
if (rsc) {
|
||||
if (!regmap)
|
||||
return -ENOMEM;
|
||||
|
||||
*regmap = devm_ioremap(&pdev->dev,
|
||||
rsc->start, resource_size(rsc));
|
||||
if (!*regmap)
|
||||
return -ENOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dsi_pll_init(struct platform_device *pdev, struct dsi_pll_resource **pll)
|
||||
{
|
||||
int rc = 0;
|
||||
const char *label;
|
||||
struct dsi_pll_resource *pll_res = NULL;
|
||||
|
||||
if (!pdev->dev.of_node) {
|
||||
pr_err("Invalid DSI PHY node\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
pll_res = devm_kzalloc(&pdev->dev, sizeof(struct dsi_pll_resource),
|
||||
GFP_KERNEL);
|
||||
if (!pll_res)
|
||||
return -ENOMEM;
|
||||
|
||||
*pll = pll_res;
|
||||
|
||||
label = of_get_property(pdev->dev.of_node, "pll-label", NULL);
|
||||
if (!label)
|
||||
DSI_PLL_INFO(pll_res, "DSI pll label not specified\n");
|
||||
else
|
||||
DSI_PLL_INFO(pll_res, "DSI pll label = %s\n", label);
|
||||
|
||||
/**
|
||||
* Currently, Only supports 5nm PLL version. Will add
|
||||
* support for other versions as needed.
|
||||
*/
|
||||
|
||||
if (!strcmp(label, "dsi_pll_5nm"))
|
||||
pll_res->pll_revision = DSI_PLL_5NM;
|
||||
else
|
||||
return -ENOTSUPP;
|
||||
|
||||
rc = of_property_read_u32(pdev->dev.of_node, "cell-index",
|
||||
&pll_res->index);
|
||||
if (rc) {
|
||||
DSI_PLL_ERR(pll_res, "Unable to get the cell-index rc=%d\n", rc);
|
||||
pll_res->index = 0;
|
||||
}
|
||||
|
||||
pll_res->ssc_en = of_property_read_bool(pdev->dev.of_node,
|
||||
"qcom,dsi-pll-ssc-en");
|
||||
|
||||
if (pll_res->ssc_en) {
|
||||
DSI_PLL_INFO(pll_res, "PLL SSC enabled\n");
|
||||
|
||||
rc = of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,ssc-frequency-hz", &pll_res->ssc_freq);
|
||||
|
||||
rc = of_property_read_u32(pdev->dev.of_node,
|
||||
"qcom,ssc-ppm", &pll_res->ssc_ppm);
|
||||
|
||||
pll_res->ssc_center = false;
|
||||
|
||||
label = of_get_property(pdev->dev.of_node,
|
||||
"qcom,dsi-pll-ssc-mode", NULL);
|
||||
|
||||
if (label && !strcmp(label, "center-spread"))
|
||||
pll_res->ssc_center = true;
|
||||
}
|
||||
|
||||
|
||||
if (dsi_pll_get_ioresources(pdev, &pll_res->pll_base, "pll_base")) {
|
||||
DSI_PLL_ERR(pll_res, "Unable to remap pll base resources\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
pr_info("PLL base=%p\n", pll_res->pll_base);
|
||||
|
||||
if (dsi_pll_get_ioresources(pdev, &pll_res->phy_base, "dsi_phy")) {
|
||||
DSI_PLL_ERR(pll_res, "Unable to remap pll phy base resources\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (dsi_pll_get_ioresources(pdev, &pll_res->dyn_pll_base,
|
||||
"dyn_refresh_base")) {
|
||||
DSI_PLL_ERR(pll_res, "Unable to remap dynamic pll base resources\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (dsi_pll_get_ioresources(pdev, &pll_res->gdsc_base, "gdsc_base")) {
|
||||
DSI_PLL_ERR(pll_res, "Unable to remap gdsc base resources\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
rc = dsi_pll_clock_register(pdev, pll_res);
|
||||
if (rc) {
|
||||
DSI_PLL_ERR(pll_res, "clock register failed rc=%d\n", rc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
233
msm/dsi/dsi_pll.h
Parasts fails
233
msm/dsi/dsi_pll.h
Parasts fails
@@ -0,0 +1,233 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __DSI_PLL_H
|
||||
#define __DSI_PLL_H
|
||||
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/regmap.h>
|
||||
#include "clk-regmap.h"
|
||||
#include "clk-regmap-divider.h"
|
||||
#include "clk-regmap-mux.h"
|
||||
#include "dsi_defs.h"
|
||||
|
||||
#define DSI_PLL_DBG(p, fmt, ...) DRM_DEV_DEBUG(NULL, "[msm-dsi-debug]: DSI_PLL_%d: "\
|
||||
fmt, p ? p->index : -1, ##__VA_ARGS__)
|
||||
#define DSI_PLL_ERR(p, fmt, ...) DRM_DEV_ERROR(NULL, "[msm-dsi-error]: DSI_PLL_%d: "\
|
||||
fmt, p ? p->index : -1, ##__VA_ARGS__)
|
||||
#define DSI_PLL_INFO(p, fmt, ...) DRM_DEV_INFO(NULL, "[msm-dsi-info]: DSI_PLL_%d: "\
|
||||
fmt, p ? p->index : -1, ##__VA_ARGS__)
|
||||
#define DSI_PLL_WARN(p, fmt, ...) DRM_WARN("[msm-dsi-warn]: DSI_PLL_%d: "\
|
||||
fmt, p ? p->index : -1, ##__VA_ARGS__)
|
||||
|
||||
#define DSI_PLL_REG_W(base, offset, data) \
|
||||
writel_relaxed((data), (base) + (offset))
|
||||
#define DSI_PLL_REG_R(base, offset) readl_relaxed((base) + (offset))
|
||||
|
||||
#define PLL_CALC_DATA(addr0, addr1, data0, data1) \
|
||||
(((data1) << 24) | ((((addr1) / 4) & 0xFF) << 16) | \
|
||||
((data0) << 8) | (((addr0) / 4) & 0xFF))
|
||||
|
||||
#define DSI_DYN_PLL_REG_W(base, offset, addr0, addr1, data0, data1) \
|
||||
writel_relaxed(PLL_CALC_DATA(addr0, addr1, data0, data1), \
|
||||
(base) + (offset))
|
||||
|
||||
#define upper_8_bit(x) ((((x) >> 2) & 0x100) >> 8)
|
||||
|
||||
#define DFPS_MAX_NUM_OF_FRAME_RATES 16
|
||||
#define MAX_DSI_PLL_EN_SEQS 10
|
||||
|
||||
/* Register offsets for 5nm PHY PLL */
|
||||
#define MMSS_DSI_PHY_PLL_PLL_CNTRL (0x0014)
|
||||
#define MMSS_DSI_PHY_PLL_PLL_BKG_KVCO_CAL_EN (0x002C)
|
||||
#define MMSS_DSI_PHY_PLL_PLLLOCK_CMP_EN (0x009C)
|
||||
|
||||
struct lpfr_cfg {
|
||||
unsigned long vco_rate;
|
||||
u32 r;
|
||||
};
|
||||
|
||||
enum {
|
||||
DSI_PLL_5NM,
|
||||
DSI_UNKNOWN_PLL,
|
||||
};
|
||||
|
||||
struct dfps_pll_codes {
|
||||
uint32_t pll_codes_1;
|
||||
uint32_t pll_codes_2;
|
||||
uint32_t pll_codes_3;
|
||||
};
|
||||
|
||||
struct dfps_codes_info {
|
||||
uint32_t is_valid;
|
||||
uint32_t clk_rate; /* hz */
|
||||
struct dfps_pll_codes pll_codes;
|
||||
};
|
||||
|
||||
struct dfps_info {
|
||||
uint32_t vco_rate_cnt;
|
||||
struct dfps_codes_info codes_dfps[DFPS_MAX_NUM_OF_FRAME_RATES];
|
||||
};
|
||||
|
||||
struct dsi_pll_resource {
|
||||
|
||||
/*
|
||||
* dsi base register, phy, gdsc and dynamic refresh
|
||||
* register mapping
|
||||
*/
|
||||
void __iomem *pll_base;
|
||||
void __iomem *phy_base;
|
||||
void __iomem *gdsc_base;
|
||||
void __iomem *dyn_pll_base;
|
||||
|
||||
s64 vco_current_rate;
|
||||
s64 vco_locking_rate;
|
||||
s64 vco_ref_clk_rate;
|
||||
|
||||
/*
|
||||
* Certain pll's needs to update the same vco rate after resume in
|
||||
* suspend/resume scenario. Cached the vco rate for such plls.
|
||||
*/
|
||||
unsigned long vco_cached_rate;
|
||||
u32 cached_cfg0;
|
||||
u32 cached_cfg1;
|
||||
u32 cached_outdiv;
|
||||
|
||||
u32 cached_postdiv1;
|
||||
u32 cached_postdiv3;
|
||||
|
||||
u32 pll_revision;
|
||||
|
||||
|
||||
/* HW recommended delay during configuration of vco clock rate */
|
||||
u32 vco_delay;
|
||||
|
||||
|
||||
/*
|
||||
* Certain plls' do not allow vco rate update if it is on. Keep track of
|
||||
* status for them to turn on/off after set rate success.
|
||||
*/
|
||||
bool pll_on;
|
||||
|
||||
/*
|
||||
* handoff_status is true of pll is already enabled by bootloader with
|
||||
* continuous splash enable case. Clock API will call the handoff API
|
||||
* to enable the status. It is disabled if continuous splash
|
||||
* feature is disabled.
|
||||
*/
|
||||
bool handoff_resources;
|
||||
|
||||
/*
|
||||
* caching the pll trim codes in the case of dynamic refresh
|
||||
*/
|
||||
int cache_pll_trim_codes[3];
|
||||
|
||||
/*
|
||||
* for maintaining the status of saving trim codes
|
||||
*/
|
||||
bool reg_upd;
|
||||
|
||||
|
||||
/*
|
||||
* PLL index if multiple index are available. Eg. in case of
|
||||
* DSI we have 2 plls.
|
||||
*/
|
||||
uint32_t index;
|
||||
|
||||
bool ssc_en; /* share pll with master */
|
||||
bool ssc_center; /* default is down spread */
|
||||
u32 ssc_freq;
|
||||
u32 ssc_ppm;
|
||||
|
||||
struct dsi_pll_resource *slave;
|
||||
|
||||
/*
|
||||
* target pll revision information
|
||||
*/
|
||||
int revision;
|
||||
|
||||
void *priv;
|
||||
|
||||
/*
|
||||
* dynamic refresh pll codes stored in this structure
|
||||
*/
|
||||
struct dfps_info *dfps;
|
||||
|
||||
/*
|
||||
* for cases where dfps trigger happens before first
|
||||
* suspend/resume and handoff is not finished.
|
||||
*/
|
||||
bool dfps_trigger;
|
||||
};
|
||||
|
||||
struct dsi_pll_vco_clk {
|
||||
struct clk_hw hw;
|
||||
unsigned long ref_clk_rate;
|
||||
u64 min_rate;
|
||||
u64 max_rate;
|
||||
u32 pll_en_seq_cnt;
|
||||
struct lpfr_cfg *lpfr_lut;
|
||||
u32 lpfr_lut_size;
|
||||
void *priv;
|
||||
|
||||
int (*pll_enable_seqs[MAX_DSI_PLL_EN_SEQS])
|
||||
(struct dsi_pll_resource *pll_res);
|
||||
};
|
||||
|
||||
struct dsi_pll_vco_calc {
|
||||
s32 div_frac_start1;
|
||||
s32 div_frac_start2;
|
||||
s32 div_frac_start3;
|
||||
s64 dec_start1;
|
||||
s64 dec_start2;
|
||||
s64 pll_plllock_cmp1;
|
||||
s64 pll_plllock_cmp2;
|
||||
s64 pll_plllock_cmp3;
|
||||
};
|
||||
|
||||
static inline bool is_gdsc_disabled(struct dsi_pll_resource *pll_res)
|
||||
{
|
||||
if (!pll_res->gdsc_base) {
|
||||
WARN(1, "gdsc_base register is not defined\n");
|
||||
return true;
|
||||
}
|
||||
return readl_relaxed(pll_res->gdsc_base) & BIT(31) ? false : true;
|
||||
}
|
||||
|
||||
static inline int dsi_pll_div_prepare(struct clk_hw *hw)
|
||||
{
|
||||
struct clk_hw *parent_hw = clk_hw_get_parent(hw);
|
||||
/* Restore the divider's value */
|
||||
return hw->init->ops->set_rate(hw, clk_hw_get_rate(hw),
|
||||
clk_hw_get_rate(parent_hw));
|
||||
}
|
||||
|
||||
static inline int dsi_set_mux_sel(void *context, unsigned int reg,
|
||||
unsigned int val)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dsi_get_mux_sel(void *context, unsigned int reg,
|
||||
unsigned int *val)
|
||||
{
|
||||
*val = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct dsi_pll_vco_clk *to_vco_clk_hw(struct clk_hw *hw)
|
||||
{
|
||||
return container_of(hw, struct dsi_pll_vco_clk, hw);
|
||||
}
|
||||
|
||||
int dsi_pll_clock_register_5nm(struct platform_device *pdev,
|
||||
struct dsi_pll_resource *pll_res);
|
||||
|
||||
int dsi_pll_init(struct platform_device *pdev,
|
||||
struct dsi_pll_resource **pll_res);
|
||||
#endif
|
2336
msm/dsi/dsi_pll_5nm.c
Parasts fails
2336
msm/dsi/dsi_pll_5nm.c
Parasts fails
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Ielādēt izmaiņas
Atsaukties uz šo jaunā problēmā
Block a user