disp: msm: dsi: snapshot of dsi from 4.14 to 4.19
This change is a snapshot of dsi files taken of 4.14 as of commit 764f7c2 (Merge remote-tracking branch 'quic/dev/msm-4.14-display' into msm-4.14) Change-Id: I8361a844c35a4450f7800964a8da2741676fd6c7 Signed-off-by: Satya Rama Aditya Pinapala <psraditya30@codeaurora.org>
This commit is contained in:
parent
91f4bcda9d
commit
edef6ae040
@ -64,6 +64,7 @@ static void dsi_catalog_cmn_init(struct dsi_ctrl_hw *ctrl,
|
||||
ctrl->ops.set_continuous_clk = dsi_ctrl_hw_cmn_set_continuous_clk;
|
||||
ctrl->ops.wait4dynamic_refresh_done =
|
||||
dsi_ctrl_hw_cmn_wait4dynamic_refresh_done;
|
||||
ctrl->ops.hs_req_sel = dsi_ctrl_hw_cmn_hs_req_sel;
|
||||
|
||||
switch (version) {
|
||||
case DSI_CTRL_VERSION_1_4:
|
||||
@ -261,6 +262,7 @@ static void dsi_catalog_phy_4_0_init(struct dsi_phy_hw *phy)
|
||||
dsi_phy_hw_v4_0_dyn_refresh_helper;
|
||||
phy->ops.dyn_refresh_ops.cache_phy_timings =
|
||||
dsi_phy_hw_v4_0_cache_phy_timings;
|
||||
phy->ops.set_continuous_clk = dsi_phy_hw_v4_0_set_continuous_clk;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,6 +115,7 @@ int dsi_phy_hw_timing_val_v4_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
|
||||
int dsi_phy_hw_v4_0_lane_reset(struct dsi_phy_hw *phy);
|
||||
void dsi_phy_hw_v4_0_toggle_resync_fifo(struct dsi_phy_hw *phy);
|
||||
void dsi_phy_hw_v4_0_reset_clk_en_sel(struct dsi_phy_hw *phy);
|
||||
void dsi_phy_hw_v4_0_set_continuous_clk(struct dsi_phy_hw *phy, bool enable);
|
||||
|
||||
/* DSI controller common ops */
|
||||
u32 dsi_ctrl_hw_cmn_get_interrupt_status(struct dsi_ctrl_hw *ctrl);
|
||||
@ -239,6 +240,7 @@ void dsi_ctrl_hw_22_config_clk_gating(struct dsi_ctrl_hw *ctrl, bool enable,
|
||||
enum dsi_clk_gate_type clk_selection);
|
||||
|
||||
void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable);
|
||||
void dsi_ctrl_hw_cmn_hs_req_sel(struct dsi_ctrl_hw *ctrl, bool sel_phy);
|
||||
|
||||
/* dynamic refresh specific functions */
|
||||
void dsi_phy_hw_v3_0_dyn_refresh_helper(struct dsi_phy_hw *phy, u32 offset);
|
||||
|
@ -1272,23 +1272,15 @@ static int dsi_display_link_clk_force_update(void *client)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = dsi_display_link_clk_disable(l_clks,
|
||||
(DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
|
||||
mngr->dsi_ctrl_count, mngr->master_ndx);
|
||||
if (rc) {
|
||||
pr_err("%s, failed to stop link clk, rc = %d\n",
|
||||
__func__, rc);
|
||||
rc = dsi_clk_update_link_clk_state(mngr, l_clks, (DSI_LINK_LP_CLK |
|
||||
DSI_LINK_HS_CLK), DSI_CLK_OFF, false);
|
||||
if (rc)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = dsi_display_link_clk_enable(l_clks,
|
||||
(DSI_LINK_LP_CLK | DSI_LINK_HS_CLK),
|
||||
mngr->dsi_ctrl_count, mngr->master_ndx);
|
||||
if (rc) {
|
||||
pr_err("%s, failed to start link clk rc= %d\n",
|
||||
__func__, rc);
|
||||
rc = dsi_clk_update_link_clk_state(mngr, l_clks, (DSI_LINK_LP_CLK |
|
||||
DSI_LINK_HS_CLK), DSI_CLK_ON, true);
|
||||
if (rc)
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
mutex_unlock(&mngr->clk_mutex);
|
||||
|
@ -34,22 +34,6 @@
|
||||
|
||||
#define TICKS_IN_MICRO_SECOND 1000000
|
||||
|
||||
/**
|
||||
* enum dsi_ctrl_driver_ops - controller driver ops
|
||||
*/
|
||||
enum dsi_ctrl_driver_ops {
|
||||
DSI_CTRL_OP_POWER_STATE_CHANGE,
|
||||
DSI_CTRL_OP_CMD_ENGINE,
|
||||
DSI_CTRL_OP_VID_ENGINE,
|
||||
DSI_CTRL_OP_HOST_ENGINE,
|
||||
DSI_CTRL_OP_CMD_TX,
|
||||
DSI_CTRL_OP_HOST_INIT,
|
||||
DSI_CTRL_OP_TPG,
|
||||
DSI_CTRL_OP_PHY_SW_RESET,
|
||||
DSI_CTRL_OP_ASYNC_TIMING,
|
||||
DSI_CTRL_OP_MAX
|
||||
};
|
||||
|
||||
struct dsi_ctrl_list_item {
|
||||
struct dsi_ctrl *ctrl;
|
||||
struct list_head list;
|
||||
@ -833,6 +817,7 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
|
||||
u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane,
|
||||
byte_clk_rate;
|
||||
struct dsi_host_common_cfg *host_cfg = &config->common_config;
|
||||
struct dsi_split_link_config *split_link = &host_cfg->split_link;
|
||||
struct dsi_mode_info *timing = &config->video_timing;
|
||||
u64 dsi_transfer_time_us = mode->priv_info->dsi_transfer_time_us;
|
||||
u64 min_dsi_clk_hz = mode->priv_info->min_dsi_clk_hz;
|
||||
@ -850,6 +835,9 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
|
||||
if (host_cfg->data_lanes & DSI_DATA_LANE_3)
|
||||
num_of_lanes++;
|
||||
|
||||
if (split_link->split_link_enabled)
|
||||
num_of_lanes = split_link->lanes_per_sublink;
|
||||
|
||||
config->common_config.num_data_lanes = num_of_lanes;
|
||||
config->common_config.bpp = bpp;
|
||||
|
||||
@ -943,6 +931,7 @@ static int dsi_ctrl_copy_and_pad_cmd(struct dsi_ctrl *dsi_ctrl,
|
||||
int rc = 0;
|
||||
u8 *buf = NULL;
|
||||
u32 len, i;
|
||||
u8 cmd_type = 0;
|
||||
|
||||
len = packet->size;
|
||||
len += 0x3; len &= ~0x03; /* Align to 32 bits */
|
||||
@ -965,7 +954,11 @@ static int dsi_ctrl_copy_and_pad_cmd(struct dsi_ctrl *dsi_ctrl,
|
||||
|
||||
|
||||
/* send embedded BTA for read commands */
|
||||
if ((buf[2] & 0x3f) == MIPI_DSI_DCS_READ)
|
||||
cmd_type = buf[2] & 0x3f;
|
||||
if ((cmd_type == MIPI_DSI_DCS_READ) ||
|
||||
(cmd_type == MIPI_DSI_GENERIC_READ_REQUEST_0_PARAM) ||
|
||||
(cmd_type == MIPI_DSI_GENERIC_READ_REQUEST_1_PARAM) ||
|
||||
(cmd_type == MIPI_DSI_GENERIC_READ_REQUEST_2_PARAM))
|
||||
buf[3] |= BIT(5);
|
||||
|
||||
*buffer = buf;
|
||||
@ -1509,7 +1502,7 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
|
||||
cmd = buff[0];
|
||||
switch (cmd) {
|
||||
case MIPI_DSI_RX_ACKNOWLEDGE_AND_ERROR_REPORT:
|
||||
pr_err("Rx ACK_ERROR\n");
|
||||
pr_err("Rx ACK_ERROR 0x%x\n", cmd);
|
||||
rc = 0;
|
||||
break;
|
||||
case MIPI_DSI_RX_GENERIC_SHORT_READ_RESPONSE_1BYTE:
|
||||
@ -1525,7 +1518,7 @@ static int dsi_message_rx(struct dsi_ctrl *dsi_ctrl,
|
||||
rc = dsi_parse_long_read_resp(msg, buff);
|
||||
break;
|
||||
default:
|
||||
pr_warn("Invalid response\n");
|
||||
pr_warn("Invalid response: 0x%x\n", cmd);
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
@ -1601,6 +1594,18 @@ static int dsi_disable_ulps(struct dsi_ctrl *dsi_ctrl)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dsi_ctrl_enable_error_interrupts(struct dsi_ctrl *dsi_ctrl)
|
||||
{
|
||||
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE &&
|
||||
!dsi_ctrl->host_config.u.video_engine.bllp_lp11_en &&
|
||||
!dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en)
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw,
|
||||
0xFF00A0);
|
||||
else
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw,
|
||||
0xFF00E0);
|
||||
}
|
||||
|
||||
static int dsi_ctrl_drv_state_init(struct dsi_ctrl *dsi_ctrl)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -1730,6 +1735,9 @@ static int dsi_ctrl_dts_parse(struct dsi_ctrl *dsi_ctrl,
|
||||
dsi_ctrl->null_insertion_enabled = of_property_read_bool(of_node,
|
||||
"qcom,null-insertion-enabled");
|
||||
|
||||
dsi_ctrl->split_link_supported = of_property_read_bool(of_node,
|
||||
"qcom,split-link-supported");
|
||||
|
||||
rc = of_property_read_u32(of_node, "frame-threshold-time-us",
|
||||
&frame_threshold_time_us);
|
||||
if (rc) {
|
||||
@ -2217,7 +2225,7 @@ int dsi_ctrl_setup(struct dsi_ctrl *dsi_ctrl)
|
||||
}
|
||||
|
||||
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
|
||||
dsi_ctrl_enable_error_interrupts(dsi_ctrl);
|
||||
dsi_ctrl->hw.ops.ctrl_en(&dsi_ctrl->hw, true);
|
||||
|
||||
mutex_unlock(&dsi_ctrl->ctrl_lock);
|
||||
@ -2340,6 +2348,12 @@ static void dsi_ctrl_handle_error_status(struct dsi_ctrl *dsi_ctrl,
|
||||
if (error & 0x3000E00)
|
||||
pr_err("dsi PHY contention error: 0x%lx\n", error);
|
||||
|
||||
/* ignore TX timeout if blpp_lp11 is disabled */
|
||||
if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE &&
|
||||
!dsi_ctrl->host_config.u.video_engine.bllp_lp11_en &&
|
||||
!dsi_ctrl->host_config.u.video_engine.eof_bllp_lp11_en)
|
||||
error &= ~DSI_HS_TX_TIMEOUT;
|
||||
|
||||
/* TX timeout error */
|
||||
if (error & 0xE0) {
|
||||
if (error & 0xA0) {
|
||||
@ -2637,27 +2651,34 @@ int dsi_ctrl_host_timing_update(struct dsi_ctrl *dsi_ctrl)
|
||||
}
|
||||
|
||||
/**
|
||||
* dsi_ctrl_update_host_init_state() - Update the host initialization state.
|
||||
* dsi_ctrl_update_host_state() - Update the host initialization state.
|
||||
* @dsi_ctrl: DSI controller handle.
|
||||
* @op: ctrl driver ops
|
||||
* @enable: boolean signifying host state.
|
||||
*
|
||||
* Update the host initialization status only while exiting from ulps during
|
||||
* suspend state.
|
||||
* Update the host status only while exiting from ulps during suspend state.
|
||||
*
|
||||
* Return: error code.
|
||||
*/
|
||||
int dsi_ctrl_update_host_init_state(struct dsi_ctrl *dsi_ctrl, bool enable)
|
||||
int dsi_ctrl_update_host_state(struct dsi_ctrl *dsi_ctrl,
|
||||
enum dsi_ctrl_driver_ops op, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 state = enable ? 0x1 : 0x0;
|
||||
|
||||
rc = dsi_ctrl_check_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, state);
|
||||
if (!dsi_ctrl)
|
||||
return rc;
|
||||
mutex_lock(&dsi_ctrl->ctrl_lock);
|
||||
rc = dsi_ctrl_check_state(dsi_ctrl, op, state);
|
||||
if (rc) {
|
||||
pr_err("[DSI_%d] Controller state check failed, rc=%d\n",
|
||||
dsi_ctrl->cell_index, rc);
|
||||
mutex_unlock(&dsi_ctrl->ctrl_lock);
|
||||
return rc;
|
||||
}
|
||||
dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_HOST_INIT, state);
|
||||
|
||||
dsi_ctrl_update_state(dsi_ctrl, op, state);
|
||||
mutex_unlock(&dsi_ctrl->ctrl_lock);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -2720,7 +2741,7 @@ int dsi_ctrl_host_init(struct dsi_ctrl *dsi_ctrl, bool is_splash_enabled)
|
||||
}
|
||||
|
||||
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw, 0x0);
|
||||
dsi_ctrl->hw.ops.enable_error_interrupts(&dsi_ctrl->hw, 0xFF00E0);
|
||||
dsi_ctrl_enable_error_interrupts(dsi_ctrl);
|
||||
|
||||
pr_debug("[DSI_%d]Host initialization complete, continuous splash status:%d\n",
|
||||
dsi_ctrl->cell_index, is_splash_enabled);
|
||||
@ -2749,6 +2770,16 @@ void dsi_ctrl_isr_configure(struct dsi_ctrl *dsi_ctrl, bool enable)
|
||||
mutex_unlock(&dsi_ctrl->ctrl_lock);
|
||||
}
|
||||
|
||||
void dsi_ctrl_hs_req_sel(struct dsi_ctrl *dsi_ctrl, bool sel_phy)
|
||||
{
|
||||
if (!dsi_ctrl)
|
||||
return;
|
||||
|
||||
mutex_lock(&dsi_ctrl->ctrl_lock);
|
||||
dsi_ctrl->hw.ops.hs_req_sel(&dsi_ctrl->hw, sel_phy);
|
||||
mutex_unlock(&dsi_ctrl->ctrl_lock);
|
||||
}
|
||||
|
||||
void dsi_ctrl_set_continuous_clk(struct dsi_ctrl *dsi_ctrl, bool enable)
|
||||
{
|
||||
if (!dsi_ctrl)
|
||||
|
@ -75,6 +75,22 @@ enum dsi_engine_state {
|
||||
DSI_CTRL_ENGINE_MAX,
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dsi_ctrl_driver_ops - controller driver ops
|
||||
*/
|
||||
enum dsi_ctrl_driver_ops {
|
||||
DSI_CTRL_OP_POWER_STATE_CHANGE,
|
||||
DSI_CTRL_OP_CMD_ENGINE,
|
||||
DSI_CTRL_OP_VID_ENGINE,
|
||||
DSI_CTRL_OP_HOST_ENGINE,
|
||||
DSI_CTRL_OP_CMD_TX,
|
||||
DSI_CTRL_OP_HOST_INIT,
|
||||
DSI_CTRL_OP_TPG,
|
||||
DSI_CTRL_OP_PHY_SW_RESET,
|
||||
DSI_CTRL_OP_ASYNC_TIMING,
|
||||
DSI_CTRL_OP_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* struct dsi_ctrl_power_info - digital and analog power supplies for dsi host
|
||||
* @digital: Digital power supply required to turn on DSI controller hardware.
|
||||
@ -212,6 +228,7 @@ struct dsi_ctrl_interrupts {
|
||||
* @null_insertion_enabled: A boolean property to allow dsi controller to
|
||||
* insert null packet.
|
||||
* @modeupdated: Boolean to send new roi if mode is updated.
|
||||
* @split_link_supported: Boolean to check if hw supports split link.
|
||||
*/
|
||||
struct dsi_ctrl {
|
||||
struct platform_device *pdev;
|
||||
@ -267,6 +284,7 @@ struct dsi_ctrl {
|
||||
bool phy_isolation_enabled;
|
||||
bool null_insertion_enabled;
|
||||
bool modeupdated;
|
||||
bool split_link_supported;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -786,15 +804,24 @@ int dsi_ctrl_get_host_engine_init_state(struct dsi_ctrl *dsi_ctrl,
|
||||
*/
|
||||
int dsi_ctrl_wait_for_cmd_mode_mdp_idle(struct dsi_ctrl *dsi_ctrl);
|
||||
/**
|
||||
* dsi_ctrl_update_host_init_state() - Set the host initialization state
|
||||
* dsi_ctrl_update_host_state() - Set the host state
|
||||
*/
|
||||
int dsi_ctrl_update_host_init_state(struct dsi_ctrl *dsi_ctrl, bool en);
|
||||
int dsi_ctrl_update_host_state(struct dsi_ctrl *dsi_ctrl,
|
||||
enum dsi_ctrl_driver_ops op, bool en);
|
||||
|
||||
/**
|
||||
* dsi_ctrl_pixel_format_to_bpp() - returns number of bits per pxl
|
||||
*/
|
||||
int dsi_ctrl_pixel_format_to_bpp(enum dsi_pixel_format dst_format);
|
||||
|
||||
/**
|
||||
* dsi_ctrl_hs_req_sel() - API to enable continuous clk support through phy
|
||||
* @dsi_ctrl: DSI controller handle.
|
||||
* @sel_phy: Boolean to control whether to select phy or
|
||||
* controller
|
||||
*/
|
||||
void dsi_ctrl_hs_req_sel(struct dsi_ctrl *dsi_ctrl, bool sel_phy);
|
||||
|
||||
/**
|
||||
* dsi_ctrl_set_continuous_clk() - API to set/unset force clock lane HS request.
|
||||
* @dsi_ctrl: DSI controller handle.
|
||||
|
@ -823,6 +823,12 @@ struct dsi_ctrl_hw_ops {
|
||||
* @ctrl: Pointer to the controller host hardware.
|
||||
*/
|
||||
int (*wait4dynamic_refresh_done)(struct dsi_ctrl_hw *ctrl);
|
||||
/**
|
||||
* hw.ops.hs_req_sel() - enable continuous clk support through phy
|
||||
* @ctrl: Pointer to the controller host hardware.
|
||||
* @sel_phy: Bool to control whether to select phy or controller
|
||||
*/
|
||||
void (*hs_req_sel)(struct dsi_ctrl_hw *ctrl, bool sel_phy);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -19,6 +19,8 @@
|
||||
#define DSI_CTRL_DYNAMIC_FORCE_ON (0x23F|BIT(8)|BIT(9)|BIT(11)|BIT(21))
|
||||
#define DSI_CTRL_CMD_MISR_ENABLE BIT(28)
|
||||
#define DSI_CTRL_VIDEO_MISR_ENABLE BIT(16)
|
||||
#define DSI_CTRL_DMA_LINK_SEL (BIT(12)|BIT(13))
|
||||
#define DSI_CTRL_MDP0_LINK_SEL (BIT(20)|BIT(22))
|
||||
|
||||
/* Unsupported formats default to RGB888 */
|
||||
static const u8 cmd_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
|
||||
@ -26,6 +28,38 @@ static const u8 cmd_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
|
||||
static const u8 video_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
|
||||
0x0, 0x1, 0x2, 0x3, 0x3, 0x3, 0x3 };
|
||||
|
||||
/**
|
||||
* dsi_split_link_setup() - setup dsi split link configurations
|
||||
* @ctrl: Pointer to the controller host hardware.
|
||||
* @cfg: DSI host configuration that is common to both video and
|
||||
* command modes.
|
||||
*/
|
||||
static void dsi_split_link_setup(struct dsi_ctrl_hw *ctrl,
|
||||
struct dsi_host_common_cfg *cfg)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
if (!cfg->split_link.split_link_enabled)
|
||||
return;
|
||||
|
||||
reg = DSI_R32(ctrl, DSI_SPLIT_LINK);
|
||||
|
||||
/* DMA_LINK_SEL */
|
||||
reg &= ~(0x7 << 12);
|
||||
reg |= DSI_CTRL_DMA_LINK_SEL;
|
||||
|
||||
/* MDP0_LINK_SEL */
|
||||
reg &= ~(0x7 << 20);
|
||||
reg |= DSI_CTRL_MDP0_LINK_SEL;
|
||||
|
||||
/* EN */
|
||||
reg |= 0x1;
|
||||
|
||||
/* DSI_SPLIT_LINK */
|
||||
DSI_W32(ctrl, DSI_SPLIT_LINK, reg);
|
||||
wmb(); /* make sure split link is asserted */
|
||||
}
|
||||
|
||||
/**
|
||||
* dsi_setup_trigger_controls() - setup dsi trigger configurations
|
||||
* @ctrl: Pointer to the controller host hardware.
|
||||
@ -57,6 +91,7 @@ void dsi_ctrl_hw_cmn_host_setup(struct dsi_ctrl_hw *ctrl,
|
||||
u32 reg_value = 0;
|
||||
|
||||
dsi_setup_trigger_controls(ctrl, cfg);
|
||||
dsi_split_link_setup(ctrl, cfg);
|
||||
|
||||
/* Setup clocking timing controls */
|
||||
reg_value = ((cfg->t_clk_post & 0x3F) << 8);
|
||||
@ -1533,6 +1568,19 @@ int dsi_ctrl_hw_cmn_wait_for_cmd_mode_mdp_idle(struct dsi_ctrl_hw *ctrl)
|
||||
return rc;
|
||||
}
|
||||
|
||||
void dsi_ctrl_hw_cmn_hs_req_sel(struct dsi_ctrl_hw *ctrl, bool sel_phy)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
||||
reg = DSI_R32(ctrl, DSI_LANE_CTRL);
|
||||
if (sel_phy)
|
||||
reg &= ~BIT(24);
|
||||
else
|
||||
reg |= BIT(24);
|
||||
DSI_W32(ctrl, DSI_LANE_CTRL, reg);
|
||||
wmb(); /* make sure request is set */
|
||||
}
|
||||
|
||||
void dsi_ctrl_hw_cmn_set_continuous_clk(struct dsi_ctrl_hw *ctrl, bool enable)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
@ -145,6 +145,7 @@
|
||||
#define DSI_SECURE_DISPLAY_BLOCK_COMMAND_COLOR (0x02D0)
|
||||
#define DSI_SECURE_DISPLAY_BLOCK_VIDEO_COLOR (0x02D4)
|
||||
#define DSI_LOGICAL_LANE_SWAP_CTRL (0x0310)
|
||||
#define DSI_SPLIT_LINK (0x0330)
|
||||
|
||||
|
||||
#endif /* _DSI_CTRL_REG_H_ */
|
||||
|
@ -78,6 +78,11 @@ static int dsi_display_config_clk_gating(struct dsi_display *display,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (display->panel->host_config.force_hs_clk_lane) {
|
||||
pr_debug("no dsi clock gating for continuous clock mode\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mctrl = &display->ctrl[display->clk_master_idx];
|
||||
if (!mctrl) {
|
||||
pr_err("Invalid controller\n");
|
||||
@ -586,8 +591,11 @@ static bool dsi_display_validate_reg_read(struct dsi_panel *panel)
|
||||
for (j = 0; j < config->groups; ++j) {
|
||||
for (i = 0; i < len; ++i) {
|
||||
if (config->return_buf[i] !=
|
||||
config->status_value[group + i])
|
||||
config->status_value[group + i]) {
|
||||
DRM_ERROR("mismatch: 0x%x\n",
|
||||
config->return_buf[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == len)
|
||||
@ -828,6 +836,11 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
|
||||
if (te_check_override && gpio_is_valid(dsi_display->disp_te_gpio))
|
||||
status_mode = ESD_MODE_PANEL_TE;
|
||||
|
||||
if (status_mode == ESD_MODE_PANEL_TE) {
|
||||
rc = dsi_display_status_check_te(dsi_display);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
|
||||
DSI_ALL_CLKS, DSI_CLK_ON);
|
||||
|
||||
@ -843,23 +856,25 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
|
||||
} else if (status_mode == ESD_MODE_PANEL_TE) {
|
||||
rc = dsi_display_status_check_te(dsi_display);
|
||||
} else {
|
||||
pr_warn("unsupported check status mode\n");
|
||||
pr_warn("Unsupported check status mode: %d\n", status_mode);
|
||||
panel->esd_config.esd_enabled = false;
|
||||
}
|
||||
|
||||
/* Unmask error interrupts */
|
||||
/* Unmask error interrupts if check passed*/
|
||||
if (rc > 0) {
|
||||
dsi_display_set_ctrl_esd_check_flag(dsi_display, false);
|
||||
dsi_display_mask_ctrl_error_interrupts(dsi_display, mask,
|
||||
false);
|
||||
} else {
|
||||
/* Handle Panel failures during display disable sequence */
|
||||
atomic_set(&panel->esd_recovery_pending, 1);
|
||||
}
|
||||
|
||||
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
|
||||
DSI_ALL_CLKS, DSI_CLK_OFF);
|
||||
|
||||
exit:
|
||||
/* Handle Panel failures during display disable sequence */
|
||||
if (rc <=0)
|
||||
atomic_set(&panel->esd_recovery_pending, 1);
|
||||
|
||||
release_panel_lock:
|
||||
dsi_panel_release_panel_lock(panel);
|
||||
SDE_EVT32(SDE_EVTLOG_FUNC_EXIT);
|
||||
@ -1620,12 +1635,25 @@ static int dsi_display_debugfs_deinit(struct dsi_display *display)
|
||||
static void adjust_timing_by_ctrl_count(const struct dsi_display *display,
|
||||
struct dsi_display_mode *mode)
|
||||
{
|
||||
mode->timing.h_active /= display->ctrl_count;
|
||||
mode->timing.h_front_porch /= display->ctrl_count;
|
||||
mode->timing.h_sync_width /= display->ctrl_count;
|
||||
mode->timing.h_back_porch /= display->ctrl_count;
|
||||
mode->timing.h_skew /= display->ctrl_count;
|
||||
mode->pixel_clk_khz /= display->ctrl_count;
|
||||
struct dsi_host_common_cfg *host = &display->panel->host_config;
|
||||
bool is_split_link = host->split_link.split_link_enabled;
|
||||
u32 sublinks_count = host->split_link.num_sublinks;
|
||||
|
||||
if (is_split_link && sublinks_count > 1) {
|
||||
mode->timing.h_active /= sublinks_count;
|
||||
mode->timing.h_front_porch /= sublinks_count;
|
||||
mode->timing.h_sync_width /= sublinks_count;
|
||||
mode->timing.h_back_porch /= sublinks_count;
|
||||
mode->timing.h_skew /= sublinks_count;
|
||||
mode->pixel_clk_khz /= sublinks_count;
|
||||
} else {
|
||||
mode->timing.h_active /= display->ctrl_count;
|
||||
mode->timing.h_front_porch /= display->ctrl_count;
|
||||
mode->timing.h_sync_width /= display->ctrl_count;
|
||||
mode->timing.h_back_porch /= display->ctrl_count;
|
||||
mode->timing.h_skew /= display->ctrl_count;
|
||||
mode->pixel_clk_khz /= display->ctrl_count;
|
||||
}
|
||||
}
|
||||
|
||||
static int dsi_display_is_ulps_req_valid(struct dsi_display *display,
|
||||
@ -2366,7 +2394,9 @@ static int dsi_display_ctrl_init(struct dsi_display *display)
|
||||
} else {
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
rc = dsi_ctrl_update_host_init_state(ctrl->ctrl, true);
|
||||
rc = dsi_ctrl_update_host_state(ctrl->ctrl,
|
||||
DSI_CTRL_OP_HOST_INIT,
|
||||
true);
|
||||
if (rc)
|
||||
pr_debug("host init update failed rc=%d\n", rc);
|
||||
}
|
||||
@ -2450,6 +2480,25 @@ static int dsi_display_ctrl_host_disable(struct dsi_display *display)
|
||||
struct dsi_display_ctrl *m_ctrl, *ctrl;
|
||||
|
||||
m_ctrl = &display->ctrl[display->cmd_master_idx];
|
||||
/*
|
||||
* For platforms where ULPS is controlled by DSI controller block,
|
||||
* do not disable dsi controller block if lanes are to be
|
||||
* kept in ULPS during suspend. So just update the SW state
|
||||
* and return early.
|
||||
*/
|
||||
if (display->panel->ulps_suspend_enabled &&
|
||||
!m_ctrl->phy->hw.ops.ulps_ops.ulps_request) {
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
rc = dsi_ctrl_update_host_state(ctrl->ctrl,
|
||||
DSI_CTRL_OP_HOST_ENGINE,
|
||||
false);
|
||||
if (rc)
|
||||
pr_debug("host state update failed %d\n", rc);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
if (!ctrl->ctrl || (ctrl == m_ctrl))
|
||||
@ -4609,6 +4658,42 @@ static int dsi_display_force_update_dsi_clk(struct dsi_display *display)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dsi_display_validate_split_link(struct dsi_display *display)
|
||||
{
|
||||
int i, rc = 0;
|
||||
struct dsi_display_ctrl *ctrl;
|
||||
struct dsi_host_common_cfg *host = &display->panel->host_config;
|
||||
|
||||
if (!host->split_link.split_link_enabled)
|
||||
return 0;
|
||||
|
||||
if (display->panel->panel_mode == DSI_OP_CMD_MODE) {
|
||||
pr_err("[%s] split link is not supported in command mode\n",
|
||||
display->name);
|
||||
rc = -ENOTSUPP;
|
||||
goto error;
|
||||
}
|
||||
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
if (!ctrl->ctrl->split_link_supported) {
|
||||
pr_err("[%s] split link is not supported by hw\n",
|
||||
display->name);
|
||||
rc = -ENOTSUPP;
|
||||
goto error;
|
||||
}
|
||||
|
||||
set_bit(DSI_PHY_SPLIT_LINK, ctrl->phy->hw.feature_map);
|
||||
}
|
||||
|
||||
pr_debug("Split link is enabled\n");
|
||||
return 0;
|
||||
|
||||
error:
|
||||
host->split_link.split_link_enabled = false;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* dsi_display_bind - bind dsi device with controlling device
|
||||
* @dev: Pointer to base of platform device
|
||||
@ -4649,8 +4734,28 @@ static int dsi_display_bind(struct device *dev,
|
||||
|
||||
if (!display->fw)
|
||||
display->name = display->panel_node->name;
|
||||
|
||||
/* defer bind if ext bridge driver is not loaded */
|
||||
if (display->panel && display->panel->host_config.ext_bridge_mode) {
|
||||
for (i = 0; i < display->ext_bridge_cnt; i++) {
|
||||
if (!of_drm_find_bridge(
|
||||
display->ext_bridge[i].node_of)) {
|
||||
pr_debug("defer for bridge[%d] %s\n", i,
|
||||
display->ext_bridge[i].node_of->full_name);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&display->display_lock);
|
||||
|
||||
rc = dsi_display_validate_split_link(display);
|
||||
if (rc) {
|
||||
pr_err("[%s] split link validation failed, rc=%d\n",
|
||||
display->name, rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = dsi_display_debugfs_init(display);
|
||||
if (rc) {
|
||||
pr_err("[%s] debugfs init failed, rc=%d\n", display->name, rc);
|
||||
@ -5273,7 +5378,7 @@ static struct dsi_display_ext_bridge *dsi_display_ext_get_bridge(
|
||||
sde_conn = to_sde_connector(conn_iter);
|
||||
if (sde_conn->encoder == bridge->encoder) {
|
||||
display = sde_conn->display;
|
||||
for (i = 0; i < display->ctrl_count; i++) {
|
||||
display_for_each_ctrl(i, display) {
|
||||
if (display->ext_bridge[i].bridge == bridge)
|
||||
return &display->ext_bridge[i];
|
||||
}
|
||||
@ -5440,6 +5545,9 @@ int dsi_display_drm_ext_bridge_init(struct dsi_display *display,
|
||||
struct drm_bridge *prev_bridge = bridge;
|
||||
int rc = 0, i;
|
||||
|
||||
if (display->panel && !display->panel->host_config.ext_bridge_mode)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < display->ext_bridge_cnt; i++) {
|
||||
struct dsi_display_ext_bridge *ext_bridge_info =
|
||||
&display->ext_bridge[i];
|
||||
@ -5750,8 +5858,10 @@ int dsi_display_get_modes(struct dsi_display *display,
|
||||
{
|
||||
struct dsi_dfps_capabilities dfps_caps;
|
||||
struct dsi_display_ctrl *ctrl;
|
||||
struct dsi_host_common_cfg *host = &display->panel->host_config;
|
||||
bool is_split_link;
|
||||
u32 num_dfps_rates, panel_mode_count, total_mode_count;
|
||||
u32 mode_idx, array_idx = 0;
|
||||
u32 sublinks_count, mode_idx, array_idx = 0;
|
||||
struct dsi_dyn_clk_caps *dyn_clk_caps;
|
||||
int i, start, end, rc = -EINVAL;
|
||||
|
||||
@ -5827,15 +5937,25 @@ int dsi_display_get_modes(struct dsi_display *display,
|
||||
panel_mode.timing.dsi_transfer_time_us;
|
||||
}
|
||||
|
||||
panel_mode.timing.h_active *= display->ctrl_count;
|
||||
panel_mode.timing.h_front_porch *= display->ctrl_count;
|
||||
panel_mode.timing.h_sync_width *= display->ctrl_count;
|
||||
panel_mode.timing.h_back_porch *= display->ctrl_count;
|
||||
panel_mode.timing.h_skew *= display->ctrl_count;
|
||||
panel_mode.pixel_clk_khz *= display->ctrl_count;
|
||||
is_split_link = host->split_link.split_link_enabled;
|
||||
sublinks_count = host->split_link.num_sublinks;
|
||||
if (is_split_link && sublinks_count > 1) {
|
||||
panel_mode.timing.h_active *= sublinks_count;
|
||||
panel_mode.timing.h_front_porch *= sublinks_count;
|
||||
panel_mode.timing.h_sync_width *= sublinks_count;
|
||||
panel_mode.timing.h_back_porch *= sublinks_count;
|
||||
panel_mode.timing.h_skew *= sublinks_count;
|
||||
panel_mode.pixel_clk_khz *= sublinks_count;
|
||||
} else {
|
||||
panel_mode.timing.h_active *= display->ctrl_count;
|
||||
panel_mode.timing.h_front_porch *= display->ctrl_count;
|
||||
panel_mode.timing.h_sync_width *= display->ctrl_count;
|
||||
panel_mode.timing.h_back_porch *= display->ctrl_count;
|
||||
panel_mode.timing.h_skew *= display->ctrl_count;
|
||||
panel_mode.pixel_clk_khz *= display->ctrl_count;
|
||||
}
|
||||
|
||||
start = array_idx;
|
||||
|
||||
for (i = 0; i < num_dfps_rates; i++) {
|
||||
struct dsi_display_mode *sub_mode =
|
||||
&display->modes[array_idx];
|
||||
@ -5886,6 +6006,7 @@ int dsi_display_get_panel_vfp(void *dsi_display,
|
||||
u32 count, refresh_rate = 0;
|
||||
struct dsi_dfps_capabilities dfps_caps;
|
||||
struct dsi_display *display = (struct dsi_display *)dsi_display;
|
||||
struct dsi_host_common_cfg *host;
|
||||
|
||||
if (!display)
|
||||
return -EINVAL;
|
||||
@ -5909,7 +6030,11 @@ int dsi_display_get_panel_vfp(void *dsi_display,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
h_active *= display->ctrl_count;
|
||||
host = &display->panel->host_config;
|
||||
if (host->split_link.split_link_enabled)
|
||||
h_active *= host->split_link.num_sublinks;
|
||||
else
|
||||
h_active *= display->ctrl_count;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
struct dsi_display_mode *m = &display->modes[i];
|
||||
@ -6574,7 +6699,8 @@ int dsi_display_prepare(struct dsi_display *display)
|
||||
if (display->is_cont_splash_enabled &&
|
||||
display->config.panel_mode == DSI_OP_VIDEO_MODE) {
|
||||
pr_err("DMS not supported on first frame\n");
|
||||
return -EINVAL;
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* update dsi ctrl for new mode */
|
||||
@ -6771,8 +6897,7 @@ static int dsi_display_qsync(struct dsi_display *display, bool enable)
|
||||
|
||||
mutex_lock(&display->display_lock);
|
||||
|
||||
for (i = 0; i < display->ctrl_count; i++) {
|
||||
|
||||
display_for_each_ctrl(i, display) {
|
||||
if (enable) {
|
||||
/* send the commands to enable qsync */
|
||||
rc = dsi_panel_send_qsync_on_dcs(display->panel, i);
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <linux/slab.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/pwm.h>
|
||||
#include <video/mipi_display.h>
|
||||
|
||||
#include "dsi_panel.h"
|
||||
@ -587,17 +588,16 @@ error:
|
||||
static int dsi_panel_wled_register(struct dsi_panel *panel,
|
||||
struct dsi_backlight_config *bl)
|
||||
{
|
||||
int rc = 0;
|
||||
struct backlight_device *bd;
|
||||
|
||||
bd = backlight_device_get_by_type(BACKLIGHT_RAW);
|
||||
if (!bd) {
|
||||
pr_err("[%s] fail raw backlight register\n", panel->name);
|
||||
rc = -EINVAL;
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
bl->raw_bd = bd;
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dsi_panel_update_backlight(struct dsi_panel *panel,
|
||||
@ -620,6 +620,57 @@ static int dsi_panel_update_backlight(struct dsi_panel *panel,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int dsi_panel_update_pwm_backlight(struct dsi_panel *panel,
|
||||
u32 bl_lvl)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 duty = 0;
|
||||
u32 period_ns = 0;
|
||||
struct dsi_backlight_config *bl;
|
||||
|
||||
if (!panel) {
|
||||
pr_err("Invalid Params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
bl = &panel->bl_config;
|
||||
if (!bl->pwm_bl) {
|
||||
pr_err("pwm device not found\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
period_ns = bl->pwm_period_usecs * NSEC_PER_USEC;
|
||||
duty = bl_lvl * period_ns;
|
||||
duty /= bl->bl_max_level;
|
||||
|
||||
rc = pwm_config(bl->pwm_bl, duty, period_ns);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to change pwm config, rc=\n", panel->name,
|
||||
rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bl_lvl == 0 && bl->pwm_enabled) {
|
||||
pwm_disable(bl->pwm_bl);
|
||||
bl->pwm_enabled = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bl->pwm_enabled) {
|
||||
rc = pwm_enable(bl->pwm_bl);
|
||||
if (rc) {
|
||||
pr_err("[%s] failed to enable pwm, rc=\n", panel->name,
|
||||
rc);
|
||||
goto error;
|
||||
}
|
||||
|
||||
bl->pwm_enabled = true;
|
||||
}
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -638,6 +689,9 @@ int dsi_panel_set_backlight(struct dsi_panel *panel, u32 bl_lvl)
|
||||
break;
|
||||
case DSI_BACKLIGHT_EXTERNAL:
|
||||
break;
|
||||
case DSI_BACKLIGHT_PWM:
|
||||
rc = dsi_panel_update_pwm_backlight(panel, bl_lvl);
|
||||
break;
|
||||
default:
|
||||
pr_err("Backlight type(%d) not supported\n", bl->type);
|
||||
rc = -ENOTSUPP;
|
||||
@ -662,6 +716,7 @@ static u32 dsi_panel_get_brightness(struct dsi_backlight_config *bl)
|
||||
break;
|
||||
case DSI_BACKLIGHT_DCS:
|
||||
case DSI_BACKLIGHT_EXTERNAL:
|
||||
case DSI_BACKLIGHT_PWM:
|
||||
default:
|
||||
/*
|
||||
* Ideally, we should read the backlight level from the
|
||||
@ -681,6 +736,22 @@ void dsi_panel_bl_handoff(struct dsi_panel *panel)
|
||||
bl->bl_level = dsi_panel_get_brightness(bl);
|
||||
}
|
||||
|
||||
static int dsi_panel_pwm_register(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dsi_backlight_config *bl = &panel->bl_config;
|
||||
|
||||
bl->pwm_bl = devm_of_pwm_get(panel->parent, panel->panel_of_node, NULL);
|
||||
if (IS_ERR_OR_NULL(bl->pwm_bl)) {
|
||||
rc = PTR_ERR(bl->pwm_bl);
|
||||
pr_err("[%s] failed to request pwm, rc=%d\n", panel->name,
|
||||
rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dsi_panel_bl_register(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -697,6 +768,9 @@ static int dsi_panel_bl_register(struct dsi_panel *panel)
|
||||
break;
|
||||
case DSI_BACKLIGHT_EXTERNAL:
|
||||
break;
|
||||
case DSI_BACKLIGHT_PWM:
|
||||
rc = dsi_panel_pwm_register(panel);
|
||||
break;
|
||||
default:
|
||||
pr_err("Backlight type(%d) not supported\n", bl->type);
|
||||
rc = -ENOTSUPP;
|
||||
@ -707,6 +781,13 @@ error:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dsi_panel_pwm_unregister(struct dsi_panel *panel)
|
||||
{
|
||||
struct dsi_backlight_config *bl = &panel->bl_config;
|
||||
|
||||
devm_pwm_put(panel->parent, bl->pwm_bl);
|
||||
}
|
||||
|
||||
static int dsi_panel_bl_unregister(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -722,6 +803,9 @@ static int dsi_panel_bl_unregister(struct dsi_panel *panel)
|
||||
break;
|
||||
case DSI_BACKLIGHT_EXTERNAL:
|
||||
break;
|
||||
case DSI_BACKLIGHT_PWM:
|
||||
dsi_panel_pwm_unregister(panel);
|
||||
break;
|
||||
default:
|
||||
pr_err("Backlight type(%d) not supported\n", bl->type);
|
||||
rc = -ENOTSUPP;
|
||||
@ -1085,6 +1169,44 @@ static int dsi_panel_parse_misc_host_config(struct dsi_host_common_cfg *host,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dsi_panel_parse_split_link_config(struct dsi_host_common_cfg *host,
|
||||
struct dsi_parser_utils *utils,
|
||||
const char *name)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 val = 0;
|
||||
bool supported = false;
|
||||
struct dsi_split_link_config *split_link = &host->split_link;
|
||||
|
||||
supported = utils->read_bool(utils->data, "qcom,split-link-enabled");
|
||||
|
||||
if (!supported) {
|
||||
pr_debug("[%s] Split link is not supported\n", name);
|
||||
split_link->split_link_enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
rc = utils->read_u32(utils->data, "qcom,sublinks-count", &val);
|
||||
if (rc || val < 1) {
|
||||
pr_debug("[%s] Using default sublinks count\n", name);
|
||||
split_link->num_sublinks = 2;
|
||||
} else {
|
||||
split_link->num_sublinks = val;
|
||||
}
|
||||
|
||||
rc = utils->read_u32(utils->data, "qcom,lanes-per-sublink", &val);
|
||||
if (rc || val < 1) {
|
||||
pr_debug("[%s] Using default lanes per sublink\n", name);
|
||||
split_link->lanes_per_sublink = 2;
|
||||
} else {
|
||||
split_link->lanes_per_sublink = val;
|
||||
}
|
||||
|
||||
pr_debug("[%s] Split link is supported %d-%d\n", name,
|
||||
split_link->num_sublinks, split_link->lanes_per_sublink);
|
||||
split_link->split_link_enabled = true;
|
||||
}
|
||||
|
||||
static int dsi_panel_parse_host_config(struct dsi_panel *panel)
|
||||
{
|
||||
int rc = 0;
|
||||
@ -1130,6 +1252,9 @@ static int dsi_panel_parse_host_config(struct dsi_panel *panel)
|
||||
goto error;
|
||||
}
|
||||
|
||||
dsi_panel_parse_split_link_config(&panel->host_config, utils,
|
||||
panel->name);
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
@ -2021,34 +2146,14 @@ static int dsi_panel_parse_bl_pwm_config(struct dsi_panel *panel)
|
||||
struct dsi_backlight_config *config = &panel->bl_config;
|
||||
struct dsi_parser_utils *utils = &panel->utils;
|
||||
|
||||
rc = utils->read_u32(utils->data, "qcom,dsi-bl-pmic-bank-select",
|
||||
rc = utils->read_u32(utils->data, "qcom,bl-pmic-pwm-period-usecs",
|
||||
&val);
|
||||
if (rc) {
|
||||
pr_err("bl-pmic-bank-select is not defined, rc=%d\n", rc);
|
||||
goto error;
|
||||
}
|
||||
config->pwm_pmic_bank = val;
|
||||
|
||||
rc = utils->read_u32(utils->data, "qcom,dsi-bl-pmic-pwm-frequency",
|
||||
&val);
|
||||
if (rc) {
|
||||
pr_err("bl-pmic-bank-select is not defined, rc=%d\n", rc);
|
||||
pr_err("bl-pmic-pwm-period-usecs is not defined, rc=%d\n", rc);
|
||||
goto error;
|
||||
}
|
||||
config->pwm_period_usecs = val;
|
||||
|
||||
config->pwm_pmi_control = utils->read_bool(utils->data,
|
||||
"qcom,mdss-dsi-bl-pwm-pmi");
|
||||
|
||||
config->pwm_gpio = utils->get_named_gpio(utils->data,
|
||||
"qcom,mdss-dsi-pwm-gpio",
|
||||
0);
|
||||
if (!gpio_is_valid(config->pwm_gpio)) {
|
||||
pr_err("pwm gpio is invalid\n");
|
||||
rc = -EINVAL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
return rc;
|
||||
}
|
||||
@ -2139,9 +2244,17 @@ static int dsi_panel_parse_bl_config(struct dsi_panel *panel)
|
||||
"qcom,platform-bklight-en-gpio",
|
||||
0);
|
||||
if (!gpio_is_valid(panel->bl_config.en_gpio)) {
|
||||
pr_debug("[%s] failed get bklt gpio, rc=%d\n", panel->name, rc);
|
||||
rc = 0;
|
||||
goto error;
|
||||
if (panel->bl_config.en_gpio == -EPROBE_DEFER) {
|
||||
pr_debug("[%s] failed to get bklt gpio, rc=%d\n",
|
||||
panel->name, rc);
|
||||
rc = -EPROBE_DEFER;
|
||||
goto error;
|
||||
} else {
|
||||
pr_debug("[%s] failed to get bklt gpio, rc=%d\n",
|
||||
panel->name, rc);
|
||||
rc = 0;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
@ -2341,12 +2454,16 @@ int dsi_dsc_populate_static_param(struct msm_display_dsc_info *dsc)
|
||||
|
||||
|
||||
static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode,
|
||||
struct dsi_parser_utils *utils)
|
||||
struct dsi_parser_utils *utils)
|
||||
{
|
||||
const char *data;
|
||||
u32 len, i;
|
||||
int rc = 0;
|
||||
struct dsi_display_mode_priv_info *priv_info;
|
||||
struct dsi_mode_info *timing = NULL;
|
||||
|
||||
if (!mode || !mode->priv_info)
|
||||
return -EINVAL;
|
||||
|
||||
priv_info = mode->priv_info;
|
||||
|
||||
@ -2366,9 +2483,11 @@ static int dsi_panel_parse_phy_timing(struct dsi_display_mode *mode,
|
||||
priv_info->phy_timing_len = len;
|
||||
}
|
||||
|
||||
mode->pixel_clk_khz = (DSI_H_TOTAL_DSC(&mode->timing) *
|
||||
DSI_V_TOTAL(&mode->timing) *
|
||||
mode->timing.refresh_rate) / 1000;
|
||||
timing = &mode->timing;
|
||||
|
||||
mode->pixel_clk_khz = (DSI_H_TOTAL(&mode->timing) *
|
||||
DSI_V_TOTAL(&mode->timing) *
|
||||
mode->timing.refresh_rate) / 1000;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -3111,9 +3230,11 @@ struct dsi_panel *dsi_panel_get(struct device *parent,
|
||||
pr_err("failed to parse power config, rc=%d\n", rc);
|
||||
|
||||
rc = dsi_panel_parse_bl_config(panel);
|
||||
if (rc)
|
||||
if (rc) {
|
||||
pr_err("failed to parse backlight config, rc=%d\n", rc);
|
||||
|
||||
if (rc == -EPROBE_DEFER)
|
||||
goto error;
|
||||
}
|
||||
|
||||
rc = dsi_panel_parse_misc_features(panel);
|
||||
if (rc)
|
||||
@ -3637,10 +3758,14 @@ int dsi_panel_set_lp1(struct dsi_panel *panel)
|
||||
}
|
||||
|
||||
mutex_lock(&panel->panel_lock);
|
||||
if (!panel->panel_initialized)
|
||||
goto exit;
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP1);
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_LP1 cmd, rc=%d\n",
|
||||
panel->name, rc);
|
||||
exit:
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
@ -3655,10 +3780,14 @@ int dsi_panel_set_lp2(struct dsi_panel *panel)
|
||||
}
|
||||
|
||||
mutex_lock(&panel->panel_lock);
|
||||
if (!panel->panel_initialized)
|
||||
goto exit;
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_LP2);
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_LP2 cmd, rc=%d\n",
|
||||
panel->name, rc);
|
||||
exit:
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
@ -3673,10 +3802,14 @@ int dsi_panel_set_nolp(struct dsi_panel *panel)
|
||||
}
|
||||
|
||||
mutex_lock(&panel->panel_lock);
|
||||
if (!panel->panel_initialized)
|
||||
goto exit;
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_NOLP);
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_NOLP cmd, rc=%d\n",
|
||||
panel->name, rc);
|
||||
exit:
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
@ -3868,6 +4001,7 @@ int dsi_panel_send_roi_dcs(struct dsi_panel *panel, int ctrl_idx,
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
|
||||
dsi_panel_destroy_cmd_packets(set);
|
||||
dsi_panel_dealloc_cmd_packets(set);
|
||||
|
||||
return rc;
|
||||
}
|
||||
@ -4004,11 +4138,11 @@ int dsi_panel_enable(struct dsi_panel *panel)
|
||||
mutex_lock(&panel->panel_lock);
|
||||
|
||||
rc = dsi_panel_tx_cmd_set(panel, DSI_CMD_SET_ON);
|
||||
if (rc) {
|
||||
if (rc)
|
||||
pr_err("[%s] failed to send DSI_CMD_SET_ON cmds, rc=%d\n",
|
||||
panel->name, rc);
|
||||
}
|
||||
panel->panel_initialized = true;
|
||||
else
|
||||
panel->panel_initialized = true;
|
||||
mutex_unlock(&panel->panel_lock);
|
||||
return rc;
|
||||
}
|
||||
|
@ -102,10 +102,9 @@ struct dsi_backlight_config {
|
||||
|
||||
int en_gpio;
|
||||
/* PWM params */
|
||||
bool pwm_pmi_control;
|
||||
u32 pwm_pmic_bank;
|
||||
struct pwm_device *pwm_bl;
|
||||
bool pwm_enabled;
|
||||
u32 pwm_period_usecs;
|
||||
int pwm_gpio;
|
||||
|
||||
/* WLED params */
|
||||
struct led_trigger *wled;
|
||||
|
@ -1139,7 +1139,6 @@ int dsi_phy_conv_logical_to_phy_lane(
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* dsi_phy_config_dynamic_refresh() - Configure dynamic refresh registers
|
||||
* @phy: DSI PHY handle
|
||||
@ -1239,6 +1238,27 @@ void dsi_phy_dynamic_refresh_clear(struct msm_dsi_phy *phy)
|
||||
mutex_unlock(&phy->phy_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* dsi_phy_set_continuous_clk() - set/unset force clock lane HS request
|
||||
* @phy: DSI PHY handle
|
||||
* @enable: variable to control continuous clock
|
||||
*/
|
||||
void dsi_phy_set_continuous_clk(struct msm_dsi_phy *phy, bool enable)
|
||||
{
|
||||
if (!phy)
|
||||
return;
|
||||
|
||||
mutex_lock(&phy->phy_lock);
|
||||
|
||||
if (phy->hw.ops.set_continuous_clk)
|
||||
phy->hw.ops.set_continuous_clk(&phy->hw, enable);
|
||||
else
|
||||
pr_warn("set_continuous_clk ops not present\n");
|
||||
|
||||
mutex_unlock(&phy->phy_lock);
|
||||
|
||||
}
|
||||
|
||||
void dsi_phy_drv_register(void)
|
||||
{
|
||||
platform_driver_register(&dsi_phy_platform_driver);
|
||||
|
@ -330,5 +330,13 @@ void dsi_phy_dynamic_refresh_clear(struct msm_dsi_phy *phy);
|
||||
* @size: Number of phy lane settings.
|
||||
*/
|
||||
int dsi_phy_dyn_refresh_cache_phy_timings(struct msm_dsi_phy *phy,
|
||||
u32 *dst, u32 size);
|
||||
|
||||
u32 *dst, u32 size);
|
||||
/**
|
||||
* dsi_phy_set_continuous_clk() - API to set/unset force clock lane HS request.
|
||||
* @phy: DSI PHY Handle.
|
||||
* @enable: variable to control continuous clock.
|
||||
*/
|
||||
void dsi_phy_set_continuous_clk(struct msm_dsi_phy *phy, bool enable);
|
||||
|
||||
#endif /* _DSI_PHY_H_ */
|
||||
|
@ -40,11 +40,13 @@ enum dsi_phy_version {
|
||||
* enum dsi_phy_hw_features - features supported by DSI PHY hardware
|
||||
* @DSI_PHY_DPHY: Supports DPHY
|
||||
* @DSI_PHY_CPHY: Supports CPHY
|
||||
* @DSI_PHY_SPLIT_LINK: Supports Split Link
|
||||
* @DSI_PHY_MAX_FEATURES:
|
||||
*/
|
||||
enum dsi_phy_hw_features {
|
||||
DSI_PHY_DPHY,
|
||||
DSI_PHY_CPHY,
|
||||
DSI_PHY_SPLIT_LINK,
|
||||
DSI_PHY_MAX_FEATURES
|
||||
};
|
||||
|
||||
@ -303,6 +305,13 @@ struct dsi_phy_hw_ops {
|
||||
*/
|
||||
void (*reset_clk_en_sel)(struct dsi_phy_hw *phy);
|
||||
|
||||
/**
|
||||
* set_continuous_clk() - Set continuous clock
|
||||
* @phy: Pointer to DSI PHY hardware object
|
||||
* @enable: Bool to control continuous clock request.
|
||||
*/
|
||||
void (*set_continuous_clk)(struct dsi_phy_hw *phy, bool enable);
|
||||
|
||||
void *timing_ops;
|
||||
struct phy_ulps_config_ops ulps_ops;
|
||||
struct phy_dyn_refresh_ops dyn_refresh_ops;
|
||||
|
@ -34,23 +34,17 @@
|
||||
#define DSIPHY_CMN_REGULATOR_CAL_STATUS1 0x0068
|
||||
#define DSI_MDP_ULPS_CLAMP_ENABLE_OFF 0x0054
|
||||
|
||||
/* n = 0..3 for data lanes and n = 4 for clock lane */
|
||||
#define DSIPHY_DLNX_CFG0(n) (0x100 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_CFG1(n) (0x104 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_CFG2(n) (0x108 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_CFG3(n) (0x10C + ((n) * 0x80))
|
||||
/* n = 0..3 for data lanes and n = 4 for clock lane
|
||||
* t for count per lane
|
||||
*/
|
||||
#define DSIPHY_DLNX_CFG(n, t) \
|
||||
(0x100 + ((t) * 0x04) + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL(n, t) \
|
||||
(0x118 + ((t) * 0x04) + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_STRENGTH_CTRL(n, t) \
|
||||
(0x138 + ((t) * 0x04) + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TEST_DATAPATH(n) (0x110 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TEST_STR(n) (0x114 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_4(n) (0x118 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_5(n) (0x11C + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_6(n) (0x120 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_7(n) (0x124 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_8(n) (0x128 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_9(n) (0x12C + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_10(n) (0x130 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_TIMING_CTRL_11(n) (0x134 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_STRENGTH_CTRL_0(n) (0x138 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_STRENGTH_CTRL_1(n) (0x13C + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_BIST_POLY(n) (0x140 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_BIST_SEED0(n) (0x144 + ((n) * 0x80))
|
||||
#define DSIPHY_DLNX_BIST_SEED1(n) (0x148 + ((n) * 0x80))
|
||||
@ -80,10 +74,15 @@ void dsi_phy_hw_v2_0_regulator_enable(struct dsi_phy_hw *phy,
|
||||
struct dsi_phy_per_lane_cfgs *reg_cfg)
|
||||
{
|
||||
int i;
|
||||
bool is_split_link = test_bit(DSI_PHY_SPLIT_LINK, phy->feature_map);
|
||||
|
||||
for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(i), reg_cfg->lane[i][0]);
|
||||
|
||||
if (is_split_link)
|
||||
DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(DSI_LOGICAL_CLOCK_LANE+1),
|
||||
reg_cfg->lane[DSI_LOGICAL_CLOCK_LANE][0]);
|
||||
|
||||
/* make sure all values are written to hardware */
|
||||
wmb();
|
||||
|
||||
@ -108,35 +107,55 @@ void dsi_phy_hw_v2_0_regulator_disable(struct dsi_phy_hw *phy)
|
||||
void dsi_phy_hw_v2_0_enable(struct dsi_phy_hw *phy,
|
||||
struct dsi_phy_cfg *cfg)
|
||||
{
|
||||
int i;
|
||||
int i, j;
|
||||
struct dsi_phy_per_lane_cfgs *lanecfg = &cfg->lanecfg;
|
||||
struct dsi_phy_per_lane_cfgs *timing = &cfg->timing;
|
||||
struct dsi_phy_per_lane_cfgs *strength = &cfg->strength;
|
||||
u32 data;
|
||||
bool is_split_link = test_bit(DSI_PHY_SPLIT_LINK, phy->feature_map);
|
||||
|
||||
DSI_W32(phy, DSIPHY_CMN_LDO_CNTRL, 0x1C);
|
||||
|
||||
DSI_W32(phy, DSIPHY_CMN_GLBL_TEST_CTRL, 0x1);
|
||||
for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
|
||||
|
||||
DSI_W32(phy, DSIPHY_DLNX_CFG0(i), cfg->lanecfg.lane[i][0]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_CFG1(i), cfg->lanecfg.lane[i][1]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_CFG2(i), cfg->lanecfg.lane[i][2]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_CFG3(i), cfg->lanecfg.lane[i][3]);
|
||||
for (j = 0; j < lanecfg->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_CFG(i, j),
|
||||
lanecfg->lane[i][j]);
|
||||
|
||||
DSI_W32(phy, DSIPHY_DLNX_TEST_STR(i), 0x88);
|
||||
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_4(i), timing->lane[i][0]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_5(i), timing->lane[i][1]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_6(i), timing->lane[i][2]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_7(i), timing->lane[i][3]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_8(i), timing->lane[i][4]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_9(i), timing->lane[i][5]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_10(i), timing->lane[i][6]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL_11(i), timing->lane[i][7]);
|
||||
for (j = 0; j < timing->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL(i, j),
|
||||
timing->lane[i][j]);
|
||||
|
||||
for (j = 0; j < strength->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL(i, j),
|
||||
strength->lane[i][j]);
|
||||
}
|
||||
|
||||
if (is_split_link) {
|
||||
i = DSI_LOGICAL_CLOCK_LANE;
|
||||
|
||||
for (j = 0; j < lanecfg->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_CFG(i+1, j),
|
||||
lanecfg->lane[i][j]);
|
||||
|
||||
DSI_W32(phy, DSIPHY_DLNX_TEST_STR(i+1), 0x0);
|
||||
DSI_W32(phy, DSIPHY_DLNX_TEST_DATAPATH(i+1), 0x88);
|
||||
|
||||
for (j = 0; j < timing->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_TIMING_CTRL(i+1, j),
|
||||
timing->lane[i][j]);
|
||||
|
||||
for (j = 0; j < strength->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL(i+1, j),
|
||||
strength->lane[i][j]);
|
||||
|
||||
/* enable split link for cmn clk cfg1 */
|
||||
data = DSI_R32(phy, DSIPHY_CMN_CLK_CFG1);
|
||||
data |= BIT(1);
|
||||
DSI_W32(phy, DSIPHY_CMN_CLK_CFG1, data);
|
||||
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_0(i),
|
||||
cfg->strength.lane[i][0]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i),
|
||||
cfg->strength.lane[i][1]);
|
||||
}
|
||||
|
||||
/* make sure all values are written to hardware before enabling phy */
|
||||
@ -193,13 +212,20 @@ void dsi_phy_hw_v2_0_disable(struct dsi_phy_hw *phy,
|
||||
*/
|
||||
void dsi_phy_hw_v2_0_idle_on(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg)
|
||||
{
|
||||
int i = 0;
|
||||
int i = 0, j;
|
||||
struct dsi_phy_per_lane_cfgs *strength = &cfg->strength;
|
||||
bool is_split_link = test_bit(DSI_PHY_SPLIT_LINK, phy->feature_map);
|
||||
|
||||
for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_0(i),
|
||||
cfg->strength.lane[i][0]);
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i),
|
||||
cfg->strength.lane[i][1]);
|
||||
for (j = 0; j < strength->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL(i, j),
|
||||
strength->lane[i][j]);
|
||||
}
|
||||
if (is_split_link) {
|
||||
i = DSI_LOGICAL_CLOCK_LANE;
|
||||
for (j = 0; j < strength->count_per_lane; j++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL(i+1, j),
|
||||
strength->lane[i][j]);
|
||||
}
|
||||
wmb(); /* make sure write happens */
|
||||
pr_debug("[DSI_%d]Phy enabled out of idle screen\n", phy->index);
|
||||
@ -213,14 +239,23 @@ void dsi_phy_hw_v2_0_idle_on(struct dsi_phy_hw *phy, struct dsi_phy_cfg *cfg)
|
||||
void dsi_phy_hw_v2_0_idle_off(struct dsi_phy_hw *phy)
|
||||
{
|
||||
int i = 0;
|
||||
bool is_split_link = test_bit(DSI_PHY_SPLIT_LINK, phy->feature_map);
|
||||
|
||||
DSI_W32(phy, DSIPHY_CMN_CTRL_0, 0x7f);
|
||||
for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(i), 0x1c);
|
||||
if (is_split_link)
|
||||
DSI_W32(phy, DSIPHY_DLNX_VREG_CNTRL(DSI_LOGICAL_CLOCK_LANE+1),
|
||||
0x1c);
|
||||
|
||||
DSI_W32(phy, DSIPHY_CMN_LDO_CNTRL, 0x1C);
|
||||
|
||||
for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++)
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL_1(i), 0x0);
|
||||
DSI_W32(phy, DSIPHY_DLNX_STRENGTH_CTRL(i, 1), 0x0);
|
||||
if (is_split_link)
|
||||
DSI_W32(phy,
|
||||
DSIPHY_DLNX_STRENGTH_CTRL(DSI_LOGICAL_CLOCK_LANE+1, 1), 0x0);
|
||||
|
||||
wmb(); /* make sure write happens */
|
||||
pr_debug("[DSI_%d]Phy disabled during idle screen\n", phy->index);
|
||||
}
|
||||
|
@ -182,12 +182,6 @@ static void dsi_phy_hw_v4_0_lane_settings(struct dsi_phy_hw *phy,
|
||||
DSI_W32(phy, DSIPHY_LNX_TX_DCTRL(i), tx_dctrl[i]);
|
||||
}
|
||||
|
||||
if (cfg->force_clk_lane_hs) {
|
||||
u32 reg = DSI_R32(phy, DSIPHY_CMN_LANE_CTRL1);
|
||||
|
||||
reg |= BIT(5) | BIT(6);
|
||||
DSI_W32(phy, DSIPHY_CMN_LANE_CTRL1, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -692,3 +686,18 @@ int dsi_phy_hw_v4_0_cache_phy_timings(struct dsi_phy_per_lane_cfgs *timings,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dsi_phy_hw_v4_0_set_continuous_clk(struct dsi_phy_hw *phy, bool enable)
|
||||
{
|
||||
u32 reg = 0;
|
||||
|
||||
reg = DSI_R32(phy, DSIPHY_CMN_LANE_CTRL1);
|
||||
|
||||
if (enable)
|
||||
reg |= BIT(5) | BIT(6);
|
||||
else
|
||||
reg &= ~(BIT(5) | BIT(6));
|
||||
|
||||
DSI_W32(phy, DSIPHY_CMN_LANE_CTRL1, reg);
|
||||
wmb(); /* make sure request is set */
|
||||
}
|
||||
|
@ -64,6 +64,14 @@ static int dsi_pwr_parse_supply_node(struct dsi_parser_utils *utils,
|
||||
regs->vregs[i].disable_load = tmp;
|
||||
|
||||
/* Optional values */
|
||||
rc = utils->read_u32(node, "qcom,supply-off-min-voltage", &tmp);
|
||||
if (rc) {
|
||||
pr_debug("off-min-voltage not specified\n");
|
||||
rc = 0;
|
||||
} else {
|
||||
regs->vregs[i].off_min_voltage = tmp;
|
||||
}
|
||||
|
||||
rc = utils->read_u32(node, "qcom,supply-pre-on-sleep", &tmp);
|
||||
if (rc) {
|
||||
pr_debug("pre-on-sleep not specified\n");
|
||||
@ -158,6 +166,11 @@ static int dsi_pwr_enable_vregs(struct dsi_regulator_info *regs, bool enable)
|
||||
if (regs->vregs[i].pre_off_sleep)
|
||||
msleep(regs->vregs[i].pre_off_sleep);
|
||||
|
||||
if (regs->vregs[i].off_min_voltage)
|
||||
(void)regulator_set_voltage(regs->vregs[i].vreg,
|
||||
regs->vregs[i].off_min_voltage,
|
||||
regs->vregs[i].max_voltage);
|
||||
|
||||
(void)regulator_set_load(regs->vregs[i].vreg,
|
||||
regs->vregs[i].disable_load);
|
||||
(void)regulator_disable(regs->vregs[i].vreg);
|
||||
|
@ -21,6 +21,7 @@ struct dsi_parser_utils;
|
||||
* @max_voltage: Maximum voltage in uV.
|
||||
* @enable_load: Load, in uA, when enabled.
|
||||
* @disable_load: Load, in uA, when disabled.
|
||||
* @off_min_voltage: Minimum voltage in uV when regulator is disabled.
|
||||
* @pre_on_sleep: Sleep, in ms, before enabling the regulator.
|
||||
* @post_on_sleep: Sleep, in ms, after enabling the regulator.
|
||||
* @pre_off_sleep: Sleep, in ms, before disabling the regulator.
|
||||
@ -33,6 +34,7 @@ struct dsi_vreg {
|
||||
u32 max_voltage;
|
||||
u32 enable_load;
|
||||
u32 disable_load;
|
||||
u32 off_min_voltage;
|
||||
u32 pre_on_sleep;
|
||||
u32 post_on_sleep;
|
||||
u32 pre_off_sleep;
|
||||
|
@ -506,7 +506,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
||||
sde_connector_event_notify(conn, DRM_EVENT_SDE_HW_RECOVERY,
|
||||
sizeof(uint8_t), event);
|
||||
} else if (cmd_enc->pp_timeout_report_cnt) {
|
||||
SDE_DBG_DUMP("panic");
|
||||
SDE_DBG_DUMP("dsi_dbg_bus", "panic");
|
||||
}
|
||||
|
||||
/* request a ctl reset before the next kickoff */
|
||||
|
@ -1292,9 +1292,19 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
|
||||
SDE_ERROR("dsi %d connector init failed\n", i);
|
||||
dsi_display_drm_bridge_deinit(display);
|
||||
sde_encoder_destroy(encoder);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
rc = dsi_display_drm_ext_bridge_init(display,
|
||||
encoder, connector);
|
||||
if (rc) {
|
||||
SDE_ERROR("dsi %d ext bridge init failed\n", rc);
|
||||
dsi_display_drm_bridge_deinit(display);
|
||||
sde_encoder_destroy(encoder);
|
||||
sde_connector_destroy(connector);
|
||||
}
|
||||
|
||||
/* wb */
|
||||
for (i = 0; i < sde_kms->wb_display_count &&
|
||||
priv->num_encoders < max_encoders; ++i) {
|
||||
@ -2193,7 +2203,6 @@ static void _sde_kms_post_open(struct msm_kms *kms, struct drm_file *file)
|
||||
struct drm_connector *connector = NULL;
|
||||
struct drm_connector_list_iter conn_iter;
|
||||
struct sde_connector *sde_conn = NULL;
|
||||
int i;
|
||||
|
||||
if (!kms) {
|
||||
SDE_ERROR("invalid kms\n");
|
||||
@ -2211,18 +2220,6 @@ static void _sde_kms_post_open(struct msm_kms *kms, struct drm_file *file)
|
||||
if (!dev->mode_config.poll_enabled)
|
||||
return;
|
||||
|
||||
/* init external dsi bridge here to make sure ext bridge is probed*/
|
||||
for (i = 0; i < sde_kms->dsi_display_count; ++i) {
|
||||
struct dsi_display *dsi_display;
|
||||
|
||||
dsi_display = sde_kms->dsi_displays[i];
|
||||
if (dsi_display->bridge) {
|
||||
dsi_display_drm_ext_bridge_init(dsi_display,
|
||||
dsi_display->bridge->base.encoder,
|
||||
dsi_display->drm_conn);
|
||||
}
|
||||
}
|
||||
|
||||
mutex_lock(&dev->mode_config.mutex);
|
||||
drm_connector_list_iter_begin(dev, &conn_iter);
|
||||
drm_for_each_connector_iter(connector, &conn_iter) {
|
||||
|
@ -4517,7 +4517,8 @@ void sde_dbg_init_dbg_buses(u32 hwversion)
|
||||
memset(&dbg->dbgbus_vbif_rt, 0, sizeof(dbg->dbgbus_vbif_rt));
|
||||
|
||||
if (IS_SM8150_TARGET(hwversion) || IS_SM6150_TARGET(hwversion) ||
|
||||
IS_SDMMAGPIE_TARGET(hwversion)) {
|
||||
IS_SDMMAGPIE_TARGET(hwversion) ||
|
||||
IS_SDMTRINKET_TARGET(hwversion)) {
|
||||
dbg->dbgbus_sde.entries = dbg_bus_sde_sm8150;
|
||||
dbg->dbgbus_sde.cmn.entries_size =
|
||||
ARRAY_SIZE(dbg_bus_sde_sm8150);
|
||||
|
Loading…
Reference in New Issue
Block a user