Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/bridge: analogix_dp: add the PSR function support

The full name of PSR is Panel Self Refresh, panel device could refresh
itself with the hardware framebuffer in panel, this would make lots of
sense to save the power consumption.

This patch have exported two symbols for platform driver to implement
the PSR function in hardware side:
- analogix_dp_active_psr()
- analogix_dp_inactive_psr()

Reviewed-by: Archit Taneja <architt@codeaurora.org>
Signed-off-by: Yakir Yang <ykk@rock-chips.com>
Signed-off-by: Sean Paul <seanpaul@chromium.org>

authored by

Yakir Yang and committed by
Sean Paul
5b3f84f2 5182c1a5

+174
+81
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c
··· 97 97 return 0; 98 98 } 99 99 100 + int analogix_dp_enable_psr(struct device *dev) 101 + { 102 + struct analogix_dp_device *dp = dev_get_drvdata(dev); 103 + struct edp_vsc_psr psr_vsc; 104 + 105 + if (!dp->psr_support) 106 + return -EINVAL; 107 + 108 + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ 109 + memset(&psr_vsc, 0, sizeof(psr_vsc)); 110 + psr_vsc.sdp_header.HB0 = 0; 111 + psr_vsc.sdp_header.HB1 = 0x7; 112 + psr_vsc.sdp_header.HB2 = 0x2; 113 + psr_vsc.sdp_header.HB3 = 0x8; 114 + 115 + psr_vsc.DB0 = 0; 116 + psr_vsc.DB1 = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; 117 + 118 + analogix_dp_send_psr_spd(dp, &psr_vsc); 119 + return 0; 120 + } 121 + EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); 122 + 123 + int analogix_dp_disable_psr(struct device *dev) 124 + { 125 + struct analogix_dp_device *dp = dev_get_drvdata(dev); 126 + struct edp_vsc_psr psr_vsc; 127 + 128 + if (!dp->psr_support) 129 + return -EINVAL; 130 + 131 + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ 132 + memset(&psr_vsc, 0, sizeof(psr_vsc)); 133 + psr_vsc.sdp_header.HB0 = 0; 134 + psr_vsc.sdp_header.HB1 = 0x7; 135 + psr_vsc.sdp_header.HB2 = 0x2; 136 + psr_vsc.sdp_header.HB3 = 0x8; 137 + 138 + psr_vsc.DB0 = 0; 139 + psr_vsc.DB1 = 0; 140 + 141 + analogix_dp_send_psr_spd(dp, &psr_vsc); 142 + return 0; 143 + } 144 + EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); 145 + 146 + static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) 147 + { 148 + unsigned char psr_version; 149 + 150 + analogix_dp_read_byte_from_dpcd(dp, DP_PSR_SUPPORT, &psr_version); 151 + dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version); 152 + 153 + return (psr_version & DP_PSR_IS_SUPPORTED) ? true : false; 154 + } 155 + 156 + static void analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) 157 + { 158 + unsigned char psr_en; 159 + 160 + /* Disable psr function */ 161 + analogix_dp_read_byte_from_dpcd(dp, DP_PSR_EN_CFG, &psr_en); 162 + psr_en &= ~DP_PSR_ENABLE; 163 + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en); 164 + 165 + /* Main-Link transmitter remains active during PSR active states */ 166 + psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION; 167 + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en); 168 + 169 + /* Enable psr function */ 170 + psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE | 171 + DP_PSR_CRC_VERIFICATION; 172 + analogix_dp_write_byte_to_dpcd(dp, DP_PSR_EN_CFG, psr_en); 173 + 174 + analogix_dp_enable_psr_crc(dp); 175 + } 176 + 100 177 static unsigned char analogix_dp_calc_edid_check_sum(unsigned char *edid_data) 101 178 { 102 179 int i; ··· 998 921 999 922 /* Enable video */ 1000 923 analogix_dp_start_video(dp); 924 + 925 + dp->psr_support = analogix_dp_detect_sink_psr(dp); 926 + if (dp->psr_support) 927 + analogix_dp_enable_sink_psr(dp); 1001 928 } 1002 929 1003 930 /*
+5
drivers/gpu/drm/bridge/analogix/analogix_dp_core.h
··· 177 177 int hpd_gpio; 178 178 bool force_hpd; 179 179 unsigned char edid[EDID_BLOCK_LENGTH * 2]; 180 + bool psr_support; 180 181 181 182 struct mutex panel_lock; 182 183 bool panel_is_modeset; ··· 282 281 void analogix_dp_config_video_slave_mode(struct analogix_dp_device *dp); 283 282 void analogix_dp_enable_scrambling(struct analogix_dp_device *dp); 284 283 void analogix_dp_disable_scrambling(struct analogix_dp_device *dp); 284 + void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp); 285 + void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, 286 + struct edp_vsc_psr *vsc); 287 + 285 288 #endif /* _ANALOGIX_DP_CORE_H */
+51
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c
··· 1322 1322 reg |= SCRAMBLING_DISABLE; 1323 1323 writel(reg, dp->reg_base + ANALOGIX_DP_TRAINING_PTN_SET); 1324 1324 } 1325 + 1326 + void analogix_dp_enable_psr_crc(struct analogix_dp_device *dp) 1327 + { 1328 + writel(PSR_VID_CRC_ENABLE, dp->reg_base + ANALOGIX_DP_CRC_CON); 1329 + } 1330 + 1331 + void analogix_dp_send_psr_spd(struct analogix_dp_device *dp, 1332 + struct edp_vsc_psr *vsc) 1333 + { 1334 + unsigned int val; 1335 + 1336 + /* don't send info frame */ 1337 + val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); 1338 + val &= ~IF_EN; 1339 + writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); 1340 + 1341 + /* configure single frame update mode */ 1342 + writel(PSR_FRAME_UP_TYPE_BURST | PSR_CRC_SEL_HARDWARE, 1343 + dp->reg_base + ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL); 1344 + 1345 + /* configure VSC HB0~HB3 */ 1346 + writel(vsc->sdp_header.HB0, dp->reg_base + ANALOGIX_DP_SPD_HB0); 1347 + writel(vsc->sdp_header.HB1, dp->reg_base + ANALOGIX_DP_SPD_HB1); 1348 + writel(vsc->sdp_header.HB2, dp->reg_base + ANALOGIX_DP_SPD_HB2); 1349 + writel(vsc->sdp_header.HB3, dp->reg_base + ANALOGIX_DP_SPD_HB3); 1350 + 1351 + /* configure reused VSC PB0~PB3, magic number from vendor */ 1352 + writel(0x00, dp->reg_base + ANALOGIX_DP_SPD_PB0); 1353 + writel(0x16, dp->reg_base + ANALOGIX_DP_SPD_PB1); 1354 + writel(0xCE, dp->reg_base + ANALOGIX_DP_SPD_PB2); 1355 + writel(0x5D, dp->reg_base + ANALOGIX_DP_SPD_PB3); 1356 + 1357 + /* configure DB0 / DB1 values */ 1358 + writel(vsc->DB0, dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB0); 1359 + writel(vsc->DB1, dp->reg_base + ANALOGIX_DP_VSC_SHADOW_DB1); 1360 + 1361 + /* set reuse spd inforframe */ 1362 + val = readl(dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); 1363 + val |= REUSE_SPD_EN; 1364 + writel(val, dp->reg_base + ANALOGIX_DP_VIDEO_CTL_3); 1365 + 1366 + /* mark info frame update */ 1367 + val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); 1368 + val = (val | IF_UP) & ~IF_EN; 1369 + writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); 1370 + 1371 + /* send info frame */ 1372 + val = readl(dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); 1373 + val |= IF_EN; 1374 + writel(val, dp->reg_base + ANALOGIX_DP_PKT_SEND_CTL); 1375 + }
+34
drivers/gpu/drm/bridge/analogix/analogix_dp_reg.h
··· 22 22 #define ANALOGIX_DP_VIDEO_CTL_8 0x3C 23 23 #define ANALOGIX_DP_VIDEO_CTL_10 0x44 24 24 25 + #define ANALOGIX_DP_SPDIF_AUDIO_CTL_0 0xD8 26 + 25 27 #define ANALOGIX_DP_PLL_REG_1 0xfc 26 28 #define ANALOGIX_DP_PLL_REG_2 0x9e4 27 29 #define ANALOGIX_DP_PLL_REG_3 0x9e8 ··· 31 29 #define ANALOGIX_DP_PLL_REG_5 0xa00 32 30 33 31 #define ANALOGIX_DP_PD 0x12c 32 + 33 + #define ANALOGIX_DP_IF_TYPE 0x244 34 + #define ANALOGIX_DP_IF_PKT_DB1 0x254 35 + #define ANALOGIX_DP_IF_PKT_DB2 0x258 36 + #define ANALOGIX_DP_SPD_HB0 0x2F8 37 + #define ANALOGIX_DP_SPD_HB1 0x2FC 38 + #define ANALOGIX_DP_SPD_HB2 0x300 39 + #define ANALOGIX_DP_SPD_HB3 0x304 40 + #define ANALOGIX_DP_SPD_PB0 0x308 41 + #define ANALOGIX_DP_SPD_PB1 0x30C 42 + #define ANALOGIX_DP_SPD_PB2 0x310 43 + #define ANALOGIX_DP_SPD_PB3 0x314 44 + #define ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL 0x318 45 + #define ANALOGIX_DP_VSC_SHADOW_DB0 0x31C 46 + #define ANALOGIX_DP_VSC_SHADOW_DB1 0x320 34 47 35 48 #define ANALOGIX_DP_LANE_MAP 0x35C 36 49 ··· 120 103 121 104 #define ANALOGIX_DP_SOC_GENERAL_CTL 0x800 122 105 106 + #define ANALOGIX_DP_CRC_CON 0x890 107 + 123 108 /* ANALOGIX_DP_TX_SW_RESET */ 124 109 #define RESET_DP_TX (0x1 << 0) 125 110 ··· 170 151 #define VID_CHK_UPDATE_TYPE_SHIFT (4) 171 152 #define VID_CHK_UPDATE_TYPE_1 (0x1 << 4) 172 153 #define VID_CHK_UPDATE_TYPE_0 (0x0 << 4) 154 + #define REUSE_SPD_EN (0x1 << 3) 173 155 174 156 /* ANALOGIX_DP_VIDEO_CTL_8 */ 175 157 #define VID_HRES_TH(x) (((x) & 0xf) << 4) ··· 186 166 #define REF_CLK_24M (0x1 << 0) 187 167 #define REF_CLK_27M (0x0 << 0) 188 168 #define REF_CLK_MASK (0x1 << 0) 169 + 170 + /* ANALOGIX_DP_PSR_FRAME_UPDATE_CTRL */ 171 + #define PSR_FRAME_UP_TYPE_BURST (0x1 << 0) 172 + #define PSR_FRAME_UP_TYPE_SINGLE (0x0 << 0) 173 + #define PSR_CRC_SEL_HARDWARE (0x1 << 1) 174 + #define PSR_CRC_SEL_MANUALLY (0x0 << 1) 189 175 190 176 /* ANALOGIX_DP_LANE_MAP */ 191 177 #define LANE3_MAP_LOGIC_LANE_0 (0x0 << 6) ··· 401 375 #define VIDEO_MODE_MASK (0x1 << 0) 402 376 #define VIDEO_MODE_SLAVE_MODE (0x1 << 0) 403 377 #define VIDEO_MODE_MASTER_MODE (0x0 << 0) 378 + 379 + /* ANALOGIX_DP_PKT_SEND_CTL */ 380 + #define IF_UP (0x1 << 4) 381 + #define IF_EN (0x1 << 0) 382 + 383 + /* ANALOGIX_DP_CRC_CON */ 384 + #define PSR_VID_CRC_FLUSH (0x1 << 2) 385 + #define PSR_VID_CRC_ENABLE (0x1 << 0) 404 386 405 387 #endif /* _ANALOGIX_DP_REG_H */
+3
include/drm/bridge/analogix_dp.h
··· 38 38 struct drm_connector *); 39 39 }; 40 40 41 + int analogix_dp_enable_psr(struct device *dev); 42 + int analogix_dp_disable_psr(struct device *dev); 43 + 41 44 int analogix_dp_resume(struct device *dev); 42 45 int analogix_dp_suspend(struct device *dev); 43 46