From 6f23cfed09dc50e532a5d6a535bb992102d03cab Mon Sep 17 00:00:00 2001
From: Sandor Yu <Sandor.yu@nxp.com>
Date: Wed, 27 Nov 2019 19:08:42 +0800
Subject: [PATCH] LF-94: drm: hdmi: imx: Add hdmi phy video mode valid function

Add hdmi phy video mode valid function to filter the video modes.

Signed-off-by: Sandor Yu <Sandor.yu@nxp.com>
Reviewed-by: Robby Cai <robby.cai@nxp.com>
---
 drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c |  8 +++++++-
 drivers/gpu/drm/imx/cdn-mhdp-hdmi-phy.c         | 23 +++++++++++++++++++++++
 drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c           |  2 ++
 drivers/gpu/drm/imx/cdn-mhdp-phy.h              |  2 ++
 include/drm/bridge/cdns-mhdp-common.h           |  2 ++
 5 files changed, 36 insertions(+), 1 deletion(-)

--- a/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-hdmi-core.c
@@ -352,7 +352,9 @@ static enum drm_mode_status
 cdns_hdmi_bridge_mode_valid(struct drm_bridge *bridge,
 			  const struct drm_display_mode *mode)
 {
+	struct cdns_mhdp_device *mhdp = bridge->driver_private;
 	enum drm_mode_status mode_status = MODE_OK;
+	int ret;
 
 	/* We don't support double-clocked and Interlaced modes */
 	if (mode->flags & DRM_MODE_FLAG_DBLCLK ||
@@ -367,6 +369,11 @@ cdns_hdmi_bridge_mode_valid(struct drm_b
 	if (mode->hdisplay > 3840 || mode->vdisplay > 2160)
 		return MODE_BAD_HVALUE;
 
+	mhdp->valid_mode = mode;
+	ret = cdns_mhdp_plat_call(mhdp, phy_video_valid);
+	if (ret == false)
+		return MODE_CLOCK_RANGE;
+
 	return mode_status;
 }
 
@@ -375,7 +382,6 @@ static void cdns_hdmi_bridge_mode_set(st
 				    const struct drm_display_mode *mode)
 {
 	struct cdns_mhdp_device *mhdp = bridge->driver_private;
-	struct drm_display_info *display_info = &mhdp->connector.base.display_info;
 	struct video_info *video = &mhdp->video_info;
 
 	video->v_sync_polarity = !!(mode->flags & DRM_MODE_FLAG_NVSYNC);
--- a/drivers/gpu/drm/imx/cdn-mhdp-hdmi-phy.c
+++ b/drivers/gpu/drm/imx/cdn-mhdp-hdmi-phy.c
@@ -683,6 +683,17 @@ static int hdmi_phy_power_up(struct cdns
 	return 0;
 }
 
+bool cdns_hdmi_phy_video_valid_imx8mq(struct cdns_mhdp_device *mhdp)
+{
+	u32 rate = mhdp->valid_mode->clock;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(imx8mq_ctrl_table); i++)
+			if(rate == imx8mq_ctrl_table[i].pixel_clk_freq_min)
+				return true;
+	return false;
+}
+
 int cdns_hdmi_phy_set_imx8mq(struct cdns_mhdp_device *mhdp)
 {
 	struct drm_display_mode *mode = &mhdp->mode;
@@ -711,6 +722,18 @@ int cdns_hdmi_phy_set_imx8mq(struct cdns
 	return true;
 }
 
+bool cdns_hdmi_phy_video_valid_imx8qm(struct cdns_mhdp_device *mhdp)
+{
+	u32 rate = mhdp->valid_mode->clock;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(imx8qm_ctrl_table); i++)
+			if(rate >= imx8qm_ctrl_table[i].pixel_clk_freq_min &&
+				rate <= imx8qm_ctrl_table[i].pixel_clk_freq_max)
+				return true;
+	return false;
+}
+
 int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *mhdp)
 {
 	struct drm_display_mode *mode = &mhdp->mode;
--- a/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
+++ b/drivers/gpu/drm/imx/cdn-mhdp-imxdrv.c
@@ -58,6 +58,7 @@ static struct cdns_plat_data imx8mq_hdmi
 	.bind	= cdns_hdmi_bind,
 	.unbind	= cdns_hdmi_unbind,
 	.phy_set = cdns_hdmi_phy_set_imx8mq,
+	.phy_video_valid = cdns_hdmi_phy_video_valid_imx8mq,
 	.bus_type = BUS_TYPE_NORMAL_APB,
 };
 
@@ -74,6 +75,7 @@ static struct cdns_plat_data imx8qm_hdmi
 	.bind	= cdns_hdmi_bind,
 	.unbind	= cdns_hdmi_unbind,
 	.phy_set = cdns_hdmi_phy_set_imx8qm,
+	.phy_video_valid = cdns_hdmi_phy_video_valid_imx8qm,
 	.power_on = cdns_mhdp_power_on_imx8qm,
 	.firmware_init = cdns_mhdp_firmware_init_imx8qm,
 	.pclk_rate = cdns_mhdp_pclk_rate_imx8qm,
--- a/drivers/gpu/drm/imx/cdn-mhdp-phy.h
+++ b/drivers/gpu/drm/imx/cdn-mhdp-phy.h
@@ -148,6 +148,8 @@
 
 int cdns_dp_phy_set_imx8mq(struct cdns_mhdp_device *hdp);
 int cdns_dp_phy_set_imx8qm(struct cdns_mhdp_device *hdp);
+bool cdns_hdmi_phy_video_valid_imx8mq(struct cdns_mhdp_device *hdp);
+bool cdns_hdmi_phy_video_valid_imx8qm(struct cdns_mhdp_device *hdp);
 int cdns_hdmi_phy_set_imx8mq(struct cdns_mhdp_device *hdp);
 int cdns_hdmi_phy_set_imx8qm(struct cdns_mhdp_device *hdp);
 #endif /* _CDNS_MHDP_PHY_H */
--- a/include/drm/bridge/cdns-mhdp-common.h
+++ b/include/drm/bridge/cdns-mhdp-common.h
@@ -643,6 +643,7 @@ struct cdns_plat_data {
 	void (*plat_deinit)(struct cdns_mhdp_device *mhdp);
 
 	int (*phy_set)(struct cdns_mhdp_device *mhdp);
+	bool (*phy_video_valid)(struct cdns_mhdp_device *mhdp);
 	int (*firmware_init)(struct cdns_mhdp_device *mhdp);
 	void (*pclk_rate)(struct cdns_mhdp_device *mhdp);
 
@@ -675,6 +676,7 @@ struct cdns_mhdp_device {
 
 	struct video_info	video_info;
 	struct drm_display_mode	mode;
+	const struct drm_display_mode	*valid_mode;
 	unsigned int		fw_version;
 
 	struct drm_dp_mst_topology_mgr mst_mgr;
