Re: [PATCH] drm/bridge: analogix_dp: Don't return -EBUSY when msg->size is 0 in aux transaction
Hi Tomasz, 在 2017/2/20 10:40, Tomasz Figa 写道: Hi Zain, On Mon, Feb 13, 2017 at 6:27 PM, zain wang <w...@rock-chips.com> wrote: The analogix_dp_transfer() will return -EBUSY if num_transferred is zero. But sometimes we will send a bare address packet to start the transaction, like drm_dp_i2c_xfer() show: .. /* Send a bare address packet to start the transaction. * Zero sized messages specify an address only (bare * address) transaction. */ msg.buffer = NULL; msg.size = 0; err = drm_dp_i2c_do_msg(aux, ); .. In this case, the msg->size is zero, so the num_transferred will be zero too. We can't return -EBUSY here, let's we return num_transferred if num_transferred equals msg->size. Please see my question inline. Signed-off-by: zain wang <w...@rock-chips.com> --- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 303083a..5384aca 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -1162,5 +1162,5 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) msg->reply = DP_AUX_NATIVE_REPLY_ACK; - return num_transferred > 0 ? num_transferred : -EBUSY; + return (num_transferred == msg->size) ? num_transferred : -EBUSY; I might be missing something but, looking at the code, I don't see any possibility of num_transferred ever being different than msg->size. To be honest, it doesn't seem to even make any sense keeping the local variable there, because msg->size can be simply always returned, as errors are handled by jumping to aux_error label. Yeah, I agree with you. The better way to fix this issue is to revert the changes https://patchwork.kernel.org/patch/9411711/ (returning num_transferred directly may be better here) Maybe we can revert the changes above with some new comment. @Sean, How do you think about Tomasz's comment? Thanks Zain Best regards, Tomasz ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
Re: [PATCH] drm/bridge: analogix_dp: Don't return -EBUSY when msg->size is 0 in aux transaction
Hi Sean, Could you give some comments for this patch? Thanks Zain 在 2017/2/13 17:27, zain wang 写道: The analogix_dp_transfer() will return -EBUSY if num_transferred is zero. But sometimes we will send a bare address packet to start the transaction, like drm_dp_i2c_xfer() show: .. /* Send a bare address packet to start the transaction. * Zero sized messages specify an address only (bare * address) transaction. */ msg.buffer = NULL; msg.size = 0; err = drm_dp_i2c_do_msg(aux, ); .. In this case, the msg->size is zero, so the num_transferred will be zero too. We can't return -EBUSY here, let's we return num_transferred if num_transferred equals msg->size. Signed-off-by: zain wang <w...@rock-chips.com> --- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 303083a..5384aca 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -1162,5 +1162,5 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) msg->reply = DP_AUX_NATIVE_REPLY_ACK; - return num_transferred > 0 ? num_transferred : -EBUSY; + return (num_transferred == msg->size) ? num_transferred : -EBUSY; } ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH] drm/bridge: analogix_dp: Don't return -EBUSY when msg->size is 0 in aux transaction
The analogix_dp_transfer() will return -EBUSY if num_transferred is zero. But sometimes we will send a bare address packet to start the transaction, like drm_dp_i2c_xfer() show: .. /* Send a bare address packet to start the transaction. * Zero sized messages specify an address only (bare * address) transaction. */ msg.buffer = NULL; msg.size = 0; err = drm_dp_i2c_do_msg(aux, ); .. In this case, the msg->size is zero, so the num_transferred will be zero too. We can't return -EBUSY here, let's we return num_transferred if num_transferred equals msg->size. Signed-off-by: zain wang <w...@rock-chips.com> --- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 303083a..5384aca 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -1162,5 +1162,5 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) msg->reply = DP_AUX_NATIVE_REPLY_ACK; - return num_transferred > 0 ? num_transferred : -EBUSY; + return (num_transferred == msg->size) ? num_transferred : -EBUSY; } -- 1.9.1 ___ dri-devel mailing list dri-devel@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/dri-devel
[PATCH v2] drm/bridge: analogix: Don't return -EINVAL when panel not support PSR in PSR functions
We will ignored PSR setting if panel not support it. So, in this case, we should return from analogix_dp_enable/disable_psr() without any error code. Let's retrun 0 instead of -EINVAL when panel not support PSR in analogix_dp_enable/disable_psr(). Signed-off-by: zain wang --- Changes in v2: - Remove dev_warn if panel not support PSR. drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 6e0447f..eb9bf87 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -112,7 +112,7 @@ int analogix_dp_enable_psr(struct device *dev) struct edp_vsc_psr psr_vsc; if (!dp->psr_support) - return -EINVAL; + return 0; /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); @@ -135,7 +135,7 @@ int analogix_dp_disable_psr(struct device *dev) struct edp_vsc_psr psr_vsc; if (!dp->psr_support) - return -EINVAL; + return 0; /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); -- 1.9.1
[PATCH] drm/bridge: analogix: Don't return -EINVAL when panel not support PSR in PSR functions
We will ignored PSR setting if panel not support it. So, in this case, we should return from analogix_dp_enable/disable_psr() without any error code. Let's retrun 0 instead of -EINVAL when panel not support PSR in analogix_dp_enable/disable_psr(). Signed-off-by: zain wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 6e0447f..0cb3695 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -112,7 +112,7 @@ int analogix_dp_enable_psr(struct device *dev) struct edp_vsc_psr psr_vsc; if (!dp->psr_support) - return -EINVAL; + return 0; /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); @@ -135,7 +135,7 @@ int analogix_dp_disable_psr(struct device *dev) struct edp_vsc_psr psr_vsc; if (!dp->psr_support) - return -EINVAL; + return 0; /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); @@ -878,6 +878,8 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) dp->psr_support = analogix_dp_detect_sink_psr(dp); if (dp->psr_support) analogix_dp_enable_sink_psr(dp); + else + dev_warn(dp->dev, "Sink not support PSR\n"); } /* -- 1.9.1
[PATCH] drm/panel: simple: add 8bit-bps for Sharp lq123p1jx31
Sharp lq123p1jx31 support 8bit bps. Signed-off-by: zain wang --- drivers/gpu/drm/panel/panel-simple.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 113db3c..6b0c026 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -1409,6 +1409,7 @@ static const struct drm_display_mode sharp_lq123p1jx31_mode = { static const struct panel_desc sharp_lq123p1jx31 = { .modes = _lq123p1jx31_mode, .num_modes = 1, + .bpc = 8, .size = { .width = 259, .height = 173, -- 1.9.1
[PATCH 6/6] drm: bridge/analogix: enable vop standby when entry PSR
From: zain wang <w...@rock-chips.com> make VOP standby when entry PSR to save some power. Signed-off-by: zain wang --- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 29 ++--- drivers/gpu/drm/rockchip/rockchip_drm_drv.h | 1 + drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 19 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 1c2d756..e0f3ed3 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -113,6 +113,13 @@ static void analogix_dp_psr_work(struct work_struct *work) if (!crtc) return; + spin_lock_irqsave(>psr_lock, flags); + psr_state = dp->psr_state; + spin_unlock_irqrestore(>psr_lock, flags); + + if (psr_state != EDP_VSC_PSR_STATE_ACTIVE) + rockchip_drm_vop_set_standby(crtc, false); + vact_end = crtc->mode.vtotal - crtc->mode.vsync_start + crtc->mode.vdisplay; ret = rockchip_drm_wait_line_flag(dp->encoder.crtc, vact_end, @@ -122,14 +129,20 @@ static void analogix_dp_psr_work(struct work_struct *work) return; } - spin_lock_irqsave(>psr_lock, flags); - psr_state = dp->psr_state; - spin_unlock_irqrestore(>psr_lock, flags); - - if (psr_state == EDP_VSC_PSR_STATE_ACTIVE) - analogix_dp_enable_psr(dp->dev); - else - analogix_dp_disable_psr(dp->dev); + if (psr_state == EDP_VSC_PSR_STATE_ACTIVE) { + ret = analogix_dp_enable_psr(dp->dev); + if (ret) { + dev_err(dp->dev, "failed to enable psr\n"); + return; + } + rockchip_drm_vop_set_standby(crtc, true); + } else { + ret = analogix_dp_disable_psr(dp->dev); + if (ret) { + dev_err(dp->dev, "failed to disable psr\n"); + return; + } + } } static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h index fb6226c..7149c69 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.h @@ -74,5 +74,6 @@ void rockchip_drm_dma_detach_device(struct drm_device *drm_dev, struct device *dev); int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, unsigned int mstimeout); +void rockchip_drm_vop_set_standby(struct drm_crtc *crtc, bool enabled); #endif /* _ROCKCHIP_DRM_DRV_H_ */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 1740a0b..13eabda 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -1478,6 +1478,25 @@ int rockchip_drm_wait_line_flag(struct drm_crtc *crtc, unsigned int line_num, } EXPORT_SYMBOL(rockchip_drm_wait_line_flag); +void rockchip_drm_vop_set_standby(struct drm_crtc *crtc, bool enabled) +{ + struct vop *vop = to_vop(crtc); + + if (!crtc || !vop->is_enabled) + return; + + spin_lock(>reg_lock); + + if (enabled) + VOP_CTRL_SET(vop, standby, 1); + else + VOP_CTRL_SET(vop, standby, 0); + + spin_unlock(>reg_lock); + +} +EXPORT_SYMBOL(rockchip_drm_vop_set_standby); + static int vop_bind(struct device *dev, struct device *master, void *data) { struct platform_device *pdev = to_platform_device(dev); -- 1.9.1
[PATCH v3 5/6] drm: bridge/analogix: add fast link train for eDP
From: zain wang <w...@rock-chips.com> we would meet a short black screen when exit PSR with the full link training, In this case, we should use fast link train instead of full link training. Signed-off-by: zain wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 89 +- drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 1 + 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 561b644..0516621 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,8 @@ #define to_dp(nm) container_of(nm, struct analogix_dp_device, nm) +static const int FAST_LINK_VERIFICATION = false; + struct bridge_init { struct i2c_client *client; struct device_node *node; @@ -244,6 +247,7 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) usleep_range(90, 120); } + /* Set training pattern 1 */ analogix_dp_set_training_pattern(dp, TRAINING_PTN1); @@ -481,7 +485,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) { int lane, lane_count, retval; u32 reg; - u8 link_align, link_status[2], adjust_request[2]; + u8 link_align, link_status[2], adjust_request[2], spread; usleep_range(400, 401); @@ -524,6 +528,12 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) dev_dbg(dp->dev, "final lane count = %.2x\n", dp->link_train.lane_count); + drm_dp_dpcd_readb(>aux, DP_MAX_DOWNSPREAD, ); + dp->fast_train_support = (spread & + DP_NO_AUX_HANDSHAKE_LINK_TRAINING) ? true : false; + dev_dbg(dp->dev, "fast link training %s\n", + dp->fast_train_support ? "supported" : "unsupported"); + /* set enhanced mode if available */ analogix_dp_set_enhanced_mode(dp); dp->link_train.lt_state = FINISHED; @@ -655,6 +665,75 @@ static int analogix_dp_sw_link_training(struct analogix_dp_device *dp) return retval; } +static int analogix_dp_full_link_train(struct analogix_dp_device *dp, + u32 count, u32 bwtype) +{ + analogix_dp_init_training(dp, count, bwtype); + return analogix_dp_sw_link_training(dp); +} + +static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) +{ + int lane; + int retval; + u8 link_align, link_status[2]; + enum pll_status status; + + analogix_dp_reset_macro(dp); + + analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); + analogix_dp_set_lane_count(dp, dp->link_train.lane_count); + + for (lane = 0; lane < dp->link_train.lane_count; lane++) { + analogix_dp_set_lane_link_training(dp, + dp->link_train.training_lane[lane], lane); + } + + retval = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, + status != PLL_UNLOCKED, + 120, 120 * DP_TIMEOUT_LOOP_COUNT); + + if (retval) + return retval; + + /* source Set training pattern 1 */ + analogix_dp_set_training_pattern(dp, TRAINING_PTN1); + usleep_range(500, 600); + + analogix_dp_set_training_pattern(dp, TRAINING_PTN2); + usleep_range(500, 600); + + /* TODO: enhanced_mode?*/ + analogix_dp_set_training_pattern(dp, DP_NONE); + + if (FAST_LINK_VERIFICATION) { + retval = drm_dp_dpcd_readb(>aux, + DP_LANE_ALIGN_STATUS_UPDATED, + _align); + if (retval < 0) + return retval; + + retval = drm_dp_dpcd_read(>aux, DP_LANE0_1_STATUS, + link_status, 2); + if (retval < 0) + return retval; + + if (analogix_dp_clock_recovery_ok(link_status, + dp->link_train.lane_count)) { + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + + if (analogix_dp_channel_eq_ok(link_status, link_align, + dp->link_train.lane_count)) { + analogix_dp_reduce_link_rate(dp); + return -EIO; + } + } + + return 0; +} + static int analogix_dp_set_link_train(struct analogix_dp_devi
[PATCH v3 4/6] drm: bridge/analogix: switch Main-link and eDP PHY when enable/disable psr
From: zain wang <w...@rock-chips.com> turn off Main-link and power down eDP PHY when enable psr, turn on Main-link and power up eDP PHY when disable psr. Signed-off-by: zain wang --- Changes in v3: - detecting PSR state at enable/disable_psr() avoid to make link training when sink in not PSR State. Changes in v2: - misc changes drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 123 + 1 file changed, 76 insertions(+), 47 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index c4f139a..c662e5d 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,50 +98,6 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_enable_psr(struct device *dev) -{ - struct analogix_dp_device *dp = dev_get_drvdata(dev); - struct edp_vsc_psr psr_vsc; - - if (!dp->psr_support) - return -EINVAL; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - - return analogix_dp_send_psr_spd(dp, _vsc); -} -EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); - -int analogix_dp_disable_psr(struct device *dev) -{ - struct analogix_dp_device *dp = dev_get_drvdata(dev); - struct edp_vsc_psr psr_vsc; - - if (!dp->psr_support) - return -EINVAL; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = 0; - - return analogix_dp_send_psr_spd(dp, _vsc); -} -EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); - static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) { unsigned char psr_version; @@ -162,12 +118,11 @@ static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); /* Main-Link transmitter remains active during PSR active states */ - psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_CRC_VERIFICATION; drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); /* Enable psr function */ - psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE | -DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_ENABLE | DP_PSR_CRC_VERIFICATION; drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); analogix_dp_enable_psr_crc(dp); @@ -870,6 +825,80 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) analogix_dp_enable_sink_psr(dp); } +int analogix_dp_enable_psr(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + struct edp_vsc_psr psr_vsc; + int retval; + u8 sink; + + if (!dp->psr_support) + return -EINVAL; + + drm_dp_dpcd_readb(>aux, DP_PSR_STATUS, ); + if (sink == DP_PSR_SINK_ACTIVE_RFB) + return 0; + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + + psr_vsc.DB0 = 0; + psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; + + retval = analogix_dp_send_psr_spd(dp, _vsc); + + if (!retval) { + /* Power down the eDP PHY */ + analogix_dp_set_analog_power_down(dp, POWER_ALL, true); + } + + return retval; +} +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); + +int analogix_dp_disable_psr(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + struct edp_vsc_psr psr_vsc; + int ret; + u8 sink; + + if (!dp->psr_support) + return -EINVAL; + + /* Power up the eDP PHY */ + analogix_dp_set_analog_power_down(dp, POWER_ALL, false); + + drm_dp_dpcd_readb(>aux, DP_PSR_STATUS, ); + if (sink == DP_PSR_SINK_INACTIVE) + return 0; + + ret = drm_dp_dpcd_writeb(>aux, DP_SET_POWER, DP_SET_POWER_D0); + if (ret < 0) { + dev_err(dp->dev, "Failed to set DP Power0\n"); + } + + analogix_dp_set_link_train(dp, dp->video_info.max_lane_count, + dp->video_info.max_link_rate); + + /* Prepare VSC packet as per EDP 1.4
[PATCH v3 3/6] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR
From: Yakir Yang <y...@rock-chips.com> Make sure the request PSR state takes effect in analogix_dp_send_psr_spd() function, or print the sink PSR error state if we failed to apply the requested PSR setting. Signed-off-by: zain wang Signed-off-by: Yakir Yang --- Changes in v3: None Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 6 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 6 -- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 -- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 6 -- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index bcae4dd..7faad93 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -124,8 +124,7 @@ int analogix_dp_enable_psr(struct device *dev) psr_vsc.DB0 = 0; psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - analogix_dp_send_psr_spd(dp, _vsc); - return 0; + return analogix_dp_send_psr_spd(dp, _vsc); } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); @@ -147,8 +146,7 @@ int analogix_dp_disable_psr(struct device *dev) psr_vsc.DB0 = 0; psr_vsc.DB1 = 0; - analogix_dp_send_psr_spd(dp, _vsc); - return 0; + return analogix_dp_send_psr_spd(dp, _vsc); } EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 5c6a288..cdc0535 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -20,6 +20,8 @@ #define MAX_CR_LOOP 5 #define MAX_EQ_LOOP 5 +#define DP_TIMEOUT_PSR_LOOP_MS msecs_to_jiffies(300) + /* DP_MAX_LANE_COUNT */ #define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) #define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) @@ -247,8 +249,8 @@ void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp); -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, - struct edp_vsc_psr *vsc); +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, +struct edp_vsc_psr *vsc); ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, struct drm_dp_aux_msg *msg); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index cd37ac0..9e1177c 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -992,10 +992,12 @@ void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp) writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON); } -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, - struct edp_vsc_psr *vsc) +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, +struct edp_vsc_psr *vsc) { + unsigned long timeout; unsigned int val; + u8 sink; /* don't send info frame */ val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); @@ -1036,6 +1038,25 @@ void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); val |= IF_EN; writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); + + timeout = jiffies + DP_TIMEOUT_PSR_LOOP_MS; + while (time_before(jiffies, timeout)) { + val = drm_dp_dpcd_readb(>aux, DP_PSR_STATUS, ); + if (val != 1) { + dev_err(dp->dev, "PSR_STATUS read failed ret=%d", val); + return -EBUSY; + } + + if ((vsc->DB1 && sink == DP_PSR_SINK_ACTIVE_RFB) || + (!vsc->DB1 && sink == DP_PSR_SINK_INACTIVE)) + return 0; + + usleep_range(1000, 1500); + } + + dev_warn(dp->dev, "Failed to apply PSR, sink state was [%x]", sink); + + return -ETIMEDOUT; } ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index e5471e7..1c2d756 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -105,7 +105,7 @@ static void analogix_dp_psr_work(struct work_struct *work) struct rockchip_dp_device *dp = containe
[PATCH v3 2/6] drm/bridge: remove dp init from analogix_dp_bind
From: zain wang <w...@rock-chips.com> phy_power_on() and analogix_dp_init_dp would be called in bridge_eanble, so remove them from analogix_dp_bind to be clear. Signed-off-by: zain wang --- Changes in v3: - remove changes before - remove phy_power_on() and analogix_dp_init_dp from analogix_dp_bind(). Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 4 1 file changed, 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 001b075..bcae4dd 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1389,10 +1389,6 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, pm_runtime_enable(dev); - phy_power_on(dp->phy); - - analogix_dp_init_dp(dp); - ret = devm_request_threaded_irq(>dev, dp->irq, analogix_dp_hardirq, analogix_dp_irq_thread, -- 1.9.1
[PATCH v3 1/6] drm/bridge: analogix_dp: set psr activate/deactivate when enable/disable bridge
From: zain wang <w...@rock-chips.com> There's a race between when bridge_disable and when vop_crtc_disable are called. If the flush timer triggers a new psr work between these, we will operate eDP without power shutdowned by bridge_disable. In this case, moving activate/deactivate to enable/disable bridge to avoid it. Signed-off-by: zain wang --- Changes in v3: - remove changes before. - move psr activat/deactivate to enable/disable bridge. Changes in v2: - add spin_lock to protect dpms_mode drivers/gpu/drm/rockchip/analogix_dp-rockchip.c | 4 ++-- drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 30 - drivers/gpu/drm/rockchip/rockchip_drm_psr.h | 4 ++-- drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 4 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 8548e82..e5471e7 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -159,7 +159,7 @@ static int rockchip_dp_poweron(struct analogix_dp_plat_data *plat_data) return ret; } - return 0; + return rockchip_drm_psr_activate(>encoder); } static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) @@ -168,7 +168,7 @@ static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) clk_disable_unprepare(dp->pclk); - return 0; + return rockchip_drm_psr_deactivate(>encoder); } static int rockchip_dp_get_modes(struct analogix_dp_plat_data *plat_data, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c index a553e18..4c379e9 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c @@ -57,6 +57,24 @@ out: return psr; } +static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder) +{ + struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; + struct psr_drv *psr; + unsigned long flags; + + spin_lock_irqsave(_drv->psr_list_lock, flags); + list_for_each_entry(psr, _drv->psr_list, list) { + if (psr->encoder == encoder) + goto out; + } + psr = ERR_PTR(-ENODEV); + +out: + spin_unlock_irqrestore(_drv->psr_list_lock, flags); + return psr; +} + static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state) { /* @@ -115,14 +133,14 @@ static void psr_flush_handler(unsigned long data) /** * rockchip_drm_psr_activate - activate PSR on the given pipe - * @crtc: CRTC to obtain the PSR encoder + * @encoder: encoder to obtain the PSR encoder * * Returns: * Zero on success, negative errno on failure. */ -int rockchip_drm_psr_activate(struct drm_crtc *crtc) +int rockchip_drm_psr_activate(struct drm_encoder *encoder) { - struct psr_drv *psr = find_psr_by_crtc(crtc); + struct psr_drv *psr = find_psr_by_encoder(encoder); unsigned long flags; if (IS_ERR(psr)) @@ -138,14 +156,14 @@ EXPORT_SYMBOL(rockchip_drm_psr_activate); /** * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe - * @crtc: CRTC to obtain the PSR encoder + * @encoder: encoder to obtain the PSR encoder * * Returns: * Zero on success, negative errno on failure. */ -int rockchip_drm_psr_deactivate(struct drm_crtc *crtc) +int rockchip_drm_psr_deactivate(struct drm_encoder *encoder) { - struct psr_drv *psr = find_psr_by_crtc(crtc); + struct psr_drv *psr = find_psr_by_encoder(encoder); unsigned long flags; if (IS_ERR(psr)) diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h index b420cf1..b1ea015 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h @@ -18,8 +18,8 @@ void rockchip_drm_psr_flush_all(struct drm_device *dev); int rockchip_drm_psr_flush(struct drm_crtc *crtc); -int rockchip_drm_psr_activate(struct drm_crtc *crtc); -int rockchip_drm_psr_deactivate(struct drm_crtc *crtc); +int rockchip_drm_psr_activate(struct drm_encoder *encoder); +int rockchip_drm_psr_deactivate(struct drm_encoder *encoder); int rockchip_drm_psr_register(struct drm_encoder *encoder, void (*psr_set)(struct drm_encoder *, bool enable)); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index c7eba30..1740a0b 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -566,8 +566,6 @@ static void vop_crtc_disable(struct drm_crtc *crtc) WARN_ON(vop->event); - rockchip_drm_psr_deactivate(>crtc); - /* * We need to make sure that all windows are disabled before we * disable that crtc. Otherwis
[PATCH v3 0/6] Misc changes to Rockchip PSR drivers
This serise of patches works for saving power on eDP PHY and VOP during PSR. BR, - Zain Changes in v3: - add new patch to support fast link training. - add new patch to make VOP standby when entry PSR. - Misc changes. Changes in v2: - add spin_lock to protect dpms_mode - misc changes. Yakir Yang (1): drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR zain wang (5): drm/bridge: analogix_dp: set psr activate/deactivate when enable/disable bridge drm/bridge: remove dp init from analogix_dp_bind drm: bridge/analogix: switch Main-link and eDP PHY when enable/disable psr drm: bridge/analogix: add fast link train for eDP drm: bridge/analogix: enable vop standby when entry PSR drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 218 +++-- drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 7 +- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 ++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 33 +++- drivers/gpu/drm/rockchip/rockchip_drm_drv.h| 1 + drivers/gpu/drm/rockchip/rockchip_drm_psr.c| 30 ++- drivers/gpu/drm/rockchip/rockchip_drm_psr.h| 4 +- drivers/gpu/drm/rockchip/rockchip_drm_vop.c| 23 ++- 8 files changed, 259 insertions(+), 82 deletions(-) -- 1.9.1
[PATCH v2 4/4] drm: bridge/analogix: switch Main-link and eDP PHY when enable/disable psr
turn off Main-link and power down eDP PHY when enable psr, turn on Main-link and power up eDP PHY when disable psr. Signed-off-by: zain wang --- Changes in v2: - misc changes drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 124 - 1 file changed, 70 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index bf87891..58fa1c1 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -120,57 +120,6 @@ static int analogix_dp_get_dpms_mode(struct analogix_dp_device *dp) return mode; } - -int analogix_dp_enable_psr(struct device *dev) -{ - struct analogix_dp_device *dp = dev_get_drvdata(dev); - struct edp_vsc_psr psr_vsc; - - if (!dp->psr_support) - return -EINVAL; - - if (analogix_dp_get_dpms_mode(dp) != DRM_MODE_DPMS_ON) - return -EBUSY; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - - return analogix_dp_send_psr_spd(dp, _vsc); -} -EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); - -int analogix_dp_disable_psr(struct device *dev) -{ - struct analogix_dp_device *dp = dev_get_drvdata(dev); - struct edp_vsc_psr psr_vsc; - - if (!dp->psr_support) - return -EINVAL; - - if (analogix_dp_get_dpms_mode(dp) != DRM_MODE_DPMS_ON) - return -EBUSY; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = 0; - - return analogix_dp_send_psr_spd(dp, _vsc); -} -EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); - static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) { unsigned char psr_version; @@ -191,12 +140,11 @@ static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); /* Main-Link transmitter remains active during PSR active states */ - psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_CRC_VERIFICATION; drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); /* Enable psr function */ - psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE | -DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_ENABLE | DP_PSR_CRC_VERIFICATION; drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); analogix_dp_enable_psr_crc(dp); @@ -899,6 +847,74 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) analogix_dp_enable_sink_psr(dp); } +int analogix_dp_enable_psr(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + struct edp_vsc_psr psr_vsc; + + if (!dp->psr_support) + return -EINVAL; + + if (analogix_dp_get_dpms_mode(dp) != DRM_MODE_DPMS_ON) + return -EBUSY; + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + + psr_vsc.DB0 = 0; + psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; + + analogix_dp_send_psr_spd(dp, _vsc); + + /* Power down the eDP PHY */ + analogix_dp_set_analog_power_down(dp, POWER_ALL, true); + + return 0; +} +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); + +int analogix_dp_disable_psr(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + struct edp_vsc_psr psr_vsc; + int ret; + + if (!dp->psr_support) + return -EINVAL; + + if (analogix_dp_get_dpms_mode(dp) != DRM_MODE_DPMS_ON) + return -EBUSY; + + /* Power up the eDP PHY */ + analogix_dp_set_analog_power_down(dp, POWER_ALL, false); + + ret = drm_dp_dpcd_writeb(>aux, DP_SET_POWER, DP_SET_POWER_D0); + if (ret < 0) { + dev_err(dp->dev, "Failed to set DP Power0\n"); + } + + analogix_dp_set_link_train(dp, dp->video_info.max_lane_count, + dp->video_info.max_link_rate); + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.H
[PATCH v2 3/4] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR
From: Yakir Yang <y...@rock-chips.com> Make sure the request PSR state takes effect in analogix_dp_send_psr_spd() function, or print the sink PSR error state if we failed to apply the requested PSR setting. Signed-off-by: Yakir Yang Signed-off-by: Zain Wang --- Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 6 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 6 -- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 -- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 8 --- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 1bd190e..bf87891 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -142,8 +142,7 @@ int analogix_dp_enable_psr(struct device *dev) psr_vsc.DB0 = 0; psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - analogix_dp_send_psr_spd(dp, _vsc); - return 0; + return analogix_dp_send_psr_spd(dp, _vsc); } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); @@ -168,8 +167,7 @@ int analogix_dp_disable_psr(struct device *dev) psr_vsc.DB0 = 0; psr_vsc.DB1 = 0; - analogix_dp_send_psr_spd(dp, _vsc); - return 0; + return analogix_dp_send_psr_spd(dp, _vsc); } EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 776c844..553c411 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -20,6 +20,8 @@ #define MAX_CR_LOOP 5 #define MAX_EQ_LOOP 5 +#define DP_TIMEOUT_PSR_LOOP_MS msecs_to_jiffies(300) + /* DP_MAX_LANE_COUNT */ #define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) #define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) @@ -248,8 +250,8 @@ void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp); -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, - struct edp_vsc_psr *vsc); +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, +struct edp_vsc_psr *vsc); ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, struct drm_dp_aux_msg *msg); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index cd37ac0..9e1177c 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -992,10 +992,12 @@ void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp) writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON); } -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, - struct edp_vsc_psr *vsc) +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, +struct edp_vsc_psr *vsc) { + unsigned long timeout; unsigned int val; + u8 sink; /* don't send info frame */ val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); @@ -1036,6 +1038,25 @@ void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); val |= IF_EN; writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); + + timeout = jiffies + DP_TIMEOUT_PSR_LOOP_MS; + while (time_before(jiffies, timeout)) { + val = drm_dp_dpcd_readb(>aux, DP_PSR_STATUS, ); + if (val != 1) { + dev_err(dp->dev, "PSR_STATUS read failed ret=%d", val); + return -EBUSY; + } + + if ((vsc->DB1 && sink == DP_PSR_SINK_ACTIVE_RFB) || + (!vsc->DB1 && sink == DP_PSR_SINK_INACTIVE)) + return 0; + + usleep_range(1000, 1500); + } + + dev_warn(dp->dev, "Failed to apply PSR, sink state was [%x]", sink); + + return -ETIMEDOUT; } ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index e83be15..dc106d0 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -102,10 +102,10 @@ static void analogix_dp_psr_work(struct work_struct *work) struct rockchip_dp_device *dp = container_of(work, ty
[PATCH v2 2/4] drm/bridge: analogix_dp: get sync PM when init eDP
Signed-off-by: zain wang --- Changes in v2: None drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index b4ce16a..1bd190e 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1411,10 +1411,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, } pm_runtime_enable(dev); + pm_runtime_get_sync(dev); phy_power_on(dp->phy); analogix_dp_init_dp(dp); + pm_runtime_put_sync(dev); ret = devm_request_threaded_irq(>dev, dp->irq, analogix_dp_hardirq, -- 1.9.1
[PATCH v2 1/4] drm/bridge: analogix_dp: prevent runing enable_psr when disabled bridge.
When disabled bridge, analogix_dp_enable_psr() may run due to timer was set by rockchip_drm_do_flush(), in this case we should return -EBUSY. Signed-off-by: zain wang --- Changes in v2: - add spin_lock to protect dpms_mode drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 43 +++--- drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 1 + 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 0f2e423..b4ce16a 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,6 +98,29 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } +static void analogix_dp_set_dpms_mode(struct analogix_dp_device *dp, int mode) +{ + unsigned long flags; + + spin_lock_irqsave(>dpms_mode_lock, flags); + dp->dpms_mode = mode; + spin_unlock_irqrestore(>dpms_mode_lock, flags); + +} + +static int analogix_dp_get_dpms_mode(struct analogix_dp_device *dp) +{ + unsigned long flags; + int mode; + + spin_lock_irqsave(>dpms_mode_lock, flags); + mode = dp->dpms_mode; + spin_unlock_irqrestore(>dpms_mode_lock, flags); + + return mode; +} + + int analogix_dp_enable_psr(struct device *dev) { struct analogix_dp_device *dp = dev_get_drvdata(dev); @@ -106,6 +129,9 @@ int analogix_dp_enable_psr(struct device *dev) if (!dp->psr_support) return -EINVAL; + if (analogix_dp_get_dpms_mode(dp) != DRM_MODE_DPMS_ON) + return -EBUSY; + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; @@ -129,6 +155,9 @@ int analogix_dp_disable_psr(struct device *dev) if (!dp->psr_support) return -EINVAL; + if (analogix_dp_get_dpms_mode(dp) != DRM_MODE_DPMS_ON) + return -EBUSY; + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; @@ -1073,7 +1102,7 @@ static void analogix_dp_bridge_enable(struct drm_bridge *bridge) { struct analogix_dp_device *dp = bridge->driver_private; - if (dp->dpms_mode == DRM_MODE_DPMS_ON) + if (analogix_dp_get_dpms_mode(dp) == DRM_MODE_DPMS_ON) return; pm_runtime_get_sync(dp->dev); @@ -1086,7 +1115,7 @@ static void analogix_dp_bridge_enable(struct drm_bridge *bridge) enable_irq(dp->irq); analogix_dp_commit(dp); - dp->dpms_mode = DRM_MODE_DPMS_ON; + analogix_dp_set_dpms_mode(dp, DRM_MODE_DPMS_ON); } static void analogix_dp_bridge_disable(struct drm_bridge *bridge) @@ -1094,9 +1123,11 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) struct analogix_dp_device *dp = bridge->driver_private; int ret; - if (dp->dpms_mode != DRM_MODE_DPMS_ON) + if (analogix_dp_get_dpms_mode(dp) != DRM_MODE_DPMS_ON) return; + analogix_dp_set_dpms_mode(dp, DRM_MODE_DPMS_OFF); + if (dp->plat_data->panel) { if (drm_panel_disable(dp->plat_data->panel)) { DRM_ERROR("failed to disable the panel\n"); @@ -1115,8 +1146,6 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) ret = analogix_dp_prepare_panel(dp, false, true); if (ret) DRM_ERROR("failed to setup the panel ret = %d\n", ret); - - dp->dpms_mode = DRM_MODE_DPMS_OFF; } static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, @@ -1299,7 +1328,9 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, dev_set_drvdata(dev, dp); dp->dev = >dev; - dp->dpms_mode = DRM_MODE_DPMS_OFF; + + spin_lock_init(>dpms_mode_lock); + analogix_dp_set_dpms_mode(dp, DRM_MODE_DPMS_OFF); mutex_init(>panel_lock); dp->panel_is_modeset = false; diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 5c6a288..776c844 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -166,6 +166,7 @@ struct analogix_dp_device { struct link_train link_train; struct phy *phy; int dpms_mode; + spinlock_t dpms_mode_lock; int hpd_gpio; boolforce_hpd; boolpsr_support; -- 1.9.1
[PATCH v2 0/4] Misc changes to Rockchip PSR drivers
1. prevent runing enable_psr when disabled bridge 2. get sync PM when init eDP 3. detect Sink PSR state after configuring the PSR 4. switch Main-Link and eDP phy when enable/disable psr BR, - Zain Changes in v2: - add spin_lock to protect dpms_mode - misc changes Yakir Yang (1): drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR zain wang (3): drm/bridge: analogix_dp: prevent runing enable_psr when disabled bridge. drm/bridge: analogix_dp: get sync PM when init eDP drm: bridge/analogix: switch Main-link and eDP PHY when enable/disable psr drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 137 ++--- drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 7 +- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 +++- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 8 +- 4 files changed, 125 insertions(+), 52 deletions(-) -- 1.9.1
[PATCH v1 4/4] drm: bridge/analogix: switch Main-link and eDP PHY when enable/disable psr
turn off Main-link and power down eDP PHY when enable psr, turn on Main-link and power up eDP PHY when disable psr. Signed-off-by: zain wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 105 ++--- 1 file changed, 52 insertions(+), 53 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 7177f5f..1bc98ab 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -98,56 +98,6 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_enable_psr(struct device *dev) -{ - struct analogix_dp_device *dp = dev_get_drvdata(dev); - struct edp_vsc_psr psr_vsc; - - if (!dp->psr_support) - return -EINVAL; - - if (dp->dpms_mode != DRM_MODE_DPMS_ON) - return -EBUSY; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - - return analogix_dp_send_psr_spd(dp, _vsc); -} -EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); - -int analogix_dp_disable_psr(struct device *dev) -{ - struct analogix_dp_device *dp = dev_get_drvdata(dev); - struct edp_vsc_psr psr_vsc; - - if (!dp->psr_support) - return -EINVAL; - - if (dp->dpms_mode != DRM_MODE_DPMS_ON) - return -EBUSY; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.DB0 = 0; - psr_vsc.DB1 = 0; - - return analogix_dp_send_psr_spd(dp, _vsc); -} -EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); - static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) { unsigned char psr_version; @@ -168,12 +118,11 @@ static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); /* Main-Link transmitter remains active during PSR active states */ - psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_CRC_VERIFICATION; drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); /* Enable psr function */ - psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE | -DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_ENABLE | DP_PSR_CRC_VERIFICATION; drm_dp_dpcd_writeb(>aux, DP_PSR_EN_CFG, psr_en); analogix_dp_enable_psr_crc(dp); @@ -876,6 +825,56 @@ static void analogix_dp_commit(struct analogix_dp_device *dp) analogix_dp_enable_sink_psr(dp); } +int analogix_dp_enable_psr(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + struct edp_vsc_psr psr_vsc; + + if (!dp->psr_support) + return -EINVAL; + + if (dp->dpms_mode != DRM_MODE_DPMS_ON) + return -EBUSY; + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + + psr_vsc.DB0 = 0; + psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; + + return analogix_dp_send_psr_spd(dp, _vsc); +} +EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); + +int analogix_dp_disable_psr(struct device *dev) +{ + struct analogix_dp_device *dp = dev_get_drvdata(dev); + struct edp_vsc_psr psr_vsc; + + if (!dp->psr_support) + return -EINVAL; + + if (dp->dpms_mode != DRM_MODE_DPMS_ON) + return -EBUSY; + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + + psr_vsc.DB0 = 0; + psr_vsc.DB1 = 0; + + return analogix_dp_send_psr_spd(dp, _vsc); +} +EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); + /* * This function is a bit of a catch-all for panel preparation, hopefully * simplifying the logic of functions that need to prepare/unprepare the panel -- 1.9.1
[PATCH v1 3/4] drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR
From: Yakir Yang <y...@rock-chips.com> Make sure the request PSR state takes effect in analogix_dp_send_psr_spd() function, or print the sink PSR error state if we failed to apply the requested PSR setting. Signed-off-by: Yakir Yang Signed-off-by: Zain Wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 6 ++ drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 6 -- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 -- drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 8 --- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 026ec91..7177f5f 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -119,8 +119,7 @@ int analogix_dp_enable_psr(struct device *dev) psr_vsc.DB0 = 0; psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - analogix_dp_send_psr_spd(dp, _vsc); - return 0; + return analogix_dp_send_psr_spd(dp, _vsc); } EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); @@ -145,8 +144,7 @@ int analogix_dp_disable_psr(struct device *dev) psr_vsc.DB0 = 0; psr_vsc.DB1 = 0; - analogix_dp_send_psr_spd(dp, _vsc); - return 0; + return analogix_dp_send_psr_spd(dp, _vsc); } EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 5c6a288..cdc0535 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -20,6 +20,8 @@ #define MAX_CR_LOOP 5 #define MAX_EQ_LOOP 5 +#define DP_TIMEOUT_PSR_LOOP_MS msecs_to_jiffies(300) + /* DP_MAX_LANE_COUNT */ #define DPCD_ENHANCED_FRAME_CAP(x) (((x) >> 7) & 0x1) #define DPCD_MAX_LANE_COUNT(x) ((x) & 0x1f) @@ -247,8 +249,8 @@ void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp); -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, - struct edp_vsc_psr *vsc); +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, +struct edp_vsc_psr *vsc); ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, struct drm_dp_aux_msg *msg); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index cd37ac0..9e1177c 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -992,10 +992,12 @@ void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp) writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON); } -void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, - struct edp_vsc_psr *vsc) +int analogix_dp_send_psr_spd(struct analogix_dp_device *dp, +struct edp_vsc_psr *vsc) { + unsigned long timeout; unsigned int val; + u8 sink; /* don't send info frame */ val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); @@ -1036,6 +1038,25 @@ void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); val |= IF_EN; writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); + + timeout = jiffies + DP_TIMEOUT_PSR_LOOP_MS; + while (time_before(jiffies, timeout)) { + val = drm_dp_dpcd_readb(>aux, DP_PSR_STATUS, ); + if (val != 1) { + dev_err(dp->dev, "PSR_STATUS read failed ret=%d", val); + return -EBUSY; + } + + if ((vsc->DB1 && sink == DP_PSR_SINK_ACTIVE_RFB) || + (!vsc->DB1 && sink == DP_PSR_SINK_INACTIVE)) + return 0; + + usleep_range(1000, 1500); + } + + dev_warn(dp->dev, "Failed to apply PSR, sink state was [%x]", sink); + + return -ETIMEDOUT; } ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index e83be15..dc106d0 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -102,10 +102,10 @@ static void analogix_dp_psr_work(struct work_struct *work) struct rockchip_dp_device *dp = container_of(work, typeof(*dp), psr_work);
[PATCH v1 2/4] drm/bridge: analogix_dp: get sync PM when init eDP
Signed-off-by: zain wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 206529a..026ec91 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -1386,10 +1386,12 @@ int analogix_dp_bind(struct device *dev, struct drm_device *drm_dev, } pm_runtime_enable(dev); + pm_runtime_get_sync(dev); phy_power_on(dp->phy); analogix_dp_init_dp(dp); + pm_runtime_put_sync(dev); ret = devm_request_threaded_irq(>dev, dp->irq, analogix_dp_hardirq, -- 1.9.1
[PATCH v1 1/4] drm/bridge: analogix_dp: prevent runing enable_psr when disabled bridge.
When disabled bridge, analogix_dp_enable_psr() may run due to timer was set by rockchip_drm_do_flush(), in this case we should return -EBUSY. Signed-off-by: zain wang --- drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 0f2e423..206529a 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -106,6 +106,9 @@ int analogix_dp_enable_psr(struct device *dev) if (!dp->psr_support) return -EINVAL; + if (dp->dpms_mode != DRM_MODE_DPMS_ON) + return -EBUSY; + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; @@ -129,6 +132,9 @@ int analogix_dp_disable_psr(struct device *dev) if (!dp->psr_support) return -EINVAL; + if (dp->dpms_mode != DRM_MODE_DPMS_ON) + return -EBUSY; + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ memset(_vsc, 0, sizeof(psr_vsc)); psr_vsc.sdp_header.HB0 = 0; @@ -1097,6 +1103,8 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) if (dp->dpms_mode != DRM_MODE_DPMS_ON) return; + dp->dpms_mode = DRM_MODE_DPMS_OFF; + if (dp->plat_data->panel) { if (drm_panel_disable(dp->plat_data->panel)) { DRM_ERROR("failed to disable the panel\n"); @@ -1115,8 +1123,6 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) ret = analogix_dp_prepare_panel(dp, false, true); if (ret) DRM_ERROR("failed to setup the panel ret = %d\n", ret); - - dp->dpms_mode = DRM_MODE_DPMS_OFF; } static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, -- 1.9.1
[PATCH v1 0/4] Misc changes to Rockchip PSR drivers
1. prevent runing enable_psr when disabled bridge 2. get sync PM when init eDP 3. detect Sink PSR state after configuring the PSR 4. switch Main-Link and eDP phy when enable/disable psr BR, - Zain Yakir Yang (1): drm/bridge: analogix_dp: detect Sink PSR state after configuring the PSR zain wang (3): drm/bridge: analogix_dp: prevent runing enable_psr when disabled bridge. drm/bridge: analogix_dp: get sync PM when init eDP drm: bridge/analogix: switch Main-link and eDP PHY when enable/disable psr drivers/gpu/drm/bridge/analogix/analogix_dp_core.c | 107 +++-- drivers/gpu/drm/bridge/analogix/analogix_dp_core.h | 6 +- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 25 - drivers/gpu/drm/rockchip/analogix_dp-rockchip.c| 8 +- 4 files changed, 88 insertions(+), 58 deletions(-) -- 1.9.1