mirror of
https://github.com/Fishwaldo/build.git
synced 2025-07-23 13:29:33 +00:00
Update H3 HDMI driver in u-boot
This commit is contained in:
parent
25040a9baa
commit
7958a8c59a
2 changed files with 192 additions and 556 deletions
|
@ -1,8 +1,10 @@
|
|||
commit 8e81ba0e8e97eb7deeb4f1cd49886c8a7db1c780
|
||||
commit b973987576822640f35dbb805a048b1706dc8e6d
|
||||
Author: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Tue Nov 8 01:04:32 2016 +0100
|
||||
|
||||
First fully working HDMI driver. Needs cleanup and testing
|
||||
sunxi: video: Add video driver for H3 SoC
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
|
||||
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
|
||||
index be9fcfd..a414f69 100644
|
||||
|
@ -528,21 +530,27 @@ index db34904..d05b745 100644
|
|||
obj-$(CONFIG_VIDEO_VESA) += vesa.o
|
||||
diff --git a/drivers/video/sun8i_display.c b/drivers/video/sun8i_display.c
|
||||
new file mode 100644
|
||||
index 0000000..48de695
|
||||
index 0000000..e596e4c
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/sun8i_display.c
|
||||
@@ -0,0 +1,1112 @@
|
||||
@@ -0,0 +1,928 @@
|
||||
+/*
|
||||
+ * Display driver for sun8i Allwinner SoCs.
|
||||
+ * Display driver for sunxi Allwinner SoCs with DE2.
|
||||
+ *
|
||||
+ * (C) Copyright 2016 Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
+ * Copyright (C) 2016 Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
+ *
|
||||
+ * Based on multiple works:
|
||||
+ * Based on sunxi_display.c:
|
||||
+ * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
|
||||
+ * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * Based on Linux DRM driver:
|
||||
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
|
||||
+ * Copyright (c) 2016 Allwinnertech Co., Ltd.
|
||||
+ *
|
||||
+ * Based on rk_hdmi.c:
|
||||
+ * Copyright (c) 2015 Google, Inc
|
||||
+ * Copyright 2014 Rockchip Inc.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
|
@ -550,16 +558,9 @@ index 0000000..48de695
|
|||
+
|
||||
+#include <asm/arch/clock.h>
|
||||
+#include <asm/arch/display2.h>
|
||||
+#include <asm/arch/gpio.h>
|
||||
+#include <asm/arch/pwm.h>
|
||||
+#include <asm/global_data.h>
|
||||
+#include <asm/gpio.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <errno.h>
|
||||
+#include <fdtdec.h>
|
||||
+#include <fdt_support.h>
|
||||
+#include <i2c.h>
|
||||
+#include <malloc.h>
|
||||
+#include <video_fb.h>
|
||||
+#include "videomodes.h"
|
||||
+
|
||||
|
@ -582,92 +583,55 @@ index 0000000..48de695
|
|||
+
|
||||
+#ifdef CONFIG_VIDEO_HDMI
|
||||
+
|
||||
+static void hdmi_read_lock(void)
|
||||
+{
|
||||
+ writel(0x45, SUNXI_HDMI_BASE + 0x10010);
|
||||
+ writel(0x45, SUNXI_HDMI_BASE + 0x10011);
|
||||
+ writel(0x52, SUNXI_HDMI_BASE + 0x10012);
|
||||
+ writel(0x54, SUNXI_HDMI_BASE + 0x10013);
|
||||
+}
|
||||
+
|
||||
+static void hdmi_read_unlock(void)
|
||||
+{
|
||||
+ writel(0x52, SUNXI_HDMI_BASE + 0x10010);
|
||||
+ writel(0x54, SUNXI_HDMI_BASE + 0x10011);
|
||||
+ writel(0x41, SUNXI_HDMI_BASE + 0x10012);
|
||||
+ writel(0x57, SUNXI_HDMI_BASE + 0x10013);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Wait up to 200ms for value to be set in given part of reg.
|
||||
+ */
|
||||
+static int await_completion(u32 *reg, u32 mask, u32 val, u32 usec)
|
||||
+{
|
||||
+ unsigned long tmo = timer_get_us() + usec;
|
||||
+
|
||||
+ while ((readl(reg) & mask) != val) {
|
||||
+ if (timer_get_us() > tmo)
|
||||
+ return -ETIME;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void sun8i_hdmi_phy_init(void)
|
||||
+{
|
||||
+ unsigned long tmo;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ writel(0, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(1 << 0, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(0));
|
||||
+ udelay(5);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 16), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 1), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(16));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(1));
|
||||
+ udelay(10);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 2), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(2));
|
||||
+ udelay(5);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 3), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(3));
|
||||
+ udelay(40);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 19), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(19));
|
||||
+ udelay(100);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(18));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, 7 << 4);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 18), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (7 << 4), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ /* Note that Allwinner code doesn't fail in case of timeout */
|
||||
+ tmo = timer_get_us() + 2000;
|
||||
+ while ((readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x80) == 0) {
|
||||
+ if (timer_get_us() > tmo) {
|
||||
+ printf("Warning: HDMI phy init timeout!\n");
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (await_completion(SUN8I_HDMI_PHY_STATUS_REG, 0x80, 0x80, 2000))
|
||||
+ printf("Warning: HDMI phy init timeout!\n");
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (15 << 8), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 7), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, 0xf << 8);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(7));
|
||||
+
|
||||
+ writel(0x39dc5040, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(0x80084343, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+
|
||||
+ udelay(10000);
|
||||
+
|
||||
+ writel(1, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG) | (1 << 25), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ udelay(100000);
|
||||
+
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG) | (3 << 30), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG) | ((tmp & 0x1f800) >> 11),
|
||||
+ SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FF0F7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x80639000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C405, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+ /* enable read access to HDMI controller*/
|
||||
+ writel(0x54524545, SUNXI_HDMI_BASE + 0x10010);
|
||||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE+ 0x8080);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x8080);
|
||||
+
|
||||
+ udelay(1);
|
||||
+
|
||||
|
@ -708,7 +672,7 @@ index 0000000..48de695
|
|||
+ unsigned long tmo = timer_get_us() + hpd_delay * 1000;
|
||||
+ int status = 0;
|
||||
+
|
||||
+ /* Set pll3 to 297MHz */
|
||||
+ /* Set pll3 to 297 MHz */
|
||||
+ clock_set_pll3(297000000);
|
||||
+
|
||||
+ /* Set hdmi parent to pll3 */
|
||||
|
@ -726,8 +690,6 @@ index 0000000..48de695
|
|||
+
|
||||
+ sun8i_hdmi_phy_init();
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ while (timer_get_us() < tmo) {
|
||||
+ if (readl(SUN8I_HDMI_PHY_STATUS_REG) & SUNXI_HDMI_HPD_DETECT) {
|
||||
+ status = 1;
|
||||
|
@ -735,8 +697,6 @@ index 0000000..48de695
|
|||
+ }
|
||||
+ }
|
||||
+
|
||||
+ hdmi_read_unlock();
|
||||
+
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
|
@ -834,21 +794,14 @@ index 0000000..48de695
|
|||
+ int i, r, ext_blocks = 0;
|
||||
+
|
||||
+ /* Reset i2c controller */
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ writeb(0, SUN8I_HDMI_I2CM_SOFTRSTZ);
|
||||
+ if (await_completion(SUN8I_HDMI_I2CM_SOFTRSTZ,
|
||||
+ SUN8I_HMDI_DDC_CTRL_RESET, SUN8I_HMDI_DDC_CTRL_RESET, 500)) {
|
||||
+ printf("Error: DDC reset failed!\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ writel(0x05, SUN8I_HDMI_I2CM_DIV);
|
||||
+ writel(0x08, SUN8I_HDMI_I2CM_INT);
|
||||
+ writel(0xd8, SUN8I_HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
|
||||
+ writel(0xfe, SUN8I_HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
|
||||
+ writel(SUN8I_HMDI_DDC_ADDR_SLAVE_ADDR, SUN8I_HDMI_I2CM_SLAVE);
|
||||
+ writel(SUN8I_HMDI_DDC_ADDR_SEG_ADDR, SUN8I_HDMI_I2CM_SEGADDR);
|
||||
+ writeb(0x05, SUN8I_HDMI_I2CM_DIV);
|
||||
+ writeb(0x08, SUN8I_HDMI_I2CM_INT);
|
||||
+ writeb(0xd8, SUN8I_HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
|
||||
+ writeb(0xfe, SUN8I_HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
|
||||
+ writeb(SUN8I_HMDI_DDC_ADDR_SLAVE_ADDR, SUN8I_HDMI_I2CM_SLAVE);
|
||||
+ writeb(SUN8I_HMDI_DDC_ADDR_SEG_ADDR, SUN8I_HDMI_I2CM_SEGADDR);
|
||||
+
|
||||
+ r = sunxi_hdmi_edid_get_block(0, (u8 *)&edid1);
|
||||
+ if (r == 0) {
|
||||
|
@ -871,8 +824,6 @@ index 0000000..48de695
|
|||
+ }
|
||||
+ }
|
||||
+
|
||||
+ hdmi_read_unlock();
|
||||
+
|
||||
+ if (r)
|
||||
+ return r;
|
||||
+
|
||||
|
@ -955,7 +906,7 @@ index 0000000..48de695
|
|||
+
|
||||
+ clrbits_le32(SUN8I_DE_SEL_REG, 1);
|
||||
+
|
||||
+ writel(DE_MUX_GLB_CTL_rt_en | DE_MUX_GLB_CTL_rtwb_port, &de_glb_regs->ctl);
|
||||
+ writel(DE_MUX_GLB_CTL_rt_en, &de_glb_regs->ctl);
|
||||
+ writel(0, &de_glb_regs->status);
|
||||
+ writel(1, &de_glb_regs->dbuff);
|
||||
+ writel(size, &de_glb_regs->size);
|
||||
|
@ -1076,7 +1027,6 @@ index 0000000..48de695
|
|||
+
|
||||
+ /* Reset off */
|
||||
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TCON0);
|
||||
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TCON1);
|
||||
+
|
||||
+ /* Clock on */
|
||||
+ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TCON0);
|
||||
|
@ -1088,7 +1038,7 @@ index 0000000..48de695
|
|||
+ writel(0, &lcdc->gint0); /* Disable all interrupts */
|
||||
+
|
||||
+ /* Set all io lines to tristate */
|
||||
+ //writel(0x0fffffff, &lcdc->io_tri);
|
||||
+ writel(0x0fffffff, &lcdc->io_tri);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_lcdc_enable(void)
|
||||
|
@ -1107,7 +1057,7 @@ index 0000000..48de695
|
|||
+ if (mode->vmode == FB_VMODE_INTERLACED)
|
||||
+ delay /= 2;
|
||||
+ if (tcon == 1)
|
||||
+ delay -= 5;
|
||||
+ delay -= 2;
|
||||
+
|
||||
+ return (delay > 31) ? 31 : delay;
|
||||
+}
|
||||
|
@ -1119,11 +1069,6 @@ index 0000000..48de695
|
|||
+ struct sun8i_lcdc_reg * const lcdc =
|
||||
+ (struct sun8i_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||
+ int bp, clk_delay, total, yres;
|
||||
+ //u32 val;
|
||||
+
|
||||
+ sunxi_lcdc_pll_set(mode->pixclock_khz, clk_div);
|
||||
+
|
||||
+ udelay(500);
|
||||
+
|
||||
+ setbits_le32(&lcdc->gctl, SUN8I_TCON_GCTL_TCON_En);
|
||||
+
|
||||
|
@ -1158,22 +1103,10 @@ index 0000000..48de695
|
|||
+ writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
|
||||
+ &lcdc->basic5);
|
||||
+
|
||||
+ //FIXME: are those needed?
|
||||
+ //writel(1 << 16 | 1, &lcdc->ps_sync);
|
||||
+
|
||||
+ /*val = SUN8I_TCON1_IO_POL_IO2_inv;
|
||||
+ if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
|
||||
+ val |= SUN8I_TCON1_IO_POL_IO1_inv;
|
||||
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
|
||||
+ val |= SUN8I_TCON1_IO_POL_IO0_inv;
|
||||
+ writel(val, &lcdc->io_pol);*/
|
||||
+
|
||||
+ writel(0, &lcdc->ceu_ctl);
|
||||
+ writel(0, &lcdc->fill_ctl);
|
||||
+
|
||||
+ /* Set all io lines to tristate */
|
||||
+ writel(0x0fffffff, &lcdc->io_tri);
|
||||
+
|
||||
+ sunxi_lcdc_pll_set(mode->pixclock_khz, clk_div);
|
||||
+}
|
||||
+#endif /* CONFIG_VIDEO_HDMI */
|
||||
+
|
||||
|
@ -1183,41 +1116,6 @@ index 0000000..48de695
|
|||
+{
|
||||
+ u8 tmp;
|
||||
+
|
||||
+ // Vendor Specific Infoframe (VSI)
|
||||
+ // enable VSD auto scheduling
|
||||
+ writeb(0x08, SUNXI_HDMI_BASE + 0xB045);
|
||||
+
|
||||
+ // HDMI OUI
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x2045);
|
||||
+ writeb(0x0c, SUNXI_HDMI_BASE + 0x2044);
|
||||
+ writeb(0x03, SUNXI_HDMI_BASE + 0x6041);
|
||||
+
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0xA044, ((timings->vic & 0x100) == 0x100) ?
|
||||
+ // 0x20 : (((timings->vic & 0x80) == 0x80) ?
|
||||
+ // 0x40 : 0x00));
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0xA045, ((timings->vic & 0x100) == 0x100) ? (timings->vic & 0x7f) : 0x00);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0xA045);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0xA044);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x2046);
|
||||
+
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x3046);
|
||||
+ writeb(0x11, SUNXI_HDMI_BASE + 0x3047);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x4044);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0052);
|
||||
+ writeb(0x11, SUNXI_HDMI_BASE + 0x8051);
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ tmp = readb(SUNXI_HDMI_BASE + 0x0040) | 0x08;
|
||||
+ writeb(tmp, SUNXI_HDMI_BASE + 0x0040);
|
||||
+
|
||||
+ hdmi_read_unlock();
|
||||
+
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0x4045, video->is_yuv ? 0x02 : 0x00);
|
||||
+ // is this ok?
|
||||
+ //writeb(0x12, SUNXI_HDMI_BASE + 0x4045);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x4045);
|
||||
+
|
||||
+ if (mode->pixclock_khz <= 27000)
|
||||
+ tmp = 0x40; /* SD-modes, ITU601 colorspace */
|
||||
+ else
|
||||
|
@ -1228,39 +1126,31 @@ index 0000000..48de695
|
|||
+ else
|
||||
+ tmp |= 0x28; /* 16 : 9 */
|
||||
+
|
||||
+ setbits_8(SUNXI_HDMI_BASE + 0x0040, 0x08);
|
||||
+ writeb(0x60, SUNXI_HDMI_BASE + 0x4045);
|
||||
+ writeb(tmp, SUNXI_HDMI_BASE + 0xC044);
|
||||
+
|
||||
+ //writeb(video->is_yuv ? 0x00 : 0x08, SUNXI_HDMI_BASE + 0xC045);
|
||||
+ // is this ok?
|
||||
+ //writeb(0x88, SUNXI_HDMI_BASE + 0xC045);
|
||||
+ writeb(0x08, SUNXI_HDMI_BASE + 0xC045);
|
||||
+
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0x4046, timings->vic & 0x7f);
|
||||
+ writeb(0x88, SUNXI_HDMI_BASE + 0xC045);
|
||||
+}
|
||||
+
|
||||
+static int hdmi_phy_set(u32 divider)
|
||||
+{
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG)&(~0xf000), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ switch(divider)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ //if(hdmi_version == 0)
|
||||
+ // writel(0x31dc5fc0, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ //else
|
||||
+ writel(0x30dc5fc0, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(0x30dc5fc0, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(0x800863C0, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(200);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ if(((tmp&0x1f800)>>11) < 0x3d)
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|(((tmp&0x1f800)>>11)+2), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ if (tmp < 0x3d)
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp + 2);
|
||||
+ else
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x3f, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, 0x3f);
|
||||
+ mdelay(100);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063b000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
|
@ -1271,11 +1161,11 @@ index 0000000..48de695
|
|||
+ writel(0x80084381, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(100);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|((tmp&0x1f800)>>11), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063a800, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C485, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
|
@ -1285,11 +1175,11 @@ index 0000000..48de695
|
|||
+ writel(0x80084343, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(100);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|((tmp&0x1f800)>>11), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063b000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C405, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
|
@ -1299,11 +1189,11 @@ index 0000000..48de695
|
|||
+ writel(0x8008430a, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(100);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|((tmp&0x1f800)>>11), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063b000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C405, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
|
@ -1319,59 +1209,12 @@ index 0000000..48de695
|
|||
+ int clk_div)
|
||||
+{
|
||||
+ u8 invidconf, v_blanking;
|
||||
+ u32 x_res, y_res, hfp, h_blanking, hsw;
|
||||
+ /*struct sunxi_ccm_reg * const ccm =
|
||||
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||||
+ u32 h_blanking;
|
||||
+
|
||||
+ clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_M_MASK,
|
||||
+ CCM_HDMI_CTRL_M(clk_div));
|
||||
+
|
||||
+ udelay(500);*/
|
||||
+ printf("HDMI PHY divider: %d\n", clk_div);
|
||||
+
|
||||
+ if(clk_div == 0) {
|
||||
+ if(hdmi_phy_set(clk_div) != 0) {
|
||||
+ printf("HDMI divider is invalid!\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if(hdmi_phy_set(clk_div) != 0) {
|
||||
+ printf("Can't set HDMI phy!\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x8080);
|
||||
+
|
||||
+ udelay(1);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0xF01F);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8403);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x904C);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x904E);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0xD04C);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8250);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8A50);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8272);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x40C0);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x86F0);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0EE3);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8EE2);
|
||||
+ writeb(0xf0, SUNXI_HDMI_BASE + 0xA049);
|
||||
+ writeb(0x1e, SUNXI_HDMI_BASE + 0xB045);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x00C1);
|
||||
+ writeb(0x03, SUNXI_HDMI_BASE + 0x00C1);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x00C0);
|
||||
+ writeb(0x10, SUNXI_HDMI_BASE + 0x40C1);
|
||||
+ writeb(0xfd, SUNXI_HDMI_BASE + 0x0081);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0081);
|
||||
+ writeb(0xfd, SUNXI_HDMI_BASE + 0x0081);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0010);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0011);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8010);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8011);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0013);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8012);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8013);
|
||||
+
|
||||
+ invidconf = 0;
|
||||
+ if(mode->vmode & FB_VMODE_INTERLACED)
|
||||
|
@ -1381,58 +1224,39 @@ index 0000000..48de695
|
|||
+ if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
|
||||
+ invidconf |= 0x40;
|
||||
+
|
||||
+ x_res = mode->xres; //timings->x_res << timings->pixel_repeat;
|
||||
+ y_res = mode->yres; //timings->y_res << timings->pixel_repeat;
|
||||
+ hfp = mode->right_margin; //timings->hor_front_porch << timings->pixel_repeat;
|
||||
+ hsw = mode->hsync_len; //timings->hor_sync_time << timings->pixel_repeat;
|
||||
+// h_blanking = (timings->hor_back_porch + timings->hor_front_porch +
|
||||
+// timings->hor_sync_time) << timings->pixel_repeat;
|
||||
+ h_blanking = mode->left_margin + mode->right_margin + mode->hsync_len;
|
||||
+ v_blanking = mode->upper_margin + mode->lower_margin + mode->vsync_len;
|
||||
+
|
||||
+ printf("pixel_clk: %d\n", mode->pixclock_khz * 1000);
|
||||
+ printf("pixel_repeat: %s\n", mode->vmode & FB_VMODE_DOUBLE ? "true" : "false");
|
||||
+ printf("x_res: %d\n", x_res);
|
||||
+ printf("y_res: %d\n", y_res);
|
||||
+ //printf("hor_total_time: %d\n",);
|
||||
+ printf("hor_back_porch: %d\n", mode->left_margin);
|
||||
+ printf("hor_front_porch: %d\n", hfp);
|
||||
+ printf("hor_sync_time: %d\n", hsw);
|
||||
+ //printf("ver_total_time: %d\n",);
|
||||
+ printf("ver_back_porch: %d\n", mode->upper_margin);
|
||||
+ printf("ver_front_porch: %d\n", mode->lower_margin);
|
||||
+ printf("ver_sync_time: %d\n", mode->vsync_len);
|
||||
+ printf("hor_sync_polarity: %s\n", mode->sync & FB_SYNC_HOR_HIGH_ACT ? "true" : "false");
|
||||
+ printf("ver_sync_polarity: %s\n", mode->sync & FB_SYNC_VERT_HIGH_ACT ? "true" : "false");
|
||||
+ printf("b_interlace: %s\n", mode->vmode & FB_VMODE_INTERLACED ? "true" : "false");
|
||||
+
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x0840);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x4845);
|
||||
+ writeb(invidconf | 0x10, SUNXI_HDMI_BASE + 0x0040);
|
||||
+ writeb(((invidconf < 96) ? 0x03 : 0x00), SUNXI_HDMI_BASE + 0x10001);
|
||||
+ writeb((u8)(x_res >> 8), SUNXI_HDMI_BASE + 0x8040);
|
||||
+ writeb((u8)(mode->vsync_len), SUNXI_HDMI_BASE + 0x4043);
|
||||
+ writeb((u8)(y_res >> 8), SUNXI_HDMI_BASE + 0x8042);
|
||||
+ writeb((u8)(h_blanking >> 8), SUNXI_HDMI_BASE + 0x0042);
|
||||
+ writeb((u8)(mode->lower_margin), SUNXI_HDMI_BASE + 0x4042);
|
||||
+ writeb((u8)(hfp >> 8), SUNXI_HDMI_BASE + 0x4041);
|
||||
+ writeb((u8)(hsw >> 8), SUNXI_HDMI_BASE + 0xC041);
|
||||
+ writeb((u8)(x_res & 0xff), SUNXI_HDMI_BASE + 0x0041);
|
||||
+ writeb((u8)(h_blanking & 0xff), SUNXI_HDMI_BASE + 0x8041);
|
||||
+ writeb((u8)(hfp & 0xff), SUNXI_HDMI_BASE + 0x4040);
|
||||
+ writeb((u8)(hsw & 0xff), SUNXI_HDMI_BASE + 0xC040);
|
||||
+ writeb((u8)(y_res & 0xff), SUNXI_HDMI_BASE + 0x0043);
|
||||
+
|
||||
+ writeb(mode->xres >> 8, SUNXI_HDMI_BASE + 0x8040);
|
||||
+ writeb(mode->xres, SUNXI_HDMI_BASE + 0x0041);
|
||||
+ writeb(mode->yres >> 8, SUNXI_HDMI_BASE + 0x8042);
|
||||
+ writeb(mode->yres, SUNXI_HDMI_BASE + 0x0043);
|
||||
+ writeb(mode->vsync_len, SUNXI_HDMI_BASE + 0x4043);
|
||||
+ writeb(h_blanking >> 8, SUNXI_HDMI_BASE + 0x0042);
|
||||
+ writeb(h_blanking, SUNXI_HDMI_BASE + 0x8041);
|
||||
+ writeb(mode->lower_margin, SUNXI_HDMI_BASE + 0x4042);
|
||||
+ writeb(mode->right_margin >> 8, SUNXI_HDMI_BASE + 0x4041);
|
||||
+ writeb(mode->right_margin, SUNXI_HDMI_BASE + 0x4040);
|
||||
+ writeb(mode->hsync_len >> 8, SUNXI_HDMI_BASE + 0xC041);
|
||||
+ writeb(mode->hsync_len, SUNXI_HDMI_BASE + 0xC040);
|
||||
+ writeb(v_blanking, SUNXI_HDMI_BASE + 0x8043);
|
||||
+
|
||||
+ writeb(0x0c, SUNXI_HDMI_BASE + 0x0045);
|
||||
+ writeb(0x20, SUNXI_HDMI_BASE + 0x8044);
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x8045);
|
||||
+ writeb(0x0b, SUNXI_HDMI_BASE + 0x0046);
|
||||
+ writeb(0x16, SUNXI_HDMI_BASE + 0x0047);
|
||||
+ writeb(0x21, SUNXI_HDMI_BASE + 0x8046);
|
||||
+ writeb(mode->vmode & FB_VMODE_DOUBLE ? 0x21 : 0x10, SUNXI_HDMI_BASE + 0x3048);
|
||||
+ writeb(mode->vmode & FB_VMODE_DOUBLE ? 0x41 : 0x40, SUNXI_HDMI_BASE + 0x0401);
|
||||
+
|
||||
+ writeb(0x40, SUNXI_HDMI_BASE + 0x0401);
|
||||
+ writeb(0x07, SUNXI_HDMI_BASE + 0x8400);
|
||||
+
|
||||
+ // default value, written 0 by rk_hdmi
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x8401);
|
||||
+
|
||||
+ writeb(0x47, SUNXI_HDMI_BASE + 0x0402);
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x0800);
|
||||
+ writeb(0x07, SUNXI_HDMI_BASE + 0x0801);
|
||||
|
@ -1448,14 +1272,11 @@ index 0000000..48de695
|
|||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0082);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0081);
|
||||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0840);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_hdmi_enable(void)
|
||||
+{
|
||||
+ udelay(100);
|
||||
+ writeb(readb(SUN8I_HDMI_PHY_CTRL_REG) | (15 << 12), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, 0xf << 12);
|
||||
+ printf("hdmi enabled\n");
|
||||
+}
|
||||
+
|
||||
|
@ -1484,9 +1305,6 @@ index 0000000..48de695
|
|||
+ sunxi_composer_enable();
|
||||
+ sunxi_lcdc_enable();
|
||||
+ sunxi_hdmi_enable();
|
||||
+// sunxi_composer_init();
|
||||
+// sunxi_composer_mode_set(mode, address);
|
||||
+// sunxi_composer_enable();
|
||||
+#endif
|
||||
+ break;
|
||||
+ }
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
commit 8e81ba0e8e97eb7deeb4f1cd49886c8a7db1c780
|
||||
commit b973987576822640f35dbb805a048b1706dc8e6d
|
||||
Author: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
Date: Tue Nov 8 01:04:32 2016 +0100
|
||||
|
||||
First fully working HDMI driver. Needs cleanup and testing
|
||||
sunxi: video: Add video driver for H3 SoC
|
||||
|
||||
Signed-off-by: Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
|
||||
diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun6i.h b/arch/arm/include/asm/arch-sunxi/clock_sun6i.h
|
||||
index be9fcfd..a414f69 100644
|
||||
|
@ -528,21 +530,27 @@ index db34904..d05b745 100644
|
|||
obj-$(CONFIG_VIDEO_VESA) += vesa.o
|
||||
diff --git a/drivers/video/sun8i_display.c b/drivers/video/sun8i_display.c
|
||||
new file mode 100644
|
||||
index 0000000..48de695
|
||||
index 0000000..e596e4c
|
||||
--- /dev/null
|
||||
+++ b/drivers/video/sun8i_display.c
|
||||
@@ -0,0 +1,1112 @@
|
||||
@@ -0,0 +1,928 @@
|
||||
+/*
|
||||
+ * Display driver for sun8i Allwinner SoCs.
|
||||
+ * Display driver for sunxi Allwinner SoCs with DE2.
|
||||
+ *
|
||||
+ * (C) Copyright 2016 Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
+ * Copyright (C) 2016 Jernej Skrabec <jernej.skrabec@siol.net>
|
||||
+ *
|
||||
+ * Based on multiple works:
|
||||
+ * Based on sunxi_display.c:
|
||||
+ * (C) Copyright 2013-2014 Luc Verhaegen <libv@skynet.be>
|
||||
+ * (C) Copyright 2014-2015 Hans de Goede <hdegoede@redhat.com>
|
||||
+ *
|
||||
+ * Based on Linux DRM driver:
|
||||
+ * Copyright (C) 2016 Jean-Francois Moine <moinejf@free.fr>
|
||||
+ * Copyright (c) 2016 Allwinnertech Co., Ltd.
|
||||
+ *
|
||||
+ * Based on rk_hdmi.c:
|
||||
+ * Copyright (c) 2015 Google, Inc
|
||||
+ * Copyright 2014 Rockchip Inc.
|
||||
+ *
|
||||
+ * SPDX-License-Identifier: GPL-2.0+
|
||||
+ */
|
||||
+
|
||||
|
@ -550,16 +558,9 @@ index 0000000..48de695
|
|||
+
|
||||
+#include <asm/arch/clock.h>
|
||||
+#include <asm/arch/display2.h>
|
||||
+#include <asm/arch/gpio.h>
|
||||
+#include <asm/arch/pwm.h>
|
||||
+#include <asm/global_data.h>
|
||||
+#include <asm/gpio.h>
|
||||
+#include <asm/io.h>
|
||||
+#include <errno.h>
|
||||
+#include <fdtdec.h>
|
||||
+#include <fdt_support.h>
|
||||
+#include <i2c.h>
|
||||
+#include <malloc.h>
|
||||
+#include <video_fb.h>
|
||||
+#include "videomodes.h"
|
||||
+
|
||||
|
@ -582,92 +583,55 @@ index 0000000..48de695
|
|||
+
|
||||
+#ifdef CONFIG_VIDEO_HDMI
|
||||
+
|
||||
+static void hdmi_read_lock(void)
|
||||
+{
|
||||
+ writel(0x45, SUNXI_HDMI_BASE + 0x10010);
|
||||
+ writel(0x45, SUNXI_HDMI_BASE + 0x10011);
|
||||
+ writel(0x52, SUNXI_HDMI_BASE + 0x10012);
|
||||
+ writel(0x54, SUNXI_HDMI_BASE + 0x10013);
|
||||
+}
|
||||
+
|
||||
+static void hdmi_read_unlock(void)
|
||||
+{
|
||||
+ writel(0x52, SUNXI_HDMI_BASE + 0x10010);
|
||||
+ writel(0x54, SUNXI_HDMI_BASE + 0x10011);
|
||||
+ writel(0x41, SUNXI_HDMI_BASE + 0x10012);
|
||||
+ writel(0x57, SUNXI_HDMI_BASE + 0x10013);
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Wait up to 200ms for value to be set in given part of reg.
|
||||
+ */
|
||||
+static int await_completion(u32 *reg, u32 mask, u32 val, u32 usec)
|
||||
+{
|
||||
+ unsigned long tmo = timer_get_us() + usec;
|
||||
+
|
||||
+ while ((readl(reg) & mask) != val) {
|
||||
+ if (timer_get_us() > tmo)
|
||||
+ return -ETIME;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void sun8i_hdmi_phy_init(void)
|
||||
+{
|
||||
+ unsigned long tmo;
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ writel(0, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(1 << 0, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(0));
|
||||
+ udelay(5);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 16), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 1), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(16));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(1));
|
||||
+ udelay(10);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 2), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(2));
|
||||
+ udelay(5);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 3), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(3));
|
||||
+ udelay(40);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 19), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(19));
|
||||
+ udelay(100);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(18));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, 7 << 4);
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 18), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (7 << 4), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ /* Note that Allwinner code doesn't fail in case of timeout */
|
||||
+ tmo = timer_get_us() + 2000;
|
||||
+ while ((readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x80) == 0) {
|
||||
+ if (timer_get_us() > tmo) {
|
||||
+ printf("Warning: HDMI phy init timeout!\n");
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (await_completion(SUN8I_HDMI_PHY_STATUS_REG, 0x80, 0x80, 2000))
|
||||
+ printf("Warning: HDMI phy init timeout!\n");
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (15 << 8), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG) | (1 << 7), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, 0xf << 8);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, BIT(7));
|
||||
+
|
||||
+ writel(0x39dc5040, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(0x80084343, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+
|
||||
+ udelay(10000);
|
||||
+
|
||||
+ writel(1, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG) | (1 << 25), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ udelay(100000);
|
||||
+
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG) | (3 << 30), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG) | ((tmp & 0x1f800) >> 11),
|
||||
+ SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FF0F7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x80639000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C405, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+ /* enable read access to HDMI controller*/
|
||||
+ writel(0x54524545, SUNXI_HDMI_BASE + 0x10010);
|
||||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE+ 0x8080);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x8080);
|
||||
+
|
||||
+ udelay(1);
|
||||
+
|
||||
|
@ -708,7 +672,7 @@ index 0000000..48de695
|
|||
+ unsigned long tmo = timer_get_us() + hpd_delay * 1000;
|
||||
+ int status = 0;
|
||||
+
|
||||
+ /* Set pll3 to 297MHz */
|
||||
+ /* Set pll3 to 297 MHz */
|
||||
+ clock_set_pll3(297000000);
|
||||
+
|
||||
+ /* Set hdmi parent to pll3 */
|
||||
|
@ -726,8 +690,6 @@ index 0000000..48de695
|
|||
+
|
||||
+ sun8i_hdmi_phy_init();
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ while (timer_get_us() < tmo) {
|
||||
+ if (readl(SUN8I_HDMI_PHY_STATUS_REG) & SUNXI_HDMI_HPD_DETECT) {
|
||||
+ status = 1;
|
||||
|
@ -735,8 +697,6 @@ index 0000000..48de695
|
|||
+ }
|
||||
+ }
|
||||
+
|
||||
+ hdmi_read_unlock();
|
||||
+
|
||||
+ return status;
|
||||
+}
|
||||
+
|
||||
|
@ -834,21 +794,14 @@ index 0000000..48de695
|
|||
+ int i, r, ext_blocks = 0;
|
||||
+
|
||||
+ /* Reset i2c controller */
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ writeb(0, SUN8I_HDMI_I2CM_SOFTRSTZ);
|
||||
+ if (await_completion(SUN8I_HDMI_I2CM_SOFTRSTZ,
|
||||
+ SUN8I_HMDI_DDC_CTRL_RESET, SUN8I_HMDI_DDC_CTRL_RESET, 500)) {
|
||||
+ printf("Error: DDC reset failed!\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ writel(0x05, SUN8I_HDMI_I2CM_DIV);
|
||||
+ writel(0x08, SUN8I_HDMI_I2CM_INT);
|
||||
+ writel(0xd8, SUN8I_HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
|
||||
+ writel(0xfe, SUN8I_HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
|
||||
+ writel(SUN8I_HMDI_DDC_ADDR_SLAVE_ADDR, SUN8I_HDMI_I2CM_SLAVE);
|
||||
+ writel(SUN8I_HMDI_DDC_ADDR_SEG_ADDR, SUN8I_HDMI_I2CM_SEGADDR);
|
||||
+ writeb(0x05, SUN8I_HDMI_I2CM_DIV);
|
||||
+ writeb(0x08, SUN8I_HDMI_I2CM_INT);
|
||||
+ writeb(0xd8, SUN8I_HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
|
||||
+ writeb(0xfe, SUN8I_HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
|
||||
+ writeb(SUN8I_HMDI_DDC_ADDR_SLAVE_ADDR, SUN8I_HDMI_I2CM_SLAVE);
|
||||
+ writeb(SUN8I_HMDI_DDC_ADDR_SEG_ADDR, SUN8I_HDMI_I2CM_SEGADDR);
|
||||
+
|
||||
+ r = sunxi_hdmi_edid_get_block(0, (u8 *)&edid1);
|
||||
+ if (r == 0) {
|
||||
|
@ -871,8 +824,6 @@ index 0000000..48de695
|
|||
+ }
|
||||
+ }
|
||||
+
|
||||
+ hdmi_read_unlock();
|
||||
+
|
||||
+ if (r)
|
||||
+ return r;
|
||||
+
|
||||
|
@ -955,7 +906,7 @@ index 0000000..48de695
|
|||
+
|
||||
+ clrbits_le32(SUN8I_DE_SEL_REG, 1);
|
||||
+
|
||||
+ writel(DE_MUX_GLB_CTL_rt_en | DE_MUX_GLB_CTL_rtwb_port, &de_glb_regs->ctl);
|
||||
+ writel(DE_MUX_GLB_CTL_rt_en, &de_glb_regs->ctl);
|
||||
+ writel(0, &de_glb_regs->status);
|
||||
+ writel(1, &de_glb_regs->dbuff);
|
||||
+ writel(size, &de_glb_regs->size);
|
||||
|
@ -1076,7 +1027,6 @@ index 0000000..48de695
|
|||
+
|
||||
+ /* Reset off */
|
||||
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TCON0);
|
||||
+ setbits_le32(&ccm->ahb_reset1_cfg, 1 << AHB_RESET_OFFSET_TCON1);
|
||||
+
|
||||
+ /* Clock on */
|
||||
+ setbits_le32(&ccm->ahb_gate1, 1 << AHB_GATE_OFFSET_TCON0);
|
||||
|
@ -1088,7 +1038,7 @@ index 0000000..48de695
|
|||
+ writel(0, &lcdc->gint0); /* Disable all interrupts */
|
||||
+
|
||||
+ /* Set all io lines to tristate */
|
||||
+ //writel(0x0fffffff, &lcdc->io_tri);
|
||||
+ writel(0x0fffffff, &lcdc->io_tri);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_lcdc_enable(void)
|
||||
|
@ -1107,7 +1057,7 @@ index 0000000..48de695
|
|||
+ if (mode->vmode == FB_VMODE_INTERLACED)
|
||||
+ delay /= 2;
|
||||
+ if (tcon == 1)
|
||||
+ delay -= 5;
|
||||
+ delay -= 2;
|
||||
+
|
||||
+ return (delay > 31) ? 31 : delay;
|
||||
+}
|
||||
|
@ -1119,11 +1069,6 @@ index 0000000..48de695
|
|||
+ struct sun8i_lcdc_reg * const lcdc =
|
||||
+ (struct sun8i_lcdc_reg *)SUNXI_LCD0_BASE;
|
||||
+ int bp, clk_delay, total, yres;
|
||||
+ //u32 val;
|
||||
+
|
||||
+ sunxi_lcdc_pll_set(mode->pixclock_khz, clk_div);
|
||||
+
|
||||
+ udelay(500);
|
||||
+
|
||||
+ setbits_le32(&lcdc->gctl, SUN8I_TCON_GCTL_TCON_En);
|
||||
+
|
||||
|
@ -1158,22 +1103,10 @@ index 0000000..48de695
|
|||
+ writel(SUNXI_LCDC_X(mode->hsync_len) | SUNXI_LCDC_Y(mode->vsync_len),
|
||||
+ &lcdc->basic5);
|
||||
+
|
||||
+ //FIXME: are those needed?
|
||||
+ //writel(1 << 16 | 1, &lcdc->ps_sync);
|
||||
+
|
||||
+ /*val = SUN8I_TCON1_IO_POL_IO2_inv;
|
||||
+ if (mode->sync & FB_SYNC_HOR_HIGH_ACT)
|
||||
+ val |= SUN8I_TCON1_IO_POL_IO1_inv;
|
||||
+ if (mode->sync & FB_SYNC_VERT_HIGH_ACT)
|
||||
+ val |= SUN8I_TCON1_IO_POL_IO0_inv;
|
||||
+ writel(val, &lcdc->io_pol);*/
|
||||
+
|
||||
+ writel(0, &lcdc->ceu_ctl);
|
||||
+ writel(0, &lcdc->fill_ctl);
|
||||
+
|
||||
+ /* Set all io lines to tristate */
|
||||
+ writel(0x0fffffff, &lcdc->io_tri);
|
||||
+
|
||||
+ sunxi_lcdc_pll_set(mode->pixclock_khz, clk_div);
|
||||
+}
|
||||
+#endif /* CONFIG_VIDEO_HDMI */
|
||||
+
|
||||
|
@ -1183,41 +1116,6 @@ index 0000000..48de695
|
|||
+{
|
||||
+ u8 tmp;
|
||||
+
|
||||
+ // Vendor Specific Infoframe (VSI)
|
||||
+ // enable VSD auto scheduling
|
||||
+ writeb(0x08, SUNXI_HDMI_BASE + 0xB045);
|
||||
+
|
||||
+ // HDMI OUI
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x2045);
|
||||
+ writeb(0x0c, SUNXI_HDMI_BASE + 0x2044);
|
||||
+ writeb(0x03, SUNXI_HDMI_BASE + 0x6041);
|
||||
+
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0xA044, ((timings->vic & 0x100) == 0x100) ?
|
||||
+ // 0x20 : (((timings->vic & 0x80) == 0x80) ?
|
||||
+ // 0x40 : 0x00));
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0xA045, ((timings->vic & 0x100) == 0x100) ? (timings->vic & 0x7f) : 0x00);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0xA045);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0xA044);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x2046);
|
||||
+
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x3046);
|
||||
+ writeb(0x11, SUNXI_HDMI_BASE + 0x3047);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x4044);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0052);
|
||||
+ writeb(0x11, SUNXI_HDMI_BASE + 0x8051);
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ tmp = readb(SUNXI_HDMI_BASE + 0x0040) | 0x08;
|
||||
+ writeb(tmp, SUNXI_HDMI_BASE + 0x0040);
|
||||
+
|
||||
+ hdmi_read_unlock();
|
||||
+
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0x4045, video->is_yuv ? 0x02 : 0x00);
|
||||
+ // is this ok?
|
||||
+ //writeb(0x12, SUNXI_HDMI_BASE + 0x4045);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x4045);
|
||||
+
|
||||
+ if (mode->pixclock_khz <= 27000)
|
||||
+ tmp = 0x40; /* SD-modes, ITU601 colorspace */
|
||||
+ else
|
||||
|
@ -1228,39 +1126,31 @@ index 0000000..48de695
|
|||
+ else
|
||||
+ tmp |= 0x28; /* 16 : 9 */
|
||||
+
|
||||
+ setbits_8(SUNXI_HDMI_BASE + 0x0040, 0x08);
|
||||
+ writeb(0x60, SUNXI_HDMI_BASE + 0x4045);
|
||||
+ writeb(tmp, SUNXI_HDMI_BASE + 0xC044);
|
||||
+
|
||||
+ //writeb(video->is_yuv ? 0x00 : 0x08, SUNXI_HDMI_BASE + 0xC045);
|
||||
+ // is this ok?
|
||||
+ //writeb(0x88, SUNXI_HDMI_BASE + 0xC045);
|
||||
+ writeb(0x08, SUNXI_HDMI_BASE + 0xC045);
|
||||
+
|
||||
+ //writeb(SUNXI_HDMI_BASE + 0x4046, timings->vic & 0x7f);
|
||||
+ writeb(0x88, SUNXI_HDMI_BASE + 0xC045);
|
||||
+}
|
||||
+
|
||||
+static int hdmi_phy_set(u32 divider)
|
||||
+{
|
||||
+ u32 tmp;
|
||||
+
|
||||
+ writel(readl(SUN8I_HDMI_PHY_CTRL_REG)&(~0xf000), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ switch(divider)
|
||||
+ {
|
||||
+ case 1:
|
||||
+ //if(hdmi_version == 0)
|
||||
+ // writel(0x31dc5fc0, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ //else
|
||||
+ writel(0x30dc5fc0, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(0x30dc5fc0, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(0x800863C0, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(200);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ if(((tmp&0x1f800)>>11) < 0x3d)
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|(((tmp&0x1f800)>>11)+2), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ if (tmp < 0x3d)
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp + 2);
|
||||
+ else
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x3f, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, 0x3f);
|
||||
+ mdelay(100);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063b000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
|
@ -1271,11 +1161,11 @@ index 0000000..48de695
|
|||
+ writel(0x80084381, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(100);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|((tmp&0x1f800)>>11), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063a800, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C485, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
|
@ -1285,11 +1175,11 @@ index 0000000..48de695
|
|||
+ writel(0x80084343, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(100);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|((tmp&0x1f800)>>11), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063b000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C405, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
|
@ -1299,11 +1189,11 @@ index 0000000..48de695
|
|||
+ writel(0x8008430a, SUN8I_HDMI_PHY_CLK_REG);
|
||||
+ mdelay(10);
|
||||
+ writel(0x00000001, SUN8I_HDMI_PHY_UNK3_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0x02000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(25));
|
||||
+ mdelay(100);
|
||||
+ tmp = readl(SUN8I_HDMI_PHY_STATUS_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|0xC0000000, SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ writel(readl(SUN8I_HDMI_PHY_PLL_REG)|((tmp&0x1f800)>>11), SUN8I_HDMI_PHY_PLL_REG);
|
||||
+ tmp = (readl(SUN8I_HDMI_PHY_STATUS_REG) & 0x1f800) >> 11;
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, BIT(31) | BIT(30));
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_PLL_REG, tmp);
|
||||
+ writel(0x01FFFF7F, SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ writel(0x8063b000, SUN8I_HDMI_PHY_UNK1_REG);
|
||||
+ writel(0x0F81C405, SUN8I_HDMI_PHY_UNK2_REG);
|
||||
|
@ -1319,59 +1209,12 @@ index 0000000..48de695
|
|||
+ int clk_div)
|
||||
+{
|
||||
+ u8 invidconf, v_blanking;
|
||||
+ u32 x_res, y_res, hfp, h_blanking, hsw;
|
||||
+ /*struct sunxi_ccm_reg * const ccm =
|
||||
+ (struct sunxi_ccm_reg *)SUNXI_CCM_BASE;
|
||||
+ u32 h_blanking;
|
||||
+
|
||||
+ clrsetbits_le32(&ccm->hdmi_clk_cfg, CCM_HDMI_CTRL_M_MASK,
|
||||
+ CCM_HDMI_CTRL_M(clk_div));
|
||||
+
|
||||
+ udelay(500);*/
|
||||
+ printf("HDMI PHY divider: %d\n", clk_div);
|
||||
+
|
||||
+ if(clk_div == 0) {
|
||||
+ if(hdmi_phy_set(clk_div) != 0) {
|
||||
+ printf("HDMI divider is invalid!\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if(hdmi_phy_set(clk_div) != 0) {
|
||||
+ printf("Can't set HDMI phy!\n");
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ hdmi_read_lock();
|
||||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x8080);
|
||||
+
|
||||
+ udelay(1);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0xF01F);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8403);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x904C);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x904E);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0xD04C);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8250);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8A50);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8272);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x40C0);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x86F0);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0EE3);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8EE2);
|
||||
+ writeb(0xf0, SUNXI_HDMI_BASE + 0xA049);
|
||||
+ writeb(0x1e, SUNXI_HDMI_BASE + 0xB045);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x00C1);
|
||||
+ writeb(0x03, SUNXI_HDMI_BASE + 0x00C1);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x00C0);
|
||||
+ writeb(0x10, SUNXI_HDMI_BASE + 0x40C1);
|
||||
+ writeb(0xfd, SUNXI_HDMI_BASE + 0x0081);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0081);
|
||||
+ writeb(0xfd, SUNXI_HDMI_BASE + 0x0081);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0010);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0011);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8010);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8011);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x0013);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8012);
|
||||
+ writeb(0xff, SUNXI_HDMI_BASE + 0x8013);
|
||||
+
|
||||
+ invidconf = 0;
|
||||
+ if(mode->vmode & FB_VMODE_INTERLACED)
|
||||
|
@ -1381,58 +1224,39 @@ index 0000000..48de695
|
|||
+ if(mode->sync & FB_SYNC_VERT_HIGH_ACT)
|
||||
+ invidconf |= 0x40;
|
||||
+
|
||||
+ x_res = mode->xres; //timings->x_res << timings->pixel_repeat;
|
||||
+ y_res = mode->yres; //timings->y_res << timings->pixel_repeat;
|
||||
+ hfp = mode->right_margin; //timings->hor_front_porch << timings->pixel_repeat;
|
||||
+ hsw = mode->hsync_len; //timings->hor_sync_time << timings->pixel_repeat;
|
||||
+// h_blanking = (timings->hor_back_porch + timings->hor_front_porch +
|
||||
+// timings->hor_sync_time) << timings->pixel_repeat;
|
||||
+ h_blanking = mode->left_margin + mode->right_margin + mode->hsync_len;
|
||||
+ v_blanking = mode->upper_margin + mode->lower_margin + mode->vsync_len;
|
||||
+
|
||||
+ printf("pixel_clk: %d\n", mode->pixclock_khz * 1000);
|
||||
+ printf("pixel_repeat: %s\n", mode->vmode & FB_VMODE_DOUBLE ? "true" : "false");
|
||||
+ printf("x_res: %d\n", x_res);
|
||||
+ printf("y_res: %d\n", y_res);
|
||||
+ //printf("hor_total_time: %d\n",);
|
||||
+ printf("hor_back_porch: %d\n", mode->left_margin);
|
||||
+ printf("hor_front_porch: %d\n", hfp);
|
||||
+ printf("hor_sync_time: %d\n", hsw);
|
||||
+ //printf("ver_total_time: %d\n",);
|
||||
+ printf("ver_back_porch: %d\n", mode->upper_margin);
|
||||
+ printf("ver_front_porch: %d\n", mode->lower_margin);
|
||||
+ printf("ver_sync_time: %d\n", mode->vsync_len);
|
||||
+ printf("hor_sync_polarity: %s\n", mode->sync & FB_SYNC_HOR_HIGH_ACT ? "true" : "false");
|
||||
+ printf("ver_sync_polarity: %s\n", mode->sync & FB_SYNC_VERT_HIGH_ACT ? "true" : "false");
|
||||
+ printf("b_interlace: %s\n", mode->vmode & FB_VMODE_INTERLACED ? "true" : "false");
|
||||
+
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x0840);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x4845);
|
||||
+ writeb(invidconf | 0x10, SUNXI_HDMI_BASE + 0x0040);
|
||||
+ writeb(((invidconf < 96) ? 0x03 : 0x00), SUNXI_HDMI_BASE + 0x10001);
|
||||
+ writeb((u8)(x_res >> 8), SUNXI_HDMI_BASE + 0x8040);
|
||||
+ writeb((u8)(mode->vsync_len), SUNXI_HDMI_BASE + 0x4043);
|
||||
+ writeb((u8)(y_res >> 8), SUNXI_HDMI_BASE + 0x8042);
|
||||
+ writeb((u8)(h_blanking >> 8), SUNXI_HDMI_BASE + 0x0042);
|
||||
+ writeb((u8)(mode->lower_margin), SUNXI_HDMI_BASE + 0x4042);
|
||||
+ writeb((u8)(hfp >> 8), SUNXI_HDMI_BASE + 0x4041);
|
||||
+ writeb((u8)(hsw >> 8), SUNXI_HDMI_BASE + 0xC041);
|
||||
+ writeb((u8)(x_res & 0xff), SUNXI_HDMI_BASE + 0x0041);
|
||||
+ writeb((u8)(h_blanking & 0xff), SUNXI_HDMI_BASE + 0x8041);
|
||||
+ writeb((u8)(hfp & 0xff), SUNXI_HDMI_BASE + 0x4040);
|
||||
+ writeb((u8)(hsw & 0xff), SUNXI_HDMI_BASE + 0xC040);
|
||||
+ writeb((u8)(y_res & 0xff), SUNXI_HDMI_BASE + 0x0043);
|
||||
+
|
||||
+ writeb(mode->xres >> 8, SUNXI_HDMI_BASE + 0x8040);
|
||||
+ writeb(mode->xres, SUNXI_HDMI_BASE + 0x0041);
|
||||
+ writeb(mode->yres >> 8, SUNXI_HDMI_BASE + 0x8042);
|
||||
+ writeb(mode->yres, SUNXI_HDMI_BASE + 0x0043);
|
||||
+ writeb(mode->vsync_len, SUNXI_HDMI_BASE + 0x4043);
|
||||
+ writeb(h_blanking >> 8, SUNXI_HDMI_BASE + 0x0042);
|
||||
+ writeb(h_blanking, SUNXI_HDMI_BASE + 0x8041);
|
||||
+ writeb(mode->lower_margin, SUNXI_HDMI_BASE + 0x4042);
|
||||
+ writeb(mode->right_margin >> 8, SUNXI_HDMI_BASE + 0x4041);
|
||||
+ writeb(mode->right_margin, SUNXI_HDMI_BASE + 0x4040);
|
||||
+ writeb(mode->hsync_len >> 8, SUNXI_HDMI_BASE + 0xC041);
|
||||
+ writeb(mode->hsync_len, SUNXI_HDMI_BASE + 0xC040);
|
||||
+ writeb(v_blanking, SUNXI_HDMI_BASE + 0x8043);
|
||||
+
|
||||
+ writeb(0x0c, SUNXI_HDMI_BASE + 0x0045);
|
||||
+ writeb(0x20, SUNXI_HDMI_BASE + 0x8044);
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x8045);
|
||||
+ writeb(0x0b, SUNXI_HDMI_BASE + 0x0046);
|
||||
+ writeb(0x16, SUNXI_HDMI_BASE + 0x0047);
|
||||
+ writeb(0x21, SUNXI_HDMI_BASE + 0x8046);
|
||||
+ writeb(mode->vmode & FB_VMODE_DOUBLE ? 0x21 : 0x10, SUNXI_HDMI_BASE + 0x3048);
|
||||
+ writeb(mode->vmode & FB_VMODE_DOUBLE ? 0x41 : 0x40, SUNXI_HDMI_BASE + 0x0401);
|
||||
+
|
||||
+ writeb(0x40, SUNXI_HDMI_BASE + 0x0401);
|
||||
+ writeb(0x07, SUNXI_HDMI_BASE + 0x8400);
|
||||
+
|
||||
+ // default value, written 0 by rk_hdmi
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x8401);
|
||||
+
|
||||
+ writeb(0x47, SUNXI_HDMI_BASE + 0x0402);
|
||||
+ writeb(0x01, SUNXI_HDMI_BASE + 0x0800);
|
||||
+ writeb(0x07, SUNXI_HDMI_BASE + 0x0801);
|
||||
|
@ -1448,14 +1272,11 @@ index 0000000..48de695
|
|||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0082);
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0081);
|
||||
+
|
||||
+ writeb(0x00, SUNXI_HDMI_BASE + 0x0840);
|
||||
+}
|
||||
+
|
||||
+static void sunxi_hdmi_enable(void)
|
||||
+{
|
||||
+ udelay(100);
|
||||
+ writeb(readb(SUN8I_HDMI_PHY_CTRL_REG) | (15 << 12), SUN8I_HDMI_PHY_CTRL_REG);
|
||||
+ setbits_le32(SUN8I_HDMI_PHY_CTRL_REG, 0xf << 12);
|
||||
+ printf("hdmi enabled\n");
|
||||
+}
|
||||
+
|
||||
|
@ -1484,9 +1305,6 @@ index 0000000..48de695
|
|||
+ sunxi_composer_enable();
|
||||
+ sunxi_lcdc_enable();
|
||||
+ sunxi_hdmi_enable();
|
||||
+// sunxi_composer_init();
|
||||
+// sunxi_composer_mode_set(mode, address);
|
||||
+// sunxi_composer_enable();
|
||||
+#endif
|
||||
+ break;
|
||||
+ }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue