Merge "disp: msm: dsi: disallow backlight update during panel mode switch"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
34b32d77f8
@@ -192,6 +192,14 @@ static void dsi_catalog_phy_2_0_init(struct dsi_phy_hw *phy)
|
||||
dsi_phy_hw_calculate_timing_params;
|
||||
phy->ops.phy_timing_val = dsi_phy_hw_timing_val_v2_0;
|
||||
phy->ops.clamp_ctrl = dsi_phy_hw_v2_0_clamp_ctrl;
|
||||
phy->ops.dyn_refresh_ops.dyn_refresh_config =
|
||||
dsi_phy_hw_v2_0_dyn_refresh_config;
|
||||
phy->ops.dyn_refresh_ops.dyn_refresh_pipe_delay =
|
||||
dsi_phy_hw_v2_0_dyn_refresh_pipe_delay;
|
||||
phy->ops.dyn_refresh_ops.dyn_refresh_helper =
|
||||
dsi_phy_hw_v2_0_dyn_refresh_helper;
|
||||
phy->ops.dyn_refresh_ops.cache_phy_timings =
|
||||
dsi_phy_hw_v2_0_cache_phy_timings;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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_CATALOG_H_
|
||||
@@ -80,6 +80,13 @@ void dsi_phy_hw_v2_0_idle_off(struct dsi_phy_hw *phy);
|
||||
int dsi_phy_hw_timing_val_v2_0(struct dsi_phy_per_lane_cfgs *timing_cfg,
|
||||
u32 *timing_val, u32 size);
|
||||
void dsi_phy_hw_v2_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable);
|
||||
void dsi_phy_hw_v2_0_dyn_refresh_helper(struct dsi_phy_hw *phy, u32 offset);
|
||||
void dsi_phy_hw_v2_0_dyn_refresh_config(struct dsi_phy_hw *phy,
|
||||
struct dsi_phy_cfg *cfg, bool is_master);
|
||||
void dsi_phy_hw_v2_0_dyn_refresh_pipe_delay(struct dsi_phy_hw *phy,
|
||||
struct dsi_dyn_clk_delay *delay);
|
||||
int dsi_phy_hw_v2_0_cache_phy_timings(struct dsi_phy_per_lane_cfgs *timings,
|
||||
u32 *dst, u32 size);
|
||||
|
||||
/* Definitions for 10nm PHY hardware driver */
|
||||
void dsi_phy_hw_v3_0_regulator_enable(struct dsi_phy_hw *phy,
|
||||
|
@@ -106,11 +106,13 @@ struct dsi_link_lp_clk_info {
|
||||
/**
|
||||
* struct link_clk_freq - Clock frequency information for Link clocks
|
||||
* @byte_clk_rate: Frequency of DSI byte_clk in KHz.
|
||||
* @byte_intf_clk_rate: Frequency of DSI byte_intf_clk in KHz.
|
||||
* @pixel_clk_rate: Frequency of DSI pixel_clk in KHz.
|
||||
* @esc_clk_rate: Frequency of DSI escape clock in KHz.
|
||||
*/
|
||||
struct link_clk_freq {
|
||||
u32 byte_clk_rate;
|
||||
u32 byte_intf_clk_rate;
|
||||
u32 pix_clk_rate;
|
||||
u32 esc_clk_rate;
|
||||
};
|
||||
@@ -292,10 +294,12 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index);
|
||||
* dsi_clk_set_byte_clk_rate() - set frequency for byte clock
|
||||
* @client: DSI clock client pointer.
|
||||
* @byte_clk: Pixel clock rate in Hz.
|
||||
* @byte_intf_clk: Byte interface clock rate in Hz.
|
||||
* @index: Index of the DSI controller.
|
||||
* return: error code in case of failure or 0 for success.
|
||||
*/
|
||||
int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index);
|
||||
int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk,
|
||||
u64 byte_intf_clk, u32 index);
|
||||
|
||||
/**
|
||||
* dsi_clk_update_parent() - update parent clocks for specified clock
|
||||
|
@@ -130,15 +130,16 @@ int dsi_clk_set_pixel_clk_rate(void *client, u64 pixel_clk, u32 index)
|
||||
* dsi_clk_set_byte_clk_rate() - set frequency for byte clock
|
||||
* @client: DSI clock client pointer.
|
||||
* @byte_clk: Byte clock rate in Hz.
|
||||
* @byte_intf_clk: Byte interface clock rate in Hz.
|
||||
* @index: Index of the DSI controller.
|
||||
* return: error code in case of failure or 0 for success.
|
||||
*/
|
||||
int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index)
|
||||
int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk,
|
||||
u64 byte_intf_clk, u32 index)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dsi_clk_client_info *c = client;
|
||||
struct dsi_clk_mngr *mngr;
|
||||
u64 byte_intf_rate;
|
||||
|
||||
mngr = c->mngr;
|
||||
rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_clk, byte_clk);
|
||||
@@ -148,12 +149,14 @@ int dsi_clk_set_byte_clk_rate(void *client, u64 byte_clk, u32 index)
|
||||
mngr->link_clks[index].freq.byte_clk_rate = byte_clk;
|
||||
|
||||
if (mngr->link_clks[index].hs_clks.byte_intf_clk) {
|
||||
byte_intf_rate = mngr->link_clks[index].freq.byte_clk_rate / 2;
|
||||
rc = clk_set_rate(mngr->link_clks[index].hs_clks.byte_intf_clk,
|
||||
byte_intf_rate);
|
||||
byte_intf_clk);
|
||||
if (rc)
|
||||
DSI_ERR("failed to set clk rate for byte intf clk=%d\n",
|
||||
rc);
|
||||
else
|
||||
mngr->link_clks[index].freq.byte_intf_clk_rate =
|
||||
byte_intf_clk;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -344,12 +347,10 @@ static int dsi_link_hs_clk_set_rate(struct dsi_link_hs_clk_info *link_hs_clks,
|
||||
|
||||
/*
|
||||
* If byte_intf_clk is present, set rate for that too.
|
||||
* For DPHY: byte_intf_clk_rate = byte_clk_rate / 2
|
||||
* todo: this needs to be revisited when support for CPHY is added
|
||||
*/
|
||||
if (link_hs_clks->byte_intf_clk) {
|
||||
rc = clk_set_rate(link_hs_clks->byte_intf_clk,
|
||||
(l_clks->freq.byte_clk_rate / 2));
|
||||
l_clks->freq.byte_intf_clk_rate);
|
||||
if (rc) {
|
||||
DSI_ERR("set_rate failed for byte_intf_clk rc = %d\n",
|
||||
rc);
|
||||
|
@@ -269,10 +269,6 @@ dsi_ctrl_get_aspace(struct dsi_ctrl *dsi_ctrl,
|
||||
|
||||
static void dsi_ctrl_flush_cmd_dma_queue(struct dsi_ctrl *dsi_ctrl)
|
||||
{
|
||||
u32 status;
|
||||
u32 mask = DSI_CMD_MODE_DMA_DONE;
|
||||
struct dsi_ctrl_hw_ops dsi_hw_ops = dsi_ctrl->hw.ops;
|
||||
|
||||
/*
|
||||
* If a command is triggered right after another command,
|
||||
* check if the previous command transfer is completed. If
|
||||
@@ -281,21 +277,8 @@ static void dsi_ctrl_flush_cmd_dma_queue(struct dsi_ctrl *dsi_ctrl)
|
||||
* completed before triggering the next command by
|
||||
* flushing the workqueue.
|
||||
*/
|
||||
status = dsi_hw_ops.get_interrupt_status(&dsi_ctrl->hw);
|
||||
if (atomic_read(&dsi_ctrl->dma_irq_trig)) {
|
||||
cancel_work_sync(&dsi_ctrl->dma_cmd_wait);
|
||||
} else if (status & mask) {
|
||||
atomic_set(&dsi_ctrl->dma_irq_trig, 1);
|
||||
status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE);
|
||||
dsi_hw_ops.clear_interrupt_status(
|
||||
&dsi_ctrl->hw,
|
||||
status);
|
||||
dsi_ctrl_disable_status_interrupt(dsi_ctrl,
|
||||
DSI_SINT_CMD_MODE_DMA_DONE);
|
||||
complete_all(&dsi_ctrl->irq_info.cmd_dma_done);
|
||||
cancel_work_sync(&dsi_ctrl->dma_cmd_wait);
|
||||
DSI_CTRL_DEBUG(dsi_ctrl,
|
||||
"dma_tx done but irq not yet triggered\n");
|
||||
} else {
|
||||
flush_workqueue(dsi_ctrl->dma_cmd_workq);
|
||||
}
|
||||
@@ -319,24 +302,11 @@ static void dsi_ctrl_dma_cmd_wait_for_done(struct work_struct *work)
|
||||
*/
|
||||
if (atomic_read(&dsi_ctrl->dma_irq_trig))
|
||||
goto done;
|
||||
/*
|
||||
* If IRQ wasn't triggered check interrupt status register for
|
||||
* transfer done before waiting.
|
||||
*/
|
||||
status = dsi_hw_ops.get_interrupt_status(&dsi_ctrl->hw);
|
||||
if (status & mask) {
|
||||
status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE);
|
||||
dsi_hw_ops.clear_interrupt_status(&dsi_ctrl->hw,
|
||||
status);
|
||||
dsi_ctrl_disable_status_interrupt(dsi_ctrl,
|
||||
DSI_SINT_CMD_MODE_DMA_DONE);
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = wait_for_completion_timeout(
|
||||
&dsi_ctrl->irq_info.cmd_dma_done,
|
||||
msecs_to_jiffies(DSI_CTRL_TX_TO_MS));
|
||||
if (ret == 0) {
|
||||
if (ret == 0 && !atomic_read(&dsi_ctrl->dma_irq_trig)) {
|
||||
status = dsi_hw_ops.get_interrupt_status(&dsi_ctrl->hw);
|
||||
if (status & mask) {
|
||||
status |= (DSI_CMD_MODE_DMA_DONE | DSI_BTA_DONE);
|
||||
@@ -877,9 +847,9 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
|
||||
{
|
||||
int rc = 0;
|
||||
u32 num_of_lanes = 0;
|
||||
u32 bpp, frame_time_us;
|
||||
u32 bpp, frame_time_us, byte_intf_clk_div;
|
||||
u64 h_period, v_period, bit_rate, pclk_rate, bit_rate_per_lane,
|
||||
byte_clk_rate;
|
||||
byte_clk_rate, byte_intf_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;
|
||||
@@ -924,14 +894,20 @@ static int dsi_ctrl_update_link_freqs(struct dsi_ctrl *dsi_ctrl,
|
||||
do_div(pclk_rate, bpp);
|
||||
byte_clk_rate = bit_rate_per_lane;
|
||||
do_div(byte_clk_rate, 8);
|
||||
byte_intf_clk_rate = byte_clk_rate;
|
||||
byte_intf_clk_div = host_cfg->byte_intf_clk_div;
|
||||
do_div(byte_intf_clk_rate, byte_intf_clk_div);
|
||||
|
||||
DSI_CTRL_DEBUG(dsi_ctrl, "bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n",
|
||||
bit_rate, bit_rate_per_lane);
|
||||
DSI_CTRL_DEBUG(dsi_ctrl, "byte_clk_rate = %llu, pclk_rate = %llu\n",
|
||||
byte_clk_rate, pclk_rate);
|
||||
DSI_CTRL_DEBUG(dsi_ctrl, "byte_clk_rate = %llu, byte_intf_clk = %llu\n",
|
||||
byte_clk_rate, byte_intf_clk_rate);
|
||||
DSI_CTRL_DEBUG(dsi_ctrl, "pclk_rate = %llu\n", pclk_rate);
|
||||
|
||||
dsi_ctrl->clk_freq.byte_clk_rate = byte_clk_rate;
|
||||
dsi_ctrl->clk_freq.pix_clk_rate = pclk_rate;
|
||||
dsi_ctrl->clk_freq.esc_clk_rate = config->esc_clk_rate_hz;
|
||||
dsi_ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate;
|
||||
config->bit_clk_rate_hz = dsi_ctrl->clk_freq.byte_clk_rate * 8;
|
||||
|
||||
rc = dsi_clk_set_link_frequencies(clk_handle, dsi_ctrl->clk_freq,
|
||||
@@ -1268,23 +1244,33 @@ static void dsi_kickoff_msg_tx(struct dsi_ctrl *dsi_ctrl,
|
||||
* result in smmu write faults with DSI as client.
|
||||
*/
|
||||
if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
|
||||
if (dsi_ctrl->version < DSI_CTRL_VERSION_2_4)
|
||||
dsi_hw_ops.soft_reset(&dsi_ctrl->hw);
|
||||
dsi_ctrl->cmd_len = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static u32 dsi_ctrl_validate_msg_flags(const struct mipi_dsi_msg *msg,
|
||||
static u32 dsi_ctrl_validate_msg_flags(struct dsi_ctrl *dsi_ctrl,
|
||||
const struct mipi_dsi_msg *msg,
|
||||
u32 flags)
|
||||
{
|
||||
/*
|
||||
* ASYNC command wait mode is not supported for FIFO commands.
|
||||
* Waiting after a command is transferred cannot be guaranteed
|
||||
* if DSI_CTRL_CMD_ASYNC_WAIT flag is set.
|
||||
* ASYNC command wait mode is not supported for
|
||||
* - commands sent using DSI FIFO memory
|
||||
* - DSI read commands
|
||||
* - DCS commands sent in non-embedded mode
|
||||
* - whenever an explicit wait time is specificed for the command
|
||||
* since the wait time cannot be guaranteed in async mode
|
||||
* - video mode panels
|
||||
*/
|
||||
if ((flags & DSI_CTRL_CMD_FIFO_STORE) ||
|
||||
msg->wait_ms)
|
||||
flags & DSI_CTRL_CMD_READ ||
|
||||
flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE ||
|
||||
msg->wait_ms ||
|
||||
(dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE))
|
||||
flags &= ~DSI_CTRL_CMD_ASYNC_WAIT;
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
@@ -1313,7 +1299,7 @@ static int dsi_message_tx(struct dsi_ctrl *dsi_ctrl,
|
||||
goto error;
|
||||
}
|
||||
|
||||
flags = dsi_ctrl_validate_msg_flags(msg, flags);
|
||||
flags = dsi_ctrl_validate_msg_flags(dsi_ctrl, msg, flags);
|
||||
|
||||
if (dsi_ctrl->dma_wait_queued)
|
||||
dsi_ctrl_flush_cmd_dma_queue(dsi_ctrl);
|
||||
@@ -2692,6 +2678,10 @@ void dsi_ctrl_enable_status_interrupt(struct dsi_ctrl *dsi_ctrl,
|
||||
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw,
|
||||
dsi_ctrl->irq_info.irq_stat_mask);
|
||||
}
|
||||
|
||||
if (intr_idx == DSI_SINT_CMD_MODE_DMA_DONE)
|
||||
dsi_ctrl->hw.ops.enable_status_interrupts(&dsi_ctrl->hw,
|
||||
dsi_ctrl->irq_info.irq_stat_mask);
|
||||
++(dsi_ctrl->irq_info.irq_stat_refcount[intr_idx]);
|
||||
|
||||
if (event_info)
|
||||
@@ -3196,6 +3186,7 @@ int dsi_ctrl_cmd_tx_trigger(struct dsi_ctrl *dsi_ctrl, u32 flags)
|
||||
BIT(DSI_FIFO_OVERFLOW), false);
|
||||
|
||||
if (flags & DSI_CTRL_CMD_NON_EMBEDDED_MODE) {
|
||||
if (dsi_ctrl->version < DSI_CTRL_VERSION_2_4)
|
||||
dsi_hw_ops.soft_reset(&dsi_ctrl->hw);
|
||||
dsi_ctrl->cmd_len = 0;
|
||||
}
|
||||
|
@@ -217,6 +217,22 @@ enum dsi_dfps_type {
|
||||
DSI_DFPS_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dsi_dyn_clk_feature_type - Dynamic clock feature support type
|
||||
* @DSI_DYN_CLK_TYPE_LEGACY: Constant FPS is not supported
|
||||
* @DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_HFP: Constant FPS supported with
|
||||
* change in hfp
|
||||
* @DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_VFP: Constant FPS supported with
|
||||
* change in vfp
|
||||
* @DSI_DYN_CLK_TYPE_MAX:
|
||||
*/
|
||||
enum dsi_dyn_clk_feature_type {
|
||||
DSI_DYN_CLK_TYPE_LEGACY = 0,
|
||||
DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_HFP,
|
||||
DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_VFP,
|
||||
DSI_DYN_CLK_TYPE_MAX
|
||||
};
|
||||
|
||||
/**
|
||||
* enum dsi_cmd_set_type - DSI command set type
|
||||
* @DSI_CMD_SET_PRE_ON: Panel pre on
|
||||
@@ -450,6 +466,7 @@ struct dsi_split_link_config {
|
||||
* @ext_bridge_mode: External bridge is connected.
|
||||
* @force_hs_clk_lane: Send continuous clock to the panel.
|
||||
* @dsi_split_link_config: Split Link Configuration.
|
||||
* @byte_intf_clk_div: Determines the factor for calculating byte intf clock.
|
||||
*/
|
||||
struct dsi_host_common_cfg {
|
||||
enum dsi_pixel_format dst_format;
|
||||
@@ -473,6 +490,7 @@ struct dsi_host_common_cfg {
|
||||
bool ext_bridge_mode;
|
||||
bool force_hs_clk_lane;
|
||||
struct dsi_split_link_config split_link;
|
||||
u32 byte_intf_clk_div;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -801,7 +801,7 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
|
||||
struct dsi_display *dsi_display = display;
|
||||
struct dsi_panel *panel;
|
||||
u32 status_mode;
|
||||
int rc = 0x1;
|
||||
int rc = 0x1, ret;
|
||||
u32 mask;
|
||||
|
||||
if (!dsi_display || !dsi_display->panel)
|
||||
@@ -839,8 +839,10 @@ int dsi_display_check_status(struct drm_connector *connector, void *display,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
|
||||
ret = dsi_display_clk_ctrl(dsi_display->dsi_clk_handle,
|
||||
DSI_ALL_CLKS, DSI_CLK_ON);
|
||||
if (ret)
|
||||
goto release_panel_lock;
|
||||
|
||||
/* Mask error interrupts before attempting ESD read */
|
||||
mask = BIT(DSI_FIFO_OVERFLOW) | BIT(DSI_FIFO_UNDERFLOW);
|
||||
@@ -3861,6 +3863,22 @@ static bool dsi_display_is_seamless_dfps_possible(
|
||||
return true;
|
||||
}
|
||||
|
||||
void dsi_display_update_byte_intf_div(struct dsi_display *display)
|
||||
{
|
||||
struct dsi_host_common_cfg *config;
|
||||
struct dsi_display_ctrl *m_ctrl;
|
||||
int phy_ver;
|
||||
|
||||
m_ctrl = &display->ctrl[display->cmd_master_idx];
|
||||
config = &display->panel->host_config;
|
||||
|
||||
phy_ver = dsi_phy_get_version(m_ctrl->phy);
|
||||
if (phy_ver <= DSI_PHY_VERSION_2_0)
|
||||
config->byte_intf_clk_div = 1;
|
||||
else
|
||||
config->byte_intf_clk_div = 2;
|
||||
}
|
||||
|
||||
static int dsi_display_update_dsi_bitrate(struct dsi_display *display,
|
||||
u32 bit_clk_rate)
|
||||
{
|
||||
@@ -3883,8 +3901,9 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display,
|
||||
display_for_each_ctrl(i, display) {
|
||||
struct dsi_display_ctrl *dsi_disp_ctrl = &display->ctrl[i];
|
||||
struct dsi_ctrl *ctrl = dsi_disp_ctrl->ctrl;
|
||||
u32 num_of_lanes = 0, bpp;
|
||||
u64 bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate;
|
||||
u32 num_of_lanes = 0, bpp, byte_intf_clk_div;
|
||||
u64 bit_rate, pclk_rate, bit_rate_per_lane, byte_clk_rate,
|
||||
byte_intf_clk_rate;
|
||||
struct dsi_host_common_cfg *host_cfg;
|
||||
|
||||
mutex_lock(&ctrl->ctrl_lock);
|
||||
@@ -3914,12 +3933,18 @@ static int dsi_display_update_dsi_bitrate(struct dsi_display *display,
|
||||
do_div(pclk_rate, bpp);
|
||||
byte_clk_rate = bit_rate_per_lane;
|
||||
do_div(byte_clk_rate, 8);
|
||||
byte_intf_clk_rate = byte_clk_rate;
|
||||
byte_intf_clk_div = host_cfg->byte_intf_clk_div;
|
||||
do_div(byte_intf_clk_rate, byte_intf_clk_div);
|
||||
|
||||
DSI_DEBUG("bit_clk_rate = %llu, bit_clk_rate_per_lane = %llu\n",
|
||||
bit_rate, bit_rate_per_lane);
|
||||
DSI_DEBUG("byte_clk_rate = %llu, pclk_rate = %llu\n",
|
||||
byte_clk_rate, pclk_rate);
|
||||
DSI_DEBUG("byte_clk_rate = %llu, byte_intf_clk_rate = %llu\n",
|
||||
byte_clk_rate, byte_intf_clk_rate);
|
||||
DSI_DEBUG("pclk_rate = %llu\n", pclk_rate);
|
||||
|
||||
ctrl->clk_freq.byte_clk_rate = byte_clk_rate;
|
||||
ctrl->clk_freq.byte_intf_clk_rate = byte_intf_clk_rate;
|
||||
ctrl->clk_freq.pix_clk_rate = pclk_rate;
|
||||
rc = dsi_clk_set_link_frequencies(display->dsi_clk_handle,
|
||||
ctrl->clk_freq, ctrl->cell_index);
|
||||
@@ -4013,7 +4038,8 @@ static int _dsi_display_dyn_update_clks(struct dsi_display *display,
|
||||
if (!ctrl->ctrl)
|
||||
continue;
|
||||
rc = dsi_clk_set_byte_clk_rate(display->dsi_clk_handle,
|
||||
ctrl->ctrl->clk_freq.byte_clk_rate, i);
|
||||
ctrl->ctrl->clk_freq.byte_clk_rate,
|
||||
ctrl->ctrl->clk_freq.byte_intf_clk_rate, i);
|
||||
if (rc) {
|
||||
DSI_ERR("failed to set byte rate for index:%d\n", i);
|
||||
goto recover_byte_clk;
|
||||
@@ -4076,7 +4102,8 @@ recover_byte_clk:
|
||||
if (!ctrl->ctrl)
|
||||
continue;
|
||||
dsi_clk_set_byte_clk_rate(display->dsi_clk_handle,
|
||||
bkp_freq->byte_clk_rate, i);
|
||||
bkp_freq->byte_clk_rate,
|
||||
bkp_freq->byte_intf_clk_rate, i);
|
||||
}
|
||||
|
||||
exit:
|
||||
@@ -4112,6 +4139,7 @@ static int dsi_display_dynamic_clk_switch_vid(struct dsi_display *display,
|
||||
|
||||
/* back up existing rates to handle failure case */
|
||||
bkp_freq.byte_clk_rate = m_ctrl->ctrl->clk_freq.byte_clk_rate;
|
||||
bkp_freq.byte_intf_clk_rate = m_ctrl->ctrl->clk_freq.byte_intf_clk_rate;
|
||||
bkp_freq.pix_clk_rate = m_ctrl->ctrl->clk_freq.pix_clk_rate;
|
||||
bkp_freq.esc_clk_rate = m_ctrl->ctrl->clk_freq.esc_clk_rate;
|
||||
|
||||
@@ -4196,6 +4224,7 @@ static int dsi_display_dfps_update(struct dsi_display *display,
|
||||
struct dsi_dfps_capabilities dfps_caps;
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
struct dsi_dyn_clk_caps *dyn_clk_caps;
|
||||
|
||||
if (!display || !dsi_mode || !display->panel) {
|
||||
DSI_ERR("Invalid params\n");
|
||||
@@ -4204,8 +4233,9 @@ static int dsi_display_dfps_update(struct dsi_display *display,
|
||||
timing = &dsi_mode->timing;
|
||||
|
||||
dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
|
||||
if (!dfps_caps.dfps_support) {
|
||||
DSI_ERR("dfps not supported\n");
|
||||
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
||||
if (!dfps_caps.dfps_support && !dyn_clk_caps->maintain_const_fps) {
|
||||
DSI_ERR("dfps or constant fps not supported\n");
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
@@ -4482,7 +4512,32 @@ static int dsi_display_set_mode_sub(struct dsi_display *display,
|
||||
display->name, rc);
|
||||
goto error;
|
||||
}
|
||||
} else if (mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK) {
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
rc = dsi_ctrl_update_host_config(ctrl->ctrl,
|
||||
&display->config, mode, mode->dsi_mode_flags,
|
||||
display->dsi_clk_handle);
|
||||
if (rc) {
|
||||
DSI_ERR("failed to update ctrl config\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (priv_info->phy_timing_len) {
|
||||
display_for_each_ctrl(i, display) {
|
||||
ctrl = &display->ctrl[i];
|
||||
rc = dsi_phy_set_timing_params(ctrl->phy,
|
||||
priv_info->phy_timing_val,
|
||||
priv_info->phy_timing_len,
|
||||
commit_phy_timing);
|
||||
if (rc)
|
||||
DSI_ERR("Fail to add timing params\n");
|
||||
}
|
||||
}
|
||||
if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK))
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (mode->dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK) {
|
||||
if (display->panel->panel_mode == DSI_OP_VIDEO_MODE) {
|
||||
rc = dsi_display_dynamic_clk_switch_vid(display, mode);
|
||||
if (rc)
|
||||
@@ -4939,6 +4994,7 @@ static int dsi_display_bind(struct device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
dsi_display_update_byte_intf_div(display);
|
||||
rc = dsi_display_mipi_host_init(display);
|
||||
if (rc) {
|
||||
DSI_ERR("[%s] failed to initialize mipi host, rc=%d\n",
|
||||
@@ -5872,6 +5928,53 @@ int dsi_display_get_mode_count(struct dsi_display *display,
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dsi_display_adjust_mode_timing(
|
||||
struct dsi_dyn_clk_caps *dyn_clk_caps,
|
||||
struct dsi_display_mode *dsi_mode,
|
||||
int lanes, int bpp)
|
||||
{
|
||||
u64 new_htotal, new_vtotal, htotal, vtotal, old_htotal, div;
|
||||
|
||||
if (!dyn_clk_caps->maintain_const_fps)
|
||||
return;
|
||||
/*
|
||||
* When there is a dynamic clock switch, there is small change
|
||||
* in FPS. To compensate for this difference in FPS, hfp or vfp
|
||||
* is adjusted. It has been assumed that the refined porch values
|
||||
* are supported by the panel. This logic can be enhanced further
|
||||
* in future by taking min/max porches supported by the panel.
|
||||
*/
|
||||
switch (dyn_clk_caps->type) {
|
||||
case DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_HFP:
|
||||
vtotal = DSI_V_TOTAL(&dsi_mode->timing);
|
||||
old_htotal = dsi_h_total_dce(&dsi_mode->timing);
|
||||
new_htotal = dsi_mode->timing.clk_rate_hz * lanes;
|
||||
div = bpp * vtotal * dsi_mode->timing.refresh_rate;
|
||||
do_div(new_htotal, div);
|
||||
if (old_htotal > new_htotal)
|
||||
dsi_mode->timing.h_front_porch -=
|
||||
(old_htotal - new_htotal);
|
||||
else
|
||||
dsi_mode->timing.h_front_porch +=
|
||||
(new_htotal - old_htotal);
|
||||
break;
|
||||
|
||||
case DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_VFP:
|
||||
htotal = dsi_h_total_dce(&dsi_mode->timing);
|
||||
new_vtotal = dsi_mode->timing.clk_rate_hz * lanes;
|
||||
div = bpp * htotal * dsi_mode->timing.refresh_rate;
|
||||
do_div(new_vtotal, div);
|
||||
dsi_mode->timing.v_front_porch = new_vtotal -
|
||||
dsi_mode->timing.v_back_porch -
|
||||
dsi_mode->timing.v_sync_width -
|
||||
dsi_mode->timing.v_active;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _dsi_display_populate_bit_clks(struct dsi_display *display,
|
||||
int start, int end, u32 *mode_idx)
|
||||
{
|
||||
@@ -5911,6 +6014,9 @@ static void _dsi_display_populate_bit_clks(struct dsi_display *display,
|
||||
* be based on user or device tree preferrence.
|
||||
*/
|
||||
src->timing.clk_rate_hz = dyn_clk_caps->bit_clk_list[0];
|
||||
|
||||
dsi_display_adjust_mode_timing(dyn_clk_caps, src, lanes, bpp);
|
||||
|
||||
src->pixel_clk_khz =
|
||||
div_u64(src->timing.clk_rate_hz * lanes, bpp);
|
||||
src->pixel_clk_khz /= 1000;
|
||||
@@ -5930,6 +6036,10 @@ static void _dsi_display_populate_bit_clks(struct dsi_display *display,
|
||||
}
|
||||
memcpy(dst, src, sizeof(struct dsi_display_mode));
|
||||
dst->timing.clk_rate_hz = dyn_clk_caps->bit_clk_list[i];
|
||||
|
||||
dsi_display_adjust_mode_timing(dyn_clk_caps, dst, lanes,
|
||||
bpp);
|
||||
|
||||
dst->pixel_clk_khz =
|
||||
div_u64(dst->timing.clk_rate_hz * lanes, bpp);
|
||||
dst->pixel_clk_khz /= 1000;
|
||||
@@ -6224,13 +6334,28 @@ int dsi_display_find_mode(struct dsi_display *display,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static inline bool dsi_display_mode_switch_dfps(struct dsi_display_mode *cur,
|
||||
struct dsi_display_mode *adj)
|
||||
{
|
||||
/*
|
||||
* If there is a change in the hfp or vfp of the current and adjoining
|
||||
* mode,then either it is a dfps mode switch or dynamic clk change with
|
||||
* constant fps.
|
||||
*/
|
||||
if ((cur->timing.h_front_porch != adj->timing.h_front_porch) ||
|
||||
(cur->timing.v_front_porch != adj->timing.v_front_porch))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* dsi_display_validate_mode_change() - Validate mode change case.
|
||||
* @display: DSI display handle.
|
||||
* @cur_mode: Current mode.
|
||||
* @adj_mode: Mode to be set.
|
||||
* MSM_MODE_FLAG_SEAMLESS_VRR flag is set if there
|
||||
* is change in fps but vactive and hactive are same.
|
||||
* is change in hfp or vfp but vactive and hactive are same.
|
||||
* DSI_MODE_FLAG_DYN_CLK flag is set if there
|
||||
* is change in clk but vactive and hactive are same.
|
||||
* Return: error code.
|
||||
@@ -6254,14 +6379,15 @@ int dsi_display_validate_mode_change(struct dsi_display *display,
|
||||
}
|
||||
|
||||
mutex_lock(&display->display_lock);
|
||||
|
||||
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
||||
if ((cur_mode->timing.v_active == adj_mode->timing.v_active) &&
|
||||
(cur_mode->timing.h_active == adj_mode->timing.h_active)) {
|
||||
/* dfps change use case */
|
||||
if (cur_mode->timing.refresh_rate !=
|
||||
adj_mode->timing.refresh_rate) {
|
||||
(cur_mode->timing.h_active == adj_mode->timing.h_active) &&
|
||||
(cur_mode->panel_mode == adj_mode->panel_mode)) {
|
||||
/* dfps and dynamic clock with const fps use case */
|
||||
if (dsi_display_mode_switch_dfps(cur_mode, adj_mode)) {
|
||||
dsi_panel_get_dfps_caps(display->panel, &dfps_caps);
|
||||
if (dfps_caps.dfps_support) {
|
||||
if (dfps_caps.dfps_support ||
|
||||
dyn_clk_caps->maintain_const_fps) {
|
||||
DSI_DEBUG("Mode switch is seamless variable refresh\n");
|
||||
adj_mode->dsi_mode_flags |= DSI_MODE_FLAG_VRR;
|
||||
SDE_EVT32(cur_mode->timing.refresh_rate,
|
||||
@@ -6273,10 +6399,11 @@ int dsi_display_validate_mode_change(struct dsi_display *display,
|
||||
|
||||
/* dynamic clk change use case */
|
||||
if (cur_mode->pixel_clk_khz != adj_mode->pixel_clk_khz) {
|
||||
dyn_clk_caps = &(display->panel->dyn_clk_caps);
|
||||
if (dyn_clk_caps->dyn_clk_support) {
|
||||
DSI_DEBUG("dynamic clk change detected\n");
|
||||
if (adj_mode->dsi_mode_flags & DSI_MODE_FLAG_VRR) {
|
||||
if ((adj_mode->dsi_mode_flags &
|
||||
DSI_MODE_FLAG_VRR) &&
|
||||
(!dyn_clk_caps->maintain_const_fps)) {
|
||||
DSI_ERR("dfps and dyn clk not supported in same commit\n");
|
||||
rc = -ENOTSUPP;
|
||||
goto error;
|
||||
@@ -6794,13 +6921,15 @@ int dsi_display_prepare(struct dsi_display *display)
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!display->is_cont_splash_enabled) {
|
||||
/* update dsi ctrl for new mode */
|
||||
rc = dsi_display_pre_switch(display);
|
||||
if (rc)
|
||||
DSI_ERR("[%s] panel pre-prepare-res-switch failed, rc=%d\n",
|
||||
DSI_ERR("[%s] panel pre-switch failed, rc=%d\n",
|
||||
display->name, rc);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(mode->dsi_mode_flags & DSI_MODE_FLAG_POMS) &&
|
||||
(!display->is_cont_splash_enabled)) {
|
||||
|
@@ -253,6 +253,7 @@ static void dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
static void dsi_bridge_disable(struct drm_bridge *bridge)
|
||||
{
|
||||
int rc = 0;
|
||||
int private_flags;
|
||||
struct dsi_display *display;
|
||||
struct dsi_bridge *c_bridge = to_dsi_bridge(bridge);
|
||||
|
||||
@@ -261,19 +262,15 @@ static void dsi_bridge_disable(struct drm_bridge *bridge)
|
||||
return;
|
||||
}
|
||||
display = c_bridge->display;
|
||||
private_flags =
|
||||
bridge->encoder->crtc->state->adjusted_mode.private_flags;
|
||||
|
||||
if (display && display->drm_conn) {
|
||||
if (bridge->encoder->crtc->state->adjusted_mode.private_flags &
|
||||
MSM_MODE_FLAG_SEAMLESS_POMS) {
|
||||
display->poms_pending = true;
|
||||
/* Disable ESD thread, during panel mode switch */
|
||||
sde_connector_schedule_status_work(display->drm_conn,
|
||||
false);
|
||||
} else {
|
||||
display->poms_pending = false;
|
||||
display->poms_pending =
|
||||
private_flags & MSM_MODE_FLAG_SEAMLESS_POMS;
|
||||
|
||||
sde_connector_helper_bridge_disable(display->drm_conn);
|
||||
}
|
||||
}
|
||||
|
||||
rc = dsi_display_pre_disable(c_bridge->display);
|
||||
if (rc) {
|
||||
@@ -426,6 +423,7 @@ static bool dsi_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
/* Reject seamless transition when active changed */
|
||||
if (crtc_state->active_changed &&
|
||||
((dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_VRR) ||
|
||||
(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_POMS) ||
|
||||
(dsi_mode.dsi_mode_flags & DSI_MODE_FLAG_DYN_CLK))) {
|
||||
DSI_ERR("seamless upon active changed 0x%x %d\n",
|
||||
dsi_mode.dsi_mode_flags, crtc_state->active_changed);
|
||||
|
@@ -1175,6 +1175,7 @@ static int dsi_panel_parse_dyn_clk_caps(struct dsi_panel *panel)
|
||||
struct dsi_dyn_clk_caps *dyn_clk_caps = &panel->dyn_clk_caps;
|
||||
struct dsi_parser_utils *utils = &panel->utils;
|
||||
const char *name = panel->name;
|
||||
const char *type;
|
||||
|
||||
supported = utils->read_bool(utils->data, "qcom,dsi-dyn-clk-enable");
|
||||
|
||||
@@ -1207,6 +1208,24 @@ static int dsi_panel_parse_dyn_clk_caps(struct dsi_panel *panel)
|
||||
|
||||
dyn_clk_caps->dyn_clk_support = true;
|
||||
|
||||
type = utils->get_property(utils->data,
|
||||
"qcom,dsi-dyn-clk-type", NULL);
|
||||
if (!type) {
|
||||
dyn_clk_caps->type = DSI_DYN_CLK_TYPE_LEGACY;
|
||||
dyn_clk_caps->maintain_const_fps = false;
|
||||
return 0;
|
||||
}
|
||||
if (!strcmp(type, "constant-fps-adjust-hfp")) {
|
||||
dyn_clk_caps->type = DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_HFP;
|
||||
dyn_clk_caps->maintain_const_fps = true;
|
||||
} else if (!strcmp(type, "constant-fps-adjust-vfp")) {
|
||||
dyn_clk_caps->type = DSI_DYN_CLK_TYPE_CONST_FPS_ADJUST_VFP;
|
||||
dyn_clk_caps->maintain_const_fps = true;
|
||||
} else {
|
||||
dyn_clk_caps->type = DSI_DYN_CLK_TYPE_LEGACY;
|
||||
dyn_clk_caps->maintain_const_fps = false;
|
||||
}
|
||||
DSI_DEBUG("Dynamic clock type is [%s]\n", type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3704,9 +3723,11 @@ int dsi_panel_get_mode(struct dsi_panel *panel,
|
||||
if (panel->panel_mode_switch_enabled) {
|
||||
rc = dsi_panel_parse_panel_mode_caps(mode, utils);
|
||||
if (rc) {
|
||||
DSI_ERR("PMS: failed to parse panel mode\n");
|
||||
rc = 0;
|
||||
mode->panel_mode = panel->panel_mode;
|
||||
DSI_INFO(
|
||||
"POMS: panel mode isn't specified in timing[%d]\n",
|
||||
child_idx);
|
||||
}
|
||||
} else {
|
||||
mode->panel_mode = panel->panel_mode;
|
||||
|
@@ -82,6 +82,8 @@ struct dsi_dyn_clk_caps {
|
||||
bool dyn_clk_support;
|
||||
u32 *bit_clk_list;
|
||||
u32 bit_clk_list_len;
|
||||
enum dsi_dyn_clk_feature_type type;
|
||||
bool maintain_const_fps;
|
||||
};
|
||||
|
||||
struct dsi_pinctrl_info {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/delay.h>
|
||||
@@ -239,15 +239,18 @@ static bool dsi_parser_parse_prop(struct device *dev,
|
||||
{
|
||||
bool found = false;
|
||||
char *out = strsep(&buf, "=");
|
||||
size_t buf_len;
|
||||
|
||||
if (!out || !buf)
|
||||
goto end;
|
||||
|
||||
prop->raw = devm_kzalloc(dev, strlen(buf) + 1, GFP_KERNEL);
|
||||
buf_len = strlen(buf);
|
||||
|
||||
prop->raw = devm_kzalloc(dev, buf_len + 1, GFP_KERNEL);
|
||||
if (!prop->raw)
|
||||
goto end;
|
||||
|
||||
strlcpy(prop->raw, buf, strlen(buf) + 1);
|
||||
strlcpy(prop->raw, buf, buf_len + 1);
|
||||
|
||||
found = true;
|
||||
|
||||
|
@@ -111,6 +111,11 @@ static const struct of_device_id msm_dsi_phy_of_match[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
int dsi_phy_get_version(struct msm_dsi_phy *phy)
|
||||
{
|
||||
return phy->ver_info->version;
|
||||
}
|
||||
|
||||
static int dsi_phy_regmap_init(struct platform_device *pdev,
|
||||
struct msm_dsi_phy *phy)
|
||||
{
|
||||
|
@@ -125,6 +125,14 @@ struct msm_dsi_phy *dsi_phy_get(struct device_node *of_node);
|
||||
*/
|
||||
void dsi_phy_put(struct msm_dsi_phy *dsi_phy);
|
||||
|
||||
/**
|
||||
* dsi_phy_get_version() - returns dsi phy version
|
||||
* @dsi_phy: DSI PHY handle.
|
||||
*
|
||||
* Return: phy version
|
||||
*/
|
||||
int dsi_phy_get_version(struct msm_dsi_phy *phy);
|
||||
|
||||
/**
|
||||
* dsi_phy_drv_init() - initialize dsi phy driver
|
||||
* @dsi_phy: DSI PHY handle.
|
||||
|
@@ -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/math64.h>
|
||||
@@ -64,6 +64,83 @@
|
||||
#define DSIPHY_PLL_CLKBUFLR_EN 0x041C
|
||||
#define DSIPHY_PLL_PLL_BANDGAP 0x0508
|
||||
|
||||
/* dynamic refresh control registers */
|
||||
#define DSI_DYN_REFRESH_CTRL 0x000
|
||||
#define DSI_DYN_REFRESH_PIPE_DELAY 0x004
|
||||
#define DSI_DYN_REFRESH_PIPE_DELAY2 0x008
|
||||
#define DSI_DYN_REFRESH_PLL_DELAY 0x00C
|
||||
#define DSI_DYN_REFRESH_STATUS 0x010
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL0 0x014
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL1 0x018
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL2 0x01C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL3 0x020
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL4 0x024
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL5 0x028
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL6 0x02C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL7 0x030
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL8 0x034
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL9 0x038
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL10 0x03C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL11 0x040
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL12 0x044
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL13 0x048
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL14 0x04C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL15 0x050
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL16 0x054
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL17 0x058
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL18 0x05C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL19 0x060
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL20 0x064
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL21 0x068
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL22 0x06C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL23 0x070
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL24 0x074
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL25 0x078
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL26 0x07C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL27 0x080
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL28 0x084
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL29 0x088
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL30 0x08C
|
||||
#define DSI_DYN_REFRESH_PLL_CTRL31 0x090
|
||||
#define DSI_DYN_REFRESH_PLL_UPPER_ADDR 0x094
|
||||
#define DSI_DYN_REFRESH_PLL_UPPER_ADDR2 0x098
|
||||
|
||||
#define DSIPHY_DLN0_CFG1 0x0104
|
||||
#define DSIPHY_DLN0_TIMING_CTRL_4 0x0118
|
||||
#define DSIPHY_DLN0_TIMING_CTRL_5 0x011C
|
||||
#define DSIPHY_DLN0_TIMING_CTRL_6 0x0120
|
||||
#define DSIPHY_DLN0_TIMING_CTRL_7 0x0124
|
||||
#define DSIPHY_DLN0_TIMING_CTRL_8 0x0128
|
||||
|
||||
#define DSIPHY_DLN1_CFG1 0x0184
|
||||
#define DSIPHY_DLN1_TIMING_CTRL_4 0x0198
|
||||
#define DSIPHY_DLN1_TIMING_CTRL_5 0x019C
|
||||
#define DSIPHY_DLN1_TIMING_CTRL_6 0x01A0
|
||||
#define DSIPHY_DLN1_TIMING_CTRL_7 0x01A4
|
||||
#define DSIPHY_DLN1_TIMING_CTRL_8 0x01A8
|
||||
|
||||
#define DSIPHY_DLN2_CFG1 0x0204
|
||||
#define DSIPHY_DLN2_TIMING_CTRL_4 0x0218
|
||||
#define DSIPHY_DLN2_TIMING_CTRL_5 0x021C
|
||||
#define DSIPHY_DLN2_TIMING_CTRL_6 0x0220
|
||||
#define DSIPHY_DLN2_TIMING_CTRL_7 0x0224
|
||||
#define DSIPHY_DLN2_TIMING_CTRL_8 0x0228
|
||||
|
||||
#define DSIPHY_DLN3_CFG1 0x0284
|
||||
#define DSIPHY_DLN3_TIMING_CTRL_4 0x0298
|
||||
#define DSIPHY_DLN3_TIMING_CTRL_5 0x029C
|
||||
#define DSIPHY_DLN3_TIMING_CTRL_6 0x02A0
|
||||
#define DSIPHY_DLN3_TIMING_CTRL_7 0x02A4
|
||||
#define DSIPHY_DLN3_TIMING_CTRL_8 0x02A8
|
||||
|
||||
#define DSIPHY_CKLN_CFG1 0x0304
|
||||
#define DSIPHY_CKLN_TIMING_CTRL_4 0x0318
|
||||
#define DSIPHY_CKLN_TIMING_CTRL_5 0x031C
|
||||
#define DSIPHY_CKLN_TIMING_CTRL_6 0x0320
|
||||
#define DSIPHY_CKLN_TIMING_CTRL_7 0x0324
|
||||
#define DSIPHY_CKLN_TIMING_CTRL_8 0x0328
|
||||
|
||||
#define DSIPHY_PLL_RESETSM_CNTRL5 0x043c
|
||||
/**
|
||||
* regulator_enable() - enable regulators for DSI PHY
|
||||
* @phy: Pointer to DSI PHY hardware object.
|
||||
@@ -299,3 +376,261 @@ void dsi_phy_hw_v2_0_clamp_ctrl(struct dsi_phy_hw *phy, bool enable)
|
||||
DSI_PHY_DBG(phy, "clamp disabled\n");
|
||||
}
|
||||
}
|
||||
|
||||
void dsi_phy_hw_v2_0_dyn_refresh_config(struct dsi_phy_hw *phy,
|
||||
struct dsi_phy_cfg *cfg, bool is_master)
|
||||
{
|
||||
u32 glbl_tst_cntrl;
|
||||
|
||||
if (is_master) {
|
||||
glbl_tst_cntrl = DSI_R32(phy, DSIPHY_CMN_GLBL_TEST_CTRL);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL0,
|
||||
DSIPHY_CMN_GLBL_TEST_CTRL,
|
||||
DSIPHY_PLL_PLL_BANDGAP,
|
||||
glbl_tst_cntrl | BIT(1), 0x1);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL1,
|
||||
DSIPHY_PLL_RESETSM_CNTRL5,
|
||||
DSIPHY_PLL_PLL_BANDGAP, 0x0D, 0x03);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL2,
|
||||
DSIPHY_PLL_RESETSM_CNTRL5,
|
||||
DSIPHY_CMN_PLL_CNTRL, 0x1D, 0x00);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL3,
|
||||
DSIPHY_CMN_CTRL_1, DSIPHY_DLN0_CFG1, 0x20, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL4,
|
||||
DSIPHY_DLN1_CFG1, DSIPHY_DLN2_CFG1, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL5,
|
||||
DSIPHY_DLN3_CFG1, DSIPHY_CKLN_CFG1, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL6,
|
||||
DSIPHY_DLN0_TIMING_CTRL_4,
|
||||
DSIPHY_DLN1_TIMING_CTRL_4,
|
||||
cfg->timing.lane[0][0], cfg->timing.lane[1][0]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL7,
|
||||
DSIPHY_DLN2_TIMING_CTRL_4,
|
||||
DSIPHY_DLN3_TIMING_CTRL_4,
|
||||
cfg->timing.lane[2][0], cfg->timing.lane[3][0]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL8,
|
||||
DSIPHY_CKLN_TIMING_CTRL_4,
|
||||
DSIPHY_DLN0_TIMING_CTRL_5,
|
||||
cfg->timing.lane[4][0], cfg->timing.lane[0][1]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9,
|
||||
DSIPHY_DLN1_TIMING_CTRL_5,
|
||||
DSIPHY_DLN2_TIMING_CTRL_5,
|
||||
cfg->timing.lane[1][1], cfg->timing.lane[2][1]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL10,
|
||||
DSIPHY_DLN3_TIMING_CTRL_5,
|
||||
DSIPHY_CKLN_TIMING_CTRL_5,
|
||||
cfg->timing.lane[3][1], cfg->timing.lane[4][1]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL11,
|
||||
DSIPHY_DLN0_TIMING_CTRL_6,
|
||||
DSIPHY_DLN1_TIMING_CTRL_6,
|
||||
cfg->timing.lane[0][2], cfg->timing.lane[1][2]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL12,
|
||||
DSIPHY_DLN2_TIMING_CTRL_6,
|
||||
DSIPHY_DLN3_TIMING_CTRL_6,
|
||||
cfg->timing.lane[2][2], cfg->timing.lane[3][2]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL13,
|
||||
DSIPHY_CKLN_TIMING_CTRL_6,
|
||||
DSIPHY_DLN0_TIMING_CTRL_7,
|
||||
cfg->timing.lane[4][2], cfg->timing.lane[0][3]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL14,
|
||||
DSIPHY_DLN1_TIMING_CTRL_7,
|
||||
DSIPHY_DLN2_TIMING_CTRL_7,
|
||||
cfg->timing.lane[1][3], cfg->timing.lane[2][3]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL15,
|
||||
DSIPHY_DLN3_TIMING_CTRL_7,
|
||||
DSIPHY_CKLN_TIMING_CTRL_7,
|
||||
cfg->timing.lane[3][3], cfg->timing.lane[4][3]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base,
|
||||
DSI_DYN_REFRESH_PLL_CTRL16,
|
||||
DSIPHY_DLN0_TIMING_CTRL_8,
|
||||
DSIPHY_DLN1_TIMING_CTRL_8,
|
||||
cfg->timing.lane[0][4], cfg->timing.lane[1][4]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL17,
|
||||
DSIPHY_DLN2_TIMING_CTRL_8,
|
||||
DSIPHY_DLN3_TIMING_CTRL_8,
|
||||
cfg->timing.lane[2][4], cfg->timing.lane[3][4]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL18,
|
||||
DSIPHY_CKLN_TIMING_CTRL_8, DSIPHY_CMN_CTRL_1,
|
||||
cfg->timing.lane[4][4], 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL30,
|
||||
DSIPHY_CMN_GLBL_TEST_CTRL,
|
||||
DSIPHY_CMN_GLBL_TEST_CTRL,
|
||||
((glbl_tst_cntrl) & (~BIT(2))),
|
||||
((glbl_tst_cntrl) & (~BIT(2))));
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL31,
|
||||
DSIPHY_CMN_GLBL_TEST_CTRL,
|
||||
DSIPHY_CMN_GLBL_TEST_CTRL,
|
||||
((glbl_tst_cntrl) & (~BIT(2))),
|
||||
((glbl_tst_cntrl) & (~BIT(2))));
|
||||
} else {
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL0,
|
||||
DSIPHY_DLN0_CFG1, DSIPHY_DLN1_CFG1, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL1,
|
||||
DSIPHY_DLN2_CFG1, DSIPHY_DLN3_CFG1, 0x0, 0x0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL2,
|
||||
DSIPHY_CKLN_CFG1, DSIPHY_DLN0_TIMING_CTRL_4,
|
||||
0x0, cfg->timing.lane[0][0]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL3,
|
||||
DSIPHY_DLN1_TIMING_CTRL_4,
|
||||
DSIPHY_DLN2_TIMING_CTRL_4,
|
||||
cfg->timing.lane[1][0], cfg->timing.lane[2][0]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL4,
|
||||
DSIPHY_DLN3_TIMING_CTRL_4,
|
||||
DSIPHY_CKLN_TIMING_CTRL_4,
|
||||
cfg->timing.lane[3][0], cfg->timing.lane[4][0]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL5,
|
||||
DSIPHY_DLN0_TIMING_CTRL_5,
|
||||
DSIPHY_DLN1_TIMING_CTRL_5,
|
||||
cfg->timing.lane[0][1], cfg->timing.lane[1][1]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL6,
|
||||
DSIPHY_DLN2_TIMING_CTRL_5,
|
||||
DSIPHY_DLN3_TIMING_CTRL_5,
|
||||
cfg->timing.lane[2][1], cfg->timing.lane[3][1]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL7,
|
||||
DSIPHY_CKLN_TIMING_CTRL_5,
|
||||
DSIPHY_DLN0_TIMING_CTRL_6,
|
||||
cfg->timing.lane[4][1], cfg->timing.lane[0][2]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL8,
|
||||
DSIPHY_DLN1_TIMING_CTRL_6,
|
||||
DSIPHY_DLN2_TIMING_CTRL_6,
|
||||
cfg->timing.lane[1][2], cfg->timing.lane[2][2]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL9,
|
||||
DSIPHY_DLN3_TIMING_CTRL_6,
|
||||
DSIPHY_CKLN_TIMING_CTRL_6,
|
||||
cfg->timing.lane[3][2], cfg->timing.lane[4][2]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL10,
|
||||
DSIPHY_DLN0_TIMING_CTRL_7,
|
||||
DSIPHY_DLN1_TIMING_CTRL_7,
|
||||
cfg->timing.lane[0][3], cfg->timing.lane[1][3]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL11,
|
||||
DSIPHY_DLN2_TIMING_CTRL_7,
|
||||
DSIPHY_DLN3_TIMING_CTRL_7,
|
||||
cfg->timing.lane[2][3], cfg->timing.lane[3][3]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL12,
|
||||
DSIPHY_CKLN_TIMING_CTRL_7,
|
||||
DSIPHY_DLN0_TIMING_CTRL_8,
|
||||
cfg->timing.lane[4][3], cfg->timing.lane[0][4]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL13,
|
||||
DSIPHY_DLN1_TIMING_CTRL_8,
|
||||
DSIPHY_DLN2_TIMING_CTRL_8,
|
||||
cfg->timing.lane[1][4], cfg->timing.lane[2][4]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL14,
|
||||
DSIPHY_DLN3_TIMING_CTRL_8,
|
||||
DSIPHY_CKLN_TIMING_CTRL_8,
|
||||
cfg->timing.lane[3][4], cfg->timing.lane[4][4]);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL15,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL16,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL17,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL18,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL19,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL20,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL21,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL22,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL23,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL24,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL25,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL26,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL27,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL28,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL29,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL30,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_DYN_REF_REG_W(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_CTRL31,
|
||||
0x0110, 0x0110, 0, 0);
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_UPPER_ADDR,
|
||||
0x0);
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_UPPER_ADDR2,
|
||||
0x0);
|
||||
}
|
||||
|
||||
wmb(); /* make sure phy timings are updated*/
|
||||
}
|
||||
|
||||
void dsi_phy_hw_v2_0_dyn_refresh_pipe_delay(struct dsi_phy_hw *phy,
|
||||
struct dsi_dyn_clk_delay *delay)
|
||||
{
|
||||
if (!delay)
|
||||
return;
|
||||
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_PIPE_DELAY,
|
||||
delay->pipe_delay);
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_PIPE_DELAY2,
|
||||
delay->pipe_delay2);
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_PLL_DELAY,
|
||||
delay->pll_delay);
|
||||
}
|
||||
|
||||
void dsi_phy_hw_v2_0_dyn_refresh_helper(struct dsi_phy_hw *phy, u32 offset)
|
||||
{
|
||||
u32 reg;
|
||||
|
||||
/*
|
||||
* if no offset is mentioned then this means we want to clear
|
||||
* the dynamic refresh ctrl register which is the last step
|
||||
* of dynamic refresh sequence.
|
||||
*/
|
||||
if (!offset) {
|
||||
reg = DSI_GEN_R32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL);
|
||||
reg &= ~(BIT(0) | BIT(8));
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL, reg);
|
||||
wmb(); /* ensure dynamic fps is cleared */
|
||||
return;
|
||||
}
|
||||
|
||||
if (offset & BIT(DYN_REFRESH_INTF_SEL)) {
|
||||
reg = DSI_GEN_R32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL);
|
||||
reg |= BIT(13);
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL, reg);
|
||||
}
|
||||
|
||||
if (offset & BIT(DYN_REFRESH_SWI_CTRL)) {
|
||||
reg = DSI_GEN_R32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL);
|
||||
reg |= BIT(0);
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL, reg);
|
||||
}
|
||||
|
||||
if (offset & BIT(DYN_REFRESH_SW_TRIGGER)) {
|
||||
reg = DSI_GEN_R32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL);
|
||||
reg |= BIT(8);
|
||||
DSI_GEN_W32(phy->dyn_pll_base, DSI_DYN_REFRESH_CTRL, reg);
|
||||
wmb(); /* ensure dynamic fps is triggered */
|
||||
}
|
||||
}
|
||||
|
||||
int dsi_phy_hw_v2_0_cache_phy_timings(struct dsi_phy_per_lane_cfgs *timings,
|
||||
u32 *dst, u32 size)
|
||||
{
|
||||
int i, j, count = 0;
|
||||
|
||||
if (!timings || !dst || !size)
|
||||
return -EINVAL;
|
||||
|
||||
if (size != (DSI_LANE_MAX * DSI_MAX_SETTINGS)) {
|
||||
pr_err("size mis-match\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = DSI_LOGICAL_LANE_0; i < DSI_LANE_MAX; i++) {
|
||||
for (j = 0; j < DSI_MAX_SETTINGS; j++) {
|
||||
dst[count] = timings->lane[i][j];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -94,8 +94,7 @@ static int sde_backlight_device_update_status(struct backlight_device *bd)
|
||||
if (!bl_lvl && brightness)
|
||||
bl_lvl = 1;
|
||||
|
||||
if (display->panel->bl_config.bl_update ==
|
||||
BL_UPDATE_DELAY_UNTIL_FIRST_FRAME && !c_conn->allow_bl_update) {
|
||||
if (!c_conn->allow_bl_update) {
|
||||
c_conn->unset_bl_level = bl_lvl;
|
||||
return 0;
|
||||
}
|
||||
@@ -532,9 +531,7 @@ static int _sde_connector_update_bl_scale(struct sde_connector *c_conn)
|
||||
|
||||
bl_config = &dsi_display->panel->bl_config;
|
||||
|
||||
if (dsi_display->panel->bl_config.bl_update ==
|
||||
BL_UPDATE_DELAY_UNTIL_FIRST_FRAME &&
|
||||
!c_conn->allow_bl_update) {
|
||||
if (!c_conn->allow_bl_update) {
|
||||
c_conn->unset_bl_level = bl_config->bl_level;
|
||||
return 0;
|
||||
}
|
||||
@@ -797,21 +794,29 @@ void sde_connector_helper_bridge_disable(struct drm_connector *connector)
|
||||
{
|
||||
int rc;
|
||||
struct sde_connector *c_conn = NULL;
|
||||
struct dsi_display *display;
|
||||
bool poms_pending = false;
|
||||
|
||||
if (!connector)
|
||||
return;
|
||||
|
||||
c_conn = to_sde_connector(connector);
|
||||
if (c_conn->connector_type == DRM_MODE_CONNECTOR_DSI) {
|
||||
display = (struct dsi_display *) c_conn->display;
|
||||
poms_pending = display->poms_pending;
|
||||
}
|
||||
|
||||
if (!poms_pending) {
|
||||
rc = _sde_connector_update_dirty_properties(connector);
|
||||
if (rc) {
|
||||
SDE_ERROR("conn %d final pre kickoff failed %d\n",
|
||||
connector->base.id, rc);
|
||||
SDE_EVT32(connector->base.id, SDE_EVTLOG_ERROR);
|
||||
}
|
||||
|
||||
}
|
||||
/* Disable ESD thread */
|
||||
sde_connector_schedule_status_work(connector, false);
|
||||
|
||||
c_conn = to_sde_connector(connector);
|
||||
if (c_conn->bl_device) {
|
||||
c_conn->bl_device->props.power = FB_BLANK_POWERDOWN;
|
||||
c_conn->bl_device->props.state |= BL_CORE_FBBLANK;
|
||||
@@ -2167,6 +2172,7 @@ static void sde_connector_check_status_work(struct work_struct *work)
|
||||
{
|
||||
struct sde_connector *conn;
|
||||
int rc = 0;
|
||||
struct device *dev;
|
||||
|
||||
conn = container_of(to_delayed_work(work),
|
||||
struct sde_connector, status_work);
|
||||
@@ -2176,7 +2182,9 @@ static void sde_connector_check_status_work(struct work_struct *work)
|
||||
}
|
||||
|
||||
mutex_lock(&conn->lock);
|
||||
if (!conn->ops.check_status ||
|
||||
dev = conn->base.dev->dev;
|
||||
|
||||
if (!conn->ops.check_status || dev->power.is_suspended ||
|
||||
(conn->dpms_mode != DRM_MODE_DPMS_ON)) {
|
||||
SDE_DEBUG("dpms mode: %d\n", conn->dpms_mode);
|
||||
mutex_unlock(&conn->lock);
|
||||
|
Reference in New Issue
Block a user