Merge tag 'efi-2020-07-rc6' of https://gitlab.denx.de/u-boot/custodians/u-boot-efi
[oweals/u-boot.git] / board / freescale / ls1021aqds / dcu.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014 Freescale Semiconductor, Inc.
4  * Copyright 2019 NXP
5  *
6  * FSL DCU Framebuffer driver
7  */
8
9 #include <asm/io.h>
10 #include <common.h>
11 #include <fsl_dcu_fb.h>
12 #include <i2c.h>
13 #include "div64.h"
14 #include "../common/diu_ch7301.h"
15 #include "ls1021aqds_qixis.h"
16
17 DECLARE_GLOBAL_DATA_PTR;
18
19 static int select_i2c_ch_pca9547(u8 ch, int bus_num)
20 {
21         int ret;
22 #ifdef CONFIG_DM_I2C
23         struct udevice *dev;
24
25         ret = i2c_get_chip_for_busnum(bus_num, I2C_MUX_PCA_ADDR_PRI,
26                                       1, &dev);
27         if (ret) {
28                 printf("%s: Cannot find udev for a bus %d\n", __func__,
29                        bus_num);
30                 return ret;
31         }
32         ret = dm_i2c_write(dev, 0, &ch, 1);
33 #else
34         ret = i2c_write(I2C_MUX_PCA_ADDR_PRI, 0, 1, &ch, 1);
35 #endif
36         if (ret) {
37                 puts("PCA: failed to select proper channel\n");
38                 return ret;
39         }
40
41         return 0;
42 }
43
44 unsigned int dcu_set_pixel_clock(unsigned int pixclock)
45 {
46         unsigned long long div;
47
48         div = (unsigned long long)(gd->bus_clk / 1000);
49         div *= (unsigned long long)pixclock;
50         do_div(div, 1000000000);
51
52         return div;
53 }
54
55 int platform_dcu_init(struct fb_info *fbinfo,
56                       unsigned int xres,
57                       unsigned int yres,
58                       const char *port,
59                       struct fb_videomode *dcu_fb_videomode)
60 {
61         const char *name;
62         unsigned int pixel_format;
63         int ret;
64         u8 ch;
65
66         /* Mux I2C3+I2C4 as HSYNC+VSYNC */
67 #ifdef CONFIG_DM_I2C
68         struct udevice *dev;
69
70         /* QIXIS device mount on I2C1 bus*/
71         ret = i2c_get_chip_for_busnum(0, CONFIG_SYS_I2C_QIXIS_ADDR,
72                                       1, &dev);
73         if (ret) {
74                 printf("%s: Cannot find udev for a bus %d\n", __func__,
75                        0);
76                 return ret;
77         }
78         ret = dm_i2c_read(dev, QIXIS_DCU_BRDCFG5, &ch, 1);
79         if (ret) {
80                 printf("Error: failed to read I2C @%02x\n",
81                        CONFIG_SYS_I2C_QIXIS_ADDR);
82                 return ret;
83         }
84         ch &= 0x1F;
85         ch |= 0xA0;
86         ret = dm_i2c_write(dev, QIXIS_DCU_BRDCFG5, &ch, 1);
87
88 #else
89         ret = i2c_read(CONFIG_SYS_I2C_QIXIS_ADDR, QIXIS_DCU_BRDCFG5,
90                        1, &ch, 1);
91         if (ret) {
92                 printf("Error: failed to read I2C @%02x\n",
93                        CONFIG_SYS_I2C_QIXIS_ADDR);
94                 return ret;
95         }
96         ch &= 0x1F;
97         ch |= 0xA0;
98         ret = i2c_write(CONFIG_SYS_I2C_QIXIS_ADDR, QIXIS_DCU_BRDCFG5,
99                         1, &ch, 1);
100 #endif
101         if (ret) {
102                 printf("Error: failed to write I2C @%02x\n",
103                        CONFIG_SYS_I2C_QIXIS_ADDR);
104                 return ret;
105         }
106
107         if (strncmp(port, "hdmi", 4) == 0) {
108                 unsigned long pixval;
109
110                 name = "HDMI";
111
112                 pixval = 1000000000 / dcu_fb_videomode->pixclock;
113                 pixval *= 1000;
114
115 #ifndef CONFIG_DM_I2C
116                 i2c_set_bus_num(CONFIG_SYS_I2C_DVI_BUS_NUM);
117 #endif
118                 select_i2c_ch_pca9547(I2C_MUX_CH_CH7301,
119                                       CONFIG_SYS_I2C_DVI_BUS_NUM);
120                 diu_set_dvi_encoder(pixval);
121                 select_i2c_ch_pca9547(I2C_MUX_CH_DEFAULT,
122                                       CONFIG_SYS_I2C_DVI_BUS_NUM);
123         } else {
124                 return 0;
125         }
126
127         printf("DCU: Switching to %s monitor @ %ux%u\n", name, xres, yres);
128
129         pixel_format = 32;
130         fsl_dcu_init(fbinfo, xres, yres, pixel_format);
131
132         return 0;
133 }