Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ecba7cfa authored by Maciej Purski's avatar Maciej Purski Committed by Andrzej Hajda
Browse files

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: default avatarMaciej Purski <m.purski@samsung.com>
Signed-off-by: default avatarAndrzej Hajda <a.hajda@samsung.com>
Link: https://patchwork.freedesktop.org/patch/msgid/1517568865-25219-1-git-send-email-m.purski@samsung.com
parent 8e627a1b
Loading
Loading
Loading
Loading
+41 −39
Original line number Diff line number Diff line
@@ -36,8 +36,11 @@

#define SII8620_BURST_BUF_LEN 288
#define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
#define MHL1_MAX_LCLK 225000
#define MHL3_MAX_LCLK 600000

#define MHL1_MAX_PCLK 75000
#define MHL1_MAX_PCLK_PP_MODE 150000
#define MHL3_MAX_PCLK 200000
#define MHL3_MAX_PCLK_PP_MODE 300000

enum sii8620_mode {
	CM_DISCONNECTED,
@@ -2274,17 +2277,43 @@ static void sii8620_detach(struct drm_bridge *bridge)
	rc_unregister_device(ctx->rc_dev);
}

static int sii8620_is_packing_required(struct sii8620 *ctx,
				       const struct drm_display_mode *mode)
{
	int max_pclk, max_pclk_pp_mode;

	if (sii8620_is_mhl3(ctx)) {
		max_pclk = MHL3_MAX_PCLK;
		max_pclk_pp_mode = MHL3_MAX_PCLK_PP_MODE;
	} else {
		max_pclk = MHL1_MAX_PCLK;
		max_pclk_pp_mode = MHL1_MAX_PCLK_PP_MODE;
	}

	if (mode->clock < max_pclk)
		return 0;
	else if (mode->clock < max_pclk_pp_mode)
		return 1;
	else
		return -1;
}

static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge,
					 const struct drm_display_mode *mode)
{
	struct sii8620 *ctx = bridge_to_sii8620(bridge);
	int pack_required = sii8620_is_packing_required(ctx, mode);
	bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
			MHL_DCAP_VID_LINK_PPIXEL;
	unsigned int max_pclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK :
						       MHL1_MAX_LCLK;
	max_pclk /= can_pack ? 2 : 3;

	return (mode->clock > max_pclk) ? MODE_CLOCK_HIGH : MODE_OK;
	switch (pack_required) {
	case 0:
		return MODE_OK;
	case 1:
		return (can_pack) ? MODE_OK : MODE_CLOCK_HIGH;
	default:
		return MODE_CLOCK_HIGH;
	}
}

static bool sii8620_mode_fixup(struct drm_bridge *bridge,
@@ -2292,43 +2321,16 @@ static bool sii8620_mode_fixup(struct drm_bridge *bridge,
			       struct drm_display_mode *adjusted_mode)
{
	struct sii8620 *ctx = bridge_to_sii8620(bridge);
	int max_lclk;
	bool ret = true;

	mutex_lock(&ctx->lock);

	max_lclk = sii8620_is_mhl3(ctx) ? MHL3_MAX_LCLK : MHL1_MAX_LCLK;
	if (max_lclk > 3 * adjusted_mode->clock) {
		ctx->use_packed_pixel = 0;
		goto end;
	}
	if ((ctx->devcap[MHL_DCAP_VID_LINK_MODE] & MHL_DCAP_VID_LINK_PPIXEL) &&
	    max_lclk > 2 * adjusted_mode->clock) {
		ctx->use_packed_pixel = 1;
		goto end;
	}
	ret = false;
end:
	if (ret) {
		u8 vic = drm_match_cea_mode(adjusted_mode);

		if (!vic) {
			union hdmi_infoframe frm;
			u8 mhl_vic[] = { 0, 95, 94, 93, 98 };

			/* FIXME: We need the connector here */
			drm_hdmi_vendor_infoframe_from_display_mode(
				&frm.vendor.hdmi, NULL, adjusted_mode);
			vic = frm.vendor.hdmi.vic;
			if (vic >= ARRAY_SIZE(mhl_vic))
				vic = 0;
			vic = mhl_vic[vic];
		}
		ctx->video_code = vic;
	ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
	ctx->video_code = drm_match_cea_mode(adjusted_mode);
	ctx->pixel_clock = adjusted_mode->clock;
	}

	mutex_unlock(&ctx->lock);
	return ret;

	return true;
}

static const struct drm_bridge_funcs sii8620_bridge_funcs = {