0001
0002
0003
0004
0005
0006 #define pr_fmt(fmt) "[drm-dp] %s: " fmt, __func__
0007
0008 #include <drm/drm_print.h>
0009
0010 #include "dp_link.h"
0011 #include "dp_panel.h"
0012
0013 #define DP_TEST_REQUEST_MASK 0x7F
0014
0015 enum audio_sample_rate {
0016 AUDIO_SAMPLE_RATE_32_KHZ = 0x00,
0017 AUDIO_SAMPLE_RATE_44_1_KHZ = 0x01,
0018 AUDIO_SAMPLE_RATE_48_KHZ = 0x02,
0019 AUDIO_SAMPLE_RATE_88_2_KHZ = 0x03,
0020 AUDIO_SAMPLE_RATE_96_KHZ = 0x04,
0021 AUDIO_SAMPLE_RATE_176_4_KHZ = 0x05,
0022 AUDIO_SAMPLE_RATE_192_KHZ = 0x06,
0023 };
0024
0025 enum audio_pattern_type {
0026 AUDIO_TEST_PATTERN_OPERATOR_DEFINED = 0x00,
0027 AUDIO_TEST_PATTERN_SAWTOOTH = 0x01,
0028 };
0029
0030 struct dp_link_request {
0031 u32 test_requested;
0032 u32 test_link_rate;
0033 u32 test_lane_count;
0034 };
0035
0036 struct dp_link_private {
0037 u32 prev_sink_count;
0038 struct device *dev;
0039 struct drm_device *drm_dev;
0040 struct drm_dp_aux *aux;
0041 struct dp_link dp_link;
0042
0043 struct dp_link_request request;
0044 struct mutex psm_mutex;
0045 u8 link_status[DP_LINK_STATUS_SIZE];
0046 };
0047
0048 static int dp_aux_link_power_up(struct drm_dp_aux *aux,
0049 struct dp_link_info *link)
0050 {
0051 u8 value;
0052 int err;
0053
0054 if (link->revision < 0x11)
0055 return 0;
0056
0057 err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
0058 if (err < 0)
0059 return err;
0060
0061 value &= ~DP_SET_POWER_MASK;
0062 value |= DP_SET_POWER_D0;
0063
0064 err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
0065 if (err < 0)
0066 return err;
0067
0068 usleep_range(1000, 2000);
0069
0070 return 0;
0071 }
0072
0073 static int dp_aux_link_power_down(struct drm_dp_aux *aux,
0074 struct dp_link_info *link)
0075 {
0076 u8 value;
0077 int err;
0078
0079 if (link->revision < 0x11)
0080 return 0;
0081
0082 err = drm_dp_dpcd_readb(aux, DP_SET_POWER, &value);
0083 if (err < 0)
0084 return err;
0085
0086 value &= ~DP_SET_POWER_MASK;
0087 value |= DP_SET_POWER_D3;
0088
0089 err = drm_dp_dpcd_writeb(aux, DP_SET_POWER, value);
0090 if (err < 0)
0091 return err;
0092
0093 return 0;
0094 }
0095
0096 static int dp_link_get_period(struct dp_link_private *link, int const addr)
0097 {
0098 int ret = 0;
0099 u8 data;
0100 u32 const max_audio_period = 0xA;
0101
0102
0103 if (drm_dp_dpcd_readb(link->aux, addr, &data) < 0) {
0104 DRM_ERROR("failed to read test_audio_period (0x%x)\n", addr);
0105 ret = -EINVAL;
0106 goto exit;
0107 }
0108
0109
0110 data = data & 0xF;
0111 if ((int)data > max_audio_period) {
0112 DRM_ERROR("invalid test_audio_period_ch_1 = 0x%x\n", data);
0113 ret = -EINVAL;
0114 goto exit;
0115 }
0116
0117 ret = data;
0118 exit:
0119 return ret;
0120 }
0121
0122 static int dp_link_parse_audio_channel_period(struct dp_link_private *link)
0123 {
0124 int ret = 0;
0125 struct dp_link_test_audio *req = &link->dp_link.test_audio;
0126
0127 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH1);
0128 if (ret == -EINVAL)
0129 goto exit;
0130
0131 req->test_audio_period_ch_1 = ret;
0132 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_1 = 0x%x\n", ret);
0133
0134 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH2);
0135 if (ret == -EINVAL)
0136 goto exit;
0137
0138 req->test_audio_period_ch_2 = ret;
0139 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_2 = 0x%x\n", ret);
0140
0141
0142 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH3);
0143 if (ret == -EINVAL)
0144 goto exit;
0145
0146 req->test_audio_period_ch_3 = ret;
0147 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_3 = 0x%x\n", ret);
0148
0149 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH4);
0150 if (ret == -EINVAL)
0151 goto exit;
0152
0153 req->test_audio_period_ch_4 = ret;
0154 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_4 = 0x%x\n", ret);
0155
0156 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH5);
0157 if (ret == -EINVAL)
0158 goto exit;
0159
0160 req->test_audio_period_ch_5 = ret;
0161 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_5 = 0x%x\n", ret);
0162
0163 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH6);
0164 if (ret == -EINVAL)
0165 goto exit;
0166
0167 req->test_audio_period_ch_6 = ret;
0168 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_6 = 0x%x\n", ret);
0169
0170 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH7);
0171 if (ret == -EINVAL)
0172 goto exit;
0173
0174 req->test_audio_period_ch_7 = ret;
0175 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_7 = 0x%x\n", ret);
0176
0177 ret = dp_link_get_period(link, DP_TEST_AUDIO_PERIOD_CH8);
0178 if (ret == -EINVAL)
0179 goto exit;
0180
0181 req->test_audio_period_ch_8 = ret;
0182 drm_dbg_dp(link->drm_dev, "test_audio_period_ch_8 = 0x%x\n", ret);
0183 exit:
0184 return ret;
0185 }
0186
0187 static int dp_link_parse_audio_pattern_type(struct dp_link_private *link)
0188 {
0189 int ret = 0;
0190 u8 data;
0191 ssize_t rlen;
0192 int const max_audio_pattern_type = 0x1;
0193
0194 rlen = drm_dp_dpcd_readb(link->aux,
0195 DP_TEST_AUDIO_PATTERN_TYPE, &data);
0196 if (rlen < 0) {
0197 DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen);
0198 return rlen;
0199 }
0200
0201
0202 if ((int)data > max_audio_pattern_type) {
0203 DRM_ERROR("invalid audio pattern type = 0x%x\n", data);
0204 ret = -EINVAL;
0205 goto exit;
0206 }
0207
0208 link->dp_link.test_audio.test_audio_pattern_type = data;
0209 drm_dbg_dp(link->drm_dev, "audio pattern type = 0x%x\n", data);
0210 exit:
0211 return ret;
0212 }
0213
0214 static int dp_link_parse_audio_mode(struct dp_link_private *link)
0215 {
0216 int ret = 0;
0217 u8 data;
0218 ssize_t rlen;
0219 int const max_audio_sampling_rate = 0x6;
0220 int const max_audio_channel_count = 0x8;
0221 int sampling_rate = 0x0;
0222 int channel_count = 0x0;
0223
0224 rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_AUDIO_MODE, &data);
0225 if (rlen < 0) {
0226 DRM_ERROR("failed to read link audio mode. rlen=%zd\n", rlen);
0227 return rlen;
0228 }
0229
0230
0231 sampling_rate = data & 0xF;
0232 if (sampling_rate > max_audio_sampling_rate) {
0233 DRM_ERROR("sampling rate (0x%x) greater than max (0x%x)\n",
0234 sampling_rate, max_audio_sampling_rate);
0235 ret = -EINVAL;
0236 goto exit;
0237 }
0238
0239
0240 channel_count = ((data & 0xF0) >> 4) + 1;
0241 if (channel_count > max_audio_channel_count) {
0242 DRM_ERROR("channel_count (0x%x) greater than max (0x%x)\n",
0243 channel_count, max_audio_channel_count);
0244 ret = -EINVAL;
0245 goto exit;
0246 }
0247
0248 link->dp_link.test_audio.test_audio_sampling_rate = sampling_rate;
0249 link->dp_link.test_audio.test_audio_channel_count = channel_count;
0250 drm_dbg_dp(link->drm_dev,
0251 "sampling_rate = 0x%x, channel_count = 0x%x\n",
0252 sampling_rate, channel_count);
0253 exit:
0254 return ret;
0255 }
0256
0257 static int dp_link_parse_audio_pattern_params(struct dp_link_private *link)
0258 {
0259 int ret = 0;
0260
0261 ret = dp_link_parse_audio_mode(link);
0262 if (ret)
0263 goto exit;
0264
0265 ret = dp_link_parse_audio_pattern_type(link);
0266 if (ret)
0267 goto exit;
0268
0269 ret = dp_link_parse_audio_channel_period(link);
0270
0271 exit:
0272 return ret;
0273 }
0274
0275 static bool dp_link_is_video_pattern_valid(u32 pattern)
0276 {
0277 switch (pattern) {
0278 case DP_NO_TEST_PATTERN:
0279 case DP_COLOR_RAMP:
0280 case DP_BLACK_AND_WHITE_VERTICAL_LINES:
0281 case DP_COLOR_SQUARE:
0282 return true;
0283 default:
0284 return false;
0285 }
0286 }
0287
0288
0289
0290
0291
0292
0293
0294 static bool dp_link_is_bit_depth_valid(u32 tbd)
0295 {
0296
0297 switch (tbd) {
0298 case DP_TEST_BIT_DEPTH_6:
0299 case DP_TEST_BIT_DEPTH_8:
0300 case DP_TEST_BIT_DEPTH_10:
0301 return true;
0302 default:
0303 return false;
0304 }
0305 }
0306
0307 static int dp_link_parse_timing_params1(struct dp_link_private *link,
0308 int addr, int len, u32 *val)
0309 {
0310 u8 bp[2];
0311 int rlen;
0312
0313 if (len != 2)
0314 return -EINVAL;
0315
0316
0317 rlen = drm_dp_dpcd_read(link->aux, addr, bp, len);
0318 if (rlen < len) {
0319 DRM_ERROR("failed to read 0x%x\n", addr);
0320 return -EINVAL;
0321 }
0322
0323 *val = bp[1] | (bp[0] << 8);
0324
0325 return 0;
0326 }
0327
0328 static int dp_link_parse_timing_params2(struct dp_link_private *link,
0329 int addr, int len,
0330 u32 *val1, u32 *val2)
0331 {
0332 u8 bp[2];
0333 int rlen;
0334
0335 if (len != 2)
0336 return -EINVAL;
0337
0338
0339 rlen = drm_dp_dpcd_read(link->aux, addr, bp, len);
0340 if (rlen < len) {
0341 DRM_ERROR("failed to read 0x%x\n", addr);
0342 return -EINVAL;
0343 }
0344
0345 *val1 = (bp[0] & BIT(7)) >> 7;
0346 *val2 = bp[1] | ((bp[0] & 0x7F) << 8);
0347
0348 return 0;
0349 }
0350
0351 static int dp_link_parse_timing_params3(struct dp_link_private *link,
0352 int addr, u32 *val)
0353 {
0354 u8 bp;
0355 u32 len = 1;
0356 int rlen;
0357
0358 rlen = drm_dp_dpcd_read(link->aux, addr, &bp, len);
0359 if (rlen < 1) {
0360 DRM_ERROR("failed to read 0x%x\n", addr);
0361 return -EINVAL;
0362 }
0363 *val = bp;
0364
0365 return 0;
0366 }
0367
0368
0369
0370
0371
0372
0373
0374
0375 static int dp_link_parse_video_pattern_params(struct dp_link_private *link)
0376 {
0377 int ret = 0;
0378 ssize_t rlen;
0379 u8 bp;
0380
0381 rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_PATTERN, &bp);
0382 if (rlen < 0) {
0383 DRM_ERROR("failed to read link video pattern. rlen=%zd\n",
0384 rlen);
0385 return rlen;
0386 }
0387
0388 if (!dp_link_is_video_pattern_valid(bp)) {
0389 DRM_ERROR("invalid link video pattern = 0x%x\n", bp);
0390 ret = -EINVAL;
0391 return ret;
0392 }
0393
0394 link->dp_link.test_video.test_video_pattern = bp;
0395
0396
0397 rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_MISC0, &bp);
0398 if (rlen < 0) {
0399 DRM_ERROR("failed to read link bit depth. rlen=%zd\n", rlen);
0400 return rlen;
0401 }
0402
0403
0404 link->dp_link.test_video.test_dyn_range =
0405 (bp & DP_TEST_DYNAMIC_RANGE_CEA);
0406
0407
0408 bp &= DP_TEST_BIT_DEPTH_MASK;
0409 if (!dp_link_is_bit_depth_valid(bp)) {
0410 DRM_ERROR("invalid link bit depth = 0x%x\n", bp);
0411 ret = -EINVAL;
0412 return ret;
0413 }
0414
0415 link->dp_link.test_video.test_bit_depth = bp;
0416
0417
0418 ret = dp_link_parse_timing_params1(link, DP_TEST_H_TOTAL_HI, 2,
0419 &link->dp_link.test_video.test_h_total);
0420 if (ret) {
0421 DRM_ERROR("failed to parse test_htotal(DP_TEST_H_TOTAL_HI)\n");
0422 return ret;
0423 }
0424
0425 ret = dp_link_parse_timing_params1(link, DP_TEST_V_TOTAL_HI, 2,
0426 &link->dp_link.test_video.test_v_total);
0427 if (ret) {
0428 DRM_ERROR("failed to parse test_v_total(DP_TEST_V_TOTAL_HI)\n");
0429 return ret;
0430 }
0431
0432 ret = dp_link_parse_timing_params1(link, DP_TEST_H_START_HI, 2,
0433 &link->dp_link.test_video.test_h_start);
0434 if (ret) {
0435 DRM_ERROR("failed to parse test_h_start(DP_TEST_H_START_HI)\n");
0436 return ret;
0437 }
0438
0439 ret = dp_link_parse_timing_params1(link, DP_TEST_V_START_HI, 2,
0440 &link->dp_link.test_video.test_v_start);
0441 if (ret) {
0442 DRM_ERROR("failed to parse test_v_start(DP_TEST_V_START_HI)\n");
0443 return ret;
0444 }
0445
0446 ret = dp_link_parse_timing_params2(link, DP_TEST_HSYNC_HI, 2,
0447 &link->dp_link.test_video.test_hsync_pol,
0448 &link->dp_link.test_video.test_hsync_width);
0449 if (ret) {
0450 DRM_ERROR("failed to parse (DP_TEST_HSYNC_HI)\n");
0451 return ret;
0452 }
0453
0454 ret = dp_link_parse_timing_params2(link, DP_TEST_VSYNC_HI, 2,
0455 &link->dp_link.test_video.test_vsync_pol,
0456 &link->dp_link.test_video.test_vsync_width);
0457 if (ret) {
0458 DRM_ERROR("failed to parse (DP_TEST_VSYNC_HI)\n");
0459 return ret;
0460 }
0461
0462 ret = dp_link_parse_timing_params1(link, DP_TEST_H_WIDTH_HI, 2,
0463 &link->dp_link.test_video.test_h_width);
0464 if (ret) {
0465 DRM_ERROR("failed to parse test_h_width(DP_TEST_H_WIDTH_HI)\n");
0466 return ret;
0467 }
0468
0469 ret = dp_link_parse_timing_params1(link, DP_TEST_V_HEIGHT_HI, 2,
0470 &link->dp_link.test_video.test_v_height);
0471 if (ret) {
0472 DRM_ERROR("failed to parse test_v_height\n");
0473 return ret;
0474 }
0475
0476 ret = dp_link_parse_timing_params3(link, DP_TEST_MISC1,
0477 &link->dp_link.test_video.test_rr_d);
0478 link->dp_link.test_video.test_rr_d &= DP_TEST_REFRESH_DENOMINATOR;
0479 if (ret) {
0480 DRM_ERROR("failed to parse test_rr_d (DP_TEST_MISC1)\n");
0481 return ret;
0482 }
0483
0484 ret = dp_link_parse_timing_params3(link, DP_TEST_REFRESH_RATE_NUMERATOR,
0485 &link->dp_link.test_video.test_rr_n);
0486 if (ret) {
0487 DRM_ERROR("failed to parse test_rr_n\n");
0488 return ret;
0489 }
0490
0491 drm_dbg_dp(link->drm_dev,
0492 "link video pattern = 0x%x\n"
0493 "link dynamic range = 0x%x\n"
0494 "link bit depth = 0x%x\n"
0495 "TEST_H_TOTAL = %d, TEST_V_TOTAL = %d\n"
0496 "TEST_H_START = %d, TEST_V_START = %d\n"
0497 "TEST_HSYNC_POL = %d\n"
0498 "TEST_HSYNC_WIDTH = %d\n"
0499 "TEST_VSYNC_POL = %d\n"
0500 "TEST_VSYNC_WIDTH = %d\n"
0501 "TEST_H_WIDTH = %d\n"
0502 "TEST_V_HEIGHT = %d\n"
0503 "TEST_REFRESH_DENOMINATOR = %d\n"
0504 "TEST_REFRESH_NUMERATOR = %d\n",
0505 link->dp_link.test_video.test_video_pattern,
0506 link->dp_link.test_video.test_dyn_range,
0507 link->dp_link.test_video.test_bit_depth,
0508 link->dp_link.test_video.test_h_total,
0509 link->dp_link.test_video.test_v_total,
0510 link->dp_link.test_video.test_h_start,
0511 link->dp_link.test_video.test_v_start,
0512 link->dp_link.test_video.test_hsync_pol,
0513 link->dp_link.test_video.test_hsync_width,
0514 link->dp_link.test_video.test_vsync_pol,
0515 link->dp_link.test_video.test_vsync_width,
0516 link->dp_link.test_video.test_h_width,
0517 link->dp_link.test_video.test_v_height,
0518 link->dp_link.test_video.test_rr_d,
0519 link->dp_link.test_video.test_rr_n);
0520
0521 return ret;
0522 }
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532 static int dp_link_parse_link_training_params(struct dp_link_private *link)
0533 {
0534 u8 bp;
0535 ssize_t rlen;
0536
0537 rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_LINK_RATE, &bp);
0538 if (rlen < 0) {
0539 DRM_ERROR("failed to read link rate. rlen=%zd\n", rlen);
0540 return rlen;
0541 }
0542
0543 if (!is_link_rate_valid(bp)) {
0544 DRM_ERROR("invalid link rate = 0x%x\n", bp);
0545 return -EINVAL;
0546 }
0547
0548 link->request.test_link_rate = bp;
0549 drm_dbg_dp(link->drm_dev, "link rate = 0x%x\n",
0550 link->request.test_link_rate);
0551
0552 rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_LANE_COUNT, &bp);
0553 if (rlen < 0) {
0554 DRM_ERROR("failed to read lane count. rlen=%zd\n", rlen);
0555 return rlen;
0556 }
0557 bp &= DP_MAX_LANE_COUNT_MASK;
0558
0559 if (!is_lane_count_valid(bp)) {
0560 DRM_ERROR("invalid lane count = 0x%x\n", bp);
0561 return -EINVAL;
0562 }
0563
0564 link->request.test_lane_count = bp;
0565 drm_dbg_dp(link->drm_dev, "lane count = 0x%x\n",
0566 link->request.test_lane_count);
0567 return 0;
0568 }
0569
0570
0571
0572
0573
0574
0575
0576
0577 static int dp_link_parse_phy_test_params(struct dp_link_private *link)
0578 {
0579 u8 data;
0580 ssize_t rlen;
0581
0582 rlen = drm_dp_dpcd_readb(link->aux, DP_PHY_TEST_PATTERN,
0583 &data);
0584 if (rlen < 0) {
0585 DRM_ERROR("failed to read phy link pattern. rlen=%zd\n", rlen);
0586 return rlen;
0587 }
0588
0589 link->dp_link.phy_params.phy_test_pattern_sel = data & 0x07;
0590
0591 drm_dbg_dp(link->drm_dev, "phy_test_pattern_sel = 0x%x\n", data);
0592
0593 switch (data) {
0594 case DP_PHY_TEST_PATTERN_SEL_MASK:
0595 case DP_PHY_TEST_PATTERN_NONE:
0596 case DP_PHY_TEST_PATTERN_D10_2:
0597 case DP_PHY_TEST_PATTERN_ERROR_COUNT:
0598 case DP_PHY_TEST_PATTERN_PRBS7:
0599 case DP_PHY_TEST_PATTERN_80BIT_CUSTOM:
0600 case DP_PHY_TEST_PATTERN_CP2520:
0601 return 0;
0602 default:
0603 return -EINVAL;
0604 }
0605 }
0606
0607
0608
0609
0610
0611
0612
0613 static bool dp_link_is_video_audio_test_requested(u32 link)
0614 {
0615 u8 video_audio_test = (DP_TEST_LINK_VIDEO_PATTERN |
0616 DP_TEST_LINK_AUDIO_PATTERN |
0617 DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
0618
0619 return ((link & video_audio_test) &&
0620 !(link & ~video_audio_test));
0621 }
0622
0623
0624
0625
0626
0627
0628
0629
0630 static int dp_link_parse_request(struct dp_link_private *link)
0631 {
0632 int ret = 0;
0633 u8 data;
0634 ssize_t rlen;
0635
0636
0637
0638
0639
0640 rlen = drm_dp_dpcd_readb(link->aux,
0641 DP_DEVICE_SERVICE_IRQ_VECTOR, &data);
0642 if (rlen < 0) {
0643 DRM_ERROR("aux read failed. rlen=%zd\n", rlen);
0644 return rlen;
0645 }
0646
0647 drm_dbg_dp(link->drm_dev, "device service irq vector = 0x%x\n", data);
0648
0649 if (!(data & DP_AUTOMATED_TEST_REQUEST)) {
0650 drm_dbg_dp(link->drm_dev, "no test requested\n");
0651 return 0;
0652 }
0653
0654
0655
0656
0657
0658 rlen = drm_dp_dpcd_readb(link->aux, DP_TEST_REQUEST, &data);
0659 if (rlen < 0) {
0660 DRM_ERROR("aux read failed. rlen=%zd\n", rlen);
0661 return rlen;
0662 }
0663
0664 if (!data || (data == DP_TEST_LINK_FAUX_PATTERN)) {
0665 drm_dbg_dp(link->drm_dev, "link 0x%x not supported\n", data);
0666 goto end;
0667 }
0668
0669 drm_dbg_dp(link->drm_dev, "Test:(0x%x) requested\n", data);
0670 link->request.test_requested = data;
0671 if (link->request.test_requested == DP_TEST_LINK_PHY_TEST_PATTERN) {
0672 ret = dp_link_parse_phy_test_params(link);
0673 if (ret)
0674 goto end;
0675 ret = dp_link_parse_link_training_params(link);
0676 if (ret)
0677 goto end;
0678 }
0679
0680 if (link->request.test_requested == DP_TEST_LINK_TRAINING) {
0681 ret = dp_link_parse_link_training_params(link);
0682 if (ret)
0683 goto end;
0684 }
0685
0686 if (dp_link_is_video_audio_test_requested(
0687 link->request.test_requested)) {
0688 ret = dp_link_parse_video_pattern_params(link);
0689 if (ret)
0690 goto end;
0691
0692 ret = dp_link_parse_audio_pattern_params(link);
0693 }
0694 end:
0695
0696
0697
0698
0699 if (ret) {
0700 link->dp_link.test_response = DP_TEST_NAK;
0701 } else {
0702 if (link->request.test_requested != DP_TEST_LINK_EDID_READ)
0703 link->dp_link.test_response = DP_TEST_ACK;
0704 else
0705 link->dp_link.test_response =
0706 DP_TEST_EDID_CHECKSUM_WRITE;
0707 }
0708
0709 return ret;
0710 }
0711
0712
0713
0714
0715
0716
0717
0718
0719
0720 static int dp_link_parse_sink_count(struct dp_link *dp_link)
0721 {
0722 ssize_t rlen;
0723 bool cp_ready;
0724
0725 struct dp_link_private *link = container_of(dp_link,
0726 struct dp_link_private, dp_link);
0727
0728 rlen = drm_dp_dpcd_readb(link->aux, DP_SINK_COUNT,
0729 &link->dp_link.sink_count);
0730 if (rlen < 0) {
0731 DRM_ERROR("sink count read failed. rlen=%zd\n", rlen);
0732 return rlen;
0733 }
0734
0735 cp_ready = link->dp_link.sink_count & DP_SINK_CP_READY;
0736
0737 link->dp_link.sink_count =
0738 DP_GET_SINK_COUNT(link->dp_link.sink_count);
0739
0740 drm_dbg_dp(link->drm_dev, "sink_count = 0x%x, cp_ready = 0x%x\n",
0741 link->dp_link.sink_count, cp_ready);
0742 return 0;
0743 }
0744
0745 static int dp_link_parse_sink_status_field(struct dp_link_private *link)
0746 {
0747 int len = 0;
0748
0749 link->prev_sink_count = link->dp_link.sink_count;
0750 len = dp_link_parse_sink_count(&link->dp_link);
0751 if (len < 0) {
0752 DRM_ERROR("DP parse sink count failed\n");
0753 return len;
0754 }
0755
0756 len = drm_dp_dpcd_read_link_status(link->aux,
0757 link->link_status);
0758 if (len < DP_LINK_STATUS_SIZE) {
0759 DRM_ERROR("DP link status read failed\n");
0760 return len;
0761 }
0762
0763 return dp_link_parse_request(link);
0764 }
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777 static int dp_link_process_link_training_request(struct dp_link_private *link)
0778 {
0779 if (link->request.test_requested != DP_TEST_LINK_TRAINING)
0780 return -EINVAL;
0781
0782 drm_dbg_dp(link->drm_dev,
0783 "Test:0x%x link rate = 0x%x, lane count = 0x%x\n",
0784 DP_TEST_LINK_TRAINING,
0785 link->request.test_link_rate,
0786 link->request.test_lane_count);
0787
0788 link->dp_link.link_params.num_lanes = link->request.test_lane_count;
0789 link->dp_link.link_params.rate =
0790 drm_dp_bw_code_to_link_rate(link->request.test_link_rate);
0791
0792 return 0;
0793 }
0794
0795 bool dp_link_send_test_response(struct dp_link *dp_link)
0796 {
0797 struct dp_link_private *link = NULL;
0798 int ret = 0;
0799
0800 if (!dp_link) {
0801 DRM_ERROR("invalid input\n");
0802 return false;
0803 }
0804
0805 link = container_of(dp_link, struct dp_link_private, dp_link);
0806
0807 ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_RESPONSE,
0808 dp_link->test_response);
0809
0810 return ret == 1;
0811 }
0812
0813 int dp_link_psm_config(struct dp_link *dp_link,
0814 struct dp_link_info *link_info, bool enable)
0815 {
0816 struct dp_link_private *link = NULL;
0817 int ret = 0;
0818
0819 if (!dp_link) {
0820 DRM_ERROR("invalid params\n");
0821 return -EINVAL;
0822 }
0823
0824 link = container_of(dp_link, struct dp_link_private, dp_link);
0825
0826 mutex_lock(&link->psm_mutex);
0827 if (enable)
0828 ret = dp_aux_link_power_down(link->aux, link_info);
0829 else
0830 ret = dp_aux_link_power_up(link->aux, link_info);
0831
0832 if (ret)
0833 DRM_ERROR("Failed to %s low power mode\n", enable ?
0834 "enter" : "exit");
0835 else
0836 dp_link->psm_enabled = enable;
0837
0838 mutex_unlock(&link->psm_mutex);
0839 return ret;
0840 }
0841
0842 bool dp_link_send_edid_checksum(struct dp_link *dp_link, u8 checksum)
0843 {
0844 struct dp_link_private *link = NULL;
0845 int ret = 0;
0846
0847 if (!dp_link) {
0848 DRM_ERROR("invalid input\n");
0849 return false;
0850 }
0851
0852 link = container_of(dp_link, struct dp_link_private, dp_link);
0853
0854 ret = drm_dp_dpcd_writeb(link->aux, DP_TEST_EDID_CHECKSUM,
0855 checksum);
0856 return ret == 1;
0857 }
0858
0859 static void dp_link_parse_vx_px(struct dp_link_private *link)
0860 {
0861 drm_dbg_dp(link->drm_dev, "vx: 0=%d, 1=%d, 2=%d, 3=%d\n",
0862 drm_dp_get_adjust_request_voltage(link->link_status, 0),
0863 drm_dp_get_adjust_request_voltage(link->link_status, 1),
0864 drm_dp_get_adjust_request_voltage(link->link_status, 2),
0865 drm_dp_get_adjust_request_voltage(link->link_status, 3));
0866
0867 drm_dbg_dp(link->drm_dev, "px: 0=%d, 1=%d, 2=%d, 3=%d\n",
0868 drm_dp_get_adjust_request_pre_emphasis(link->link_status, 0),
0869 drm_dp_get_adjust_request_pre_emphasis(link->link_status, 1),
0870 drm_dp_get_adjust_request_pre_emphasis(link->link_status, 2),
0871 drm_dp_get_adjust_request_pre_emphasis(link->link_status, 3));
0872
0873
0874
0875
0876
0877 drm_dbg_dp(link->drm_dev,
0878 "Current: v_level = 0x%x, p_level = 0x%x\n",
0879 link->dp_link.phy_params.v_level,
0880 link->dp_link.phy_params.p_level);
0881 link->dp_link.phy_params.v_level =
0882 drm_dp_get_adjust_request_voltage(link->link_status, 0);
0883 link->dp_link.phy_params.p_level =
0884 drm_dp_get_adjust_request_pre_emphasis(link->link_status, 0);
0885
0886 link->dp_link.phy_params.p_level >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
0887
0888 drm_dbg_dp(link->drm_dev,
0889 "Requested: v_level = 0x%x, p_level = 0x%x\n",
0890 link->dp_link.phy_params.v_level,
0891 link->dp_link.phy_params.p_level);
0892 }
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902 static int dp_link_process_phy_test_pattern_request(
0903 struct dp_link_private *link)
0904 {
0905 if (!(link->request.test_requested & DP_TEST_LINK_PHY_TEST_PATTERN)) {
0906 drm_dbg_dp(link->drm_dev, "no phy test\n");
0907 return -EINVAL;
0908 }
0909
0910 if (!is_link_rate_valid(link->request.test_link_rate) ||
0911 !is_lane_count_valid(link->request.test_lane_count)) {
0912 DRM_ERROR("Invalid: link rate = 0x%x,lane count = 0x%x\n",
0913 link->request.test_link_rate,
0914 link->request.test_lane_count);
0915 return -EINVAL;
0916 }
0917
0918 drm_dbg_dp(link->drm_dev,
0919 "Current: rate = 0x%x, lane count = 0x%x\n",
0920 link->dp_link.link_params.rate,
0921 link->dp_link.link_params.num_lanes);
0922
0923 drm_dbg_dp(link->drm_dev,
0924 "Requested: rate = 0x%x, lane count = 0x%x\n",
0925 link->request.test_link_rate,
0926 link->request.test_lane_count);
0927
0928 link->dp_link.link_params.num_lanes = link->request.test_lane_count;
0929 link->dp_link.link_params.rate =
0930 drm_dp_bw_code_to_link_rate(link->request.test_link_rate);
0931
0932 dp_link_parse_vx_px(link);
0933
0934 return 0;
0935 }
0936
0937 static u8 get_link_status(const u8 link_status[DP_LINK_STATUS_SIZE], int r)
0938 {
0939 return link_status[r - DP_LANE0_1_STATUS];
0940 }
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953 static int dp_link_process_link_status_update(struct dp_link_private *link)
0954 {
0955 bool channel_eq_done = drm_dp_channel_eq_ok(link->link_status,
0956 link->dp_link.link_params.num_lanes);
0957
0958 bool clock_recovery_done = drm_dp_clock_recovery_ok(link->link_status,
0959 link->dp_link.link_params.num_lanes);
0960
0961 drm_dbg_dp(link->drm_dev,
0962 "channel_eq_done = %d, clock_recovery_done = %d\n",
0963 channel_eq_done, clock_recovery_done);
0964
0965 if (channel_eq_done && clock_recovery_done)
0966 return -EINVAL;
0967
0968
0969 return 0;
0970 }
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983 static int dp_link_process_ds_port_status_change(struct dp_link_private *link)
0984 {
0985 if (get_link_status(link->link_status, DP_LANE_ALIGN_STATUS_UPDATED) &
0986 DP_DOWNSTREAM_PORT_STATUS_CHANGED)
0987 goto reset;
0988
0989 if (link->prev_sink_count == link->dp_link.sink_count)
0990 return -EINVAL;
0991
0992 reset:
0993
0994 link->prev_sink_count = link->dp_link.sink_count;
0995
0996 return 0;
0997 }
0998
0999 static bool dp_link_is_video_pattern_requested(struct dp_link_private *link)
1000 {
1001 return (link->request.test_requested & DP_TEST_LINK_VIDEO_PATTERN)
1002 && !(link->request.test_requested &
1003 DP_TEST_LINK_AUDIO_DISABLED_VIDEO);
1004 }
1005
1006 static bool dp_link_is_audio_pattern_requested(struct dp_link_private *link)
1007 {
1008 return (link->request.test_requested & DP_TEST_LINK_AUDIO_PATTERN);
1009 }
1010
1011 static void dp_link_reset_data(struct dp_link_private *link)
1012 {
1013 link->request = (const struct dp_link_request){ 0 };
1014 link->dp_link.test_video = (const struct dp_link_test_video){ 0 };
1015 link->dp_link.test_video.test_bit_depth = DP_TEST_BIT_DEPTH_UNKNOWN;
1016 link->dp_link.test_audio = (const struct dp_link_test_audio){ 0 };
1017 link->dp_link.phy_params.phy_test_pattern_sel = 0;
1018 link->dp_link.sink_request = 0;
1019 link->dp_link.test_response = 0;
1020 }
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030 int dp_link_process_request(struct dp_link *dp_link)
1031 {
1032 int ret = 0;
1033 struct dp_link_private *link;
1034
1035 if (!dp_link) {
1036 DRM_ERROR("invalid input\n");
1037 return -EINVAL;
1038 }
1039
1040 link = container_of(dp_link, struct dp_link_private, dp_link);
1041
1042 dp_link_reset_data(link);
1043
1044 ret = dp_link_parse_sink_status_field(link);
1045 if (ret)
1046 return ret;
1047
1048 if (link->request.test_requested == DP_TEST_LINK_EDID_READ) {
1049 dp_link->sink_request |= DP_TEST_LINK_EDID_READ;
1050 } else if (!dp_link_process_ds_port_status_change(link)) {
1051 dp_link->sink_request |= DS_PORT_STATUS_CHANGED;
1052 } else if (!dp_link_process_link_training_request(link)) {
1053 dp_link->sink_request |= DP_TEST_LINK_TRAINING;
1054 } else if (!dp_link_process_phy_test_pattern_request(link)) {
1055 dp_link->sink_request |= DP_TEST_LINK_PHY_TEST_PATTERN;
1056 } else {
1057 ret = dp_link_process_link_status_update(link);
1058 if (!ret) {
1059 dp_link->sink_request |= DP_LINK_STATUS_UPDATED;
1060 } else {
1061 if (dp_link_is_video_pattern_requested(link)) {
1062 ret = 0;
1063 dp_link->sink_request |= DP_TEST_LINK_VIDEO_PATTERN;
1064 }
1065 if (dp_link_is_audio_pattern_requested(link)) {
1066 dp_link->sink_request |= DP_TEST_LINK_AUDIO_PATTERN;
1067 ret = -EINVAL;
1068 }
1069 }
1070 }
1071
1072 drm_dbg_dp(link->drm_dev, "sink request=%#x",
1073 dp_link->sink_request);
1074 return ret;
1075 }
1076
1077 int dp_link_get_colorimetry_config(struct dp_link *dp_link)
1078 {
1079 u32 cc;
1080 struct dp_link_private *link;
1081
1082 if (!dp_link) {
1083 DRM_ERROR("invalid input\n");
1084 return -EINVAL;
1085 }
1086
1087 link = container_of(dp_link, struct dp_link_private, dp_link);
1088
1089
1090
1091
1092
1093 if (dp_link_is_video_pattern_requested(link))
1094 cc = link->dp_link.test_video.test_dyn_range;
1095 else
1096 cc = DP_TEST_DYNAMIC_RANGE_VESA;
1097
1098 return cc;
1099 }
1100
1101 int dp_link_adjust_levels(struct dp_link *dp_link, u8 *link_status)
1102 {
1103 int i;
1104 int v_max = 0, p_max = 0;
1105 struct dp_link_private *link;
1106
1107 if (!dp_link) {
1108 DRM_ERROR("invalid input\n");
1109 return -EINVAL;
1110 }
1111
1112 link = container_of(dp_link, struct dp_link_private, dp_link);
1113
1114
1115 for (i = 0; i < dp_link->link_params.num_lanes; i++) {
1116 u8 data_v = drm_dp_get_adjust_request_voltage(link_status, i);
1117 u8 data_p = drm_dp_get_adjust_request_pre_emphasis(link_status,
1118 i);
1119 drm_dbg_dp(link->drm_dev,
1120 "lane=%d req_vol_swing=%d req_pre_emphasis=%d\n",
1121 i, data_v, data_p);
1122 if (v_max < data_v)
1123 v_max = data_v;
1124 if (p_max < data_p)
1125 p_max = data_p;
1126 }
1127
1128 dp_link->phy_params.v_level = v_max >> DP_TRAIN_VOLTAGE_SWING_SHIFT;
1129 dp_link->phy_params.p_level = p_max >> DP_TRAIN_PRE_EMPHASIS_SHIFT;
1130
1131
1132
1133
1134
1135 if (dp_link->phy_params.v_level > DP_TRAIN_VOLTAGE_SWING_MAX) {
1136 drm_dbg_dp(link->drm_dev,
1137 "Requested vSwingLevel=%d, change to %d\n",
1138 dp_link->phy_params.v_level,
1139 DP_TRAIN_VOLTAGE_SWING_MAX);
1140 dp_link->phy_params.v_level = DP_TRAIN_VOLTAGE_SWING_MAX;
1141 }
1142
1143 if (dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_MAX) {
1144 drm_dbg_dp(link->drm_dev,
1145 "Requested preEmphasisLevel=%d, change to %d\n",
1146 dp_link->phy_params.p_level,
1147 DP_TRAIN_PRE_EMPHASIS_MAX);
1148 dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_MAX;
1149 }
1150
1151 if ((dp_link->phy_params.p_level > DP_TRAIN_PRE_EMPHASIS_LVL_1)
1152 && (dp_link->phy_params.v_level ==
1153 DP_TRAIN_VOLTAGE_SWING_LVL_2)) {
1154 drm_dbg_dp(link->drm_dev,
1155 "Requested preEmphasisLevel=%d, change to %d\n",
1156 dp_link->phy_params.p_level,
1157 DP_TRAIN_PRE_EMPHASIS_LVL_1);
1158 dp_link->phy_params.p_level = DP_TRAIN_PRE_EMPHASIS_LVL_1;
1159 }
1160
1161 drm_dbg_dp(link->drm_dev, "adjusted: v_level=%d, p_level=%d\n",
1162 dp_link->phy_params.v_level, dp_link->phy_params.p_level);
1163
1164 return 0;
1165 }
1166
1167 void dp_link_reset_phy_params_vx_px(struct dp_link *dp_link)
1168 {
1169 dp_link->phy_params.v_level = 0;
1170 dp_link->phy_params.p_level = 0;
1171 }
1172
1173 u32 dp_link_get_test_bits_depth(struct dp_link *dp_link, u32 bpp)
1174 {
1175 u32 tbd;
1176
1177
1178
1179
1180
1181
1182 switch (bpp) {
1183 case 18:
1184 tbd = DP_TEST_BIT_DEPTH_6;
1185 break;
1186 case 24:
1187 tbd = DP_TEST_BIT_DEPTH_8;
1188 break;
1189 case 30:
1190 tbd = DP_TEST_BIT_DEPTH_10;
1191 break;
1192 default:
1193 tbd = DP_TEST_BIT_DEPTH_UNKNOWN;
1194 break;
1195 }
1196
1197 if (tbd != DP_TEST_BIT_DEPTH_UNKNOWN)
1198 tbd = (tbd >> DP_TEST_BIT_DEPTH_SHIFT);
1199
1200 return tbd;
1201 }
1202
1203 struct dp_link *dp_link_get(struct device *dev, struct drm_dp_aux *aux)
1204 {
1205 struct dp_link_private *link;
1206 struct dp_link *dp_link;
1207
1208 if (!dev || !aux) {
1209 DRM_ERROR("invalid input\n");
1210 return ERR_PTR(-EINVAL);
1211 }
1212
1213 link = devm_kzalloc(dev, sizeof(*link), GFP_KERNEL);
1214 if (!link)
1215 return ERR_PTR(-ENOMEM);
1216
1217 link->dev = dev;
1218 link->aux = aux;
1219
1220 mutex_init(&link->psm_mutex);
1221 dp_link = &link->dp_link;
1222
1223 return dp_link;
1224 }