public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
From: Hans de Goede <hdegoede@redhat.com>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH 2/6] sunxi: video: Add hdmi support
Date: Sat, 20 Dec 2014 15:42:01 +0100	[thread overview]
Message-ID: <1419086525-7735-3-git-send-email-hdegoede@redhat.com> (raw)
In-Reply-To: <1419086525-7735-1-git-send-email-hdegoede@redhat.com>

So far we've been programming the hdmi-encoder to send out dvi data over the
hdmi connector. This works well for most devices, including hdmi devices, but
not all devices accept dvi data on a hdmi input.

Add support for sending proper hdmi data over the hdmi output found on most
sunxi boards. This can be turned on by adding by adding monitor=hdmi as option
to the video-mode env. variable.

A follow up patch will determine wether to send dvi or hdmi automatically when
EDID is used.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 arch/arm/include/asm/arch-sunxi/display.h | 33 +++++++++++-----
 drivers/video/sunxi_display.c             | 66 ++++++++++++++++++++++++++++---
 2 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/arch/arm/include/asm/arch-sunxi/display.h b/arch/arm/include/asm/arch-sunxi/display.h
index 8c4835e..838b217 100644
--- a/arch/arm/include/asm/arch-sunxi/display.h
+++ b/arch/arm/include/asm/arch-sunxi/display.h
@@ -102,23 +102,30 @@ struct sunxi_hdmi_reg {
 	u32 video_fp;			/* 0x01c */
 	u32 video_spw;			/* 0x020 */
 	u32 video_polarity;		/* 0x024 */
-	u8 res0[0x1d8];			/* 0x028 */
+	u8 res0[0x58];			/* 0x028 */
+	u8 avi_info_frame[0x14];	/* 0x080 */
+	u8 res1[0x4c];			/* 0x094 */
+	u32 qcp_packet0;		/* 0x0e0 */
+	u32 qcp_packet1;		/* 0x0e4 */
+	u8 res2[0x118];			/* 0x0e8 */
 	u32 pad_ctrl0;			/* 0x200 */
 	u32 pad_ctrl1;			/* 0x204 */
 	u32 pll_ctrl;			/* 0x208 */
 	u32 pll_dbg0;			/* 0x20c */
 	u32 pll_dbg1;			/* 0x210 */
 	u32 hpd_cec;			/* 0x214 */
-	u8 res1[0x28];			/* 0x218 */
-	u32 spd_pkt;			/* 0x240 */
-	u8 res2[0xac];			/* 0x244 */
+	u8 res3[0x28];			/* 0x218 */
+	u8 vendor_info_frame[0x14];	/* 0x240 */
+	u8 res4[0x9c];			/* 0x254 */
 	u32 pkt_ctrl0;			/* 0x2f0 */
 	u32 pkt_ctrl1;			/* 0x2f4 */
-	u8 res3[0x18];			/* 0x2f8 */
+	u8 res5[0x8];			/* 0x2f8 */
+	u32 unknown;			/* 0x300 */
+	u8 res6[0xc];			/* 0x304 */
 	u32 audio_sample_count;		/* 0x310 */
-	u8 res4[0xec];			/* 0x314 */
+	u8 res7[0xec];			/* 0x314 */
 	u32 audio_tx_fifo;		/* 0x400 */
-	u8 res5[0xfc];			/* 0x404 */
+	u8 res8[0xfc];			/* 0x404 */
 #ifndef CONFIG_MACH_SUN6I
 	u32 ddc_ctrl;			/* 0x500 */
 	u32 ddc_addr;			/* 0x504 */
@@ -131,7 +138,7 @@ struct sunxi_hdmi_reg {
 	u32 ddc_cmnd;			/* 0x520 */
 	u32 ddc_exreg;			/* 0x524 */
 	u32 ddc_clock;			/* 0x528 */
-	u8 res6[0x14];			/* 0x52c */
+	u8 res9[0x14];			/* 0x52c */
 	u32 ddc_line_ctrl;		/* 0x540 */
 #else
 	u32 ddc_ctrl;			/* 0x500 */
@@ -144,9 +151,9 @@ struct sunxi_hdmi_reg {
 	u32 ddc_fifo_status;		/* 0x51c */
 	u32 ddc_clock;			/* 0x520 */
 	u32 ddc_timeout;		/* 0x524 */
-	u8 res6[0x18];			/* 0x528 */
+	u8 res9[0x18];			/* 0x528 */
 	u32 ddc_dbg;			/* 0x540 */
-	u8 res7[0x3c];			/* 0x544 */
+	u8 res10[0x3c];			/* 0x544 */
 	u32 ddc_fifo_data;		/* 0x580 */
 #endif
 };
@@ -191,9 +198,12 @@ struct sunxi_hdmi_reg {
 #define SUNXI_HDMI_IRQ_STATUS_BITS		0x73
 #define SUNXI_HDMI_HPD_DETECT			(1 << 0)
 #define SUNXI_HDMI_VIDEO_CTRL_ENABLE		(1 << 31)
+#define SUNXI_HDMI_VIDEO_CTRL_HDMI		(1 << 30)
 #define SUNXI_HDMI_VIDEO_POL_HOR		(1 << 0)
 #define SUNXI_HDMI_VIDEO_POL_VER		(1 << 1)
 #define SUNXI_HDMI_VIDEO_POL_TX_CLK		(0x3e0 << 16)
+#define SUNXI_HDMI_QCP_PACKET0			3
+#define SUNXI_HDMI_QCP_PACKET1			0
 
 #ifdef CONFIG_MACH_SUN6I
 #define SUNXI_HDMI_PAD_CTRL0_HDP		0x7e80000f
@@ -224,6 +234,9 @@ struct sunxi_hdmi_reg {
 #define SUNXI_HDMI_PLL_DBG0_PLL3		(0 << 21)
 #define SUNXI_HDMI_PLL_DBG0_PLL7		(1 << 21)
 
+#define SUNXI_HDMI_PKT_CTRL0			0x00000f21
+#define SUNXI_HDMI_PKT_CTRL1			0x0000000f
+
 #ifdef CONFIG_MACH_SUN6I
 #define SUNXI_HMDI_DDC_CTRL_ENABLE		(1 << 0)
 #define SUNXI_HMDI_DDC_CTRL_SCL_ENABLE		(1 << 4)
diff --git a/drivers/video/sunxi_display.c b/drivers/video/sunxi_display.c
index 0997740..394153a 100644
--- a/drivers/video/sunxi_display.c
+++ b/drivers/video/sunxi_display.c
@@ -403,8 +403,55 @@ static void sunxi_drc_init(void)
 }
 #endif
 
+static void sunxi_hdmi_setup_info_frames(const struct ctfb_res_modes *mode)
+{
+	struct sunxi_hdmi_reg * const hdmi =
+		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
+	u8 checksum = 0;
+	u8 avi_info_frame[17] = {
+		0x82, 0x02, 0x0d, 0x00, 0x12, 0x00, 0x88, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00
+	};
+	u8 vendor_info_frame[19] = {
+		0x81, 0x01, 0x06, 0x29, 0x03, 0x0c, 0x00, 0x40,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00
+	};
+	int i;
+
+	if (mode->pixclock_khz <= 27000)
+		avi_info_frame[5] = 0x40; /* SD-modes, ITU601 colorspace */
+	else
+		avi_info_frame[5] = 0x80; /* HD-modes, ITU709 colorspace */
+
+	if (mode->xres * 100 / mode->yres < 156)
+		avi_info_frame[5] |= 0x18; /* 4 : 3 */
+	else
+		avi_info_frame[5] |= 0x28; /* 16 : 9 */
+
+	for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
+		checksum += avi_info_frame[i];
+
+	avi_info_frame[3] = 0x100 - checksum;
+
+	for (i = 0; i < ARRAY_SIZE(avi_info_frame); i++)
+		writeb(avi_info_frame[i], &hdmi->avi_info_frame[i]);
+
+	writel(SUNXI_HDMI_QCP_PACKET0, &hdmi->qcp_packet0);
+	writel(SUNXI_HDMI_QCP_PACKET1, &hdmi->qcp_packet1);
+
+	for (i = 0; i < ARRAY_SIZE(vendor_info_frame); i++)
+		writeb(vendor_info_frame[i], &hdmi->vendor_info_frame[i]);
+
+	writel(SUNXI_HDMI_PKT_CTRL0, &hdmi->pkt_ctrl0);
+	writel(SUNXI_HDMI_PKT_CTRL1, &hdmi->pkt_ctrl1);
+
+	setbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_HDMI);
+}
+
 static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
-				int clk_div, int clk_double)
+				bool hdmi_mode, int clk_div, int clk_double)
 {
 	struct sunxi_hdmi_reg * const hdmi =
 		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
@@ -413,6 +460,9 @@ static void sunxi_hdmi_mode_set(const struct ctfb_res_modes *mode,
 	/* Write clear interrupt status bits */
 	writel(SUNXI_HDMI_IRQ_STATUS_BITS, &hdmi->irq);
 
+	if (hdmi_mode)
+		sunxi_hdmi_setup_info_frames(mode);
+
 	/* Init various registers, select pll3 as clock source */
 	writel(SUNXI_HDMI_VIDEO_POL_TX_CLK, &hdmi->video_polarity);
 	writel(SUNXI_HDMI_PAD_CTRL0_RUN, &hdmi->pad_ctrl0);
@@ -458,7 +508,8 @@ static void sunxi_engines_init(void)
 #endif
 }
 
-static void sunxi_mode_set(const struct ctfb_res_modes *mode, unsigned int address)
+static void sunxi_mode_set(const struct ctfb_res_modes *mode, char *monitor,
+			   unsigned int address)
 {
 	struct sunxi_de_be_reg * const de_be =
 		(struct sunxi_de_be_reg *)SUNXI_DE_BE0_BASE;
@@ -468,6 +519,7 @@ static void sunxi_mode_set(const struct ctfb_res_modes *mode, unsigned int addre
 		(struct sunxi_hdmi_reg *)SUNXI_HDMI_BASE;
 	int clk_div, clk_double;
 	int retries = 3;
+	bool hdmi_mode = strcmp(monitor, "hdmi") == 0;
 
 retry:
 	clrbits_le32(&hdmi->video_ctrl, SUNXI_HDMI_VIDEO_CTRL_ENABLE);
@@ -476,7 +528,7 @@ retry:
 
 	sunxi_composer_mode_set(mode, address);
 	sunxi_lcdc_mode_set(mode, &clk_div, &clk_double);
-	sunxi_hdmi_mode_set(mode, clk_div, clk_double);
+	sunxi_hdmi_mode_set(mode, hdmi_mode, clk_div, clk_double);
 
 	setbits_le32(&de_be->reg_ctrl, SUNXI_DE_BE_REG_CTRL_LOAD_REGS);
 	setbits_le32(&de_be->mode, SUNXI_DE_BE_MODE_START);
@@ -511,6 +563,7 @@ void *video_hw_init(void)
 	const char *options;
 	unsigned int depth;
 	int ret, hpd, edid;
+	char monitor[16];
 
 	memset(&sunxi_display, 0, sizeof(struct sunxi_display));
 
@@ -521,6 +574,8 @@ void *video_hw_init(void)
 	video_get_ctfb_res_modes(RES_MODE_1024x768, 24, &mode, &depth, &options);
 	hpd = video_get_option_int(options, "hpd", 1);
 	edid = video_get_option_int(options, "edid", 1);
+	video_get_option_string(options, "monitor", monitor, sizeof(monitor),
+				"dvi");
 
 	/* Always call hdp_detect, as it also enables various clocks, etc. */
 	ret = sunxi_hdmi_hpd_detect();
@@ -541,12 +596,13 @@ void *video_hw_init(void)
 		printf("Only non-interlaced modes supported, falling back to 1024x768\n");
 		mode = &res_mode_init[RES_MODE_1024x768];
 	} else {
-		printf("Setting up a %dx%d console\n", mode->xres, mode->yres);
+		printf("Setting up a %dx%d %s console\n",
+		       mode->xres, mode->yres, monitor);
 	}
 
 	sunxi_display.enabled = true;
 	sunxi_engines_init();
-	sunxi_mode_set(mode, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
+	sunxi_mode_set(mode, monitor, gd->fb_base - CONFIG_SYS_SDRAM_BASE);
 
 	/*
 	 * These are the only members of this structure that are used. All the
-- 
2.1.0

  parent reply	other threads:[~2014-12-20 14:42 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-20 14:41 [U-Boot] [PATCH 0/6] sunxi: video: Add hdmi output fmt support + misc fixes Hans de Goede
2014-12-20 14:42 ` [U-Boot] [PATCH 1/6] edid: Add struct and defines for cea681 extension blocks Hans de Goede
2015-01-08 16:38   ` Anatolij Gustschin
2015-01-08 16:39   ` Anatolij Gustschin
2014-12-20 14:42 ` Hans de Goede [this message]
2014-12-22 12:44   ` [U-Boot] [PATCH 2/6] sunxi: video: Add hdmi support Ian Campbell
2015-01-08 16:51   ` Anatolij Gustschin
2014-12-20 14:42 ` [U-Boot] [PATCH 3/6] sunxi: video: Add sunxi_hdmi_edid_get_block helper function Hans de Goede
2014-12-22 12:46   ` Ian Campbell
2015-01-08 16:54   ` Anatolij Gustschin
2014-12-20 14:42 ` [U-Boot] [PATCH 4/6] sunxi: video: When using edid use CEA681 extension blocks to select hdmi output Hans de Goede
2014-12-22 12:47   ` Ian Campbell
2015-01-08 16:59   ` Anatolij Gustschin
2014-12-20 14:42 ` [U-Boot] [PATCH 5/6] sunxi: video: Give hotplug-detect (hpd) signal some time to show up Hans de Goede
2014-12-22 12:48   ` Ian Campbell
2014-12-24  2:25   ` B.R. Oake
2014-12-24 16:13     ` Hans de Goede
2014-12-24 18:29       ` B.R. Oake
2014-12-28  8:40         ` Hans de Goede
2015-01-03 16:43           ` B.R. Oake
2015-01-08 17:08   ` Anatolij Gustschin
2014-12-20 14:42 ` [U-Boot] [PATCH 6/6] sunxi: video: Set input sync enable Hans de Goede
2014-12-22 12:48   ` Ian Campbell
2015-01-08 17:11   ` Anatolij Gustschin
2014-12-22 12:49 ` [U-Boot] [PATCH 0/6] sunxi: video: Add hdmi output fmt support + misc fixes Ian Campbell

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=1419086525-7735-3-git-send-email-hdegoede@redhat.com \
    --to=hdegoede@redhat.com \
    --cc=u-boot@lists.denx.de \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox