aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2018-06-21 19:58:57 -0400
committerDave Airlie <airlied@redhat.com>2018-06-21 21:03:43 -0400
commitf3294568bbb19cbfc53451de192df6daae80f9b3 (patch)
treea9edc98aa1ef92a0f03c0d4a743b5dd87a3c37c0
parent8325e6e36c239d5df2eecfb7983f49e0e6f5b2a7 (diff)
parente8b92efa629dac0e70ea4145c5e70616de5f89c8 (diff)
Merge tag 'drm-misc-fixes-2018-06-21' of git://anongit.freedesktop.org/drm/drm-misc into drm-fixes
Fixes for v4.18-rc2: - A reversion of a commit in drm/sun4i to fix a run-time fault. - Various fixes to the sii8620 bridge. - Small bugfix to correctly check stride in atmel-hlcdc. Signed-off-by: Dave Airlie <airlied@redhat.com> Link: https://patchwork.freedesktop.org/patch/msgid/787d4bef-a579-4046-d0fc-f8c2c5b80c25@linux.intel.com
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c2
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c309
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c25
3 files changed, 118 insertions, 218 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
index 73c875db45f4..47e0992f3908 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c
@@ -839,7 +839,7 @@ static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
839 return ret; 839 return ret;
840 } 840 }
841 841
842 if (desc->layout.xstride && desc->layout.pstride) { 842 if (desc->layout.xstride[0] && desc->layout.pstride[0]) {
843 int ret; 843 int ret;
844 844
845 ret = drm_plane_create_rotation_property(&plane->base, 845 ret = drm_plane_create_rotation_property(&plane->base,
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 7ab36042a822..250effa0e6b8 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -36,8 +36,11 @@
36 36
37#define SII8620_BURST_BUF_LEN 288 37#define SII8620_BURST_BUF_LEN 288
38#define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3) 38#define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
39#define MHL1_MAX_LCLK 225000 39
40#define MHL3_MAX_LCLK 600000 40#define MHL1_MAX_PCLK 75000
41#define MHL1_MAX_PCLK_PP_MODE 150000
42#define MHL3_MAX_PCLK 200000
43#define MHL3_MAX_PCLK_PP_MODE 300000
41 44
42enum sii8620_mode { 45enum sii8620_mode {
43 CM_DISCONNECTED, 46 CM_DISCONNECTED,
@@ -80,6 +83,9 @@ struct sii8620 {
80 u8 devcap[MHL_DCAP_SIZE]; 83 u8 devcap[MHL_DCAP_SIZE];
81 u8 xdevcap[MHL_XDC_SIZE]; 84 u8 xdevcap[MHL_XDC_SIZE];
82 u8 avif[HDMI_INFOFRAME_SIZE(AVI)]; 85 u8 avif[HDMI_INFOFRAME_SIZE(AVI)];
86 bool feature_complete;
87 bool devcap_read;
88 bool sink_detected;
83 struct edid *edid; 89 struct edid *edid;
84 unsigned int gen2_write_burst:1; 90 unsigned int gen2_write_burst:1;
85 enum sii8620_mt_state mt_state; 91 enum sii8620_mt_state mt_state;
@@ -476,7 +482,7 @@ static void sii8620_update_array(u8 *dst, u8 *src, int count)
476 } 482 }
477} 483}
478 484
479static void sii8620_sink_detected(struct sii8620 *ctx, int ret) 485static void sii8620_identify_sink(struct sii8620 *ctx)
480{ 486{
481 static const char * const sink_str[] = { 487 static const char * const sink_str[] = {
482 [SINK_NONE] = "NONE", 488 [SINK_NONE] = "NONE",
@@ -487,7 +493,7 @@ static void sii8620_sink_detected(struct sii8620 *ctx, int ret)
487 char sink_name[20]; 493 char sink_name[20];
488 struct device *dev = ctx->dev; 494 struct device *dev = ctx->dev;
489 495
490 if (ret < 0) 496 if (!ctx->sink_detected || !ctx->devcap_read)
491 return; 497 return;
492 498
493 sii8620_fetch_edid(ctx); 499 sii8620_fetch_edid(ctx);
@@ -496,6 +502,7 @@ static void sii8620_sink_detected(struct sii8620 *ctx, int ret)
496 sii8620_mhl_disconnected(ctx); 502 sii8620_mhl_disconnected(ctx);
497 return; 503 return;
498 } 504 }
505 sii8620_set_upstream_edid(ctx);
499 506
500 if (drm_detect_hdmi_monitor(ctx->edid)) 507 if (drm_detect_hdmi_monitor(ctx->edid))
501 ctx->sink_type = SINK_HDMI; 508 ctx->sink_type = SINK_HDMI;
@@ -508,53 +515,6 @@ static void sii8620_sink_detected(struct sii8620 *ctx, int ret)
508 sink_str[ctx->sink_type], sink_name); 515 sink_str[ctx->sink_type], sink_name);
509} 516}
510 517
511static void sii8620_hsic_init(struct sii8620 *ctx)
512{
513 if (!sii8620_is_mhl3(ctx))
514 return;
515
516 sii8620_write(ctx, REG_FCGC,
517 BIT_FCGC_HSIC_HOSTMODE | BIT_FCGC_HSIC_ENABLE);
518 sii8620_setbits(ctx, REG_HRXCTRL3,
519 BIT_HRXCTRL3_HRX_STAY_RESET | BIT_HRXCTRL3_STATUS_EN, ~0);
520 sii8620_setbits(ctx, REG_TTXNUMB, MSK_TTXNUMB_TTX_NUMBPS, 4);
521 sii8620_setbits(ctx, REG_TRXCTRL, BIT_TRXCTRL_TRX_FROM_SE_COC, ~0);
522 sii8620_setbits(ctx, REG_HTXCTRL, BIT_HTXCTRL_HTX_DRVCONN1, 0);
523 sii8620_setbits(ctx, REG_KEEPER, MSK_KEEPER_MODE, VAL_KEEPER_MODE_HOST);
524 sii8620_write_seq_static(ctx,
525 REG_TDMLLCTL, 0,
526 REG_UTSRST, BIT_UTSRST_HRX_SRST | BIT_UTSRST_HTX_SRST |
527 BIT_UTSRST_KEEPER_SRST | BIT_UTSRST_FC_SRST,
528 REG_UTSRST, BIT_UTSRST_HRX_SRST | BIT_UTSRST_HTX_SRST,
529 REG_HRXINTL, 0xff,
530 REG_HRXINTH, 0xff,
531 REG_TTXINTL, 0xff,
532 REG_TTXINTH, 0xff,
533 REG_TRXINTL, 0xff,
534 REG_TRXINTH, 0xff,
535 REG_HTXINTL, 0xff,
536 REG_HTXINTH, 0xff,
537 REG_FCINTR0, 0xff,
538 REG_FCINTR1, 0xff,
539 REG_FCINTR2, 0xff,
540 REG_FCINTR3, 0xff,
541 REG_FCINTR4, 0xff,
542 REG_FCINTR5, 0xff,
543 REG_FCINTR6, 0xff,
544 REG_FCINTR7, 0xff
545 );
546}
547
548static void sii8620_edid_read(struct sii8620 *ctx, int ret)
549{
550 if (ret < 0)
551 return;
552
553 sii8620_set_upstream_edid(ctx);
554 sii8620_hsic_init(ctx);
555 sii8620_enable_hpd(ctx);
556}
557
558static void sii8620_mr_devcap(struct sii8620 *ctx) 518static void sii8620_mr_devcap(struct sii8620 *ctx)
559{ 519{
560 u8 dcap[MHL_DCAP_SIZE]; 520 u8 dcap[MHL_DCAP_SIZE];
@@ -570,6 +530,8 @@ static void sii8620_mr_devcap(struct sii8620 *ctx)
570 dcap[MHL_DCAP_ADOPTER_ID_H], dcap[MHL_DCAP_ADOPTER_ID_L], 530 dcap[MHL_DCAP_ADOPTER_ID_H], dcap[MHL_DCAP_ADOPTER_ID_L],
571 dcap[MHL_DCAP_DEVICE_ID_H], dcap[MHL_DCAP_DEVICE_ID_L]); 531 dcap[MHL_DCAP_DEVICE_ID_H], dcap[MHL_DCAP_DEVICE_ID_L]);
572 sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE); 532 sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE);
533 ctx->devcap_read = true;
534 sii8620_identify_sink(ctx);
573} 535}
574 536
575static void sii8620_mr_xdevcap(struct sii8620 *ctx) 537static void sii8620_mr_xdevcap(struct sii8620 *ctx)
@@ -807,6 +769,7 @@ static void sii8620_burst_rx_all(struct sii8620 *ctx)
807static void sii8620_fetch_edid(struct sii8620 *ctx) 769static void sii8620_fetch_edid(struct sii8620 *ctx)
808{ 770{
809 u8 lm_ddc, ddc_cmd, int3, cbus; 771 u8 lm_ddc, ddc_cmd, int3, cbus;
772 unsigned long timeout;
810 int fetched, i; 773 int fetched, i;
811 int edid_len = EDID_LENGTH; 774 int edid_len = EDID_LENGTH;
812 u8 *edid; 775 u8 *edid;
@@ -856,23 +819,31 @@ static void sii8620_fetch_edid(struct sii8620 *ctx)
856 REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK 819 REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK
857 ); 820 );
858 821
859 do { 822 int3 = 0;
860 int3 = sii8620_readb(ctx, REG_INTR3); 823 timeout = jiffies + msecs_to_jiffies(200);
824 for (;;) {
861 cbus = sii8620_readb(ctx, REG_CBUS_STATUS); 825 cbus = sii8620_readb(ctx, REG_CBUS_STATUS);
862 826 if (~cbus & BIT_CBUS_STATUS_CBUS_CONNECTED) {
863 if (int3 & BIT_DDC_CMD_DONE) 827 kfree(edid);
864 break; 828 edid = NULL;
865 829 goto end;
866 if (!(cbus & BIT_CBUS_STATUS_CBUS_CONNECTED)) { 830 }
831 if (int3 & BIT_DDC_CMD_DONE) {
832 if (sii8620_readb(ctx, REG_DDC_DOUT_CNT)
833 >= FETCH_SIZE)
834 break;
835 } else {
836 int3 = sii8620_readb(ctx, REG_INTR3);
837 }
838 if (time_is_before_jiffies(timeout)) {
839 ctx->error = -ETIMEDOUT;
840 dev_err(ctx->dev, "timeout during EDID read\n");
867 kfree(edid); 841 kfree(edid);
868 edid = NULL; 842 edid = NULL;
869 goto end; 843 goto end;
870 } 844 }
871 } while (1);
872
873 sii8620_readb(ctx, REG_DDC_STATUS);
874 while (sii8620_readb(ctx, REG_DDC_DOUT_CNT) < FETCH_SIZE)
875 usleep_range(10, 20); 845 usleep_range(10, 20);
846 }
876 847
877 sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE); 848 sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE);
878 if (fetched + FETCH_SIZE == EDID_LENGTH) { 849 if (fetched + FETCH_SIZE == EDID_LENGTH) {
@@ -971,8 +942,17 @@ static int sii8620_hw_on(struct sii8620 *ctx)
971 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 942 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
972 if (ret) 943 if (ret)
973 return ret; 944 return ret;
945
974 usleep_range(10000, 20000); 946 usleep_range(10000, 20000);
975 return clk_prepare_enable(ctx->clk_xtal); 947 ret = clk_prepare_enable(ctx->clk_xtal);
948 if (ret)
949 return ret;
950
951 msleep(100);
952 gpiod_set_value(ctx->gpio_reset, 0);
953 msleep(100);
954
955 return 0;
976} 956}
977 957
978static int sii8620_hw_off(struct sii8620 *ctx) 958static int sii8620_hw_off(struct sii8620 *ctx)
@@ -982,17 +962,6 @@ static int sii8620_hw_off(struct sii8620 *ctx)
982 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies); 962 return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
983} 963}
984 964
985static void sii8620_hw_reset(struct sii8620 *ctx)
986{
987 usleep_range(10000, 20000);
988 gpiod_set_value(ctx->gpio_reset, 0);
989 usleep_range(5000, 20000);
990 gpiod_set_value(ctx->gpio_reset, 1);
991 usleep_range(10000, 20000);
992 gpiod_set_value(ctx->gpio_reset, 0);
993 msleep(300);
994}
995
996static void sii8620_cbus_reset(struct sii8620 *ctx) 965static void sii8620_cbus_reset(struct sii8620 *ctx)
997{ 966{
998 sii8620_write(ctx, REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST 967 sii8620_write(ctx, REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST
@@ -1048,20 +1017,11 @@ static void sii8620_stop_video(struct sii8620 *ctx)
1048 1017
1049static void sii8620_set_format(struct sii8620 *ctx) 1018static void sii8620_set_format(struct sii8620 *ctx)
1050{ 1019{
1051 u8 out_fmt;
1052
1053 if (sii8620_is_mhl3(ctx)) { 1020 if (sii8620_is_mhl3(ctx)) {
1054 sii8620_setbits(ctx, REG_M3_P0CTRL, 1021 sii8620_setbits(ctx, REG_M3_P0CTRL,
1055 BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED, 1022 BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED,
1056 ctx->use_packed_pixel ? ~0 : 0); 1023 ctx->use_packed_pixel ? ~0 : 0);
1057 } else { 1024 } else {
1058 if (ctx->use_packed_pixel)
1059 sii8620_write_seq_static(ctx,
1060 REG_VID_MODE, BIT_VID_MODE_M1080P,
1061 REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1,
1062 REG_MHLTX_CTL6, 0x60
1063 );
1064 else
1065 sii8620_write_seq_static(ctx, 1025 sii8620_write_seq_static(ctx,
1066 REG_VID_MODE, 0, 1026 REG_VID_MODE, 0,
1067 REG_MHL_TOP_CTL, 1, 1027 REG_MHL_TOP_CTL, 1,
@@ -1069,15 +1029,9 @@ static void sii8620_set_format(struct sii8620 *ctx)
1069 ); 1029 );
1070 } 1030 }
1071 1031
1072 if (ctx->use_packed_pixel)
1073 out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL) |
1074 BIT_TPI_OUTPUT_CSCMODE709;
1075 else
1076 out_fmt = VAL_TPI_FORMAT(RGB, FULL);
1077
1078 sii8620_write_seq(ctx, 1032 sii8620_write_seq(ctx,
1079 REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL), 1033 REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
1080 REG_TPI_OUTPUT, out_fmt, 1034 REG_TPI_OUTPUT, VAL_TPI_FORMAT(RGB, FULL),
1081 ); 1035 );
1082} 1036}
1083 1037
@@ -1216,7 +1170,7 @@ static void sii8620_start_video(struct sii8620 *ctx)
1216 int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3); 1170 int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3);
1217 int i; 1171 int i;
1218 1172
1219 for (i = 0; i < ARRAY_SIZE(clk_spec); ++i) 1173 for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i)
1220 if (clk < clk_spec[i].max_clk) 1174 if (clk < clk_spec[i].max_clk)
1221 break; 1175 break;
1222 1176
@@ -1534,6 +1488,16 @@ static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode)
1534 ); 1488 );
1535} 1489}
1536 1490
1491static void sii8620_hpd_unplugged(struct sii8620 *ctx)
1492{
1493 sii8620_disable_hpd(ctx);
1494 ctx->sink_type = SINK_NONE;
1495 ctx->sink_detected = false;
1496 ctx->feature_complete = false;
1497 kfree(ctx->edid);
1498 ctx->edid = NULL;
1499}
1500
1537static void sii8620_disconnect(struct sii8620 *ctx) 1501static void sii8620_disconnect(struct sii8620 *ctx)
1538{ 1502{
1539 sii8620_disable_gen2_write_burst(ctx); 1503 sii8620_disable_gen2_write_burst(ctx);
@@ -1561,7 +1525,7 @@ static void sii8620_disconnect(struct sii8620 *ctx)
1561 REG_MHL_DP_CTL6, 0x2A, 1525 REG_MHL_DP_CTL6, 0x2A,
1562 REG_MHL_DP_CTL7, 0x03 1526 REG_MHL_DP_CTL7, 0x03
1563 ); 1527 );
1564 sii8620_disable_hpd(ctx); 1528 sii8620_hpd_unplugged(ctx);
1565 sii8620_write_seq_static(ctx, 1529 sii8620_write_seq_static(ctx,
1566 REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE, 1530 REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
1567 REG_MHL_COC_CTL1, 0x07, 1531 REG_MHL_COC_CTL1, 0x07,
@@ -1609,10 +1573,8 @@ static void sii8620_disconnect(struct sii8620 *ctx)
1609 memset(ctx->xstat, 0, sizeof(ctx->xstat)); 1573 memset(ctx->xstat, 0, sizeof(ctx->xstat));
1610 memset(ctx->devcap, 0, sizeof(ctx->devcap)); 1574 memset(ctx->devcap, 0, sizeof(ctx->devcap));
1611 memset(ctx->xdevcap, 0, sizeof(ctx->xdevcap)); 1575 memset(ctx->xdevcap, 0, sizeof(ctx->xdevcap));
1576 ctx->devcap_read = false;
1612 ctx->cbus_status = 0; 1577 ctx->cbus_status = 0;
1613 ctx->sink_type = SINK_NONE;
1614 kfree(ctx->edid);
1615 ctx->edid = NULL;
1616 sii8620_mt_cleanup(ctx); 1578 sii8620_mt_cleanup(ctx);
1617} 1579}
1618 1580
@@ -1703,9 +1665,6 @@ static void sii8620_status_changed_path(struct sii8620 *ctx)
1703 sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), 1665 sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
1704 MHL_DST_LM_CLK_MODE_NORMAL 1666 MHL_DST_LM_CLK_MODE_NORMAL
1705 | MHL_DST_LM_PATH_ENABLED); 1667 | MHL_DST_LM_PATH_ENABLED);
1706 if (!sii8620_is_mhl3(ctx))
1707 sii8620_mt_read_devcap(ctx, false);
1708 sii8620_mt_set_cont(ctx, sii8620_sink_detected);
1709 } else { 1668 } else {
1710 sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), 1669 sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
1711 MHL_DST_LM_CLK_MODE_NORMAL); 1670 MHL_DST_LM_CLK_MODE_NORMAL);
@@ -1722,9 +1681,14 @@ static void sii8620_msc_mr_write_stat(struct sii8620 *ctx)
1722 sii8620_update_array(ctx->stat, st, MHL_DST_SIZE); 1681 sii8620_update_array(ctx->stat, st, MHL_DST_SIZE);
1723 sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE); 1682 sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE);
1724 1683
1725 if (ctx->stat[MHL_DST_CONNECTED_RDY] & MHL_DST_CONN_DCAP_RDY) 1684 if (ctx->stat[MHL_DST_CONNECTED_RDY] & st[MHL_DST_CONNECTED_RDY] &
1685 MHL_DST_CONN_DCAP_RDY) {
1726 sii8620_status_dcap_ready(ctx); 1686 sii8620_status_dcap_ready(ctx);
1727 1687
1688 if (!sii8620_is_mhl3(ctx))
1689 sii8620_mt_read_devcap(ctx, false);
1690 }
1691
1728 if (st[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED) 1692 if (st[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
1729 sii8620_status_changed_path(ctx); 1693 sii8620_status_changed_path(ctx);
1730} 1694}
@@ -1808,8 +1772,11 @@ static void sii8620_msc_mr_set_int(struct sii8620 *ctx)
1808 } 1772 }
1809 if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_REQ) 1773 if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_REQ)
1810 sii8620_send_features(ctx); 1774 sii8620_send_features(ctx);
1811 if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_COMPLETE) 1775 if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_COMPLETE) {
1812 sii8620_edid_read(ctx, 0); 1776 ctx->feature_complete = true;
1777 if (ctx->edid)
1778 sii8620_enable_hpd(ctx);
1779 }
1813} 1780}
1814 1781
1815static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx) 1782static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx)
@@ -1884,6 +1851,15 @@ static void sii8620_irq_msc(struct sii8620 *ctx)
1884 if (stat & BIT_CBUS_MSC_MR_WRITE_STAT) 1851 if (stat & BIT_CBUS_MSC_MR_WRITE_STAT)
1885 sii8620_msc_mr_write_stat(ctx); 1852 sii8620_msc_mr_write_stat(ctx);
1886 1853
1854 if (stat & BIT_CBUS_HPD_CHG) {
1855 if (ctx->cbus_status & BIT_CBUS_STATUS_CBUS_HPD) {
1856 ctx->sink_detected = true;
1857 sii8620_identify_sink(ctx);
1858 } else {
1859 sii8620_hpd_unplugged(ctx);
1860 }
1861 }
1862
1887 if (stat & BIT_CBUS_MSC_MR_SET_INT) 1863 if (stat & BIT_CBUS_MSC_MR_SET_INT)
1888 sii8620_msc_mr_set_int(ctx); 1864 sii8620_msc_mr_set_int(ctx);
1889 1865
@@ -1931,14 +1907,6 @@ static void sii8620_irq_edid(struct sii8620 *ctx)
1931 ctx->mt_state = MT_STATE_DONE; 1907 ctx->mt_state = MT_STATE_DONE;
1932} 1908}
1933 1909
1934static void sii8620_scdt_high(struct sii8620 *ctx)
1935{
1936 sii8620_write_seq_static(ctx,
1937 REG_INTR8_MASK, BIT_CEA_NEW_AVI | BIT_CEA_NEW_VSI,
1938 REG_TPI_SC, BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI,
1939 );
1940}
1941
1942static void sii8620_irq_scdt(struct sii8620 *ctx) 1910static void sii8620_irq_scdt(struct sii8620 *ctx)
1943{ 1911{
1944 u8 stat = sii8620_readb(ctx, REG_INTR5); 1912 u8 stat = sii8620_readb(ctx, REG_INTR5);
@@ -1946,53 +1914,13 @@ static void sii8620_irq_scdt(struct sii8620 *ctx)
1946 if (stat & BIT_INTR_SCDT_CHANGE) { 1914 if (stat & BIT_INTR_SCDT_CHANGE) {
1947 u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3); 1915 u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
1948 1916
1949 if (cstat & BIT_TMDS_CSTAT_P3_SCDT) { 1917 if (cstat & BIT_TMDS_CSTAT_P3_SCDT)
1950 if (ctx->sink_type == SINK_HDMI) 1918 sii8620_start_video(ctx);
1951 /* enable infoframe interrupt */
1952 sii8620_scdt_high(ctx);
1953 else
1954 sii8620_start_video(ctx);
1955 }
1956 } 1919 }
1957 1920
1958 sii8620_write(ctx, REG_INTR5, stat); 1921 sii8620_write(ctx, REG_INTR5, stat);
1959} 1922}
1960 1923
1961static void sii8620_new_vsi(struct sii8620 *ctx)
1962{
1963 u8 vsif[11];
1964
1965 sii8620_write(ctx, REG_RX_HDMI_CTRL2,
1966 VAL_RX_HDMI_CTRL2_DEFVAL |
1967 BIT_RX_HDMI_CTRL2_VSI_MON_SEL_VSI);
1968 sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, vsif,
1969 ARRAY_SIZE(vsif));
1970}
1971
1972static void sii8620_new_avi(struct sii8620 *ctx)
1973{
1974 sii8620_write(ctx, REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL);
1975 sii8620_read_buf(ctx, REG_RX_HDMI_MON_PKT_HEADER1, ctx->avif,
1976 ARRAY_SIZE(ctx->avif));
1977}
1978
1979static void sii8620_irq_infr(struct sii8620 *ctx)
1980{
1981 u8 stat = sii8620_readb(ctx, REG_INTR8)
1982 & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI);
1983
1984 sii8620_write(ctx, REG_INTR8, stat);
1985
1986 if (stat & BIT_CEA_NEW_VSI)
1987 sii8620_new_vsi(ctx);
1988
1989 if (stat & BIT_CEA_NEW_AVI)
1990 sii8620_new_avi(ctx);
1991
1992 if (stat & (BIT_CEA_NEW_VSI | BIT_CEA_NEW_AVI))
1993 sii8620_start_video(ctx);
1994}
1995
1996static void sii8620_got_xdevcap(struct sii8620 *ctx, int ret) 1924static void sii8620_got_xdevcap(struct sii8620 *ctx, int ret)
1997{ 1925{
1998 if (ret < 0) 1926 if (ret < 0)
@@ -2043,11 +1971,11 @@ static void sii8620_irq_ddc(struct sii8620 *ctx)
2043 1971
2044 if (stat & BIT_DDC_CMD_DONE) { 1972 if (stat & BIT_DDC_CMD_DONE) {
2045 sii8620_write(ctx, REG_INTR3_MASK, 0); 1973 sii8620_write(ctx, REG_INTR3_MASK, 0);
2046 if (sii8620_is_mhl3(ctx)) 1974 if (sii8620_is_mhl3(ctx) && !ctx->feature_complete)
2047 sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE), 1975 sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE),
2048 MHL_INT_RC_FEAT_REQ); 1976 MHL_INT_RC_FEAT_REQ);
2049 else 1977 else
2050 sii8620_edid_read(ctx, 0); 1978 sii8620_enable_hpd(ctx);
2051 } 1979 }
2052 sii8620_write(ctx, REG_INTR3, stat); 1980 sii8620_write(ctx, REG_INTR3, stat);
2053} 1981}
@@ -2074,7 +2002,6 @@ static irqreturn_t sii8620_irq_thread(int irq, void *data)
2074 { BIT_FAST_INTR_STAT_EDID, sii8620_irq_edid }, 2002 { BIT_FAST_INTR_STAT_EDID, sii8620_irq_edid },
2075 { BIT_FAST_INTR_STAT_DDC, sii8620_irq_ddc }, 2003 { BIT_FAST_INTR_STAT_DDC, sii8620_irq_ddc },
2076 { BIT_FAST_INTR_STAT_SCDT, sii8620_irq_scdt }, 2004 { BIT_FAST_INTR_STAT_SCDT, sii8620_irq_scdt },
2077 { BIT_FAST_INTR_STAT_INFR, sii8620_irq_infr },
2078 }; 2005 };
2079 struct sii8620 *ctx = data; 2006 struct sii8620 *ctx = data;
2080 u8 stats[LEN_FAST_INTR_STAT]; 2007 u8 stats[LEN_FAST_INTR_STAT];
@@ -2112,7 +2039,6 @@ static void sii8620_cable_in(struct sii8620 *ctx)
2112 dev_err(dev, "Error powering on, %d.\n", ret); 2039 dev_err(dev, "Error powering on, %d.\n", ret);
2113 return; 2040 return;
2114 } 2041 }
2115 sii8620_hw_reset(ctx);
2116 2042
2117 sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver)); 2043 sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver));
2118 ret = sii8620_clear_error(ctx); 2044 ret = sii8620_clear_error(ctx);
@@ -2268,17 +2194,43 @@ static void sii8620_detach(struct drm_bridge *bridge)
2268 rc_unregister_device(ctx->rc_dev); 2194 rc_unregister_device(ctx->rc_dev);
2269} 2195}
2270 2196
2197static int sii8620_is_packing_required(struct sii8620 *ctx,
2198 const struct drm_display_mode *mode)
2199{
2200 int max_pclk, max_pclk_pp_mode;
2201
2202 if (sii8620_is_mhl3(ctx)) {
2203 max_pclk = MHL3_MAX_PCLK;
2204 max_pclk_pp_mode = MHL3_MAX_PCLK_PP_MODE;
2205 } else {
2206 max_pclk = MHL1_MAX_PCLK;
2207 max_pclk_pp_mode = MHL1_MAX_PCLK_PP_MODE;
2208 }
2209
2210 if (mode->clock < max_pclk)
2211 return 0;
2212 else if (mode->clock < max_pclk_pp_mode)
2213 return 1;
2214 else
2215 return -1;
2216}
2217
2271static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge, 2218static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge,
2272 const struct drm_display_mode *mode) 2219 const struct drm_display_mode *mode)
2273{ 2220{
2274 struct sii8620 *ctx = bridge_to_sii8620(bridge); 2221 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2222 int pack_required = sii8620_is_packing_required(ctx, mode);
2275 bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] & 2223 bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
2276 MHL_DCAP_VID_LINK_PPIXEL; 2224 MHL_DCAP_VID_LINK_PPIXEL;
2277 unsigned int max_pclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK :
2278 MHL1_MAX_LCLK;
2279 max_pclk /= can_pack ? 2 : 3;
2280 2225
2281 return (mode->clock > max_pclk) ? MODE_CLOCK_HIGH : MODE_OK; 2226 switch (pack_required) {
2227 case 0:
2228 return MODE_OK;
2229 case 1:
2230 return (can_pack) ? MODE_OK : MODE_CLOCK_HIGH;
2231 default:
2232 return MODE_CLOCK_HIGH;
2233 }
2282} 2234}
2283 2235
2284static bool sii8620_mode_fixup(struct drm_bridge *bridge, 2236static bool sii8620_mode_fixup(struct drm_bridge *bridge,
@@ -2286,43 +2238,16 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge,
2286 struct drm_display_mode *adjusted_mode) 2238 struct drm_display_mode *adjusted_mode)
2287{ 2239{
2288 struct sii8620 *ctx = bridge_to_sii8620(bridge); 2240 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2289 int max_lclk;
2290 bool ret = true;
2291 2241
2292 mutex_lock(&ctx->lock); 2242 mutex_lock(&ctx->lock);
2293 2243
2294 max_lclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK : MHL1_MAX_LCLK; 2244 ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
2295 if (max_lclk > 3 * adjusted_mode->clock) { 2245 ctx->video_code = drm_match_cea_mode(adjusted_mode);
2296 ctx->use_packed_pixel = 0; 2246 ctx->pixel_clock = adjusted_mode->clock;
2297 goto end; 2247
2298 }
2299 if ((ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL) &&
2300 max_lclk > 2 * adjusted_mode->clock) {
2301 ctx->use_packed_pixel = 1;
2302 goto end;
2303 }
2304 ret = false;
2305end:
2306 if (ret) {
2307 u8 vic = drm_match_cea_mode(adjusted_mode);
2308
2309 if (!vic) {
2310 union hdmi_infoframe frm;
2311 u8 mhl_vic[] = { 0, 95, 94, 93, 98 };
2312
2313 /* FIXME: We need the connector here */
2314 drm_hdmi_vendor_infoframe_from_display_mode(
2315 &frm.vendor.hdmi, NULL, adjusted_mode);
2316 vic = frm.vendor.hdmi.vic;
2317 if (vic >= ARRAY_SIZE(mhl_vic))
2318 vic = 0;
2319 vic = mhl_vic[vic];
2320 }
2321 ctx->video_code = vic;
2322 ctx->pixel_clock = adjusted_mode->clock;
2323 }
2324 mutex_unlock(&ctx->lock); 2248 mutex_unlock(&ctx->lock);
2325 return ret; 2249
2250 return true;
2326} 2251}
2327 2252
2328static const struct drm_bridge_funcs sii8620_bridge_funcs = { 2253static const struct drm_bridge_funcs sii8620_bridge_funcs = {
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index 08747fc3ee71..8232b39e16ca 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -17,7 +17,6 @@
17#include <drm/drm_encoder.h> 17#include <drm/drm_encoder.h>
18#include <drm/drm_modes.h> 18#include <drm/drm_modes.h>
19#include <drm/drm_of.h> 19#include <drm/drm_of.h>
20#include <drm/drm_panel.h>
21 20
22#include <uapi/drm/drm_mode.h> 21#include <uapi/drm/drm_mode.h>
23 22
@@ -418,9 +417,6 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
418static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, 417static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
419 const struct drm_display_mode *mode) 418 const struct drm_display_mode *mode)
420{ 419{
421 struct drm_panel *panel = tcon->panel;
422 struct drm_connector *connector = panel->connector;
423 struct drm_display_info display_info = connector->display_info;
424 unsigned int bp, hsync, vsync; 420 unsigned int bp, hsync, vsync;
425 u8 clk_delay; 421 u8 clk_delay;
426 u32 val = 0; 422 u32 val = 0;
@@ -478,27 +474,6 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
478 if (mode->flags & DRM_MODE_FLAG_PVSYNC) 474 if (mode->flags & DRM_MODE_FLAG_PVSYNC)
479 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; 475 val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE;
480 476
481 /*
482 * On A20 and similar SoCs, the only way to achieve Positive Edge
483 * (Rising Edge), is setting dclk clock phase to 2/3(240°).
484 * By default TCON works in Negative Edge(Falling Edge),
485 * this is why phase is set to 0 in that case.
486 * Unfortunately there's no way to logically invert dclk through
487 * IO_POL register.
488 * The only acceptable way to work, triple checked with scope,
489 * is using clock phase set to 0° for Negative Edge and set to 240°
490 * for Positive Edge.
491 * On A33 and similar SoCs there would be a 90° phase option,
492 * but it divides also dclk by 2.
493 * Following code is a way to avoid quirks all around TCON
494 * and DOTCLOCK drivers.
495 */
496 if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_POSEDGE)
497 clk_set_phase(tcon->dclk, 240);
498
499 if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE)
500 clk_set_phase(tcon->dclk, 0);
501
502 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, 477 regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG,
503 SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE, 478 SUN4I_TCON0_IO_POL_HSYNC_POSITIVE | SUN4I_TCON0_IO_POL_VSYNC_POSITIVE,
504 val); 479 val);