xref: /openbmc/u-boot/board/freescale/ls1021aqds/dcu.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
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