disp: msm: dsi: add support for phy/pll bypass
This change adds support for bypassing hw access in DSI PHY/PLL drivers which enables the DSI driver to run on emulation platforms that might be missing those modules. Change-Id: I3e83155a79d60f2357606746214d776cefabd651 Signed-off-by: Rajkumar Subbiah <quic_rsubbia@quicinc.com> Signed-off-by: Shamika Joshi <quic_shamjosh@quicinc.com> Signed-off-by: Alex Danila <quic_eadanila@quicinc.com>
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

parent
8f1d4ca416
commit
6d5a850504
@@ -111,6 +111,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
|
|||||||
* @version: DSI controller version.
|
* @version: DSI controller version.
|
||||||
* @index: DSI controller instance ID.
|
* @index: DSI controller instance ID.
|
||||||
* @phy_isolation_enabled: DSI controller works isolated from phy.
|
* @phy_isolation_enabled: DSI controller works isolated from phy.
|
||||||
|
* @phy_pll_bypass: DSI PHY/PLL drivers bypass HW access.
|
||||||
* @null_insertion_enabled: DSI controller inserts null packet.
|
* @null_insertion_enabled: DSI controller inserts null packet.
|
||||||
*
|
*
|
||||||
* This function setups the catalog information in the dsi_ctrl_hw object.
|
* This function setups the catalog information in the dsi_ctrl_hw object.
|
||||||
@@ -119,7 +120,8 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
|
|||||||
*/
|
*/
|
||||||
int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
|
int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
|
||||||
enum dsi_ctrl_version version, u32 index,
|
enum dsi_ctrl_version version, u32 index,
|
||||||
bool phy_isolation_enabled, bool null_insertion_enabled)
|
bool phy_isolation_enabled, bool phy_pll_bypass,
|
||||||
|
bool null_insertion_enabled)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
@@ -143,6 +145,7 @@ int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
|
|||||||
case DSI_CTRL_VERSION_2_3:
|
case DSI_CTRL_VERSION_2_3:
|
||||||
case DSI_CTRL_VERSION_2_4:
|
case DSI_CTRL_VERSION_2_4:
|
||||||
ctrl->phy_isolation_enabled = phy_isolation_enabled;
|
ctrl->phy_isolation_enabled = phy_isolation_enabled;
|
||||||
|
ctrl->phy_pll_bypass = phy_pll_bypass;
|
||||||
dsi_catalog_cmn_init(ctrl, version);
|
dsi_catalog_cmn_init(ctrl, version);
|
||||||
break;
|
break;
|
||||||
case DSI_CTRL_VERSION_2_5:
|
case DSI_CTRL_VERSION_2_5:
|
||||||
@@ -151,6 +154,7 @@ int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
|
|||||||
case DSI_CTRL_VERSION_2_8:
|
case DSI_CTRL_VERSION_2_8:
|
||||||
ctrl->widebus_support = true;
|
ctrl->widebus_support = true;
|
||||||
ctrl->phy_isolation_enabled = phy_isolation_enabled;
|
ctrl->phy_isolation_enabled = phy_isolation_enabled;
|
||||||
|
ctrl->phy_pll_bypass = phy_pll_bypass;
|
||||||
dsi_catalog_cmn_init(ctrl, version);
|
dsi_catalog_cmn_init(ctrl, version);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -324,6 +328,8 @@ int dsi_catalog_phy_pll_setup(struct dsi_phy_hw *phy, u32 pll_ver)
|
|||||||
if (pll_ver >= DSI_PLL_VERSION_UNKNOWN) {
|
if (pll_ver >= DSI_PLL_VERSION_UNKNOWN) {
|
||||||
DSI_ERR("Unsupported version: %d\n", pll_ver);
|
DSI_ERR("Unsupported version: %d\n", pll_ver);
|
||||||
return -EOPNOTSUPP;
|
return -EOPNOTSUPP;
|
||||||
|
} else if (phy->phy_pll_bypass) {
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (pll_ver) {
|
switch (pll_ver) {
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
* @version: DSI controller version.
|
* @version: DSI controller version.
|
||||||
* @index: DSI controller instance ID.
|
* @index: DSI controller instance ID.
|
||||||
* @phy_isolation_enabled: DSI controller works isolated from phy.
|
* @phy_isolation_enabled: DSI controller works isolated from phy.
|
||||||
|
* @phy_pll_bypass: DSI PHY/PLL drivers bypass HW access.
|
||||||
* @null_insertion_enabled: DSI controller inserts null packet.
|
* @null_insertion_enabled: DSI controller inserts null packet.
|
||||||
*
|
*
|
||||||
* This function setups the catalog information in the dsi_ctrl_hw object.
|
* This function setups the catalog information in the dsi_ctrl_hw object.
|
||||||
@@ -24,7 +25,8 @@
|
|||||||
*/
|
*/
|
||||||
int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
|
int dsi_catalog_ctrl_setup(struct dsi_ctrl_hw *ctrl,
|
||||||
enum dsi_ctrl_version version, u32 index,
|
enum dsi_ctrl_version version, u32 index,
|
||||||
bool phy_isolation_enabled, bool null_insertion_enabled);
|
bool phy_isolation_enabled, bool phy_pll_bypass,
|
||||||
|
bool null_insertion_enabled);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* dsi_catalog_phy_setup() - return catalog info for dsi phy hardware
|
* dsi_catalog_phy_setup() - return catalog info for dsi phy hardware
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _DSI_CLK_H_
|
#ifndef _DSI_CLK_H_
|
||||||
@@ -209,6 +210,7 @@ typedef int (*pll_toggle_cb)(void *priv, bool prepare);
|
|||||||
* @priv_data pointer to private data
|
* @priv_data pointer to private data
|
||||||
* @master_ndx master DSI controller index
|
* @master_ndx master DSI controller index
|
||||||
* @dsi_ctrl_count number of DSI controllers
|
* @dsi_ctrl_count number of DSI controllers
|
||||||
|
* @phy_pll_bypass bypass PLL clock related operations
|
||||||
*/
|
*/
|
||||||
struct dsi_clk_info {
|
struct dsi_clk_info {
|
||||||
char name[MAX_STRING_LEN];
|
char name[MAX_STRING_LEN];
|
||||||
@@ -225,6 +227,7 @@ struct dsi_clk_info {
|
|||||||
void *priv_data;
|
void *priv_data;
|
||||||
u32 master_ndx;
|
u32 master_ndx;
|
||||||
u32 dsi_ctrl_count;
|
u32 dsi_ctrl_count;
|
||||||
|
bool phy_pll_bypass;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
|
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
@@ -41,6 +42,7 @@ struct dsi_clk_mngr {
|
|||||||
pre_clockon_cb pre_clkon_cb;
|
pre_clockon_cb pre_clkon_cb;
|
||||||
|
|
||||||
bool is_cont_splash_enabled;
|
bool is_cont_splash_enabled;
|
||||||
|
bool phy_pll_bypass;
|
||||||
void *priv_data;
|
void *priv_data;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -119,6 +121,10 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index)
|
|||||||
struct dsi_clk_mngr *mngr;
|
struct dsi_clk_mngr *mngr;
|
||||||
|
|
||||||
mngr = c->mngr;
|
mngr = c->mngr;
|
||||||
|
|
||||||
|
if (mngr->phy_pll_bypass)
|
||||||
|
return 0;
|
||||||
|
|
||||||
rc = clk_set_rate(mngr->link_clks[index].hs_clks.pixel_clk, pixel_clk);
|
rc = clk_set_rate(mngr->link_clks[index].hs_clks.pixel_clk, pixel_clk);
|
||||||
if (rc)
|
if (rc)
|
||||||
DSI_ERR("failed to set clk rate for pixel clk, rc=%d\n", rc);
|
DSI_ERR("failed to set clk rate for pixel clk, rc=%d\n", rc);
|
||||||
@@ -144,6 +150,10 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk,
|
|||||||
struct dsi_clk_mngr *mngr;
|
struct dsi_clk_mngr *mngr;
|
||||||
|
|
||||||
mngr = c->mngr;
|
mngr = c->mngr;
|
||||||
|
|
||||||
|
if (mngr->phy_pll_bypass)
|
||||||
|
return 0;
|
||||||
|
|
||||||
rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk);
|
rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk);
|
||||||
if (rc)
|
if (rc)
|
||||||
DSI_ERR("failed to set clk rate for byte clk, rc=%d\n", rc);
|
DSI_ERR("failed to set clk rate for byte clk, rc=%d\n", rc);
|
||||||
@@ -333,6 +343,9 @@ static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks,
|
|||||||
if (mngr->is_cont_splash_enabled)
|
if (mngr->is_cont_splash_enabled)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (mngr->phy_pll_bypass)
|
||||||
|
return 0;
|
||||||
|
|
||||||
rc = clk_set_rate(link_hs_clks->byte_clk,
|
rc = clk_set_rate(link_hs_clks->byte_clk,
|
||||||
l_clks->freq.byte_clk_rate);
|
l_clks->freq.byte_clk_rate);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -1451,6 +1464,7 @@ void *dsi_display_clk_mngr_register(struct dsi_clk_info *info)
|
|||||||
mngr->phy_config_cb = info->phy_config_cb;
|
mngr->phy_config_cb = info->phy_config_cb;
|
||||||
mngr->phy_pll_toggle_cb = info->phy_pll_toggle_cb;
|
mngr->phy_pll_toggle_cb = info->phy_pll_toggle_cb;
|
||||||
mngr->priv_data = info->priv_data;
|
mngr->priv_data = info->priv_data;
|
||||||
|
mngr->phy_pll_bypass = info->phy_pll_bypass;
|
||||||
memcpy(mngr->name, info->name, MAX_STRING_LEN);
|
memcpy(mngr->name, info->name, MAX_STRING_LEN);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@@ -2066,6 +2066,9 @@ static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl,
|
|||||||
dsi_ctrl->split_link_supported = of_property_read_bool(of_node,
|
dsi_ctrl->split_link_supported = of_property_read_bool(of_node,
|
||||||
"qcom,split-link-supported");
|
"qcom,split-link-supported");
|
||||||
|
|
||||||
|
dsi_ctrl->phy_pll_bypass = of_property_read_bool(of_node,
|
||||||
|
"qcom,dsi-phy-pll-bypass");
|
||||||
|
|
||||||
rc = of_property_read_u32(of_node, "frame-threshold-time-us",
|
rc = of_property_read_u32(of_node, "frame-threshold-time-us",
|
||||||
&frame_threshold_time_us);
|
&frame_threshold_time_us);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -2139,7 +2142,7 @@ static int dsi_ctrl_dev_probe(struct platform_device *pdev)
|
|||||||
|
|
||||||
rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
|
rc = dsi_catalog_ctrl_setup(&dsi_ctrl->hw, dsi_ctrl->version,
|
||||||
dsi_ctrl->cell_index, dsi_ctrl->phy_isolation_enabled,
|
dsi_ctrl->cell_index, dsi_ctrl->phy_isolation_enabled,
|
||||||
dsi_ctrl->null_insertion_enabled);
|
dsi_ctrl->phy_pll_bypass, dsi_ctrl->null_insertion_enabled);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DSI_CTRL_ERR(dsi_ctrl, "Catalog does not support version (%d)\n",
|
DSI_CTRL_ERR(dsi_ctrl, "Catalog does not support version (%d)\n",
|
||||||
dsi_ctrl->version);
|
dsi_ctrl->version);
|
||||||
|
@@ -234,6 +234,8 @@ struct dsi_ctrl_interrupts {
|
|||||||
* next TE for command mode.
|
* next TE for command mode.
|
||||||
* @phy_isolation_enabled: A boolean property allows to isolate the phy from
|
* @phy_isolation_enabled: A boolean property allows to isolate the phy from
|
||||||
* dsi controller and run only dsi controller.
|
* dsi controller and run only dsi controller.
|
||||||
|
* @phy_pll_bypass: A boolean property that enables skipping HW access in
|
||||||
|
* DSI PHY/PLL drivers for running on emulation platforms.
|
||||||
* @null_insertion_enabled: A boolean property to allow dsi controller to
|
* @null_insertion_enabled: A boolean property to allow dsi controller to
|
||||||
* insert null packet.
|
* insert null packet.
|
||||||
* @modeupdated: Boolean to send new roi if mode is updated.
|
* @modeupdated: Boolean to send new roi if mode is updated.
|
||||||
@@ -310,6 +312,7 @@ struct dsi_ctrl {
|
|||||||
unsigned int error_interrupt_count;
|
unsigned int error_interrupt_count;
|
||||||
|
|
||||||
bool phy_isolation_enabled;
|
bool phy_isolation_enabled;
|
||||||
|
bool phy_pll_bypass;
|
||||||
bool null_insertion_enabled;
|
bool null_insertion_enabled;
|
||||||
bool modeupdated;
|
bool modeupdated;
|
||||||
bool split_link_supported;
|
bool split_link_supported;
|
||||||
|
@@ -948,6 +948,8 @@ struct dsi_ctrl_hw_ops {
|
|||||||
* @supported_errors: Number of supported errors.
|
* @supported_errors: Number of supported errors.
|
||||||
* @phy_isolation_enabled: A boolean property allows to isolate the phy from
|
* @phy_isolation_enabled: A boolean property allows to isolate the phy from
|
||||||
* dsi controller and run only dsi controller.
|
* dsi controller and run only dsi controller.
|
||||||
|
* @phy_pll_bypass: A boolean property that enables skipping HW access in
|
||||||
|
* PHY/PLL drivers for running on emulation platforms.
|
||||||
* @null_insertion_enabled: A boolean property to allow dsi controller to
|
* @null_insertion_enabled: A boolean property to allow dsi controller to
|
||||||
* insert null packet.
|
* insert null packet.
|
||||||
* @widebus_support: 48 bit wide data bus is supported.
|
* @widebus_support: 48 bit wide data bus is supported.
|
||||||
@@ -973,6 +975,7 @@ struct dsi_ctrl_hw {
|
|||||||
u64 supported_errors;
|
u64 supported_errors;
|
||||||
|
|
||||||
bool phy_isolation_enabled;
|
bool phy_isolation_enabled;
|
||||||
|
bool phy_pll_bypass;
|
||||||
bool null_insertion_enabled;
|
bool null_insertion_enabled;
|
||||||
bool widebus_support;
|
bool widebus_support;
|
||||||
bool reset_trig_ctrl;
|
bool reset_trig_ctrl;
|
||||||
|
@@ -1440,6 +1440,11 @@ void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
|
|||||||
else
|
else
|
||||||
int_ctrl &= ~BIT(25);
|
int_ctrl &= ~BIT(25);
|
||||||
|
|
||||||
|
if (ctrl->phy_pll_bypass) {
|
||||||
|
int_ctrl &= ~BIT(25);
|
||||||
|
goto dsi_write;
|
||||||
|
}
|
||||||
|
|
||||||
/* Do not clear interrupt status */
|
/* Do not clear interrupt status */
|
||||||
int_ctrl &= 0xAAEEAAFE;
|
int_ctrl &= 0xAAEEAAFE;
|
||||||
|
|
||||||
@@ -1499,6 +1504,7 @@ void dsi_ctrl_hw_cmn_enable_error_interrupts(struct dsi_ctrl_hw *ctrl,
|
|||||||
if (errors & DSI_INTERLEAVE_OP_CONTENTION)
|
if (errors & DSI_INTERLEAVE_OP_CONTENTION)
|
||||||
int_mask0 &= ~BIT(8);
|
int_mask0 &= ~BIT(8);
|
||||||
|
|
||||||
|
dsi_write:
|
||||||
DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
|
DSI_W32(ctrl, DSI_INT_CTRL, int_ctrl);
|
||||||
DSI_W32(ctrl, DSI_ERR_INT_MASK0, int_mask0);
|
DSI_W32(ctrl, DSI_ERR_INT_MASK0, int_mask0);
|
||||||
|
|
||||||
|
@@ -70,6 +70,11 @@ static bool is_sim_panel(struct dsi_display *display)
|
|||||||
display->panel->panel_ack_disabled);
|
display->panel->panel_ack_disabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool phy_pll_bypass(struct dsi_display *display)
|
||||||
|
{
|
||||||
|
return display->ctrl[display->cmd_master_idx].phy->hw.phy_pll_bypass;
|
||||||
|
}
|
||||||
|
|
||||||
static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display,
|
static void dsi_display_mask_ctrl_error_interrupts(struct dsi_display *display,
|
||||||
u32 mask, bool enable)
|
u32 mask, bool enable)
|
||||||
{
|
{
|
||||||
@@ -773,6 +778,9 @@ static int dsi_display_read_status(struct dsi_display_ctrl *ctrl,
|
|||||||
if (!dsi_ctrl_validate_host_state(ctrl->ctrl))
|
if (!dsi_ctrl_validate_host_state(ctrl->ctrl))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
if (phy_pll_bypass(display))
|
||||||
|
return 0;
|
||||||
|
|
||||||
config = &(panel->esd_config);
|
config = &(panel->esd_config);
|
||||||
lenp = config->status_valid_params ?: config->status_cmds_rlen;
|
lenp = config->status_valid_params ?: config->status_cmds_rlen;
|
||||||
count = config->status_cmd.count;
|
count = config->status_cmd.count;
|
||||||
@@ -1067,6 +1075,9 @@ static int dsi_display_cmd_rx(struct dsi_display *display,
|
|||||||
goto release_panel_lock;
|
goto release_panel_lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (phy_pll_bypass(display))
|
||||||
|
goto release_panel_lock;
|
||||||
|
|
||||||
flags = DSI_CTRL_CMD_READ;
|
flags = DSI_CTRL_CMD_READ;
|
||||||
|
|
||||||
dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON);
|
dsi_display_clk_ctrl(display->dsi_clk_handle, DSI_ALL_CLKS, DSI_CLK_ON);
|
||||||
@@ -2810,7 +2821,7 @@ int dsi_display_phy_pll_toggle(void *priv, bool prepare)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_skip_op_required(display))
|
if (is_skip_op_required(display) || phy_pll_bypass(display))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (prepare)
|
if (prepare)
|
||||||
@@ -3254,6 +3265,9 @@ static int dsi_display_broadcast_cmd(struct dsi_display *display, struct dsi_cmd
|
|||||||
int i;
|
int i;
|
||||||
u32 flags = 0;
|
u32 flags = 0;
|
||||||
|
|
||||||
|
if (phy_pll_bypass(display))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 1. Setup commands in FIFO
|
* 1. Setup commands in FIFO
|
||||||
* 2. Trigger commands
|
* 2. Trigger commands
|
||||||
@@ -3335,7 +3349,7 @@ static int dsi_display_phy_sw_reset(struct dsi_display *display)
|
|||||||
* ctrl states are updated separately and hence we do
|
* ctrl states are updated separately and hence we do
|
||||||
* an early return
|
* an early return
|
||||||
*/
|
*/
|
||||||
if (is_skip_op_required(display)) {
|
if (is_skip_op_required(display) || phy_pll_bypass(display)) {
|
||||||
DSI_DEBUG(
|
DSI_DEBUG(
|
||||||
"cont splash/trusted vm use case, phy sw reset not required\n");
|
"cont splash/trusted vm use case, phy sw reset not required\n");
|
||||||
return 0;
|
return 0;
|
||||||
@@ -3390,6 +3404,9 @@ int dsi_host_transfer_sub(struct mipi_dsi_host *host, struct dsi_cmd_desc *cmd)
|
|||||||
|
|
||||||
display = to_dsi_display(host);
|
display = to_dsi_display(host);
|
||||||
|
|
||||||
|
if (phy_pll_bypass(display))
|
||||||
|
return 0;
|
||||||
|
|
||||||
/* Avoid sending DCS commands when ESD recovery is pending */
|
/* Avoid sending DCS commands when ESD recovery is pending */
|
||||||
if (atomic_read(&display->panel->esd_recovery_pending)) {
|
if (atomic_read(&display->panel->esd_recovery_pending)) {
|
||||||
DSI_DEBUG("ESD recovery pending\n");
|
DSI_DEBUG("ESD recovery pending\n");
|
||||||
@@ -5689,6 +5706,7 @@ static int dsi_display_bind(struct device *dev,
|
|||||||
info.priv_data = display;
|
info.priv_data = display;
|
||||||
info.master_ndx = display->clk_master_idx;
|
info.master_ndx = display->clk_master_idx;
|
||||||
info.dsi_ctrl_count = display->ctrl_count;
|
info.dsi_ctrl_count = display->ctrl_count;
|
||||||
|
info.phy_pll_bypass = phy_pll_bypass(display);
|
||||||
snprintf(info.name, MAX_STRING_LEN,
|
snprintf(info.name, MAX_STRING_LEN,
|
||||||
"DSI_MNGR-%s", display->name);
|
"DSI_MNGR-%s", display->name);
|
||||||
|
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
@@ -405,6 +405,9 @@ static int dsi_phy_driver_probe(struct platform_device *pdev)
|
|||||||
if (!dsi_phy->name)
|
if (!dsi_phy->name)
|
||||||
dsi_phy->name = DSI_PHY_DEFAULT_LABEL;
|
dsi_phy->name = DSI_PHY_DEFAULT_LABEL;
|
||||||
|
|
||||||
|
dsi_phy->hw.phy_pll_bypass = of_property_read_bool(pdev->dev.of_node,
|
||||||
|
"qcom,dsi-phy-pll-bypass");
|
||||||
|
|
||||||
DSI_PHY_DBG(dsi_phy, "Probing device\n");
|
DSI_PHY_DBG(dsi_phy, "Probing device\n");
|
||||||
|
|
||||||
dsi_phy->ver_info = ver_info;
|
dsi_phy->ver_info = ver_info;
|
||||||
|
@@ -392,6 +392,7 @@ struct dsi_phy_hw_ops {
|
|||||||
* @dyn_pll_base: VA for the DSI dynamic refresh base address.
|
* @dyn_pll_base: VA for the DSI dynamic refresh base address.
|
||||||
* @length: Length of the DSI dynamic refresh register base map.
|
* @length: Length of the DSI dynamic refresh register base map.
|
||||||
* @index: Instance ID of the controller.
|
* @index: Instance ID of the controller.
|
||||||
|
* @phy_pll_bypass: DSI PHY bypass
|
||||||
* @version: DSI PHY version.
|
* @version: DSI PHY version.
|
||||||
* @phy_clamp_base: Base address of phy clamp register map.
|
* @phy_clamp_base: Base address of phy clamp register map.
|
||||||
* @feature_map: Features supported by DSI PHY.
|
* @feature_map: Features supported by DSI PHY.
|
||||||
@@ -403,6 +404,7 @@ struct dsi_phy_hw {
|
|||||||
void __iomem *dyn_pll_base;
|
void __iomem *dyn_pll_base;
|
||||||
u32 dyn_refresh_len;
|
u32 dyn_refresh_len;
|
||||||
u32 index;
|
u32 index;
|
||||||
|
bool phy_pll_bypass;
|
||||||
|
|
||||||
enum dsi_phy_version version;
|
enum dsi_phy_version version;
|
||||||
void __iomem *phy_clamp_base;
|
void __iomem *phy_clamp_base;
|
||||||
|
@@ -119,6 +119,9 @@ static int dsi_phy_hw_v5_0_is_pll_on(struct dsi_phy_hw *phy)
|
|||||||
{
|
{
|
||||||
u32 data = 0;
|
u32 data = 0;
|
||||||
|
|
||||||
|
if (phy->phy_pll_bypass)
|
||||||
|
return 0;
|
||||||
|
|
||||||
data = DSI_R32(phy, DSIPHY_CMN_PLL_CNTRL);
|
data = DSI_R32(phy, DSIPHY_CMN_PLL_CNTRL);
|
||||||
mb(); /*make sure read happened */
|
mb(); /*make sure read happened */
|
||||||
return (data & BIT(0));
|
return (data & BIT(0));
|
||||||
@@ -435,12 +438,14 @@ void dsi_phy_hw_v5_0_enable(struct dsi_phy_hw *phy,
|
|||||||
DSI_W32(phy, DSIPHY_CMN_GLBL_DIGTOP_SPARE10, 0x1);
|
DSI_W32(phy, DSIPHY_CMN_GLBL_DIGTOP_SPARE10, 0x1);
|
||||||
udelay(500);
|
udelay(500);
|
||||||
|
|
||||||
/* wait for REFGEN READY */
|
if (!phy->phy_pll_bypass) {
|
||||||
rc = DSI_READ_POLL_TIMEOUT_ATOMIC(phy, DSIPHY_CMN_PHY_STATUS,
|
/* wait for REFGEN READY */
|
||||||
status, (status & BIT(0)), delay_us, timeout_us);
|
rc = DSI_READ_POLL_TIMEOUT_ATOMIC(phy, DSIPHY_CMN_PHY_STATUS,
|
||||||
if (rc) {
|
status, (status & BIT(0)), delay_us, timeout_us);
|
||||||
DSI_PHY_ERR(phy, "Ref gen not ready. Aborting\n");
|
if (rc) {
|
||||||
return;
|
DSI_PHY_ERR(phy, "Ref gen not ready. Aborting\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cfg->phy_type == DSI_PHY_TYPE_CPHY)
|
if (cfg->phy_type == DSI_PHY_TYPE_CPHY)
|
||||||
@@ -459,6 +464,9 @@ void dsi_phy_hw_v5_0_disable(struct dsi_phy_hw *phy,
|
|||||||
{
|
{
|
||||||
u32 data = 0;
|
u32 data = 0;
|
||||||
|
|
||||||
|
if (phy->phy_pll_bypass)
|
||||||
|
return;
|
||||||
|
|
||||||
if (dsi_phy_hw_v5_0_is_pll_on(phy))
|
if (dsi_phy_hw_v5_0_is_pll_on(phy))
|
||||||
DSI_PHY_WARN(phy, "Turning OFF PHY while PLL is on\n");
|
DSI_PHY_WARN(phy, "Turning OFF PHY while PLL is on\n");
|
||||||
|
|
||||||
@@ -497,6 +505,9 @@ void dsi_phy_hw_v5_0_reset_clk_en_sel(struct dsi_phy_hw *phy)
|
|||||||
{
|
{
|
||||||
u32 data = 0;
|
u32 data = 0;
|
||||||
|
|
||||||
|
if (phy->phy_pll_bypass)
|
||||||
|
return;
|
||||||
|
|
||||||
/*Turning off CLK_EN_SEL after retime buffer sync */
|
/*Turning off CLK_EN_SEL after retime buffer sync */
|
||||||
data = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1);
|
data = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1);
|
||||||
data &= ~BIT(4);
|
data &= ~BIT(4);
|
||||||
@@ -514,6 +525,9 @@ int dsi_phy_hw_v5_0_wait_for_lane_idle(
|
|||||||
u32 const timeout_us = 100;
|
u32 const timeout_us = 100;
|
||||||
bool split_link_enabled = dsi_phy_hw_v5_0_is_split_link_enabled(phy);
|
bool split_link_enabled = dsi_phy_hw_v5_0_is_split_link_enabled(phy);
|
||||||
|
|
||||||
|
if (phy->phy_pll_bypass)
|
||||||
|
return 0;
|
||||||
|
|
||||||
stop_state_mask = BIT(4); /* clock lane */
|
stop_state_mask = BIT(4); /* clock lane */
|
||||||
if (split_link_enabled)
|
if (split_link_enabled)
|
||||||
stop_state_mask |= BIT(5);
|
stop_state_mask |= BIT(5);
|
||||||
|
@@ -304,6 +304,8 @@ int dsi_pll_init(struct platform_device *pdev, struct dsi_pll_resource **pll)
|
|||||||
pll_res->ssc_center = true;
|
pll_res->ssc_center = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pll_res->phy_pll_bypass = of_property_read_bool(pdev->dev.of_node,
|
||||||
|
"qcom,dsi-phy-pll-bypass");
|
||||||
|
|
||||||
if (dsi_pll_get_ioresources(pdev, &pll_res->pll_base, "pll_base")) {
|
if (dsi_pll_get_ioresources(pdev, &pll_res->pll_base, "pll_base")) {
|
||||||
DSI_PLL_ERR(pll_res, "Unable to remap pll base resources\n");
|
DSI_PLL_ERR(pll_res, "Unable to remap pll base resources\n");
|
||||||
@@ -335,6 +337,9 @@ int dsi_pll_init(struct platform_device *pdev, struct dsi_pll_resource **pll)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pll_res->phy_pll_bypass)
|
||||||
|
return 0;
|
||||||
|
|
||||||
rc = dsi_pll_clock_register(pdev, pll_res);
|
rc = dsi_pll_clock_register(pdev, pll_res);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
DSI_PLL_ERR(pll_res, "clock register failed rc=%d\n", rc);
|
DSI_PLL_ERR(pll_res, "clock register failed rc=%d\n", rc);
|
||||||
|
@@ -169,6 +169,8 @@ struct dsi_pll_resource {
|
|||||||
int bpp;
|
int bpp;
|
||||||
int lanes;
|
int lanes;
|
||||||
|
|
||||||
|
bool phy_pll_bypass;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* DSI PHY type DPHY/CPHY
|
* DSI PHY type DPHY/CPHY
|
||||||
*/
|
*/
|
||||||
|
@@ -548,6 +548,9 @@ static int dsi_pll_4nm_lock_status(struct dsi_pll_resource *pll)
|
|||||||
u32 const delay_us = 100;
|
u32 const delay_us = 100;
|
||||||
u32 const timeout_us = 5000;
|
u32 const timeout_us = 5000;
|
||||||
|
|
||||||
|
if (pll->phy_pll_bypass)
|
||||||
|
return 0;
|
||||||
|
|
||||||
rc = DSI_READ_POLL_TIMEOUT_ATOMIC_GEN(pll->pll_base, pll->index, PLL_COMMON_STATUS_ONE,
|
rc = DSI_READ_POLL_TIMEOUT_ATOMIC_GEN(pll->pll_base, pll->index, PLL_COMMON_STATUS_ONE,
|
||||||
status,
|
status,
|
||||||
((status & BIT(0)) > 0),
|
((status & BIT(0)) > 0),
|
||||||
|
@@ -4720,6 +4720,9 @@ static int _sde_kms_get_splash_data(struct sde_splash_data *data)
|
|||||||
int num_displays, num_regions;
|
int num_displays, num_regions;
|
||||||
struct sde_splash_display *splash_display;
|
struct sde_splash_display *splash_display;
|
||||||
|
|
||||||
|
if (of_find_node_with_property(NULL, "qcom,sde-emulated-env"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
if (!data)
|
if (!data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user