1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2dd04832dSXiubo Li /*
3dd04832dSXiubo Li * Copyright 2014 Freescale Semiconductor, Inc.
4dd04832dSXiubo Li *
5dd04832dSXiubo Li * FSL DCU Framebuffer driver
6dd04832dSXiubo Li */
7dd04832dSXiubo Li
8dd04832dSXiubo Li #include <asm/io.h>
9dd04832dSXiubo Li #include <common.h>
10dd04832dSXiubo Li #include <fsl_dcu_fb.h>
11dd04832dSXiubo Li #include <i2c.h>
12dd04832dSXiubo Li #include "div64.h"
13dd04832dSXiubo Li #include "../common/diu_ch7301.h"
14dd04832dSXiubo Li #include "ls1021aqds_qixis.h"
15dd04832dSXiubo Li
16dd04832dSXiubo Li DECLARE_GLOBAL_DATA_PTR;
17dd04832dSXiubo Li
select_i2c_ch_pca9547(u8 ch)18dd04832dSXiubo Li static int select_i2c_ch_pca9547(u8 ch)
19dd04832dSXiubo Li {
20dd04832dSXiubo Li int ret;
21dd04832dSXiubo Li
22dd04832dSXiubo Li ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
23dd04832dSXiubo Li if (ret) {
24dd04832dSXiubo Li puts("PCA: failed to select proper channel\n");
25dd04832dSXiubo Li return ret;
26dd04832dSXiubo Li }
27dd04832dSXiubo Li
28dd04832dSXiubo Li return 0;
29dd04832dSXiubo Li }
30dd04832dSXiubo Li
dcu_set_pixel_clock(unsigned int pixclock)31dd04832dSXiubo Li unsigned int dcu_set_pixel_clock(unsigned int pixclock)
32dd04832dSXiubo Li {
33dd04832dSXiubo Li unsigned long long div;
34dd04832dSXiubo Li
35dd04832dSXiubo Li div = (unsigned long long)(gd->bus_clk / 1000);
36dd04832dSXiubo Li div *= (unsigned long long)pixclock;
37dd04832dSXiubo Li do_div(div, 1000000000);
38dd04832dSXiubo Li
39dd04832dSXiubo Li return div;
40dd04832dSXiubo Li }
41dd04832dSXiubo Li
platform_dcu_init(unsigned int xres,unsigned int yres,const char * port,struct fb_videomode * dcu_fb_videomode)42dd04832dSXiubo Li int platform_dcu_init(unsigned int xres, unsigned int yres,
43dd04832dSXiubo Li const char *port,
44dd04832dSXiubo Li struct fb_videomode *dcu_fb_videomode)
45dd04832dSXiubo Li {
46dd04832dSXiubo Li const char *name;
47dd04832dSXiubo Li unsigned int pixel_format;
48dd04832dSXiubo Li int ret;
49dd04832dSXiubo Li u8 ch;
50dd04832dSXiubo Li
51dd04832dSXiubo Li /* Mux I2C3+I2C4 as HSYNC+VSYNC */
52dd04832dSXiubo Li ret = i2c_read(CONFIG_SYS_I2C_QIXIS_ADDR, QIXIS_DCU_BRDCFG5,
53dd04832dSXiubo Li 1, &ch, 1);
54dd04832dSXiubo Li if (ret) {
55dd04832dSXiubo Li printf("Error: failed to read I2C @%02x\n",
56dd04832dSXiubo Li CONFIG_SYS_I2C_QIXIS_ADDR);
57dd04832dSXiubo Li return ret;
58dd04832dSXiubo Li }
59dd04832dSXiubo Li ch &= 0x1F;
60dd04832dSXiubo Li ch |= 0xA0;
61dd04832dSXiubo Li ret = i2c_write(CONFIG_SYS_I2C_QIXIS_ADDR, QIXIS_DCU_BRDCFG5,
62dd04832dSXiubo Li 1, &ch, 1);
63dd04832dSXiubo Li if (ret) {
64dd04832dSXiubo Li printf("Error: failed to write I2C @%02x\n",
65dd04832dSXiubo Li CONFIG_SYS_I2C_QIXIS_ADDR);
66dd04832dSXiubo Li return ret;
67dd04832dSXiubo Li }
68dd04832dSXiubo Li
69dd04832dSXiubo Li if (strncmp(port, "hdmi", 4) == 0) {
70dd04832dSXiubo Li unsigned long pixval;
71dd04832dSXiubo Li
72dd04832dSXiubo Li name = "HDMI";
73dd04832dSXiubo Li
74dd04832dSXiubo Li pixval = 1000000000 / dcu_fb_videomode->pixclock;
75dd04832dSXiubo Li pixval *= 1000;
76dd04832dSXiubo Li
77dd04832dSXiubo Li i2c_set_bus_num(CONFIG_SYS_I2C_DVI_BUS_NUM);
78dd04832dSXiubo Li select_i2c_ch_pca9547(I2C_MUX_CH_CH7301);
79dd04832dSXiubo Li diu_set_dvi_encoder(pixval);
80dd04832dSXiubo Li select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT);
81dd04832dSXiubo Li } else {
82dd04832dSXiubo Li return 0;
83dd04832dSXiubo Li }
84dd04832dSXiubo Li
85dd04832dSXiubo Li printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres);
86dd04832dSXiubo Li
87dd04832dSXiubo Li pixel_format = 32;
88dd04832dSXiubo Li fsl_dcu_init(xres, yres, pixel_format);
89dd04832dSXiubo Li
90dd04832dSXiubo Li return 0;
91dd04832dSXiubo Li }
92