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
This commit is contained in:
parent
8e627a1b1c
commit
ecba7cfa3a
|
@ -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);
|
||||
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;
|
||||
|
||||
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->pixel_clock = adjusted_mode->clock;
|
||||
}
|
||||
mutex_unlock(&ctx->lock);
|
||||
return ret;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs sii8620_bridge_funcs = {
|
||||
|
|
Loading…
Reference in New Issue