Commit 390a15a523c5aefb99008a5f67d6c8f9ec7ef63c

Authored by Oliver Brown
1 parent 42f1298bde

MLK-17404-3 arch: arm: Adding support for i.MX8 HDMI

Adding basic HDMI support for i.MX8 for splash screen.

Signed-off-by: Oliver Brown <oliver.brown@nxp.com>

Showing 3 changed files with 778 additions and 0 deletions Side-by-side Diff

arch/arm/cpu/armv8/imx8m/Makefile
... ... @@ -6,4 +6,5 @@
6 6  
7 7 obj-y += lowlevel_init.o
8 8 obj-y += clock.o clock_slice.o soc.o
  9 +obj-$(CONFIG_VIDEO_IMXDCSS) += video_common.o
arch/arm/cpu/armv8/imx8m/video_common.c
  1 +/*
  2 + * Copyright 2018 NXP
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#include <common.h>
  8 +#include <dm.h>
  9 +#include <asm/io.h>
  10 +#include <linux/errno.h>
  11 +#include <asm/arch/clock.h>
  12 +#include <asm/arch/imx-regs.h>
  13 +#include <i2c.h>
  14 +#include <asm/arch/sys_proto.h>
  15 +
  16 +#include <video_fb.h>
  17 +#include <asm/arch/video_common.h>
  18 +#include <power-domain.h>
  19 +#include <imx8_hdmi.h>
  20 +
  21 +DECLARE_GLOBAL_DATA_PTR;
  22 +
  23 +/* test congiurations */
  24 +#undef IMXDCSS_LOAD_HDMI_FIRMWARE
  25 +#undef IMXDCSS_SET_PIXEL_CLOCK
  26 +
  27 +static struct video_mode_settings gmode;
  28 +static uint32_t gpixfmt;
  29 +GraphicDevice panel;
  30 +struct video_mode_settings *imx8m_get_gmode(void)
  31 +{
  32 + return &gmode;
  33 +}
  34 +
  35 +void imx8m_show_gmode(void)
  36 +{
  37 + printf("gmode =\n"
  38 + "pixelclock = %u\n"
  39 + "xres = %u\n"
  40 + "yres = %u\n"
  41 + "hfp = %u\n"
  42 + "hbp = %u\n"
  43 + "vfp = %u\n"
  44 + "vbp = %u\n"
  45 + "hsync = %u\n"
  46 + "vsync = %u\n"
  47 + "hpol = %u\n"
  48 + "vpol = %u\n",
  49 + gmode.pixelclock,
  50 + gmode.xres,
  51 + gmode.yres,
  52 + gmode.hfp,
  53 + gmode.hbp,
  54 + gmode.vfp,
  55 + gmode.vbp, gmode.hsync, gmode.vsync, gmode.hpol, gmode.vpol);
  56 +}
  57 +
  58 +GraphicDevice *imx8m_get_gd(void)
  59 +{
  60 + return &panel;
  61 +}
  62 +
  63 +#define REG_BASE_ADDR 0x32e00000UL
  64 +
  65 +/*#define DEBUGREG*/
  66 +#ifdef DEBUGREG
  67 +#define reg32_write(addr, val) \
  68 +do { \
  69 + debug("%s():%d 0x%08x -> 0x%08x\n", __func__, __LINE__, \
  70 + (unsigned int)addr, (unsigned int)val); \
  71 + __raw_writel(val, addr); \
  72 +} while (0)
  73 +#else
  74 +#define reg32_write(addr, val) __raw_writel(val, addr)
  75 +#endif
  76 +
  77 +#define reg32_read(addr) __raw_readl(addr)
  78 +
  79 +#define reg32setbit(addr, bitpos) \
  80 + reg32_write((addr), (reg32_read((addr)) | (1<<(bitpos))))
  81 +#define reg32clearbit(addr, bitpos) \
  82 + reg32_write((addr), (reg32_read((addr)) & ~(1<<(bitpos))))
  83 +
  84 +#define reg32_read_tst(addr, val, mask) \
  85 +do { \
  86 + u32 temp = reg32_read((addr)); \
  87 + if ((temp & (mask)) == ((val) & (mask))) \
  88 + debug("%s():%d 0x%08x -> 0x%08x\n", \
  89 + __func__, __LINE__, addr, val); \
  90 + else \
  91 + debug("%s():%d 0x%08x -> 0x%08x instead of 0x%08x\n", \
  92 + __func__, __LINE__, addr, temp, val); \
  93 +} while (0)
  94 +
  95 +#define COLOR_LIST_SIZE 8
  96 +static u32 color_list_argb32[COLOR_LIST_SIZE] = {
  97 + 0xFFFFFFFF, /* white */
  98 + 0xFFFF0000, /* red */
  99 + 0xFF00FF00, /* green */
  100 + 0xFF0000FF, /* blue */
  101 + 0xFFFFFF00, /* yellow */
  102 + 0xFF00FFFF, /* cyan */
  103 + 0xFFFF00FF, /* magenta */
  104 + 0xFFC1C2C3, /* silver */
  105 +}; /*AARRGGBB */
  106 +
  107 +static unsigned int get_color_index(unsigned short px, unsigned short py,
  108 + unsigned short width, unsigned short height,
  109 + unsigned short bar_size)
  110 +{
  111 + const int mw = 5; /* margin width */
  112 + if ((py >= 0 && py < mw) || (py >= height - mw && py < height) ||
  113 + (px >= 0 && px < mw) || (px >= width - mw && px < width)) {
  114 + return 1;
  115 + }
  116 +
  117 + return py / bar_size;
  118 +}
  119 +
  120 +void imx8m_create_color_bar(void *start_address,
  121 + struct video_mode_settings *vms)
  122 +{
  123 + /*struct video_mode_settings *vms = &vm_settings[g_vm]; */
  124 + uint32_t color_bar_size = vms->yres / COLOR_LIST_SIZE;
  125 + int i, j;
  126 + u32 *pointer;
  127 + int color_index = 0;
  128 + pointer = (u32 *)start_address;
  129 + uint32_t *color_map = &color_list_argb32[0];
  130 + debug("%s(), %d: start_address %p\n",
  131 + __func__, __LINE__, start_address);
  132 + debug("%s(), %d: pointer %p\n", __func__, __LINE__, pointer);
  133 + debug("%s(), %d x %d\n", __func__, vms->xres, vms->yres);
  134 + for (i = 0; i < vms->yres; i++) {
  135 + for (j = 0; j < vms->xres; j++) {
  136 + color_index = get_color_index(j, i, vms->xres,
  137 + vms->yres,
  138 + color_bar_size);
  139 + *pointer = color_map[color_index];
  140 + pointer++;
  141 + }
  142 + }
  143 + invalidate_dcache_all();
  144 +}
  145 +
  146 +static void imx8m_set_clocks(int apb_clk, int b_clk, int hdmi_core_clk,
  147 + int p_clk, int rtr_clk)
  148 +{
  149 + if (b_clk == 800) {
  150 + /* b_clk: bus_clk_root(4) sel 2nd input source and
  151 + pre_div to 0; output should be 800M */
  152 + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_CLR(4),
  153 + (0x7 << 24) | (0x7 << 16));
  154 + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_SET(4), (0x2 << 24));
  155 + } else {
  156 + printf("b_clk does not match a supported frequency");
  157 + }
  158 + if (rtr_clk == 400) {
  159 + /* rtr_clk: bus_clk_root(6) sel 1st input source
  160 + and pre_div to 1; output should be 400M */
  161 + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_CLR(6),
  162 + (0x7 << 24) | (0x7 << 16));
  163 + reg32_write(CCM_BUS_CLK_ROOT_GEN_TAGET_SET(6),
  164 + (0x1 << 24) | (0x1 << 16));
  165 + } else {
  166 + debug("rtr_clk does not match a supported frequency");
  167 + }
  168 +
  169 +#ifdef IMXDCSS_LOAD_HDMI_FIRMWARE
  170 + /* If ROM is loading HDMI firmware then this clock should not be set */
  171 + if (hdmi_core_clk == 200) {
  172 + /* hdmi_core_clk: ip_clk_root(69) sel 1st input source and
  173 + pre_div to 0 */
  174 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(69),
  175 + (0x7 << 24) | (0x7 << 16));
  176 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(69), (0x1 << 24));
  177 + g_hdmi_core_clock = 200000000;
  178 + } else {
  179 + debug("hdmi_core_clk does not match a supported frequency");
  180 + }
  181 +#endif
  182 +
  183 +#ifdef IMXDCSS_SET_PIXEL_CLOCK
  184 + /* This would be needed for MIPI-DSI DCSS display */
  185 + if (p_clk == 27) {
  186 + /* p_clk: ip_clk_root(9) sel 1st input source and
  187 + pre_div to 1; post_div to 5, output 100M */
  188 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9),
  189 + (0x7 << 24) | (0x7 << 16));
  190 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9),
  191 + (0x1 << 24) | (29 << 16));
  192 + } else if (p_clk == 100) {
  193 + /* p_clk: ip_clk_root(9) sel 1st input source and
  194 + pre_div to 1; post_div to 5, output 100M */
  195 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9),
  196 + (0x7 << 24) | (0x7 << 16));
  197 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9),
  198 + (0x1 << 24) | (0x5 << 16));
  199 + } else if (p_clk == 120) {
  200 + /* p_clk: ip_clk_root(9) sel 1st input source and
  201 + pre_div to 1; post_div to 4, output 120M */
  202 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9),
  203 + (0x7 << 24) | (0x7 << 16));
  204 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9),
  205 + (0x1 << 24) | (0x4 << 16));
  206 + } else if (p_clk == 200) {
  207 + /* I added this to speed up the pixel clock and
  208 + get frames out faster. may need to adjust this.
  209 + */
  210 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9),
  211 + (0x7 << 24) | (0x7 << 16));
  212 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9),
  213 + (0x4 << 24) | (0x3 << 16)); /*for emu use 800 / 4 */
  214 + } else if (p_clk == 400) {
  215 + /* I added this to speed up the pixel clock and
  216 + get frames out faster. may need to adjust this.
  217 + */
  218 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_CLR(9),
  219 + (0x7 << 24) | (0x7 << 16));
  220 + reg32_write(CCM_IP_CLK_ROOT_GEN_TAGET_SET(9),
  221 + (0x4 << 24) | (0x1 << 16)); /*for emu use 800 / 2 */
  222 + } else if (p_clk == 40) { /* Do not reprogram, will get 40MHz */
  223 + } else {
  224 + debug("p_clk does not match a supported frequency");
  225 + }
  226 +#endif
  227 +}
  228 +
  229 +static int imx8m_power_init(uint32_t clock_control)
  230 +{
  231 + u32 temp;
  232 + /*struct video_mode_settings *vms = &vm_settings[g_vm]; */
  233 +
  234 + debug("\nenabling display clock...\n");
  235 + clock_enable(CCGR_DISPLAY, 1);
  236 +
  237 + reg32_write(0x303A00EC, 0x0000ffff); /*PGC_CPU_MAPPING */
  238 + reg32setbit(0x303A00F8, 10); /*PU_PGC_SW_PUP_REQ : disp was 10 */
  239 +#ifdef LOAD_HDMI_FIRMWARE
  240 + reg32setbit(0x303A00F8, 9); /*PU_PGC_SW_PUP_REQ : hdmi was 9 */
  241 +#endif
  242 + imx8m_set_clocks(133, 800, 200, 27, 400);
  243 +
  244 + /* DCSS reset */
  245 + reg32_write(0x32e2f000, 0xffffffff);
  246 +
  247 + /* DCSS clock selection */
  248 + reg32_write(0x32e2f010, clock_control);
  249 + temp = reg32_read(0x32e2f010);
  250 + debug("%s(): DCSS clock control 0x%08x\n", __func__, temp);
  251 +
  252 + /* take DCSS out of reset - not needed OFB */
  253 + /*__raw_writel(0xffffffff, 0x32e2f004); */
  254 +
  255 + return 0;
  256 +}
  257 +
  258 +static void imx8m_display_init(u64 buffer, int encoding,
  259 + struct video_mode_settings *vms)
  260 +{
  261 + /*struct video_mode_settings *vms = &vm_settings[g_vm]; */
  262 +
  263 + debug("entering %s() ...\n", __func__);
  264 + debug("%s() buffer ...\n", __func__);
  265 +
  266 + /* DTRC-CHAN2/3 */
  267 + reg32_write(REG_BASE_ADDR + 0x160c8, 0x00000002);
  268 + reg32_write(REG_BASE_ADDR + 0x170c8, 0x00000002);
  269 +
  270 + /* CHAN1_DPR */
  271 + reg32_write(REG_BASE_ADDR + 0x180c0, (unsigned int)buffer);
  272 + reg32_write(REG_BASE_ADDR + 0x18090, 0x00000002);
  273 + reg32_write(REG_BASE_ADDR + 0x180a0, vms->xres);
  274 + reg32_write(REG_BASE_ADDR + 0x180b0, vms->yres);
  275 + reg32_write(REG_BASE_ADDR + 0x18110,
  276 + (unsigned int)buffer + vms->xres * vms->yres);
  277 + reg32_write(REG_BASE_ADDR + 0x180f0, 0x00000280);
  278 + reg32_write(REG_BASE_ADDR + 0x18100, 0x000000f0);
  279 + reg32_write(REG_BASE_ADDR + 0x18070, ((vms->xres * 4) << 16));
  280 + reg32_write(REG_BASE_ADDR + 0x18050, 0x000e4203);
  281 + reg32_write(REG_BASE_ADDR + 0x18050, 0x000e4203);
  282 + reg32_write(REG_BASE_ADDR + 0x18200, 0x00000038);
  283 + reg32_write(REG_BASE_ADDR + 0x18000, 0x00000004);
  284 + reg32_write(REG_BASE_ADDR + 0x18000, 0x00000005);
  285 +
  286 + /* SCALER */
  287 + reg32_write(REG_BASE_ADDR + 0x1c008, 0x00000000);
  288 + reg32_write(REG_BASE_ADDR + 0x1c00c, 0x00000000);
  289 + reg32_write(REG_BASE_ADDR + 0x1c010, 0x00000002);
  290 + reg32_write(REG_BASE_ADDR + 0x1c014, 0x00000002);
  291 + reg32_write(REG_BASE_ADDR + 0x1c018,
  292 + ((vms->yres - 1) << 16 | (vms->xres - 1)));
  293 + reg32_write(REG_BASE_ADDR + 0x1c01c,
  294 + ((vms->yres - 1) << 16 | (vms->xres - 1)));
  295 + reg32_write(REG_BASE_ADDR + 0x1c020,
  296 + ((vms->yres - 1) << 16 | (vms->xres - 1)));
  297 + reg32_write(REG_BASE_ADDR + 0x1c024,
  298 + ((vms->yres - 1) << 16 | (vms->xres - 1)));
  299 + reg32_write(REG_BASE_ADDR + 0x1c028, 0x00000000);
  300 + reg32_write(REG_BASE_ADDR + 0x1c02c, 0x00000000);
  301 + reg32_write(REG_BASE_ADDR + 0x1c030, 0x00000000);
  302 + reg32_write(REG_BASE_ADDR + 0x1c034, 0x00000000);
  303 + reg32_write(REG_BASE_ADDR + 0x1c038, 0x00000000);
  304 + reg32_write(REG_BASE_ADDR + 0x1c03c, 0x00000000);
  305 + reg32_write(REG_BASE_ADDR + 0x1c040, 0x00000000);
  306 + reg32_write(REG_BASE_ADDR + 0x1c044, 0x00000000);
  307 + reg32_write(REG_BASE_ADDR + 0x1c048, 0x00000000);
  308 + reg32_write(REG_BASE_ADDR + 0x1c04c, 0x00002000);
  309 + reg32_write(REG_BASE_ADDR + 0x1c050, 0x00000000);
  310 + reg32_write(REG_BASE_ADDR + 0x1c054, 0x00002000);
  311 + reg32_write(REG_BASE_ADDR + 0x1c058, 0x00000000);
  312 + reg32_write(REG_BASE_ADDR + 0x1c05c, 0x00002000);
  313 + reg32_write(REG_BASE_ADDR + 0x1c060, 0x00000000);
  314 + reg32_write(REG_BASE_ADDR + 0x1c064, 0x00002000);
  315 + reg32_write(REG_BASE_ADDR + 0x1c080, 0x00000000);
  316 + reg32_write(REG_BASE_ADDR + 0x1c0c0, 0x00040000);
  317 + reg32_write(REG_BASE_ADDR + 0x1c100, 0x00000000);
  318 + reg32_write(REG_BASE_ADDR + 0x1c084, 0x00000000);
  319 + reg32_write(REG_BASE_ADDR + 0x1c0c4, 0x00000000);
  320 + reg32_write(REG_BASE_ADDR + 0x1c104, 0x00000000);
  321 + reg32_write(REG_BASE_ADDR + 0x1c088, 0x00000000);
  322 + reg32_write(REG_BASE_ADDR + 0x1c0c8, 0x00000000);
  323 + reg32_write(REG_BASE_ADDR + 0x1c108, 0x00000000);
  324 + reg32_write(REG_BASE_ADDR + 0x1c08c, 0x00000000);
  325 + reg32_write(REG_BASE_ADDR + 0x1c0cc, 0x00000000);
  326 + reg32_write(REG_BASE_ADDR + 0x1c10c, 0x00000000);
  327 + reg32_write(REG_BASE_ADDR + 0x1c090, 0x00000000);
  328 + reg32_write(REG_BASE_ADDR + 0x1c0d0, 0x00000000);
  329 + reg32_write(REG_BASE_ADDR + 0x1c110, 0x00000000);
  330 + reg32_write(REG_BASE_ADDR + 0x1c094, 0x00000000);
  331 + reg32_write(REG_BASE_ADDR + 0x1c0d4, 0x00000000);
  332 + reg32_write(REG_BASE_ADDR + 0x1c114, 0x00000000);
  333 + reg32_write(REG_BASE_ADDR + 0x1c098, 0x00000000);
  334 + reg32_write(REG_BASE_ADDR + 0x1c0d8, 0x00000000);
  335 + reg32_write(REG_BASE_ADDR + 0x1c118, 0x00000000);
  336 + reg32_write(REG_BASE_ADDR + 0x1c09c, 0x00000000);
  337 + reg32_write(REG_BASE_ADDR + 0x1c0dc, 0x00000000);
  338 + reg32_write(REG_BASE_ADDR + 0x1c11c, 0x00000000);
  339 + reg32_write(REG_BASE_ADDR + 0x1c0a0, 0x00000000);
  340 + reg32_write(REG_BASE_ADDR + 0x1c0e0, 0x00000000);
  341 + reg32_write(REG_BASE_ADDR + 0x1c120, 0x00000000);
  342 + reg32_write(REG_BASE_ADDR + 0x1c0a4, 0x00000000);
  343 + reg32_write(REG_BASE_ADDR + 0x1c0e4, 0x00000000);
  344 + reg32_write(REG_BASE_ADDR + 0x1c124, 0x00000000);
  345 + reg32_write(REG_BASE_ADDR + 0x1c0a8, 0x00000000);
  346 + reg32_write(REG_BASE_ADDR + 0x1c0e8, 0x00000000);
  347 + reg32_write(REG_BASE_ADDR + 0x1c128, 0x00000000);
  348 + reg32_write(REG_BASE_ADDR + 0x1c0ac, 0x00000000);
  349 + reg32_write(REG_BASE_ADDR + 0x1c0ec, 0x00000000);
  350 + reg32_write(REG_BASE_ADDR + 0x1c12c, 0x00000000);
  351 + reg32_write(REG_BASE_ADDR + 0x1c0b0, 0x00000000);
  352 + reg32_write(REG_BASE_ADDR + 0x1c0f0, 0x00000000);
  353 + reg32_write(REG_BASE_ADDR + 0x1c130, 0x00000000);
  354 + reg32_write(REG_BASE_ADDR + 0x1c0b4, 0x00000000);
  355 + reg32_write(REG_BASE_ADDR + 0x1c0f4, 0x00000000);
  356 + reg32_write(REG_BASE_ADDR + 0x1c134, 0x00000000);
  357 + reg32_write(REG_BASE_ADDR + 0x1c0b8, 0x00000000);
  358 + reg32_write(REG_BASE_ADDR + 0x1c0f8, 0x00000000);
  359 + reg32_write(REG_BASE_ADDR + 0x1c138, 0x00000000);
  360 + reg32_write(REG_BASE_ADDR + 0x1c0bc, 0x00000000);
  361 + reg32_write(REG_BASE_ADDR + 0x1c0fc, 0x00000000);
  362 + reg32_write(REG_BASE_ADDR + 0x1c13c, 0x00000000);
  363 + reg32_write(REG_BASE_ADDR + 0x1c140, 0x00000000);
  364 + reg32_write(REG_BASE_ADDR + 0x1c180, 0x00040000);
  365 + reg32_write(REG_BASE_ADDR + 0x1c1c0, 0x00000000);
  366 + reg32_write(REG_BASE_ADDR + 0x1c144, 0x00000000);
  367 + reg32_write(REG_BASE_ADDR + 0x1c184, 0x00000000);
  368 + reg32_write(REG_BASE_ADDR + 0x1c1c4, 0x00000000);
  369 + reg32_write(REG_BASE_ADDR + 0x1c148, 0x00000000);
  370 + reg32_write(REG_BASE_ADDR + 0x1c188, 0x00000000);
  371 + reg32_write(REG_BASE_ADDR + 0x1c1c8, 0x00000000);
  372 + reg32_write(REG_BASE_ADDR + 0x1c14c, 0x00000000);
  373 + reg32_write(REG_BASE_ADDR + 0x1c18c, 0x00000000);
  374 + reg32_write(REG_BASE_ADDR + 0x1c1cc, 0x00000000);
  375 + reg32_write(REG_BASE_ADDR + 0x1c150, 0x00000000);
  376 + reg32_write(REG_BASE_ADDR + 0x1c190, 0x00000000);
  377 + reg32_write(REG_BASE_ADDR + 0x1c1d0, 0x00000000);
  378 + reg32_write(REG_BASE_ADDR + 0x1c154, 0x00000000);
  379 + reg32_write(REG_BASE_ADDR + 0x1c194, 0x00000000);
  380 + reg32_write(REG_BASE_ADDR + 0x1c1d4, 0x00000000);
  381 + reg32_write(REG_BASE_ADDR + 0x1c158, 0x00000000);
  382 + reg32_write(REG_BASE_ADDR + 0x1c198, 0x00000000);
  383 + reg32_write(REG_BASE_ADDR + 0x1c1d8, 0x00000000);
  384 + reg32_write(REG_BASE_ADDR + 0x1c15c, 0x00000000);
  385 + reg32_write(REG_BASE_ADDR + 0x1c19c, 0x00000000);
  386 + reg32_write(REG_BASE_ADDR + 0x1c1dc, 0x00000000);
  387 + reg32_write(REG_BASE_ADDR + 0x1c160, 0x00000000);
  388 + reg32_write(REG_BASE_ADDR + 0x1c1a0, 0x00000000);
  389 + reg32_write(REG_BASE_ADDR + 0x1c1e0, 0x00000000);
  390 + reg32_write(REG_BASE_ADDR + 0x1c164, 0x00000000);
  391 + reg32_write(REG_BASE_ADDR + 0x1c1a4, 0x00000000);
  392 + reg32_write(REG_BASE_ADDR + 0x1c1e4, 0x00000000);
  393 + reg32_write(REG_BASE_ADDR + 0x1c168, 0x00000000);
  394 + reg32_write(REG_BASE_ADDR + 0x1c1a8, 0x00000000);
  395 + reg32_write(REG_BASE_ADDR + 0x1c1e8, 0x00000000);
  396 + reg32_write(REG_BASE_ADDR + 0x1c16c, 0x00000000);
  397 + reg32_write(REG_BASE_ADDR + 0x1c1ac, 0x00000000);
  398 + reg32_write(REG_BASE_ADDR + 0x1c1ec, 0x00000000);
  399 + reg32_write(REG_BASE_ADDR + 0x1c170, 0x00000000);
  400 + reg32_write(REG_BASE_ADDR + 0x1c1b0, 0x00000000);
  401 + reg32_write(REG_BASE_ADDR + 0x1c1f0, 0x00000000);
  402 + reg32_write(REG_BASE_ADDR + 0x1c174, 0x00000000);
  403 + reg32_write(REG_BASE_ADDR + 0x1c1b4, 0x00000000);
  404 + reg32_write(REG_BASE_ADDR + 0x1c1f4, 0x00000000);
  405 + reg32_write(REG_BASE_ADDR + 0x1c178, 0x00000000);
  406 + reg32_write(REG_BASE_ADDR + 0x1c1b8, 0x00000000);
  407 + reg32_write(REG_BASE_ADDR + 0x1c1f8, 0x00000000);
  408 + reg32_write(REG_BASE_ADDR + 0x1c17c, 0x00000000);
  409 + reg32_write(REG_BASE_ADDR + 0x1c1bc, 0x00000000);
  410 + reg32_write(REG_BASE_ADDR + 0x1c1fc, 0x00000000);
  411 + reg32_write(REG_BASE_ADDR + 0x1c300, 0x00000000);
  412 + reg32_write(REG_BASE_ADDR + 0x1c340, 0x00000000);
  413 + reg32_write(REG_BASE_ADDR + 0x1c380, 0x00000000);
  414 + reg32_write(REG_BASE_ADDR + 0x1c304, 0x00000000);
  415 + reg32_write(REG_BASE_ADDR + 0x1c344, 0x00000000);
  416 + reg32_write(REG_BASE_ADDR + 0x1c384, 0x00000000);
  417 + reg32_write(REG_BASE_ADDR + 0x1c308, 0x00000000);
  418 + reg32_write(REG_BASE_ADDR + 0x1c348, 0x00000000);
  419 + reg32_write(REG_BASE_ADDR + 0x1c388, 0x00000000);
  420 + reg32_write(REG_BASE_ADDR + 0x1c30c, 0x00000000);
  421 + reg32_write(REG_BASE_ADDR + 0x1c34c, 0x00000000);
  422 + reg32_write(REG_BASE_ADDR + 0x1c38c, 0x00000000);
  423 + reg32_write(REG_BASE_ADDR + 0x1c310, 0x00000000);
  424 + reg32_write(REG_BASE_ADDR + 0x1c350, 0x00000000);
  425 + reg32_write(REG_BASE_ADDR + 0x1c390, 0x00000000);
  426 + reg32_write(REG_BASE_ADDR + 0x1c314, 0x00000000);
  427 + reg32_write(REG_BASE_ADDR + 0x1c354, 0x00000000);
  428 + reg32_write(REG_BASE_ADDR + 0x1c394, 0x00000000);
  429 + reg32_write(REG_BASE_ADDR + 0x1c318, 0x00000000);
  430 + reg32_write(REG_BASE_ADDR + 0x1c358, 0x00000000);
  431 + reg32_write(REG_BASE_ADDR + 0x1c398, 0x00000000);
  432 + reg32_write(REG_BASE_ADDR + 0x1c31c, 0x00000000);
  433 + reg32_write(REG_BASE_ADDR + 0x1c35c, 0x00000000);
  434 + reg32_write(REG_BASE_ADDR + 0x1c39c, 0x00000000);
  435 + reg32_write(REG_BASE_ADDR + 0x1c320, 0x00000000);
  436 + reg32_write(REG_BASE_ADDR + 0x1c360, 0x00000000);
  437 + reg32_write(REG_BASE_ADDR + 0x1c3a0, 0x00000000);
  438 + reg32_write(REG_BASE_ADDR + 0x1c324, 0x00000000);
  439 + reg32_write(REG_BASE_ADDR + 0x1c364, 0x00000000);
  440 + reg32_write(REG_BASE_ADDR + 0x1c3a4, 0x00000000);
  441 + reg32_write(REG_BASE_ADDR + 0x1c328, 0x00000000);
  442 + reg32_write(REG_BASE_ADDR + 0x1c368, 0x00000000);
  443 + reg32_write(REG_BASE_ADDR + 0x1c3a8, 0x00000000);
  444 + reg32_write(REG_BASE_ADDR + 0x1c32c, 0x00000000);
  445 + reg32_write(REG_BASE_ADDR + 0x1c36c, 0x00000000);
  446 + reg32_write(REG_BASE_ADDR + 0x1c3ac, 0x00000000);
  447 + reg32_write(REG_BASE_ADDR + 0x1c330, 0x00000000);
  448 + reg32_write(REG_BASE_ADDR + 0x1c370, 0x00000000);
  449 + reg32_write(REG_BASE_ADDR + 0x1c3b0, 0x00000000);
  450 + reg32_write(REG_BASE_ADDR + 0x1c334, 0x00000000);
  451 + reg32_write(REG_BASE_ADDR + 0x1c374, 0x00000000);
  452 + reg32_write(REG_BASE_ADDR + 0x1c3b4, 0x00000000);
  453 + reg32_write(REG_BASE_ADDR + 0x1c338, 0x00000000);
  454 + reg32_write(REG_BASE_ADDR + 0x1c378, 0x00000000);
  455 + reg32_write(REG_BASE_ADDR + 0x1c3b8, 0x00000000);
  456 + reg32_write(REG_BASE_ADDR + 0x1c33c, 0x00000000);
  457 + reg32_write(REG_BASE_ADDR + 0x1c37c, 0x00000000);
  458 + reg32_write(REG_BASE_ADDR + 0x1c3bc, 0x00000000);
  459 + reg32_write(REG_BASE_ADDR + 0x1c200, 0x00000000);
  460 + reg32_write(REG_BASE_ADDR + 0x1c240, 0x00000000);
  461 + reg32_write(REG_BASE_ADDR + 0x1c280, 0x00000000);
  462 + reg32_write(REG_BASE_ADDR + 0x1c204, 0x00000000);
  463 + reg32_write(REG_BASE_ADDR + 0x1c244, 0x00000000);
  464 + reg32_write(REG_BASE_ADDR + 0x1c284, 0x00000000);
  465 + reg32_write(REG_BASE_ADDR + 0x1c208, 0x00000000);
  466 + reg32_write(REG_BASE_ADDR + 0x1c248, 0x00000000);
  467 + reg32_write(REG_BASE_ADDR + 0x1c288, 0x00000000);
  468 + reg32_write(REG_BASE_ADDR + 0x1c20c, 0x00000000);
  469 + reg32_write(REG_BASE_ADDR + 0x1c24c, 0x00000000);
  470 + reg32_write(REG_BASE_ADDR + 0x1c28c, 0x00000000);
  471 + reg32_write(REG_BASE_ADDR + 0x1c210, 0x00000000);
  472 + reg32_write(REG_BASE_ADDR + 0x1c250, 0x00000000);
  473 + reg32_write(REG_BASE_ADDR + 0x1c290, 0x00000000);
  474 + reg32_write(REG_BASE_ADDR + 0x1c214, 0x00000000);
  475 + reg32_write(REG_BASE_ADDR + 0x1c254, 0x00000000);
  476 + reg32_write(REG_BASE_ADDR + 0x1c294, 0x00000000);
  477 + reg32_write(REG_BASE_ADDR + 0x1c218, 0x00000000);
  478 + reg32_write(REG_BASE_ADDR + 0x1c258, 0x00000000);
  479 + reg32_write(REG_BASE_ADDR + 0x1c298, 0x00000000);
  480 + reg32_write(REG_BASE_ADDR + 0x1c21c, 0x00000000);
  481 + reg32_write(REG_BASE_ADDR + 0x1c25c, 0x00000000);
  482 + reg32_write(REG_BASE_ADDR + 0x1c29c, 0x00000000);
  483 + reg32_write(REG_BASE_ADDR + 0x1c220, 0x00000000);
  484 + reg32_write(REG_BASE_ADDR + 0x1c260, 0x00000000);
  485 + reg32_write(REG_BASE_ADDR + 0x1c2a0, 0x00000000);
  486 + reg32_write(REG_BASE_ADDR + 0x1c224, 0x00000000);
  487 + reg32_write(REG_BASE_ADDR + 0x1c264, 0x00000000);
  488 + reg32_write(REG_BASE_ADDR + 0x1c2a4, 0x00000000);
  489 + reg32_write(REG_BASE_ADDR + 0x1c228, 0x00000000);
  490 + reg32_write(REG_BASE_ADDR + 0x1c268, 0x00000000);
  491 + reg32_write(REG_BASE_ADDR + 0x1c2a8, 0x00000000);
  492 + reg32_write(REG_BASE_ADDR + 0x1c22c, 0x00000000);
  493 + reg32_write(REG_BASE_ADDR + 0x1c26c, 0x00000000);
  494 + reg32_write(REG_BASE_ADDR + 0x1c2ac, 0x00000000);
  495 + reg32_write(REG_BASE_ADDR + 0x1c230, 0x00000000);
  496 + reg32_write(REG_BASE_ADDR + 0x1c270, 0x00000000);
  497 + reg32_write(REG_BASE_ADDR + 0x1c2b0, 0x00000000);
  498 + reg32_write(REG_BASE_ADDR + 0x1c234, 0x00000000);
  499 + reg32_write(REG_BASE_ADDR + 0x1c274, 0x00000000);
  500 + reg32_write(REG_BASE_ADDR + 0x1c2b4, 0x00000000);
  501 + reg32_write(REG_BASE_ADDR + 0x1c238, 0x00000000);
  502 + reg32_write(REG_BASE_ADDR + 0x1c278, 0x00000000);
  503 + reg32_write(REG_BASE_ADDR + 0x1c2b8, 0x00000000);
  504 + reg32_write(REG_BASE_ADDR + 0x1c23c, 0x00000000);
  505 + reg32_write(REG_BASE_ADDR + 0x1c27c, 0x00000000);
  506 + reg32_write(REG_BASE_ADDR + 0x1c2bc, 0x00000000);
  507 + reg32_write(REG_BASE_ADDR + 0x1c2bc, 0x00000000);
  508 + reg32_write(REG_BASE_ADDR + 0x1c000, 0x00000011);
  509 +
  510 + /* SUBSAM */
  511 + reg32_write(REG_BASE_ADDR + 0x1b070, 0x21612161);
  512 + reg32_write(REG_BASE_ADDR + 0x1b080, 0x03ff0000);
  513 + reg32_write(REG_BASE_ADDR + 0x1b090, 0x03ff0000);
  514 +
  515 + reg32_write(REG_BASE_ADDR + 0x1b010,
  516 + (((vms->vfp + vms->vbp + vms->vsync + vms->yres -
  517 + 1) << 16) | (vms->hfp + vms->hbp + vms->hsync +
  518 + vms->xres - 1)));
  519 + reg32_write(REG_BASE_ADDR + 0x1b020,
  520 + (((vms->hsync - 1) << 16) | vms->hpol << 31 | (vms->hfp +
  521 + vms->hbp +
  522 + vms->hsync +
  523 + vms->xres -
  524 + 1)));
  525 + reg32_write(REG_BASE_ADDR + 0x1b030,
  526 + (((vms->vfp + vms->vsync -
  527 + 1) << 16) | vms->vpol << 31 | (vms->vfp - 1)));
  528 +
  529 + reg32_write(REG_BASE_ADDR + 0x1b040,
  530 + ((1 << 31) | ((vms->vsync + vms->vfp + vms->vbp) << 16) |
  531 + (vms->hsync + vms->hbp - 1)));
  532 + reg32_write(REG_BASE_ADDR + 0x1b050,
  533 + (((vms->vsync + vms->vfp + vms->vbp + vms->yres -
  534 + 1) << 16) | (vms->hsync + vms->hbp + vms->xres - 1)));
  535 +
  536 + /* subsample mode 0 none, 1 422, 2 420 */
  537 + switch (encoding) {
  538 + case 4:
  539 + reg32_write(REG_BASE_ADDR + 0x1b060, 0x00000001);
  540 + break;
  541 +
  542 + case 8:
  543 + reg32_write(REG_BASE_ADDR + 0x1b060, 0x00000002);
  544 + break;
  545 +
  546 + case 2:
  547 + case 1:
  548 + default:
  549 + reg32_write(REG_BASE_ADDR + 0x1b060, 0x0000000);
  550 + }
  551 +
  552 + reg32_write(REG_BASE_ADDR + 0x1b000, 0x00000001);
  553 +#if 0
  554 + /* not needed for splash setup */
  555 + /* HDR10 Chan3 LUT */
  556 + reg32_write(REG_BASE_ADDR + 0x03874, 0x00000000);
  557 + reg32_write(REG_BASE_ADDR + 0x03080, 0x00000000);
  558 + reg32_write(REG_BASE_ADDR + 0x03000, 0x00000000);
  559 + reg32_write(REG_BASE_ADDR + 0x03800, 0x00000000);
  560 + reg32_write(REG_BASE_ADDR + 0x07874, 0x00000000);
  561 + reg32_write(REG_BASE_ADDR + 0x07080, 0x00000000);
  562 + reg32_write(REG_BASE_ADDR + 0x07000, 0x00000000);
  563 + reg32_write(REG_BASE_ADDR + 0x07800, 0x00000000);
  564 + reg32_write(REG_BASE_ADDR + 0x0b874, 0x00000000);
  565 + reg32_write(REG_BASE_ADDR + 0x0b080, 0x00000000);
  566 + reg32_write(REG_BASE_ADDR + 0x0b000, 0x00000000);
  567 + reg32_write(REG_BASE_ADDR + 0x0b800, 0x00000000);
  568 +
  569 + /* HDR10 Tables and Registers */
  570 + /*reg32_write(REG_BASE_ADDR+0x0f074, 0x00000003); */
  571 + /*reg32_write(REG_BASE_ADDR+0x0f000, 0x00000004); */
  572 +
  573 + reg32_write(REG_BASE_ADDR + 0x0f004, 0x00000000);
  574 + reg32_write(REG_BASE_ADDR + 0x0f008, 0x00000001);
  575 + reg32_write(REG_BASE_ADDR + 0x0f00c, 0x00000000);
  576 + reg32_write(REG_BASE_ADDR + 0x0f010, 0x00000000);
  577 + reg32_write(REG_BASE_ADDR + 0x0f014, 0x00000000);
  578 + reg32_write(REG_BASE_ADDR + 0x0f018, 0x00000001);
  579 + reg32_write(REG_BASE_ADDR + 0x0f01c, 0x00000001);
  580 + reg32_write(REG_BASE_ADDR + 0x0f020, 0x00000000);
  581 + reg32_write(REG_BASE_ADDR + 0x0f024, 0x00000000);
  582 + reg32_write(REG_BASE_ADDR + 0x0f028, 0x00000000);
  583 + reg32_write(REG_BASE_ADDR + 0x0f02c, 0x00000000);
  584 + reg32_write(REG_BASE_ADDR + 0x0f030, 0x00000000);
  585 + reg32_write(REG_BASE_ADDR + 0x0f034, 0x00000000);
  586 + reg32_write(REG_BASE_ADDR + 0x0f038, 0x00000000);
  587 + reg32_write(REG_BASE_ADDR + 0x0f03c, 0x00000000);
  588 + reg32_write(REG_BASE_ADDR + 0x0f040, 0xffffffff);
  589 + reg32_write(REG_BASE_ADDR + 0x0f044, 0xffffffff);
  590 + reg32_write(REG_BASE_ADDR + 0x0f048, 0xffffffff);
  591 + reg32_write(REG_BASE_ADDR + 0x0f04c, 0x00000000);
  592 + reg32_write(REG_BASE_ADDR + 0x0f050, 0x00000000);
  593 + reg32_write(REG_BASE_ADDR + 0x0f054, 0x00000000);
  594 + reg32_write(REG_BASE_ADDR + 0x0f058, 0x00000000);
  595 + reg32_write(REG_BASE_ADDR + 0x0f05c, 0x00000000);
  596 + reg32_write(REG_BASE_ADDR + 0x0f060, 0x00000000);
  597 + reg32_write(REG_BASE_ADDR + 0x0f064, 0x00000000);
  598 + reg32_write(REG_BASE_ADDR + 0x0f068, 0xffffffff);
  599 + reg32_write(REG_BASE_ADDR + 0x0f06c, 0xffffffff);
  600 + reg32_write(REG_BASE_ADDR + 0x0f070, 0xffffffff);
  601 + reg32_write(REG_BASE_ADDR + 0x0f074, 0x00000000);
  602 + reg32_write(REG_BASE_ADDR + 0x0f000, 0x00000003);
  603 +#endif
  604 + /* DTG */
  605 + /*reg32_write(REG_BASE_ADDR + 0x20000, 0xff000484); */
  606 + /* disable local alpha */
  607 + reg32_write(REG_BASE_ADDR + 0x20000, 0xff005084);
  608 + reg32_write(REG_BASE_ADDR + 0x20004,
  609 + (((vms->vfp + vms->vbp + vms->vsync + vms->yres -
  610 + 1) << 16) | (vms->hfp + vms->hbp + vms->hsync +
  611 + vms->xres - 1)));
  612 + reg32_write(REG_BASE_ADDR + 0x20008,
  613 + (((vms->vsync + vms->vfp + vms->vbp -
  614 + 1) << 16) | (vms->hsync + vms->hbp - 1)));
  615 + reg32_write(REG_BASE_ADDR + 0x2000c,
  616 + (((vms->vsync + vms->vfp + vms->vbp + vms->yres -
  617 + 1) << 16) | (vms->hsync + vms->hbp + vms->xres - 1)));
  618 + reg32_write(REG_BASE_ADDR + 0x20010,
  619 + (((vms->vsync + vms->vfp + vms->vbp -
  620 + 1) << 16) | (vms->hsync + vms->hbp - 1)));
  621 + reg32_write(REG_BASE_ADDR + 0x20014,
  622 + (((vms->vsync + vms->vfp + vms->vbp + vms->yres -
  623 + 1) << 16) | (vms->hsync + vms->hbp + vms->xres - 1)));
  624 + reg32_write(REG_BASE_ADDR + 0x20028, 0x000b000a);
  625 +
  626 + /* disable local alpha */
  627 + reg32_write(REG_BASE_ADDR + 0x20000, 0xff005184);
  628 +
  629 + debug("leaving %s() ...\n", __func__);
  630 +}
  631 +
  632 +void imx8m_display_shutdown(void)
  633 +{
  634 + /* stop the DCSS modules in use */
  635 + /* dtg */
  636 + reg32_write(REG_BASE_ADDR + 0x20000, 0);
  637 + /* scaler */
  638 + reg32_write(REG_BASE_ADDR + 0x1c000, 0);
  639 + reg32_write(REG_BASE_ADDR + 0x1c400, 0);
  640 + reg32_write(REG_BASE_ADDR + 0x1c800, 0);
  641 + /* dpr */
  642 + reg32_write(REG_BASE_ADDR + 0x18000, 0);
  643 + reg32_write(REG_BASE_ADDR + 0x19000, 0);
  644 + reg32_write(REG_BASE_ADDR + 0x1a000, 0);
  645 + /* sub-sampler*/
  646 + reg32_write(REG_BASE_ADDR + 0x1b000, 0);
  647 +#if 0
  648 + /* reset the DCSS */
  649 + reg32_write(0x32e2f000, 0xffffe8);
  650 + udelay(100);
  651 + reg32_write(0x32e2f000, 0xffffff);
  652 +#endif
  653 +
  654 +}
  655 +void *video_hw_init(void)
  656 +{
  657 + void *fb;
  658 + int encoding = 1;
  659 +
  660 + debug("%s()\n", __func__);
  661 +
  662 + imx8m_power_init(0x1);
  663 +
  664 + panel.winSizeX = gmode.xres;
  665 + panel.winSizeY = gmode.yres;
  666 + panel.plnSizeX = gmode.xres;
  667 + panel.plnSizeY = gmode.yres;
  668 + panel.gdfBytesPP = 4;
  669 + panel.gdfIndex = GDF_32BIT_X888RGB;
  670 + panel.memSize = gmode.xres * gmode.yres * panel.gdfBytesPP;
  671 +
  672 + /* Allocate framebuffer */
  673 + fb = memalign(0x1000, roundup(panel.memSize, 0x1000));
  674 + debug("%s(): fb %p\n", __func__, fb);
  675 + if (!fb) {
  676 + printf("%s, %s(): Error allocating framebuffer!\n",
  677 + __FILE__, __func__);
  678 + return NULL;
  679 + }
  680 +
  681 + imx8m_create_color_bar((void *)((uint64_t) fb), &gmode);
  682 +
  683 + imx8_hdmi_enable(encoding, &gmode); /* may change gmode */
  684 +
  685 + /* start dccs */
  686 + imx8m_display_init((uint64_t) fb, encoding, &gmode);
  687 +
  688 + panel.frameAdrs = (ulong) fb;
  689 + debug("IMXDCSS display started ...\n");
  690 +
  691 + return &panel;
  692 +}
  693 +
  694 +void imx8m_fb_disable(void)
  695 +{
  696 + debug("%s()\n", __func__);
  697 + if (panel.frameAdrs) {
  698 +#ifdef CONFIG_VIDEO_IMX8_HDMI
  699 + imx8_hdmi_disable();
  700 +#endif
  701 + imx8m_display_shutdown();
  702 + }
  703 +
  704 +}
  705 +
  706 +int imx8m_fb_init(struct fb_videomode const *mode,
  707 + uint8_t disp, uint32_t pixfmt)
  708 +{
  709 + debug("entering %s()\n", __func__);
  710 +
  711 + if (disp > 1) {
  712 + debug("Invalid disp parameter %d for imxdcss_fb_init()\n",
  713 + disp);
  714 + return -EINVAL;
  715 + }
  716 +
  717 + memset(&gmode, 0, sizeof(struct video_mode_settings));
  718 + gmode.pixelclock = PS2KHZ(mode->pixclock) * 1000;
  719 + gmode.xres = mode->xres;
  720 + gmode.hbp = mode->left_margin;
  721 + gmode.hfp = mode->right_margin;
  722 +
  723 + gmode.yres = mode->yres;
  724 + gmode.vbp = mode->upper_margin;
  725 + gmode.vfp = mode->lower_margin;
  726 +
  727 + gmode.hsync = mode->hsync_len;
  728 + gmode.vsync = mode->vsync_len;
  729 + gmode.hpol = (mode->flag & FB_SYNC_HOR_HIGH_ACT) ? 1 : 0;
  730 + gmode.vpol = (mode->flag & FB_SYNC_VERT_HIGH_ACT) ? 1 : 0;
  731 + gpixfmt = pixfmt;
  732 +
  733 + debug("leaving %s()\n", __func__);
  734 +
  735 + return 0;
  736 +}
arch/arm/include/asm/arch-imx8m/video_common.h
  1 +/*
  2 + * Copyright 2018 NXP
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + *
  6 + */
  7 +
  8 +#ifndef __ASM_ARCH_VIDEO_COMMON_H__
  9 +#define __ASM_ARCH_VIDEO_COMMON_H__
  10 +#include <linux/fb.h>
  11 +#include <video_fb.h>
  12 +
  13 +struct video_mode_settings {
  14 + uint32_t pixelclock; /* horizontal resolution */
  15 + uint16_t xres; /* horizontal resolution */
  16 + uint16_t yres; /* vertical resolution */
  17 + uint16_t hfp; /* horizontal front porch */
  18 + uint16_t hbp; /* horizontal back porch */
  19 + uint16_t vfp; /* vertical front porch */
  20 + uint16_t vbp; /* vertical back porch */
  21 + uint16_t hsync; /* horizontal sync pulse width */
  22 + uint16_t vsync; /* vertical sync pulse width */
  23 + bool hpol; /* horizontal pulse polarity */
  24 + bool vpol; /* vertical pulse polarity */
  25 +};
  26 +
  27 +#define PS2KHZ(ps) (1000000000UL / (ps))
  28 +struct video_mode_settings *imx8m_get_gmode(void);
  29 +GraphicDevice *imx8m_get_gd(void);
  30 +void imx8m_show_gmode(void);
  31 +void imx8m_create_color_bar(
  32 + void *start_address,
  33 + struct video_mode_settings *vms);
  34 +int imx8m_fb_init(
  35 + struct fb_videomode const *mode,
  36 + uint8_t disp,
  37 + uint32_t pixfmt);
  38 +void imx8m_fb_disable(void);
  39 +
  40 +#endif /* __ASM_ARCH_VIDEO_COMMON_H__ */