All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
To: linux-renesas-soc@vger.kernel.org,
	laurent.pinchart@ideasonboard.com,
	dri-devel@lists.freedesktop.org
Cc: kuninori.morimoto.gx@renesas.com, geert@linux-m68k.org,
	airlied@linux.ie, koji.matsuoka.xm@renesas.com,
	Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
Subject: [PATCH 02/10] drm: bridge/dw_hdmi: Add R-Car Gen3 device support
Date: Fri, 11 Nov 2016 18:07:38 +0100	[thread overview]
Message-ID: <1478884066-1090-3-git-send-email-ulrich.hecht+renesas@gmail.com> (raw)
In-Reply-To: <1478884066-1090-1-git-send-email-ulrich.hecht+renesas@gmail.com>

From: Koji Matsuoka <koji.matsuoka.xm@renesas.com>

Signed-off-by: Koji Matsuoka <koji.matsuoka.xm@renesas.com>
[uli: eliminate rcar-specific connector funcs, extraneous DT properties]
Signed-off-by: Ulrich Hecht <ulrich.hecht+renesas@gmail.com>
---
 drivers/gpu/drm/bridge/dw-hdmi.c | 113 ++++++++++++++++++++++++++-------------
 include/drm/bridge/dw_hdmi.h     |   9 ++++
 2 files changed, 86 insertions(+), 36 deletions(-)

diff --git a/drivers/gpu/drm/bridge/dw-hdmi.c b/drivers/gpu/drm/bridge/dw-hdmi.c
index 7c8386b..0c1c2ec 100644
--- a/drivers/gpu/drm/bridge/dw-hdmi.c
+++ b/drivers/gpu/drm/bridge/dw-hdmi.c
@@ -1,6 +1,7 @@
 /*
  * DesignWare High-Definition Multimedia Interface (HDMI) driver
  *
+ * Copyright (C) 2015 Renesas Electronics Corporation
  * Copyright (C) 2013-2015 Mentor Graphics Inc.
  * Copyright (C) 2011-2013 Freescale Semiconductor, Inc.
  * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
@@ -21,6 +22,7 @@
 #include <linux/of_device.h>
 #include <linux/spinlock.h>
 
+#include <drm/drm_atomic_helper.h>
 #include <drm/drm_of.h>
 #include <drm/drmP.h>
 #include <drm/drm_atomic_helper.h>
@@ -154,6 +156,9 @@ struct dw_hdmi {
 	unsigned int audio_cts;
 	unsigned int audio_n;
 	bool audio_enable;
+	int ratio;
+	bool interlaced;
+	int num;
 
 	void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
 	u8 (*read)(struct dw_hdmi *hdmi, int offset);
@@ -947,6 +952,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 	const struct dw_hdmi_mpll_config *mpll_config = pdata->mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *curr_ctrl = pdata->cur_ctr;
 	const struct dw_hdmi_phy_config *phy_config = pdata->phy_config;
+	const struct dw_hdmi_multi_div *multi_div = pdata->multi_div;
 
 	if (prep)
 		return -EINVAL;
@@ -982,6 +988,13 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		    phy_config->mpixelclock)
 			break;
 
+	if (hdmi->dev_type == RCAR_HDMI) {
+		for (; multi_div->mpixelclock != ~0UL; multi_div++)
+			if (hdmi->hdmi_data.video_mode.mpixelclock <=
+			    multi_div->mpixelclock)
+				break;
+	}
+
 	if (mpll_config->mpixelclock == ~0UL ||
 	    curr_ctrl->mpixelclock == ~0UL ||
 	    phy_config->mpixelclock == ~0UL) {
@@ -990,6 +1003,13 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 		return -EINVAL;
 	}
 
+	if (multi_div->mpixelclock == ~0UL &&
+	    hdmi->dev_type == RCAR_HDMI) {
+		dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
+			hdmi->hdmi_data.video_mode.mpixelclock);
+		return -EINVAL;
+	}
+
 	/* Enable csc path */
 	if (cscon)
 		val = HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH;
@@ -1016,21 +1036,28 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 	hdmi_phy_test_clear(hdmi, 0);
 
 	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].cpce, 0x06);
-	hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
+	if (hdmi->dev_type != RCAR_HDMI)
+		hdmi_phy_i2c_write(hdmi, mpll_config->res[res_idx].gmp, 0x15);
 
 	/* CURRCTRL */
 	hdmi_phy_i2c_write(hdmi, curr_ctrl->curr[res_idx], 0x10);
 
-	hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);  /* PLLPHBYCTRL */
-	hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
-
-	hdmi_phy_i2c_write(hdmi, phy_config->term, 0x19);  /* TXTERM */
-	hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr, 0x09); /* CKSYMTXCTRL */
-	hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr, 0x0E); /* VLEVCTRL */
-
-	/* REMOVE CLK TERM */
-	hdmi_phy_i2c_write(hdmi, 0x8000, 0x05);  /* CKCALCTRL */
-
+	if (hdmi->dev_type == RCAR_HDMI)
+		hdmi_phy_i2c_write(hdmi, multi_div->multi[res_idx], 0x11);
+
+	if (hdmi->dev_type != RCAR_HDMI) {
+		hdmi_phy_i2c_write(hdmi, 0x0000, 0x13);	/* PLLPHBYCTRL */
+		hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
+
+		hdmi_phy_i2c_write(hdmi, phy_config->term,
+				   0x19);		/* TXTERM */
+		hdmi_phy_i2c_write(hdmi, phy_config->sym_ctr,
+				   0x09);		/* CKSYMTXCTRL */
+		hdmi_phy_i2c_write(hdmi, phy_config->vlev_ctr,
+				   0x0e);		/* VLEVCTRL */
+		/* REMOVE CLK TERM */
+		hdmi_phy_i2c_write(hdmi, 0x8000, 0x05);	/* CKCALCTRL */
+	}
 	dw_hdmi_phy_enable_powerdown(hdmi, false);
 
 	/* toggle TMDS enable */
@@ -1041,7 +1068,7 @@ static int hdmi_phy_configure(struct dw_hdmi *hdmi, unsigned char prep,
 	dw_hdmi_phy_gen2_txpwron(hdmi, 1);
 	dw_hdmi_phy_gen2_pddq(hdmi, 0);
 
-	if (hdmi->dev_type == RK3288_HDMI)
+	if (hdmi->dev_type == RK3288_HDMI || hdmi->dev_type == RCAR_HDMI)
 		dw_hdmi_phy_enable_spare(hdmi, 1);
 
 	/*Wait for PHY PLL lock */
@@ -1850,6 +1877,9 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)
 	encoder->bridge = bridge;
 	hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 
+	if (hdmi->interlaced)
+		hdmi->connector.interlace_allowed = true;
+
 	drm_connector_helper_add(&hdmi->connector,
 				 &dw_hdmi_connector_helper_funcs);
 
@@ -1911,6 +1941,11 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		return -EINVAL;
 	}
 
+	if (of_property_read_u32(np, "interlaced", &val) == 0)
+		hdmi->interlaced = val;
+	else
+		hdmi->interlaced = false;
+
 	ddc_node = of_parse_phandle(np, "ddc-i2c-bus", 0);
 	if (ddc_node) {
 		hdmi->ddc = of_find_i2c_adapter_by_node(ddc_node);
@@ -1929,29 +1964,27 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		return PTR_ERR(hdmi->regs);
 
 	hdmi->isfr_clk = devm_clk_get(hdmi->dev, "isfr");
-	if (IS_ERR(hdmi->isfr_clk)) {
-		ret = PTR_ERR(hdmi->isfr_clk);
-		dev_err(hdmi->dev, "Unable to get HDMI isfr clk: %d\n", ret);
-		return ret;
-	}
-
-	ret = clk_prepare_enable(hdmi->isfr_clk);
-	if (ret) {
-		dev_err(hdmi->dev, "Cannot enable HDMI isfr clock: %d\n", ret);
-		return ret;
+	if (IS_ERR(hdmi->isfr_clk))
+		hdmi->isfr_clk = NULL;
+	else {
+		ret = clk_prepare_enable(hdmi->isfr_clk);
+		if (ret) {
+			dev_err(hdmi->dev,
+				"Cannot enable HDMI isfr clock: %d\n", ret);
+			return ret;
+		}
 	}
 
 	hdmi->iahb_clk = devm_clk_get(hdmi->dev, "iahb");
-	if (IS_ERR(hdmi->iahb_clk)) {
-		ret = PTR_ERR(hdmi->iahb_clk);
-		dev_err(hdmi->dev, "Unable to get HDMI iahb clk: %d\n", ret);
-		goto err_isfr;
-	}
-
-	ret = clk_prepare_enable(hdmi->iahb_clk);
-	if (ret) {
-		dev_err(hdmi->dev, "Cannot enable HDMI iahb clock: %d\n", ret);
-		goto err_isfr;
+	if (IS_ERR(hdmi->iahb_clk))
+		hdmi->iahb_clk = NULL;
+	else {
+		ret = clk_prepare_enable(hdmi->iahb_clk);
+		if (ret) {
+			dev_err(hdmi->dev,
+				"Cannot enable HDMI iahb clock: %d\n", ret);
+			goto err_isfr;
+		}
 	}
 
 	/* Product and revision IDs */
@@ -2037,9 +2070,11 @@ int dw_hdmi_bind(struct device *dev, struct device *master,
 		hdmi->ddc = NULL;
 	}
 
-	clk_disable_unprepare(hdmi->iahb_clk);
+	if (hdmi->iahb_clk)
+		clk_disable_unprepare(hdmi->iahb_clk);
 err_isfr:
-	clk_disable_unprepare(hdmi->isfr_clk);
+	if (hdmi->isfr_clk)
+		clk_disable_unprepare(hdmi->isfr_clk);
 
 	return ret;
 }
@@ -2055,8 +2090,14 @@ void dw_hdmi_unbind(struct device *dev, struct device *master, void *data)
 	/* Disable all interrupts */
 	hdmi_writeb(hdmi, ~0, HDMI_IH_MUTE_PHY_STAT0);
 
-	clk_disable_unprepare(hdmi->iahb_clk);
-	clk_disable_unprepare(hdmi->isfr_clk);
+	hdmi->connector.funcs->destroy(&hdmi->connector);
+	hdmi->encoder->funcs->destroy(hdmi->encoder);
+
+	if (hdmi->iahb_clk)
+		clk_disable_unprepare(hdmi->iahb_clk);
+
+	if (hdmi->isfr_clk)
+		clk_disable_unprepare(hdmi->isfr_clk);
 
 	if (hdmi->i2c)
 		i2c_del_adapter(&hdmi->i2c->adap);
diff --git a/include/drm/bridge/dw_hdmi.h b/include/drm/bridge/dw_hdmi.h
index bae79f3..a620cab 100644
--- a/include/drm/bridge/dw_hdmi.h
+++ b/include/drm/bridge/dw_hdmi.h
@@ -1,4 +1,5 @@
 /*
+ * Copyright (C) 2015 Renesas Electronics Corporation
  * Copyright (C) 2011 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,6 +26,7 @@ enum dw_hdmi_devtype {
 	IMX6Q_HDMI,
 	IMX6DL_HDMI,
 	RK3288_HDMI,
+	RCAR_HDMI,
 };
 
 struct dw_hdmi_mpll_config {
@@ -40,6 +42,11 @@ struct dw_hdmi_curr_ctrl {
 	u16 curr[DW_HDMI_RES_MAX];
 };
 
+struct dw_hdmi_multi_div {
+	unsigned long mpixelclock;
+	u16 multi[DW_HDMI_RES_MAX];
+};
+
 struct dw_hdmi_phy_config {
 	unsigned long mpixelclock;
 	u16 sym_ctr;    /*clock symbol and transmitter control*/
@@ -51,9 +58,11 @@ struct dw_hdmi_plat_data {
 	enum dw_hdmi_devtype dev_type;
 	const struct dw_hdmi_mpll_config *mpll_cfg;
 	const struct dw_hdmi_curr_ctrl *cur_ctr;
+	const struct dw_hdmi_multi_div *multi_div;
 	const struct dw_hdmi_phy_config *phy_config;
 	enum drm_mode_status (*mode_valid)(struct drm_connector *connector,
 					   struct drm_display_mode *mode);
+	u32 index;
 };
 
 void dw_hdmi_unbind(struct device *dev, struct device *master, void *data);
-- 
2.7.4

  parent reply	other threads:[~2016-11-11 17:08 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-11-11 17:07 [PATCH 00/10] Renesas R8A7795/Salvator-X HDMI output Ulrich Hecht
2016-11-11 17:07 ` [PATCH 01/10] drm: bridge/dw_hdmi: add dw hdmi i2c bus adapter support Ulrich Hecht
2016-11-11 17:48   ` Vladimir Zapolskiy
2016-11-11 17:48     ` Vladimir Zapolskiy
2016-11-11 17:07 ` Ulrich Hecht [this message]
2016-11-11 17:07 ` [PATCH 03/10] drm: rcar-du: Add R8A7795 device support Ulrich Hecht
2016-11-11 17:07 ` [PATCH 04/10] drm: rcar-du: Add dw_hdmi driver startup Ulrich Hecht
2016-11-11 17:07 ` [PATCH 05/10] drm: rcar-du: Add DPLL support Ulrich Hecht
2016-11-11 17:07 ` [PATCH 06/10] drm: rcar-du: Fix display registers for R-Car Gen3 Ulrich Hecht
2016-11-11 17:07 ` [PATCH 07/10] arm64: dts: r8a7795: Add HDMI encoder support Ulrich Hecht
2016-11-11 17:07 ` [PATCH 08/10] arm64: dts: salvator-x: Add DU pins, HDMI connectors and encoder Ulrich Hecht
2016-11-11 17:07 ` [PATCH 09/10] arm64: dts: r8a7795: add HDMI support to DU Ulrich Hecht
2016-11-15 15:28   ` Sergei Shtylyov
2016-11-11 17:07 ` [PATCH 10/10] dt-bindings: drm/bridge: Add renesas,rcar-dw-hdmi Ulrich Hecht
2016-11-14 10:16 ` [PATCH 00/10] Renesas R8A7795/Salvator-X HDMI output Geert Uytterhoeven
2016-11-14 10:16   ` Geert Uytterhoeven
2016-11-14 15:22   ` Ulrich Hecht

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1478884066-1090-3-git-send-email-ulrich.hecht+renesas@gmail.com \
    --to=ulrich.hecht+renesas@gmail.com \
    --cc=airlied@linux.ie \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=geert@linux-m68k.org \
    --cc=koji.matsuoka.xm@renesas.com \
    --cc=kuninori.morimoto.gx@renesas.com \
    --cc=laurent.pinchart@ideasonboard.com \
    --cc=linux-renesas-soc@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.