|
@@ -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->pixel_clock = adjusted_mode->clock;
|
|
|
- }
|
|
|
+ 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 = {
|