Lines Matching +full:dp +full:- +full:phy

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Rockchip USBDP Combo PHY with Samsung IP block driver
18 #include <generic-phy.h>
21 #include <linux/media-bus-format.h>
24 #include <generic-phy.h>
223 struct phy phy; member
324 static int dw_dp_aux_write_data(struct dw_dp *dp, const u8 *buffer, size_t size) in dw_dp_aux_write_data() argument
329 size_t num = min_t(size_t, size - i * 4, 4); in dw_dp_aux_write_data()
335 regmap_write(dp->regmap, DPTX_AUX_DATA0 + i * 4, value); in dw_dp_aux_write_data()
341 static int dw_dp_aux_read_data(struct dw_dp *dp, u8 *buffer, size_t size) in dw_dp_aux_read_data() argument
346 size_t num = min_t(size_t, size - i * 4, 4); in dw_dp_aux_read_data()
349 regmap_read(dp->regmap, DPTX_AUX_DATA0 + i * 4, &value); in dw_dp_aux_read_data()
364 struct dw_dp *dp = dev_get_priv(aux->dev); in dw_dp_aux_transfer() local
366 if (WARN_ON(msg->size > 16)) in dw_dp_aux_transfer()
367 return -E2BIG; in dw_dp_aux_transfer()
369 switch (msg->request & ~DP_AUX_I2C_MOT) { in dw_dp_aux_transfer()
373 ret = dw_dp_aux_write_data(dp, msg->buffer, msg->size); in dw_dp_aux_transfer()
381 return -EINVAL; in dw_dp_aux_transfer()
384 if (msg->size > 0) in dw_dp_aux_transfer()
385 value = FIELD_PREP(AUX_LEN_REQ, msg->size - 1); in dw_dp_aux_transfer()
389 value |= FIELD_PREP(AUX_CMD_TYPE, msg->request); in dw_dp_aux_transfer()
390 value |= FIELD_PREP(AUX_ADDR, msg->address); in dw_dp_aux_transfer()
391 regmap_write(dp->regmap, DPTX_AUX_CMD, value); in dw_dp_aux_transfer()
393 timeout = regmap_read_poll_timeout(dp->regmap, DPTX_GENERAL_INTERRUPT, in dw_dp_aux_transfer()
399 return -ETIMEDOUT; in dw_dp_aux_transfer()
401 regmap_write(dp->regmap, DPTX_GENERAL_INTERRUPT, AUX_REPLY_EVENT); in dw_dp_aux_transfer()
403 regmap_read(dp->regmap, DPTX_AUX_STATUS, &value); in dw_dp_aux_transfer()
406 return -ETIMEDOUT; in dw_dp_aux_transfer()
409 msg->reply = FIELD_GET(AUX_STATUS, value); in dw_dp_aux_transfer()
411 if (msg->size > 0 && msg->reply == DP_AUX_NATIVE_REPLY_ACK) { in dw_dp_aux_transfer()
412 if (msg->request & DP_AUX_I2C_READ) { in dw_dp_aux_transfer()
413 size_t count = FIELD_GET(AUX_BYTES_READ, value) - 1; in dw_dp_aux_transfer()
415 if (count != msg->size) { in dw_dp_aux_transfer()
417 return -EBUSY; in dw_dp_aux_transfer()
420 ret = dw_dp_aux_read_data(dp, msg->buffer, count); in dw_dp_aux_transfer()
429 static bool dw_dp_bandwidth_ok(struct dw_dp *dp, in dw_dp_bandwidth_ok() argument
435 req_bw = mode->clock * bpp / 8; in dw_dp_bandwidth_ok()
443 static void dw_dp_hpd_init(struct dw_dp *dp) in dw_dp_hpd_init() argument
445 if (dm_gpio_is_valid(&dp->hpd_gpio) || dp->force_hpd) { in dw_dp_hpd_init()
446 regmap_update_bits(dp->regmap, DPTX_CCTL, FORCE_HPD, in dw_dp_hpd_init()
452 regmap_update_bits(dp->regmap, DPTX_HPD_INTERRUPT_ENABLE, in dw_dp_hpd_init()
458 /* Enable all top-level interrupts */ in dw_dp_hpd_init()
459 regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE, in dw_dp_hpd_init()
463 static void dw_dp_aux_init(struct dw_dp *dp) in dw_dp_aux_init() argument
465 regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, AUX_RESET, in dw_dp_aux_init()
468 regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, AUX_RESET, in dw_dp_aux_init()
471 regmap_update_bits(dp->regmap, DPTX_GENERAL_INTERRUPT_ENABLE, in dw_dp_aux_init()
476 static void dw_dp_init(struct dw_dp *dp) in dw_dp_init() argument
478 regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, CONTROLLER_RESET, in dw_dp_init()
481 regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, CONTROLLER_RESET, in dw_dp_init()
484 regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, PHY_SOFT_RESET, in dw_dp_init()
487 regmap_update_bits(dp->regmap, DPTX_SOFT_RESET_CTRL, PHY_SOFT_RESET, in dw_dp_init()
490 regmap_update_bits(dp->regmap, DPTX_CCTL, DEFAULT_FAST_LINK_TRAIN_EN, in dw_dp_init()
493 dw_dp_hpd_init(dp); in dw_dp_init()
494 dw_dp_aux_init(dp); in dw_dp_init()
497 static void dw_dp_phy_set_pattern(struct dw_dp *dp, u32 pattern) in dw_dp_phy_set_pattern() argument
499 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, TPS_SEL, in dw_dp_phy_set_pattern()
503 static void dw_dp_phy_xmit_enable(struct dw_dp *dp, u32 lanes) in dw_dp_phy_xmit_enable() argument
511 xmit_enable = GENMASK(lanes - 1, 0); in dw_dp_phy_xmit_enable()
519 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, XMIT_ENABLE, in dw_dp_phy_xmit_enable()
523 static int dw_dp_link_power_up(struct dw_dp *dp) in dw_dp_link_power_up() argument
525 struct dw_dp_link *link = &dp->link; in dw_dp_link_power_up()
529 if (link->revision < 0x11) in dw_dp_link_power_up()
532 ret = drm_dp_dpcd_readb(&dp->aux, DP_SET_POWER, &value); in dw_dp_link_power_up()
539 ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, value); in dw_dp_link_power_up()
547 static int dw_dp_link_probe(struct dw_dp *dp) in dw_dp_link_probe() argument
549 struct dw_dp_link *link = &dp->link; in dw_dp_link_probe()
553 ret = drm_dp_read_dpcd_caps(&dp->aux, link->dpcd); in dw_dp_link_probe()
557 ret = drm_dp_dpcd_readb(&dp->aux, DP_DPRX_FEATURE_ENUMERATION_LIST, in dw_dp_link_probe()
562 link->vsc_sdp_extension_for_colorimetry_supported = in dw_dp_link_probe()
565 link->revision = link->dpcd[DP_DPCD_REV]; in dw_dp_link_probe()
566 link->rate = min_t(u32, min(dp->max_link_rate, dp->phy.attrs.max_link_rate * 100), in dw_dp_link_probe()
567 drm_dp_max_link_rate(link->dpcd)); in dw_dp_link_probe()
568 link->lanes = min_t(u8, dp->phy.attrs.bus_width, in dw_dp_link_probe()
569 drm_dp_max_lane_count(link->dpcd)); in dw_dp_link_probe()
571 link->caps.enhanced_framing = drm_dp_enhanced_frame_cap(link->dpcd); in dw_dp_link_probe()
572 link->caps.tps3_supported = drm_dp_tps3_supported(link->dpcd); in dw_dp_link_probe()
573 link->caps.tps4_supported = drm_dp_tps4_supported(link->dpcd); in dw_dp_link_probe()
574 link->caps.channel_coding = drm_dp_channel_coding_supported(link->dpcd); in dw_dp_link_probe()
575 link->caps.ssc = !!(link->dpcd[DP_MAX_DOWNSPREAD] & in dw_dp_link_probe()
581 static int dw_dp_link_train_update_vs_emph(struct dw_dp *dp) in dw_dp_link_train_update_vs_emph() argument
583 struct dw_dp_link *link = &dp->link; in dw_dp_link_train_update_vs_emph()
584 struct drm_dp_link_train_set *request = &link->train.request; in dw_dp_link_train_update_vs_emph()
586 unsigned int lanes = link->lanes, *vs, *pe; in dw_dp_link_train_update_vs_emph()
590 vs = request->voltage_swing; in dw_dp_link_train_update_vs_emph()
591 pe = request->pre_emphasis; in dw_dp_link_train_update_vs_emph()
594 phy_cfg.dp.voltage[i] = vs[i]; in dw_dp_link_train_update_vs_emph()
595 phy_cfg.dp.pre[i] = pe[i]; in dw_dp_link_train_update_vs_emph()
597 phy_cfg.dp.lanes = lanes; in dw_dp_link_train_update_vs_emph()
598 phy_cfg.dp.link_rate = link->rate / 100; in dw_dp_link_train_update_vs_emph()
599 phy_cfg.dp.set_lanes = false; in dw_dp_link_train_update_vs_emph()
600 phy_cfg.dp.set_rate = false; in dw_dp_link_train_update_vs_emph()
601 phy_cfg.dp.set_voltages = true; in dw_dp_link_train_update_vs_emph()
602 ret = generic_phy_configure(&dp->phy, &phy_cfg); in dw_dp_link_train_update_vs_emph()
609 ret = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, buf, lanes); in dw_dp_link_train_update_vs_emph()
616 static int dw_dp_link_configure(struct dw_dp *dp) in dw_dp_link_configure() argument
618 struct dw_dp_link *link = &dp->link; in dw_dp_link_configure()
623 /* Move PHY to P3 */ in dw_dp_link_configure()
624 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN, in dw_dp_link_configure()
627 phy_cfg.dp.lanes = link->lanes; in dw_dp_link_configure()
628 phy_cfg.dp.link_rate = link->rate / 100; in dw_dp_link_configure()
629 phy_cfg.dp.ssc = link->caps.ssc; in dw_dp_link_configure()
630 phy_cfg.dp.set_lanes = true; in dw_dp_link_configure()
631 phy_cfg.dp.set_rate = true; in dw_dp_link_configure()
632 phy_cfg.dp.set_voltages = false; in dw_dp_link_configure()
633 ret = generic_phy_configure(&dp->phy, &phy_cfg); in dw_dp_link_configure()
637 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_LANES, in dw_dp_link_configure()
638 FIELD_PREP(PHY_LANES, link->lanes / 2)); in dw_dp_link_configure()
640 switch (link->rate) { in dw_dp_link_configure()
655 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_RATE, in dw_dp_link_configure()
658 /* Move PHY to P0 */ in dw_dp_link_configure()
659 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN, in dw_dp_link_configure()
662 dw_dp_phy_xmit_enable(dp, link->lanes); in dw_dp_link_configure()
664 buf[0] = drm_dp_link_rate_to_bw_code(link->rate); in dw_dp_link_configure()
665 buf[1] = link->lanes; in dw_dp_link_configure()
667 if (link->caps.enhanced_framing) { in dw_dp_link_configure()
669 regmap_update_bits(dp->regmap, DPTX_CCTL, ENHANCE_FRAMING_EN, in dw_dp_link_configure()
672 regmap_update_bits(dp->regmap, DPTX_CCTL, ENHANCE_FRAMING_EN, in dw_dp_link_configure()
676 ret = drm_dp_dpcd_write(&dp->aux, DP_LINK_BW_SET, buf, sizeof(buf)); in dw_dp_link_configure()
680 buf[0] = link->caps.ssc ? DP_SPREAD_AMP_0_5 : 0; in dw_dp_link_configure()
681 buf[1] = link->caps.channel_coding ? DP_SET_ANSI_8B10B : 0; in dw_dp_link_configure()
683 ret = drm_dp_dpcd_write(&dp->aux, DP_DOWNSPREAD_CTRL, buf, in dw_dp_link_configure()
693 struct drm_dp_link_train_set *request = &train->request; in dw_dp_link_train_init()
694 struct drm_dp_link_train_set *adjust = &train->adjust; in dw_dp_link_train_init()
698 request->voltage_swing[i] = 0; in dw_dp_link_train_init()
699 adjust->voltage_swing[i] = 0; in dw_dp_link_train_init()
701 request->pre_emphasis[i] = 0; in dw_dp_link_train_init()
702 adjust->pre_emphasis[i] = 0; in dw_dp_link_train_init()
705 train->clock_recovered = false; in dw_dp_link_train_init()
706 train->channel_equalized = false; in dw_dp_link_train_init()
709 static int dw_dp_link_train_set_pattern(struct dw_dp *dp, u32 pattern) in dw_dp_link_train_set_pattern() argument
717 regmap_update_bits(dp->regmap, DPTX_CCTL, SCRAMBLE_DIS, in dw_dp_link_train_set_pattern()
720 regmap_update_bits(dp->regmap, DPTX_CCTL, SCRAMBLE_DIS, in dw_dp_link_train_set_pattern()
726 dw_dp_phy_set_pattern(dp, DPTX_PHY_PATTERN_NONE); in dw_dp_link_train_set_pattern()
729 dw_dp_phy_set_pattern(dp, DPTX_PHY_PATTERN_TPS_1); in dw_dp_link_train_set_pattern()
732 dw_dp_phy_set_pattern(dp, DPTX_PHY_PATTERN_TPS_2); in dw_dp_link_train_set_pattern()
735 dw_dp_phy_set_pattern(dp, DPTX_PHY_PATTERN_TPS_3); in dw_dp_link_train_set_pattern()
738 dw_dp_phy_set_pattern(dp, DPTX_PHY_PATTERN_TPS_4); in dw_dp_link_train_set_pattern()
741 return -EINVAL; in dw_dp_link_train_set_pattern()
744 ret = drm_dp_dpcd_writeb(&dp->aux, DP_TRAINING_PATTERN_SET, in dw_dp_link_train_set_pattern()
755 struct drm_dp_link_train_set *adjust = &link->train.adjust; in dw_dp_link_get_adjustments()
758 for (i = 0; i < link->lanes; i++) { in dw_dp_link_get_adjustments()
759 adjust->voltage_swing[i] = in dw_dp_link_get_adjustments()
763 adjust->pre_emphasis[i] = in dw_dp_link_get_adjustments()
771 struct drm_dp_link_train_set *request = &train->request; in dw_dp_link_train_adjust()
772 struct drm_dp_link_train_set *adjust = &train->adjust; in dw_dp_link_train_adjust()
776 if (request->voltage_swing[i] != adjust->voltage_swing[i]) in dw_dp_link_train_adjust()
777 request->voltage_swing[i] = adjust->voltage_swing[i]; in dw_dp_link_train_adjust()
780 if (request->pre_emphasis[i] != adjust->pre_emphasis[i]) in dw_dp_link_train_adjust()
781 request->pre_emphasis[i] = adjust->pre_emphasis[i]; in dw_dp_link_train_adjust()
784 static int dw_dp_link_clock_recovery(struct dw_dp *dp) in dw_dp_link_clock_recovery() argument
786 struct dw_dp_link *link = &dp->link; in dw_dp_link_clock_recovery()
791 ret = dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_1); in dw_dp_link_clock_recovery()
796 ret = dw_dp_link_train_update_vs_emph(dp); in dw_dp_link_clock_recovery()
800 drm_dp_link_train_clock_recovery_delay(link->dpcd); in dw_dp_link_clock_recovery()
802 ret = drm_dp_dpcd_read_link_status(&dp->aux, status); in dw_dp_link_clock_recovery()
804 dev_err(dp->dev, "failed to read link status: %d\n", in dw_dp_link_clock_recovery()
809 if (drm_dp_clock_recovery_ok(status, link->lanes)) { in dw_dp_link_clock_recovery()
810 link->train.clock_recovered = true; in dw_dp_link_clock_recovery()
816 if (link->train.request.voltage_swing[0] == in dw_dp_link_clock_recovery()
817 link->train.adjust.voltage_swing[0]) in dw_dp_link_clock_recovery()
825 dw_dp_link_train_adjust(&link->train); in dw_dp_link_clock_recovery()
831 static int dw_dp_link_channel_equalization(struct dw_dp *dp) in dw_dp_link_channel_equalization() argument
833 struct dw_dp_link *link = &dp->link; in dw_dp_link_channel_equalization()
838 if (link->caps.tps4_supported) in dw_dp_link_channel_equalization()
840 else if (link->caps.tps3_supported) in dw_dp_link_channel_equalization()
844 ret = dw_dp_link_train_set_pattern(dp, pattern); in dw_dp_link_channel_equalization()
849 ret = dw_dp_link_train_update_vs_emph(dp); in dw_dp_link_channel_equalization()
853 drm_dp_link_train_channel_eq_delay(link->dpcd); in dw_dp_link_channel_equalization()
855 ret = drm_dp_dpcd_read_link_status(&dp->aux, status); in dw_dp_link_channel_equalization()
859 if (!drm_dp_clock_recovery_ok(status, link->lanes)) { in dw_dp_link_channel_equalization()
860 dev_err(dp->dev, in dw_dp_link_channel_equalization()
862 link->train.clock_recovered = false; in dw_dp_link_channel_equalization()
866 if (drm_dp_channel_eq_ok(status, link->lanes)) { in dw_dp_link_channel_equalization()
867 link->train.channel_equalized = true; in dw_dp_link_channel_equalization()
872 dw_dp_link_train_adjust(&link->train); in dw_dp_link_channel_equalization()
878 static int dw_dp_link_downgrade(struct dw_dp *dp) in dw_dp_link_downgrade() argument
880 struct dw_dp_link *link = &dp->link; in dw_dp_link_downgrade()
881 struct dw_dp_video *video = &dp->video; in dw_dp_link_downgrade()
883 switch (link->rate) { in dw_dp_link_downgrade()
885 return -EINVAL; in dw_dp_link_downgrade()
887 link->rate = 162000; in dw_dp_link_downgrade()
890 link->rate = 270000; in dw_dp_link_downgrade()
893 link->rate = 540000; in dw_dp_link_downgrade()
897 if (!dw_dp_bandwidth_ok(dp, &video->mode, video->bpp, link->lanes, in dw_dp_link_downgrade()
898 link->rate)) in dw_dp_link_downgrade()
899 return -E2BIG; in dw_dp_link_downgrade()
904 static int dw_dp_link_train(struct dw_dp *dp) in dw_dp_link_train() argument
906 struct dw_dp_link *link = &dp->link; in dw_dp_link_train()
910 dw_dp_link_train_init(&link->train); in dw_dp_link_train()
913 link->lanes, (link->lanes > 1) ? "s" : "", link->rate / 100); in dw_dp_link_train()
915 ret = dw_dp_link_configure(dp); in dw_dp_link_train()
917 dev_err(dp->dev, "failed to configure DP link: %d\n", ret); in dw_dp_link_train()
921 ret = dw_dp_link_clock_recovery(dp); in dw_dp_link_train()
923 dev_err(dp->dev, "clock recovery failed: %d\n", ret); in dw_dp_link_train()
927 if (!link->train.clock_recovered) { in dw_dp_link_train()
928 dev_err(dp->dev, "clock recovery failed, downgrading link\n"); in dw_dp_link_train()
930 ret = dw_dp_link_downgrade(dp); in dw_dp_link_train()
939 ret = dw_dp_link_channel_equalization(dp); in dw_dp_link_train()
941 dev_err(dp->dev, "channel equalization failed: %d\n", ret); in dw_dp_link_train()
945 if (!link->train.channel_equalized) { in dw_dp_link_train()
946 dev_err(dp->dev, in dw_dp_link_train()
949 ret = dw_dp_link_downgrade(dp); in dw_dp_link_train()
959 dw_dp_link_train_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE); in dw_dp_link_train()
963 static int dw_dp_link_enable(struct dw_dp *dp) in dw_dp_link_enable() argument
967 ret = dw_dp_link_power_up(dp); in dw_dp_link_enable()
971 ret = dw_dp_link_train(dp); in dw_dp_link_enable()
973 dev_err(dp->dev, "link training failed: %d\n", ret); in dw_dp_link_enable()
980 static int dw_dp_set_phy_default_config(struct dw_dp *dp) in dw_dp_set_phy_default_config() argument
982 struct dw_dp_link *link = &dp->link; in dw_dp_set_phy_default_config()
986 link->vsc_sdp_extension_for_colorimetry_supported = false; in dw_dp_set_phy_default_config()
987 link->rate = 270000; in dw_dp_set_phy_default_config()
988 link->lanes = dp->phy.attrs.bus_width; in dw_dp_set_phy_default_config()
990 link->caps.enhanced_framing = true; in dw_dp_set_phy_default_config()
991 link->caps.channel_coding = true; in dw_dp_set_phy_default_config()
992 link->caps.ssc = true; in dw_dp_set_phy_default_config()
994 /* Move PHY to P3 */ in dw_dp_set_phy_default_config()
995 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN, in dw_dp_set_phy_default_config()
998 for (i = 0; i < link->lanes; i++) { in dw_dp_set_phy_default_config()
999 phy_cfg.dp.voltage[i] = 3; in dw_dp_set_phy_default_config()
1000 phy_cfg.dp.pre[i] = 0; in dw_dp_set_phy_default_config()
1002 phy_cfg.dp.lanes = link->lanes; in dw_dp_set_phy_default_config()
1003 phy_cfg.dp.link_rate = link->rate / 100; in dw_dp_set_phy_default_config()
1004 phy_cfg.dp.ssc = link->caps.ssc; in dw_dp_set_phy_default_config()
1005 phy_cfg.dp.set_lanes = true; in dw_dp_set_phy_default_config()
1006 phy_cfg.dp.set_rate = true; in dw_dp_set_phy_default_config()
1007 phy_cfg.dp.set_voltages = true; in dw_dp_set_phy_default_config()
1008 ret = generic_phy_configure(&dp->phy, &phy_cfg); in dw_dp_set_phy_default_config()
1012 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_LANES, in dw_dp_set_phy_default_config()
1013 FIELD_PREP(PHY_LANES, link->lanes / 2)); in dw_dp_set_phy_default_config()
1015 switch (link->rate) { in dw_dp_set_phy_default_config()
1030 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_RATE, in dw_dp_set_phy_default_config()
1033 /* Move PHY to P0 */ in dw_dp_set_phy_default_config()
1034 regmap_update_bits(dp->regmap, DPTX_PHYIF_CTRL, PHY_POWERDOWN, in dw_dp_set_phy_default_config()
1037 dw_dp_phy_xmit_enable(dp, link->lanes); in dw_dp_set_phy_default_config()
1039 regmap_update_bits(dp->regmap, DPTX_CCTL, ENHANCE_FRAMING_EN, in dw_dp_set_phy_default_config()
1042 dw_dp_phy_set_pattern(dp, DPTX_PHY_PATTERN_NONE); in dw_dp_set_phy_default_config()
1046 static int dw_dp_send_sdp(struct dw_dp *dp, struct dw_dp_sdp *sdp) in dw_dp_send_sdp() argument
1048 const u8 *payload = sdp->db; in dw_dp_send_sdp()
1055 regmap_write(dp->regmap, reg, get_unaligned_le32(&sdp->header)); in dw_dp_send_sdp()
1059 regmap_write(dp->regmap, reg + i * 4, in dw_dp_send_sdp()
1062 if (sdp->flags & DPTX_SDP_VERTICAL_INTERVAL) in dw_dp_send_sdp()
1063 regmap_update_bits(dp->regmap, DPTX_SDP_VERTICAL_CTRL, in dw_dp_send_sdp()
1067 if (sdp->flags & DPTX_SDP_HORIZONTAL_INTERVAL) in dw_dp_send_sdp()
1068 regmap_update_bits(dp->regmap, DPTX_SDP_HORIZONTAL_CTRL, in dw_dp_send_sdp()
1078 sdp->header.HB0 = 0; in dw_dp_vsc_sdp_pack()
1079 sdp->header.HB1 = DP_SDP_VSC; in dw_dp_vsc_sdp_pack()
1080 sdp->header.HB2 = vsc->revision; in dw_dp_vsc_sdp_pack()
1081 sdp->header.HB3 = vsc->length; in dw_dp_vsc_sdp_pack()
1083 sdp->db[16] = (vsc->pixelformat & 0xf) << 4; in dw_dp_vsc_sdp_pack()
1084 sdp->db[16] |= vsc->colorimetry & 0xf; in dw_dp_vsc_sdp_pack()
1086 switch (vsc->bpc) { in dw_dp_vsc_sdp_pack()
1088 sdp->db[17] = 0x1; in dw_dp_vsc_sdp_pack()
1091 sdp->db[17] = 0x2; in dw_dp_vsc_sdp_pack()
1094 sdp->db[17] = 0x3; in dw_dp_vsc_sdp_pack()
1097 sdp->db[17] = 0x4; in dw_dp_vsc_sdp_pack()
1104 if (vsc->dynamic_range == DP_DYNAMIC_RANGE_CTA) in dw_dp_vsc_sdp_pack()
1105 sdp->db[17] |= 0x80; in dw_dp_vsc_sdp_pack()
1107 sdp->db[18] = vsc->content_type & 0x7; in dw_dp_vsc_sdp_pack()
1109 sdp->flags |= DPTX_SDP_VERTICAL_INTERVAL; in dw_dp_vsc_sdp_pack()
1112 static int dw_dp_send_vsc_sdp(struct dw_dp *dp) in dw_dp_send_vsc_sdp() argument
1114 struct dw_dp_video *video = &dp->video; in dw_dp_send_vsc_sdp()
1121 switch (video->color_format) { in dw_dp_send_vsc_sdp()
1137 if (video->color_format == DRM_COLOR_FORMAT_RGB444) in dw_dp_send_vsc_sdp()
1142 vsc.bpc = video->bpc; in dw_dp_send_vsc_sdp()
1148 return dw_dp_send_sdp(dp, &sdp); in dw_dp_send_vsc_sdp()
1151 static int dw_dp_video_set_pixel_mode(struct dw_dp *dp, u8 pixel_mode) in dw_dp_video_set_pixel_mode() argument
1159 return -EINVAL; in dw_dp_video_set_pixel_mode()
1162 regmap_update_bits(dp->regmap, DPTX_VSAMPLE_CTRL, PIXEL_MODE_SELECT, in dw_dp_video_set_pixel_mode()
1168 static int dw_dp_video_set_msa(struct dw_dp *dp, u8 color_format, u8 bpc, in dw_dp_video_set_msa() argument
1171 struct dw_dp_link *link = &dp->link; in dw_dp_video_set_msa()
1174 if (link->vsc_sdp_extension_for_colorimetry_supported) in dw_dp_video_set_msa()
1190 return -EINVAL; in dw_dp_video_set_msa()
1210 return -EINVAL; in dw_dp_video_set_msa()
1213 regmap_write(dp->regmap, DPTX_VIDEO_MSA1, in dw_dp_video_set_msa()
1215 regmap_write(dp->regmap, DPTX_VIDEO_MSA2, FIELD_PREP(MISC0, misc)); in dw_dp_video_set_msa()
1216 regmap_write(dp->regmap, DPTX_VIDEO_MSA3, FIELD_PREP(MISC1, misc >> 8)); in dw_dp_video_set_msa()
1221 static int dw_dp_video_enable(struct dw_dp *dp) in dw_dp_video_enable() argument
1223 struct dw_dp_video *video = &dp->video; in dw_dp_video_enable()
1224 struct dw_dp_link *link = &dp->link; in dw_dp_video_enable()
1225 struct drm_display_mode *mode = &video->mode; in dw_dp_video_enable()
1226 u8 color_format = video->color_format; in dw_dp_video_enable()
1227 u8 bpc = video->bpc; in dw_dp_video_enable()
1228 u8 pixel_mode = video->pixel_mode; in dw_dp_video_enable()
1229 u8 bpp = video->bpp, init_threshold, vic; in dw_dp_video_enable()
1232 u32 vstart = mode->vtotal - mode->vsync_start; in dw_dp_video_enable()
1233 u32 hstart = mode->htotal - mode->hsync_start; in dw_dp_video_enable()
1240 ret = dw_dp_video_set_pixel_mode(dp, pixel_mode); in dw_dp_video_enable()
1244 ret = dw_dp_video_set_msa(dp, color_format, bpc, vstart, hstart); in dw_dp_video_enable()
1248 regmap_update_bits(dp->regmap, DPTX_VSAMPLE_CTRL, VIDEO_MAPPING, in dw_dp_video_enable()
1249 FIELD_PREP(VIDEO_MAPPING, video->video_mapping)); in dw_dp_video_enable()
1253 if (mode->flags & DRM_MODE_FLAG_PHSYNC) in dw_dp_video_enable()
1255 if (mode->flags & DRM_MODE_FLAG_PVSYNC) in dw_dp_video_enable()
1257 regmap_write(dp->regmap, DPTX_VINPUT_POLARITY_CTRL, value); in dw_dp_video_enable()
1260 hactive = mode->hdisplay; in dw_dp_video_enable()
1261 hblank = mode->htotal - mode->hdisplay; in dw_dp_video_enable()
1263 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in dw_dp_video_enable()
1274 regmap_write(dp->regmap, DPTX_VIDEO_CONFIG1, value); in dw_dp_video_enable()
1277 vblank = mode->vtotal - mode->vdisplay; in dw_dp_video_enable()
1278 vactive = mode->vdisplay; in dw_dp_video_enable()
1279 regmap_write(dp->regmap, DPTX_VIDEO_CONFIG2, in dw_dp_video_enable()
1283 h_sync_width = mode->hsync_end - mode->hsync_start; in dw_dp_video_enable()
1284 h_front_porch = mode->hsync_start - mode->hdisplay; in dw_dp_video_enable()
1285 regmap_write(dp->regmap, DPTX_VIDEO_CONFIG3, in dw_dp_video_enable()
1290 v_sync_width = mode->vsync_end - mode->vsync_start; in dw_dp_video_enable()
1291 v_front_porch = mode->vsync_start - mode->vdisplay; in dw_dp_video_enable()
1292 regmap_write(dp->regmap, DPTX_VIDEO_CONFIG4, in dw_dp_video_enable()
1297 peak_stream_bandwidth = mode->clock * bpp / 8; in dw_dp_video_enable()
1298 link_bandwidth = (link->rate / 1000) * link->lanes; in dw_dp_video_enable()
1301 average_bytes_per_tu_frac = ts / 100 - average_bytes_per_tu * 10; in dw_dp_video_enable()
1318 t1 = (4 * 1000 / 9) * link->lanes; in dw_dp_video_enable()
1322 t1 = (1000 / 2) * link->lanes; in dw_dp_video_enable()
1325 t1 = (1000 / 3) * link->lanes; in dw_dp_video_enable()
1327 t1 = (3000 / 16) * link->lanes; in dw_dp_video_enable()
1332 t1 = (2000 / 5) * link->lanes; in dw_dp_video_enable()
1334 t1 = (4000 / 15) * link->lanes; in dw_dp_video_enable()
1339 t1 = (1000 / 6) * link->lanes; in dw_dp_video_enable()
1341 t1 = (1000 / 3) * link->lanes; in dw_dp_video_enable()
1343 t1 = (2000 / 9) * link->lanes; in dw_dp_video_enable()
1349 t1 = (1000 / 6) * link->lanes; in dw_dp_video_enable()
1351 t1 = (1000 / 4) * link->lanes; in dw_dp_video_enable()
1354 return -EINVAL; in dw_dp_video_enable()
1358 t2 = (link->rate / 4) * 1000 / (mode->clock / 2); in dw_dp_video_enable()
1360 t2 = (link->rate / 4) * 1000 / mode->clock; in dw_dp_video_enable()
1371 regmap_write(dp->regmap, DPTX_VIDEO_CONFIG5, in dw_dp_video_enable()
1379 hblank_interval = hblank * (link->rate / 4) / mode->clock; in dw_dp_video_enable()
1380 regmap_write(dp->regmap, DPTX_VIDEO_HBLANK_INTERVAL, in dw_dp_video_enable()
1385 regmap_update_bits(dp->regmap, DPTX_VSAMPLE_CTRL, VIDEO_STREAM_ENABLE, in dw_dp_video_enable()
1388 if (link->vsc_sdp_extension_for_colorimetry_supported) in dw_dp_video_enable()
1389 dw_dp_send_vsc_sdp(dp); in dw_dp_video_enable()
1394 static bool dw_dp_detect(struct dw_dp *dp) in dw_dp_detect() argument
1398 if (dm_gpio_is_valid(&dp->hpd_gpio)) in dw_dp_detect()
1399 return dm_gpio_get_value(&dp->hpd_gpio); in dw_dp_detect()
1401 regmap_read(dp->regmap, DPTX_HPD_STATUS, &value); in dw_dp_detect()
1403 regmap_write(dp->regmap, DPTX_HPD_STATUS, HPD_HOT_PLUG); in dw_dp_detect()
1412 struct connector_state *conn_state = &state->conn_state; in dw_dp_connector_init()
1413 struct dw_dp *dp = dev_get_priv(conn->dev); in dw_dp_connector_init() local
1416 conn_state->output_if |= dp->id ? VOP_OUTPUT_IF_DP1 : VOP_OUTPUT_IF_DP0; in dw_dp_connector_init()
1417 conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA; in dw_dp_connector_init()
1418 conn_state->color_space = V4L2_COLORSPACE_DEFAULT; in dw_dp_connector_init()
1420 clk_set_defaults(dp->dev); in dw_dp_connector_init()
1422 reset_assert(&dp->reset); in dw_dp_connector_init()
1424 reset_deassert(&dp->reset); in dw_dp_connector_init()
1426 conn_state->disp_info = rockchip_get_disp_info(conn_state->type, in dw_dp_connector_init()
1427 dp->id); in dw_dp_connector_init()
1428 dw_dp_init(dp); in dw_dp_connector_init()
1429 ret = generic_phy_power_on(&dp->phy); in dw_dp_connector_init()
1437 struct connector_state *conn_state = &state->conn_state; in dw_dp_connector_get_edid()
1438 struct dw_dp *dp = dev_get_priv(conn->dev); in dw_dp_connector_get_edid() local
1440 ret = drm_do_get_edid(&dp->aux.ddc, conn_state->edid); in dw_dp_connector_get_edid()
1452 if (fmt->bus_format == bus_format) in dw_dp_get_output_fmts_index()
1464 struct connector_state *conn_state = &state->conn_state; in dw_dp_connector_prepare()
1465 struct dw_dp *dp = dev_get_priv(conn->dev); in dw_dp_connector_prepare() local
1466 struct dw_dp_video *video = &dp->video; in dw_dp_connector_prepare()
1469 bus_fmt = dw_dp_get_output_fmts_index(conn_state->bus_format); in dw_dp_connector_prepare()
1470 video->video_mapping = possible_output_fmts[bus_fmt].video_mapping; in dw_dp_connector_prepare()
1471 video->color_format = possible_output_fmts[bus_fmt].color_format; in dw_dp_connector_prepare()
1472 video->bus_format = possible_output_fmts[bus_fmt].bus_format; in dw_dp_connector_prepare()
1473 video->bpc = possible_output_fmts[bus_fmt].bpc; in dw_dp_connector_prepare()
1474 video->bpp = possible_output_fmts[bus_fmt].bpp; in dw_dp_connector_prepare()
1481 struct connector_state *conn_state = &state->conn_state; in dw_dp_connector_enable()
1482 struct drm_display_mode *mode = &conn_state->mode; in dw_dp_connector_enable()
1483 struct dw_dp *dp = dev_get_priv(conn->dev); in dw_dp_connector_enable() local
1484 struct dw_dp_video *video = &dp->video; in dw_dp_connector_enable()
1487 memcpy(&video->mode, mode, sizeof(video->mode)); in dw_dp_connector_enable()
1488 video->pixel_mode = DPTX_MP_QUAD_PIXEL; in dw_dp_connector_enable()
1490 if (dp->force_output) { in dw_dp_connector_enable()
1491 ret = dw_dp_set_phy_default_config(dp); in dw_dp_connector_enable()
1495 ret = dw_dp_link_enable(dp); in dw_dp_connector_enable()
1502 ret = dw_dp_video_enable(dp); in dw_dp_connector_enable()
1520 struct dw_dp *dp = dev_get_priv(conn->dev); in dw_dp_connector_detect() local
1524 status = dw_dp_detect(dp); in dw_dp_connector_detect()
1530 if (state->force_output && !status) in dw_dp_connector_detect()
1531 dp->force_output = true; in dw_dp_connector_detect()
1533 if (!status && !dp->force_output) in dw_dp_connector_detect()
1534 generic_phy_power_off(&dp->phy); in dw_dp_connector_detect()
1536 if (status && !dp->force_output) { in dw_dp_connector_detect()
1537 ret = dw_dp_link_probe(dp); in dw_dp_connector_detect()
1539 printf("failed to probe DP link: %d\n", ret); in dw_dp_connector_detect()
1545 static int dw_dp_mode_valid(struct dw_dp *dp, struct hdmi_edid_data *edid_data) in dw_dp_mode_valid() argument
1547 struct dw_dp_link *link = &dp->link; in dw_dp_mode_valid()
1548 struct drm_display_info *di = &edid_data->display_info; in dw_dp_mode_valid()
1552 if (di->color_formats & DRM_COLOR_FORMAT_YCRCB420 && in dw_dp_mode_valid()
1553 link->vsc_sdp_extension_for_colorimetry_supported) in dw_dp_mode_valid()
1555 else if (di->color_formats & DRM_COLOR_FORMAT_YCRCB422) in dw_dp_mode_valid()
1557 else if (di->color_formats & DRM_COLOR_FORMAT_RGB444) in dw_dp_mode_valid()
1562 for (i = 0; i < edid_data->modes; i++) { in dw_dp_mode_valid()
1563 if (!dw_dp_bandwidth_ok(dp, &edid_data->mode_buf[i], min_bpp, link->lanes, in dw_dp_mode_valid()
1564 link->rate)) in dw_dp_mode_valid()
1565 edid_data->mode_buf[i].invalid = true; in dw_dp_mode_valid()
1571 static u32 dw_dp_get_output_bus_fmts(struct dw_dp *dp, struct hdmi_edid_data *edid_data) in dw_dp_get_output_bus_fmts() argument
1573 struct dw_dp_link *link = &dp->link; in dw_dp_get_output_bus_fmts()
1579 if (fmt->bpc > edid_data->display_info.bpc) in dw_dp_get_output_bus_fmts()
1582 if (!(edid_data->display_info.color_formats & fmt->color_format)) in dw_dp_get_output_bus_fmts()
1585 if (fmt->color_format == DRM_COLOR_FORMAT_YCRCB420 && in dw_dp_get_output_bus_fmts()
1586 !link->vsc_sdp_extension_for_colorimetry_supported) in dw_dp_get_output_bus_fmts()
1589 if (drm_mode_is_420(&edid_data->display_info, edid_data->preferred_mode) && in dw_dp_get_output_bus_fmts()
1590 fmt->color_format != DRM_COLOR_FORMAT_YCRCB420) in dw_dp_get_output_bus_fmts()
1593 if (!dw_dp_bandwidth_ok(dp, edid_data->preferred_mode, fmt->bpp, link->lanes, in dw_dp_get_output_bus_fmts()
1594 link->rate)) in dw_dp_get_output_bus_fmts()
1609 struct connector_state *conn_state = &state->conn_state; in dw_dp_connector_get_timing()
1610 struct dw_dp *dp = dev_get_priv(conn->dev); in dw_dp_connector_get_timing() local
1611 struct drm_display_mode *mode = &conn_state->mode; in dw_dp_connector_get_timing()
1619 return -ENOMEM; in dw_dp_connector_get_timing()
1625 if (!dp->force_output) { in dw_dp_connector_get_timing()
1626 ret = drm_do_get_edid(&dp->aux.ddc, conn_state->edid); in dw_dp_connector_get_timing()
1628 ret = drm_add_edid_modes(&edid_data, conn_state->edid); in dw_dp_connector_get_timing()
1636 if (state->conn_state.secondary) { in dw_dp_connector_get_timing()
1637 rect.width = state->crtc_state.max_output.width / 2; in dw_dp_connector_get_timing()
1638 rect.height = state->crtc_state.max_output.height / 2; in dw_dp_connector_get_timing()
1640 rect.width = state->crtc_state.max_output.width; in dw_dp_connector_get_timing()
1641 rect.height = state->crtc_state.max_output.height; in dw_dp_connector_get_timing()
1645 dw_dp_mode_valid(dp, &edid_data); in dw_dp_connector_get_timing()
1649 ret = -EINVAL; in dw_dp_connector_get_timing()
1661 if (state->force_output) in dw_dp_connector_get_timing()
1662 bus_fmt = dw_dp_get_output_fmts_index(state->force_bus_format); in dw_dp_connector_get_timing()
1664 bus_fmt = dw_dp_get_output_bus_fmts(dp, &edid_data); in dw_dp_connector_get_timing()
1666 conn_state->bus_format = possible_output_fmts[bus_fmt].bus_format; in dw_dp_connector_get_timing()
1670 conn_state->output_mode = ROCKCHIP_OUT_MODE_YUV420; in dw_dp_connector_get_timing()
1673 conn_state->output_mode = ROCKCHIP_OUT_MODE_S888_DUMMY; in dw_dp_connector_get_timing()
1678 conn_state->output_mode = ROCKCHIP_OUT_MODE_AAAA; in dw_dp_connector_get_timing()
1698 static int dw_dp_ddc_init(struct dw_dp *dp) in dw_dp_ddc_init() argument
1700 dp->aux.name = "dw-dp"; in dw_dp_ddc_init()
1701 dp->aux.dev = dp->dev; in dw_dp_ddc_init()
1702 dp->aux.transfer = dw_dp_aux_transfer; in dw_dp_ddc_init()
1703 dp->aux.ddc.ddc_xfer = drm_dp_i2c_xfer; in dw_dp_ddc_init()
1708 static u32 dw_dp_parse_link_frequencies(struct dw_dp *dp) in dw_dp_parse_link_frequencies() argument
1710 struct udevice *dev = dp->dev; in dw_dp_parse_link_frequencies()
1714 endpoint = rockchip_of_graph_get_endpoint_by_regs(dev->node, 1, 0); in dw_dp_parse_link_frequencies()
1718 if (of_property_read_u64(endpoint, "link-frequencies", &frequency) < 0) in dw_dp_parse_link_frequencies()
1740 static int dw_dp_parse_dt(struct dw_dp *dp) in dw_dp_parse_dt() argument
1742 dp->force_hpd = dev_read_bool(dp->dev, "force-hpd"); in dw_dp_parse_dt()
1744 dp->max_link_rate = dw_dp_parse_link_frequencies(dp); in dw_dp_parse_dt()
1745 if (!dp->max_link_rate) in dw_dp_parse_dt()
1746 dp->max_link_rate = 810000; in dw_dp_parse_dt()
1753 struct dw_dp *dp = dev_get_priv(dev); in dw_dp_probe() local
1756 ret = regmap_init_mem(dev, &dp->regmap); in dw_dp_probe()
1760 dp->id = of_alias_get_id(ofnode_to_np(dev->node), "dp"); in dw_dp_probe()
1761 if (dp->id < 0) in dw_dp_probe()
1762 dp->id = 0; in dw_dp_probe()
1764 ret = reset_get_by_index(dev, 0, &dp->reset); in dw_dp_probe()
1770 ret = gpio_request_by_name(dev, "hpd-gpios", 0, &dp->hpd_gpio, in dw_dp_probe()
1772 if (ret && ret != -ENOENT) { in dw_dp_probe()
1777 generic_phy_get_by_index(dev, 0, &dp->phy); in dw_dp_probe()
1779 dp->dev = dev; in dw_dp_probe()
1781 ret = dw_dp_parse_dt(dp); in dw_dp_probe()
1787 dw_dp_ddc_init(dp); in dw_dp_probe()
1789 rockchip_connector_bind(&dp->connector, dev, dp->id, &dw_dp_connector_funcs, NULL, in dw_dp_probe()
1797 .compatible = "rockchip,rk3588-dp",