aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/bridge/tc358767.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/bridge/tc358767.c')
-rw-r--r--drivers/gpu/drm/bridge/tc358767.c73
1 files changed, 40 insertions, 33 deletions
diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c
index 8571cfd877c5..8636e7eeb731 100644
--- a/drivers/gpu/drm/bridge/tc358767.c
+++ b/drivers/gpu/drm/bridge/tc358767.c
@@ -97,7 +97,7 @@
97#define DP0_ACTIVEVAL 0x0650 97#define DP0_ACTIVEVAL 0x0650
98#define DP0_SYNCVAL 0x0654 98#define DP0_SYNCVAL 0x0654
99#define DP0_MISC 0x0658 99#define DP0_MISC 0x0658
100#define TU_SIZE_RECOMMENDED (0x3f << 16) /* LSCLK cycles per TU */ 100#define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */
101#define BPC_6 (0 << 5) 101#define BPC_6 (0 << 5)
102#define BPC_8 (1 << 5) 102#define BPC_8 (1 << 5)
103 103
@@ -318,7 +318,7 @@ static ssize_t tc_aux_transfer(struct drm_dp_aux *aux,
318 tmp = (tmp << 8) | buf[i]; 318 tmp = (tmp << 8) | buf[i];
319 i++; 319 i++;
320 if (((i % 4) == 0) || (i == size)) { 320 if (((i % 4) == 0) || (i == size)) {
321 tc_write(DP0_AUXWDATA(i >> 2), tmp); 321 tc_write(DP0_AUXWDATA((i - 1) >> 2), tmp);
322 tmp = 0; 322 tmp = 0;
323 } 323 }
324 } 324 }
@@ -603,8 +603,15 @@ static int tc_get_display_props(struct tc_data *tc)
603 ret = drm_dp_link_probe(&tc->aux, &tc->link.base); 603 ret = drm_dp_link_probe(&tc->aux, &tc->link.base);
604 if (ret < 0) 604 if (ret < 0)
605 goto err_dpcd_read; 605 goto err_dpcd_read;
606 if ((tc->link.base.rate != 162000) && (tc->link.base.rate != 270000)) 606 if (tc->link.base.rate != 162000 && tc->link.base.rate != 270000) {
607 goto err_dpcd_inval; 607 dev_dbg(tc->dev, "Falling to 2.7 Gbps rate\n");
608 tc->link.base.rate = 270000;
609 }
610
611 if (tc->link.base.num_lanes > 2) {
612 dev_dbg(tc->dev, "Falling to 2 lanes\n");
613 tc->link.base.num_lanes = 2;
614 }
608 615
609 ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp); 616 ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp);
610 if (ret < 0) 617 if (ret < 0)
@@ -637,9 +644,6 @@ static int tc_get_display_props(struct tc_data *tc)
637err_dpcd_read: 644err_dpcd_read:
638 dev_err(tc->dev, "failed to read DPCD: %d\n", ret); 645 dev_err(tc->dev, "failed to read DPCD: %d\n", ret);
639 return ret; 646 return ret;
640err_dpcd_inval:
641 dev_err(tc->dev, "invalid DPCD\n");
642 return -EINVAL;
643} 647}
644 648
645static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode) 649static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
@@ -655,6 +659,14 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
655 int lower_margin = mode->vsync_start - mode->vdisplay; 659 int lower_margin = mode->vsync_start - mode->vdisplay;
656 int vsync_len = mode->vsync_end - mode->vsync_start; 660 int vsync_len = mode->vsync_end - mode->vsync_start;
657 661
662 /*
663 * Recommended maximum number of symbols transferred in a transfer unit:
664 * DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size,
665 * (output active video bandwidth in bytes))
666 * Must be less than tu_size.
667 */
668 max_tu_symbol = TU_SIZE_RECOMMENDED - 1;
669
658 dev_dbg(tc->dev, "set mode %dx%d\n", 670 dev_dbg(tc->dev, "set mode %dx%d\n",
659 mode->hdisplay, mode->vdisplay); 671 mode->hdisplay, mode->vdisplay);
660 dev_dbg(tc->dev, "H margin %d,%d sync %d\n", 672 dev_dbg(tc->dev, "H margin %d,%d sync %d\n",
@@ -664,13 +676,18 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
664 dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal); 676 dev_dbg(tc->dev, "total: %dx%d\n", mode->htotal, mode->vtotal);
665 677
666 678
667 /* LCD Ctl Frame Size */ 679 /*
668 tc_write(VPCTRL0, (0x40 << 20) /* VSDELAY */ | 680 * LCD Ctl Frame Size
681 * datasheet is not clear of vsdelay in case of DPI
682 * assume we do not need any delay when DPI is a source of
683 * sync signals
684 */
685 tc_write(VPCTRL0, (0 << 20) /* VSDELAY */ |
669 OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED); 686 OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED);
670 tc_write(HTIM01, (left_margin << 16) | /* H back porch */ 687 tc_write(HTIM01, (ALIGN(left_margin, 2) << 16) | /* H back porch */
671 (hsync_len << 0)); /* Hsync */ 688 (ALIGN(hsync_len, 2) << 0)); /* Hsync */
672 tc_write(HTIM02, (right_margin << 16) | /* H front porch */ 689 tc_write(HTIM02, (ALIGN(right_margin, 2) << 16) | /* H front porch */
673 (mode->hdisplay << 0)); /* width */ 690 (ALIGN(mode->hdisplay, 2) << 0)); /* width */
674 tc_write(VTIM01, (upper_margin << 16) | /* V back porch */ 691 tc_write(VTIM01, (upper_margin << 16) | /* V back porch */
675 (vsync_len << 0)); /* Vsync */ 692 (vsync_len << 0)); /* Vsync */
676 tc_write(VTIM02, (lower_margin << 16) | /* V front porch */ 693 tc_write(VTIM02, (lower_margin << 16) | /* V front porch */
@@ -689,7 +706,7 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
689 /* DP Main Stream Attributes */ 706 /* DP Main Stream Attributes */
690 vid_sync_dly = hsync_len + left_margin + mode->hdisplay; 707 vid_sync_dly = hsync_len + left_margin + mode->hdisplay;
691 tc_write(DP0_VIDSYNCDELAY, 708 tc_write(DP0_VIDSYNCDELAY,
692 (0x003e << 16) | /* thresh_dly */ 709 (max_tu_symbol << 16) | /* thresh_dly */
693 (vid_sync_dly << 0)); 710 (vid_sync_dly << 0));
694 711
695 tc_write(DP0_TOTALVAL, (mode->vtotal << 16) | (mode->htotal)); 712 tc_write(DP0_TOTALVAL, (mode->vtotal << 16) | (mode->htotal));
@@ -705,14 +722,8 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
705 tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | 722 tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
706 DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888); 723 DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
707 724
708 /* 725 tc_write(DP0_MISC, (max_tu_symbol << 23) | (TU_SIZE_RECOMMENDED << 16) |
709 * Recommended maximum number of symbols transferred in a transfer unit: 726 BPC_8);
710 * DIV_ROUND_UP((input active video bandwidth in bytes) * tu_size,
711 * (output active video bandwidth in bytes))
712 * Must be less than tu_size.
713 */
714 max_tu_symbol = TU_SIZE_RECOMMENDED - 1;
715 tc_write(DP0_MISC, (max_tu_symbol << 23) | TU_SIZE_RECOMMENDED | BPC_8);
716 727
717 return 0; 728 return 0;
718err: 729err:
@@ -808,8 +819,6 @@ static int tc_main_link_setup(struct tc_data *tc)
808 unsigned int rate; 819 unsigned int rate;
809 u32 dp_phy_ctrl; 820 u32 dp_phy_ctrl;
810 int timeout; 821 int timeout;
811 bool aligned;
812 bool ready;
813 u32 value; 822 u32 value;
814 int ret; 823 int ret;
815 u8 tmp[8]; 824 u8 tmp[8];
@@ -954,16 +963,15 @@ static int tc_main_link_setup(struct tc_data *tc)
954 ret = drm_dp_dpcd_read_link_status(aux, tmp + 2); 963 ret = drm_dp_dpcd_read_link_status(aux, tmp + 2);
955 if (ret < 0) 964 if (ret < 0)
956 goto err_dpcd_read; 965 goto err_dpcd_read;
957 ready = (tmp[2] == ((DP_CHANNEL_EQ_BITS << 4) | /* Lane1 */ 966 } while ((--timeout) &&
958 DP_CHANNEL_EQ_BITS)); /* Lane0 */ 967 !(drm_dp_channel_eq_ok(tmp + 2, tc->link.base.num_lanes)));
959 aligned = tmp[4] & DP_INTERLANE_ALIGN_DONE;
960 } while ((--timeout) && !(ready && aligned));
961 968
962 if (timeout == 0) { 969 if (timeout == 0) {
963 /* Read DPCD 0x200-0x201 */ 970 /* Read DPCD 0x200-0x201 */
964 ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT, tmp, 2); 971 ret = drm_dp_dpcd_read(aux, DP_SINK_COUNT, tmp, 2);
965 if (ret < 0) 972 if (ret < 0)
966 goto err_dpcd_read; 973 goto err_dpcd_read;
974 dev_err(dev, "channel(s) EQ not ok\n");
967 dev_info(dev, "0x0200 SINK_COUNT: 0x%02x\n", tmp[0]); 975 dev_info(dev, "0x0200 SINK_COUNT: 0x%02x\n", tmp[0]);
968 dev_info(dev, "0x0201 DEVICE_SERVICE_IRQ_VECTOR: 0x%02x\n", 976 dev_info(dev, "0x0201 DEVICE_SERVICE_IRQ_VECTOR: 0x%02x\n",
969 tmp[1]); 977 tmp[1]);
@@ -974,10 +982,6 @@ static int tc_main_link_setup(struct tc_data *tc)
974 dev_info(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n", 982 dev_info(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n",
975 tmp[6]); 983 tmp[6]);
976 984
977 if (!ready)
978 dev_err(dev, "Lane0/1 not ready\n");
979 if (!aligned)
980 dev_err(dev, "Lane0/1 not aligned\n");
981 return -EAGAIN; 985 return -EAGAIN;
982 } 986 }
983 987
@@ -1099,7 +1103,10 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
1099static int tc_connector_mode_valid(struct drm_connector *connector, 1103static int tc_connector_mode_valid(struct drm_connector *connector,
1100 struct drm_display_mode *mode) 1104 struct drm_display_mode *mode)
1101{ 1105{
1102 /* Accept any mode */ 1106 /* DPI interface clock limitation: upto 154 MHz */
1107 if (mode->clock > 154000)
1108 return MODE_CLOCK_HIGH;
1109
1103 return MODE_OK; 1110 return MODE_OK;
1104} 1111}
1105 1112