aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaciej Purski <m.purski@samsung.com>2018-02-02 05:54:25 -0500
committerAndrzej Hajda <a.hajda@samsung.com>2018-06-13 10:26:57 -0400
commitecba7cfa3afbe489288f2c819158b7402afd7ee9 (patch)
tree328459a5aa04bfa7a63b345b0cbd78faa1f0ac67
parent8e627a1b1ce8feb3e1da4428b71b9b4905f04888 (diff)
drm/bridge/sii8620: fix display modes validation
Current implementation of mode_valid() and mode_fixup() callbacks handle packed pixel modes improperly. Fix it by using proper maximum clock values from the documentation. Signed-off-by: Maciej Purski <m.purski@samsung.com> Signed-off-by: Andrzej Hajda <a.hajda@samsung.com> Link: https://patchwork.freedesktop.org/patch/msgid/1517568865-25219-1-git-send-email-m.purski@samsung.com
-rw-r--r--drivers/gpu/drm/bridge/sil-sii8620.c80
1 files changed, 41 insertions, 39 deletions
diff --git a/drivers/gpu/drm/bridge/sil-sii8620.c b/drivers/gpu/drm/bridge/sil-sii8620.c
index 720bc7c325e0..5267dc6551af 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,
@@ -2274,17 +2277,43 @@ static void sii8620_detach(struct drm_bridge *bridge)
2274 rc_unregister_device(ctx->rc_dev); 2277 rc_unregister_device(ctx->rc_dev);
2275} 2278}
2276 2279
2280static int sii8620_is_packing_required(struct sii8620 *ctx,
2281 const struct drm_display_mode *mode)
2282{
2283 int max_pclk, max_pclk_pp_mode;
2284
2285 if (sii8620_is_mhl3(ctx)) {
2286 max_pclk = MHL3_MAX_PCLK;
2287 max_pclk_pp_mode = MHL3_MAX_PCLK_PP_MODE;
2288 } else {
2289 max_pclk = MHL1_MAX_PCLK;
2290 max_pclk_pp_mode = MHL1_MAX_PCLK_PP_MODE;
2291 }
2292
2293 if (mode->clock < max_pclk)
2294 return 0;
2295 else if (mode->clock < max_pclk_pp_mode)
2296 return 1;
2297 else
2298 return -1;
2299}
2300
2277static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge, 2301static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge,
2278 const struct drm_display_mode *mode) 2302 const struct drm_display_mode *mode)
2279{ 2303{
2280 struct sii8620 *ctx = bridge_to_sii8620(bridge); 2304 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2305 int pack_required = sii8620_is_packing_required(ctx, mode);
2281 bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] & 2306 bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
2282 MHL_DCAP_VID_LINK_PPIXEL; 2307 MHL_DCAP_VID_LINK_PPIXEL;
2283 unsigned int max_pclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK :
2284 MHL1_MAX_LCLK;
2285 max_pclk /= can_pack ? 2 : 3;
2286 2308
2287 return (mode->clock > max_pclk) ? MODE_CLOCK_HIGH : MODE_OK; 2309 switch (pack_required) {
2310 case 0:
2311 return MODE_OK;
2312 case 1:
2313 return (can_pack) ? MODE_OK : MODE_CLOCK_HIGH;
2314 default:
2315 return MODE_CLOCK_HIGH;
2316 }
2288} 2317}
2289 2318
2290static bool sii8620_mode_fixup(struct drm_bridge *bridge, 2319static bool sii8620_mode_fixup(struct drm_bridge *bridge,
@@ -2292,43 +2321,16 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge,
2292 struct drm_display_mode *adjusted_mode) 2321 struct drm_display_mode *adjusted_mode)
2293{ 2322{
2294 struct sii8620 *ctx = bridge_to_sii8620(bridge); 2323 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2295 int max_lclk;
2296 bool ret = true;
2297 2324
2298 mutex_lock(&ctx->lock); 2325 mutex_lock(&ctx->lock);
2299 2326
2300 max_lclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK : MHL1_MAX_LCLK; 2327 ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
2301 if (max_lclk > 3 * adjusted_mode->clock) { 2328 ctx->video_code = drm_match_cea_mode(adjusted_mode);
2302 ctx->use_packed_pixel = 0; 2329 ctx->pixel_clock = adjusted_mode->clock;
2303 goto end; 2330
2304 }
2305 if ((ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL) &&
2306 max_lclk > 2 * adjusted_mode->clock) {
2307 ctx->use_packed_pixel = 1;
2308 goto end;
2309 }
2310 ret = false;
2311end:
2312 if (ret) {
2313 u8 vic = drm_match_cea_mode(adjusted_mode);
2314
2315 if (!vic) {
2316 union hdmi_infoframe frm;
2317 u8 mhl_vic[] = { 0, 95, 94, 93, 98 };
2318
2319 /* FIXME: We need the connector here */
2320 drm_hdmi_vendor_infoframe_from_display_mode(
2321 &frm.vendor.hdmi, NULL, adjusted_mode);
2322 vic = frm.vendor.hdmi.vic;
2323 if (vic >= ARRAY_SIZE(mhl_vic))
2324 vic = 0;
2325 vic = mhl_vic[vic];
2326 }
2327 ctx->video_code = vic;
2328 ctx->pixel_clock = adjusted_mode->clock;
2329 }
2330 mutex_unlock(&ctx->lock); 2331 mutex_unlock(&ctx->lock);
2331 return ret; 2332
2333 return true;
2332} 2334}
2333 2335
2334static const struct drm_bridge_funcs sii8620_bridge_funcs = { 2336static const struct drm_bridge_funcs sii8620_bridge_funcs = {