aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 250effa0e6b8..bd30ccf3d195 100644
--- a/drivers/gpu/drm/bridge/sil-sii8620.c
+++ b/drivers/gpu/drm/bridge/sil-sii8620.c
@@ -14,6 +14,7 @@
14#include <drm/bridge/mhl.h> 14#include <drm/bridge/mhl.h>
15#include <drm/drm_crtc.h> 15#include <drm/drm_crtc.h>
16#include <drm/drm_edid.h> 16#include <drm/drm_edid.h>
17#include <drm/drm_encoder.h>
17 18
18#include <linux/clk.h> 19#include <linux/clk.h>
19#include <linux/delay.h> 20#include <linux/delay.h>
@@ -72,9 +73,7 @@ struct sii8620 {
72 struct regulator_bulk_data supplies[2]; 73 struct regulator_bulk_data supplies[2];
73 struct mutex lock; /* context lock, protects fields below */ 74 struct mutex lock; /* context lock, protects fields below */
74 int error; 75 int error;
75 int pixel_clock;
76 unsigned int use_packed_pixel:1; 76 unsigned int use_packed_pixel:1;
77 int video_code;
78 enum sii8620_mode mode; 77 enum sii8620_mode mode;
79 enum sii8620_sink_type sink_type; 78 enum sii8620_sink_type sink_type;
80 u8 cbus_status; 79 u8 cbus_status;
@@ -82,7 +81,6 @@ struct sii8620 {
82 u8 xstat[MHL_XDS_SIZE]; 81 u8 xstat[MHL_XDS_SIZE];
83 u8 devcap[MHL_DCAP_SIZE]; 82 u8 devcap[MHL_DCAP_SIZE];
84 u8 xdevcap[MHL_XDC_SIZE]; 83 u8 xdevcap[MHL_XDC_SIZE];
85 u8 avif[HDMI_INFOFRAME_SIZE(AVI)];
86 bool feature_complete; 84 bool feature_complete;
87 bool devcap_read; 85 bool devcap_read;
88 bool sink_detected; 86 bool sink_detected;
@@ -1082,18 +1080,28 @@ static ssize_t mhl3_infoframe_pack(struct mhl3_infoframe *frame,
1082 return frm_len; 1080 return frm_len;
1083} 1081}
1084 1082
1085static void sii8620_set_infoframes(struct sii8620 *ctx) 1083static void sii8620_set_infoframes(struct sii8620 *ctx,
1084 struct drm_display_mode *mode)
1086{ 1085{
1087 struct mhl3_infoframe mhl_frm; 1086 struct mhl3_infoframe mhl_frm;
1088 union hdmi_infoframe frm; 1087 union hdmi_infoframe frm;
1089 u8 buf[31]; 1088 u8 buf[31];
1090 int ret; 1089 int ret;
1091 1090
1091 ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
1092 mode,
1093 true);
1094 if (ctx->use_packed_pixel)
1095 frm.avi.colorspace = HDMI_COLORSPACE_YUV422;
1096
1097 if (!ret)
1098 ret = hdmi_avi_infoframe_pack(&frm.avi, buf, ARRAY_SIZE(buf));
1099 if (ret > 0)
1100 sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3);
1101
1092 if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) { 1102 if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) {
1093 sii8620_write(ctx, REG_TPI_SC, 1103 sii8620_write(ctx, REG_TPI_SC,
1094 BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI); 1104 BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
1095 sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, ctx->avif + 3,
1096 ARRAY_SIZE(ctx->avif) - 3);
1097 sii8620_write(ctx, REG_PKT_FILTER_0, 1105 sii8620_write(ctx, REG_PKT_FILTER_0,
1098 BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT | 1106 BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
1099 BIT_PKT_FILTER_0_DROP_MPEG_PKT | 1107 BIT_PKT_FILTER_0_DROP_MPEG_PKT |
@@ -1102,16 +1110,6 @@ static void sii8620_set_infoframes(struct sii8620 *ctx)
1102 return; 1110 return;
1103 } 1111 }
1104 1112
1105 ret = hdmi_avi_infoframe_init(&frm.avi);
1106 frm.avi.colorspace = HDMI_COLORSPACE_YUV422;
1107 frm.avi.active_aspect = HDMI_ACTIVE_ASPECT_PICTURE;
1108 frm.avi.picture_aspect = HDMI_PICTURE_ASPECT_16_9;
1109 frm.avi.colorimetry = HDMI_COLORIMETRY_ITU_709;
1110 frm.avi.video_code = ctx->video_code;
1111 if (!ret)
1112 ret = hdmi_avi_infoframe_pack(&frm.avi, buf, ARRAY_SIZE(buf));
1113 if (ret > 0)
1114 sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3);
1115 sii8620_write(ctx, REG_PKT_FILTER_0, 1113 sii8620_write(ctx, REG_PKT_FILTER_0,
1116 BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT | 1114 BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
1117 BIT_PKT_FILTER_0_DROP_MPEG_PKT | 1115 BIT_PKT_FILTER_0_DROP_MPEG_PKT |
@@ -1131,6 +1129,9 @@ static void sii8620_set_infoframes(struct sii8620 *ctx)
1131 1129
1132static void sii8620_start_video(struct sii8620 *ctx) 1130static void sii8620_start_video(struct sii8620 *ctx)
1133{ 1131{
1132 struct drm_display_mode *mode =
1133 &ctx->bridge.encoder->crtc->state->adjusted_mode;
1134
1134 if (!sii8620_is_mhl3(ctx)) 1135 if (!sii8620_is_mhl3(ctx))
1135 sii8620_stop_video(ctx); 1136 sii8620_stop_video(ctx);
1136 1137
@@ -1167,7 +1168,7 @@ static void sii8620_start_video(struct sii8620 *ctx)
1167 MHL_XDS_LINK_RATE_6_0_GBPS, 0x40 }, 1168 MHL_XDS_LINK_RATE_6_0_GBPS, 0x40 },
1168 }; 1169 };
1169 u8 p0_ctrl = BIT_M3_P0CTRL_MHL3_P0_PORT_EN; 1170 u8 p0_ctrl = BIT_M3_P0CTRL_MHL3_P0_PORT_EN;
1170 int clk = ctx->pixel_clock * (ctx->use_packed_pixel ? 2 : 3); 1171 int clk = mode->clock * (ctx->use_packed_pixel ? 2 : 3);
1171 int i; 1172 int i;
1172 1173
1173 for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i) 1174 for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i)
@@ -1196,7 +1197,7 @@ static void sii8620_start_video(struct sii8620 *ctx)
1196 clk_spec[i].link_rate); 1197 clk_spec[i].link_rate);
1197 } 1198 }
1198 1199
1199 sii8620_set_infoframes(ctx); 1200 sii8620_set_infoframes(ctx, mode);
1200} 1201}
1201 1202
1202static void sii8620_disable_hpd(struct sii8620 *ctx) 1203static void sii8620_disable_hpd(struct sii8620 *ctx)
@@ -2242,8 +2243,6 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge,
2242 mutex_lock(&ctx->lock); 2243 mutex_lock(&ctx->lock);
2243 2244
2244 ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode); 2245 ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
2245 ctx->video_code = drm_match_cea_mode(adjusted_mode);
2246 ctx->pixel_clock = adjusted_mode->clock;
2247 2246
2248 mutex_unlock(&ctx->lock); 2247 mutex_unlock(&ctx->lock);
2249 2248