len = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value); if (len < 0) return len;
value &= ~DP_SET_POWER_MASK;
value |= DP_SET_POWER_D0;
/* retry for 1ms to give the sink time to wake up */ for (i = 0; i < 3; i++) {
len = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
usleep_range(1000, 2000); if (len == 1) break;
}
staticint msm_dp_link_parse_audio_pattern_params(struct msm_dp_link_private *link)
{ int ret = 0;
ret = msm_dp_link_parse_audio_mode(link); if (ret) gotoexit;
ret = msm_dp_link_parse_audio_pattern_type(link); if (ret) gotoexit;
ret = msm_dp_link_parse_audio_channel_period(link);
exit: return ret;
}
staticbool msm_dp_link_is_video_pattern_valid(u32 pattern)
{ switch (pattern) { case DP_NO_TEST_PATTERN: case DP_COLOR_RAMP: case DP_BLACK_AND_WHITE_VERTICAL_LINES: case DP_COLOR_SQUARE: returntrue; default: returnfalse;
}
}
/** *msm_dp_link_is_bit_depth_valid()-validatesthebitdepthrequested *@tbd:bitdepthrequestedbythesink * *Returnstrueiftherequestedbitdepthissupported.
*/ staticbool msm_dp_link_is_bit_depth_valid(u32 tbd)
{ /* DP_TEST_VIDEO_PATTERN_NONE is treated as invalid */ switch (tbd) { case DP_TEST_BIT_DEPTH_6: case DP_TEST_BIT_DEPTH_8: case DP_TEST_BIT_DEPTH_10: returntrue; default: returnfalse;
}
}
staticint msm_dp_link_parse_timing_params1(struct msm_dp_link_private *link, int addr, int len, u32 *val)
{
u8 bp[2]; int rlen;
if (len != 2) return -EINVAL;
/* Read the requested video link pattern (Byte 0x221). */
rlen = drm_dp_dpcd_read(link->aux, addr, bp, len); if (rlen < len) {
DRM_ERROR("failed to read 0x%x\n", addr); return -EINVAL;
}
*val = bp[1] | (bp[0] << 8);
return0;
}
staticint msm_dp_link_parse_timing_params2(struct msm_dp_link_private *link, int addr, int len,
u32 *val1, u32 *val2)
{
u8 bp[2]; int rlen;
if (len != 2) return -EINVAL;
/* Read the requested video link pattern (Byte 0x221). */
rlen = drm_dp_dpcd_read(link->aux, addr, bp, len); if (rlen < len) {
DRM_ERROR("failed to read 0x%x\n", addr); return -EINVAL;
}
/* Read the requested color bit depth and dynamic range (Byte 0x232) */
rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_MISC0, &bp); if (rlen < 0) {
DRM_ERROR("failed to read link bit depth. rlen=%zd\n", rlen); return rlen;
}
/* Dynamic Range */
link->msm_dp_link.test_video.test_dyn_range =
(bp & DP_TEST_DYNAMIC_RANGE_CEA);
/* Color bit depth */
bp &= DP_TEST_BIT_DEPTH_MASK; if (!msm_dp_link_is_bit_depth_valid(bp)) {
DRM_ERROR("invalid link bit depth = 0x%x\n", bp);
ret = -EINVAL; return ret;
}
link->msm_dp_link.test_video.test_bit_depth = bp;
/* resolution timing params */
ret = msm_dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2,
&link->msm_dp_link.test_video.test_h_total); if (ret) {
DRM_ERROR("failed to parse test_htotal(DP_TEST_H_TOTAL_HI)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2,
&link->msm_dp_link.test_video.test_v_total); if (ret) {
DRM_ERROR("failed to parse test_v_total(DP_TEST_V_TOTAL_HI)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2,
&link->msm_dp_link.test_video.test_h_start); if (ret) {
DRM_ERROR("failed to parse test_h_start(DP_TEST_H_START_HI)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2,
&link->msm_dp_link.test_video.test_v_start); if (ret) {
DRM_ERROR("failed to parse test_v_start(DP_TEST_V_START_HI)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2,
&link->msm_dp_link.test_video.test_hsync_pol,
&link->msm_dp_link.test_video.test_hsync_width); if (ret) {
DRM_ERROR("failed to parse (DP_TEST_HSYNC_HI)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2,
&link->msm_dp_link.test_video.test_vsync_pol,
&link->msm_dp_link.test_video.test_vsync_width); if (ret) {
DRM_ERROR("failed to parse (DP_TEST_VSYNC_HI)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2,
&link->msm_dp_link.test_video.test_h_width); if (ret) {
DRM_ERROR("failed to parse test_h_width(DP_TEST_H_WIDTH_HI)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2,
&link->msm_dp_link.test_video.test_v_height); if (ret) {
DRM_ERROR("failed to parse test_v_height\n"); return ret;
}
ret = msm_dp_link_parse_timing_params3(link, DP_TEST_MISC1,
&link->msm_dp_link.test_video.test_rr_d);
link->msm_dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR; if (ret) {
DRM_ERROR("failed to parse test_rr_d (DP_TEST_MISC1)\n"); return ret;
}
ret = msm_dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR,
&link->msm_dp_link.test_video.test_rr_n); if (ret) {
DRM_ERROR("failed to parse test_rr_n\n"); return ret;
}
switch (data) { case DP_PHY_TEST_PATTERN_SEL_MASK: case DP_PHY_TEST_PATTERN_NONE: case DP_PHY_TEST_PATTERN_D10_2: case DP_PHY_TEST_PATTERN_ERROR_COUNT: case DP_PHY_TEST_PATTERN_PRBS7: case DP_PHY_TEST_PATTERN_80BIT_CUSTOM: case DP_PHY_TEST_PATTERN_CP2520: return0; default: return -EINVAL;
}
}
bool msm_dp_link_send_test_response(struct msm_dp_link *msm_dp_link)
{ struct msm_dp_link_private *link = NULL; int ret = 0;
if (!msm_dp_link) {
DRM_ERROR("invalid input\n"); returnfalse;
}
link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_RESPONSE,
msm_dp_link->test_response);
return ret == 1;
}
int msm_dp_link_psm_config(struct msm_dp_link *msm_dp_link, struct msm_dp_link_info *link_info, bool enable)
{ struct msm_dp_link_private *link = NULL; int ret = 0;
if (!msm_dp_link) {
DRM_ERROR("invalid params\n"); return -EINVAL;
}
link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
mutex_lock(&link->psm_mutex); if (enable)
ret = msm_dp_aux_link_power_down(link->aux, link_info); else
ret = msm_dp_aux_link_power_up(link->aux, link_info);
if (ret)
DRM_ERROR("Failed to %s low power mode\n", enable ? "enter" : "exit");
mutex_unlock(&link->psm_mutex); return ret;
}
bool msm_dp_link_send_edid_checksum(struct msm_dp_link *msm_dp_link, u8 checksum)
{ struct msm_dp_link_private *link = NULL; int ret = 0;
if (!msm_dp_link) {
DRM_ERROR("invalid input\n"); returnfalse;
}
link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_EDID_CHECKSUM,
checksum); return ret == 1;
}
int msm_dp_link_get_colorimetry_config(struct msm_dp_link *msm_dp_link)
{
u32 cc = DP_MISC0_COLORIMERY_CFG_LEGACY_RGB; struct msm_dp_link_private *link;
if (!msm_dp_link) {
DRM_ERROR("invalid input\n"); return -EINVAL;
}
link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
/* *UnlessavideopatternCTStestisongoing,useRGB_VESA *OnlyRGB_VESAandRGB_CEAsupportedfornow
*/ if (msm_dp_link_is_video_pattern_requested(link)) { if (link->msm_dp_link.test_video.test_dyn_range &
DP_TEST_DYNAMIC_RANGE_CEA)
cc = DP_MISC0_COLORIMERY_CFG_CEA_RGB;
}
return cc;
}
int msm_dp_link_adjust_levels(struct msm_dp_link *msm_dp_link, u8 *link_status)
{ int i;
u8 max_p_level; int v_max = 0, p_max = 0; struct msm_dp_link_private *link;
if (!msm_dp_link) {
DRM_ERROR("invalid input\n"); return -EINVAL;
}
link = container_of(msm_dp_link, struct msm_dp_link_private, msm_dp_link);
/* use the max level across lanes */ for (i = 0; i < msm_dp_link->link_params.num_lanes; i++) {
u8 data_v = drm_dp_get_adjust_request_voltage(link_status, i);
u8 data_p = drm_dp_get_adjust_request_pre_emphasis(link_status,
i);
drm_dbg_dp(link->drm_dev, "lane=%d req_vol_swing=%d req_pre_emphasis=%d\n",
i, data_v, data_p); if (v_max < data_v)
v_max = data_v; if (p_max < data_p)
p_max = data_p;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.21Bemerkung:
(vorverarbeitet am 2026-10-11)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.