7f11123e6f3ecdad5c34f80e8f45d48fdde281b0
[oweals/u-boot.git] / board / freescale / common / diu_ch7301.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014 Freescale Semiconductor, Inc.
4  * Copyright 2019 NXP
5  * Authors: Priyanka Jain <Priyanka.Jain@freescale.com>
6  *          Wang Dongsheng <dongsheng.wang@freescale.com>
7  *
8  * This file is copied and modified from the original t1040qds/diu.c.
9  * Encoder can be used in T104x and LSx Platform.
10  */
11
12 #include <common.h>
13 #include <stdio_dev.h>
14 #include <i2c.h>
15
16 #define I2C_DVI_INPUT_DATA_FORMAT_REG           0x1F
17 #define I2C_DVI_PLL_CHARGE_CNTL_REG             0x33
18 #define I2C_DVI_PLL_DIVIDER_REG                 0x34
19 #define I2C_DVI_PLL_SUPPLY_CNTL_REG             0x35
20 #define I2C_DVI_PLL_FILTER_REG                  0x36
21 #define I2C_DVI_TEST_PATTERN_REG                0x48
22 #define I2C_DVI_POWER_MGMT_REG                  0x49
23 #define I2C_DVI_LOCK_STATE_REG                  0x4D
24 #define I2C_DVI_SYNC_POLARITY_REG               0x56
25
26 /*
27  * Set VSYNC/HSYNC to active high. This is polarity of sync signals
28  * from DIU->DVI. The DIU default is active igh, so DVI is set to
29  * active high.
30  */
31 #define I2C_DVI_INPUT_DATA_FORMAT_VAL           0x98
32
33 #define I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL  0x06
34 #define I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL      0x26
35 #define I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL       0xA0
36 #define I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL   0x08
37 #define I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL       0x16
38 #define I2C_DVI_PLL_FILTER_LOW_SPEED_VAL        0x60
39
40 /* Clear test pattern */
41 #define I2C_DVI_TEST_PATTERN_VAL                0x18
42 /* Exit Power-down mode */
43 #define I2C_DVI_POWER_MGMT_VAL                  0xC0
44
45 /* Monitor polarity is handled via DVI Sync Polarity Register */
46 #define I2C_DVI_SYNC_POLARITY_VAL               0x00
47
48 /* Programming of HDMI Chrontel CH7301 connector */
49 int diu_set_dvi_encoder(unsigned int pixclock)
50 {
51         int ret;
52         u8 temp;
53
54         temp = I2C_DVI_TEST_PATTERN_VAL;
55 #ifdef CONFIG_DM_I2C
56         struct udevice *dev;
57
58         ret = i2c_get_chip_for_busnum(CONFIG_SYS_I2C_DVI_BUS_NUM,
59                                       CONFIG_SYS_I2C_DVI_ADDR,
60                                       1, &dev);
61         if (ret) {
62                 printf("%s: Cannot find udev for a bus %d\n", __func__,
63                        CONFIG_SYS_I2C_DVI_BUS_NUM);
64                 return ret;
65         }
66         ret = dm_i2c_write(dev, I2C_DVI_TEST_PATTERN_REG, &temp, 1);
67         if (ret) {
68                 puts("I2C: failed to select proper dvi test pattern\n");
69                 return ret;
70         }
71         temp = I2C_DVI_INPUT_DATA_FORMAT_VAL;
72         ret = dm_i2c_write(dev, I2C_DVI_INPUT_DATA_FORMAT_REG, &temp, 1);
73         if (ret) {
74                 puts("I2C: failed to select dvi input data format\n");
75                 return ret;
76         }
77
78         /* Set Sync polarity register */
79         temp = I2C_DVI_SYNC_POLARITY_VAL;
80         ret = dm_i2c_write(dev, I2C_DVI_SYNC_POLARITY_REG, &temp, 1);
81         if (ret) {
82                 puts("I2C: failed to select dvi syc polarity\n");
83                 return ret;
84         }
85
86         /* Set PLL registers based on pixel clock rate*/
87         if (pixclock > 65000000) {
88                 temp = I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL;
89                 ret = dm_i2c_write(dev, I2C_DVI_PLL_CHARGE_CNTL_REG, &temp, 1);
90                 if (ret) {
91                         puts("I2C: failed to select dvi pll charge_cntl\n");
92                         return ret;
93                 }
94                 temp = I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL;
95                 ret = dm_i2c_write(dev, I2C_DVI_PLL_DIVIDER_REG, &temp, 1);
96                 if (ret) {
97                         puts("I2C: failed to select dvi pll divider\n");
98                         return ret;
99                 }
100                 temp = I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL;
101                 ret = dm_i2c_write(dev, I2C_DVI_PLL_FILTER_REG, &temp, 1);
102                 if (ret) {
103                         puts("I2C: failed to select dvi pll filter\n");
104                         return ret;
105                 }
106         } else {
107                 temp = I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL;
108                 ret = dm_i2c_write(dev, I2C_DVI_PLL_CHARGE_CNTL_REG, &temp, 1);
109                 if (ret) {
110                         puts("I2C: failed to select dvi pll charge_cntl\n");
111                         return ret;
112                 }
113                 temp = I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL;
114                 ret = dm_i2c_write(dev, I2C_DVI_PLL_DIVIDER_REG, &temp, 1);
115                 if (ret) {
116                         puts("I2C: failed to select dvi pll divider\n");
117                         return ret;
118                 }
119                 temp = I2C_DVI_PLL_FILTER_LOW_SPEED_VAL;
120                 ret = dm_i2c_write(dev, I2C_DVI_PLL_FILTER_REG, &temp, 1);
121                 if (ret) {
122                         puts("I2C: failed to select dvi pll filter\n");
123                         return ret;
124                 }
125         }
126
127         temp = I2C_DVI_POWER_MGMT_VAL;
128         ret = dm_i2c_write(dev, I2C_DVI_POWER_MGMT_REG, &temp, 1);
129         if (ret) {
130                 puts("I2C: failed to select dvi power mgmt\n");
131                 return ret;
132         }
133 #else
134         ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_TEST_PATTERN_REG, 1,
135                         &temp, 1);
136         if (ret) {
137                 puts("I2C: failed to select proper dvi test pattern\n");
138                 return ret;
139         }
140         temp = I2C_DVI_INPUT_DATA_FORMAT_VAL;
141         ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_INPUT_DATA_FORMAT_REG,
142                         1, &temp, 1);
143         if (ret) {
144                 puts("I2C: failed to select dvi input data format\n");
145                 return ret;
146         }
147
148         /* Set Sync polarity register */
149         temp = I2C_DVI_SYNC_POLARITY_VAL;
150         ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_SYNC_POLARITY_REG, 1,
151                         &temp, 1);
152         if (ret) {
153                 puts("I2C: failed to select dvi syc polarity\n");
154                 return ret;
155         }
156
157         /* Set PLL registers based on pixel clock rate*/
158         if (pixclock > 65000000) {
159                 temp = I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL;
160                 ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
161                                 I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1);
162                 if (ret) {
163                         puts("I2C: failed to select dvi pll charge_cntl\n");
164                         return ret;
165                 }
166                 temp = I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL;
167                 ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
168                                 I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
169                 if (ret) {
170                         puts("I2C: failed to select dvi pll divider\n");
171                         return ret;
172                 }
173                 temp = I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL;
174                 ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
175                                 I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
176                 if (ret) {
177                         puts("I2C: failed to select dvi pll filter\n");
178                         return ret;
179                 }
180         } else {
181                 temp = I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL;
182                 ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
183                                 I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1);
184                 if (ret) {
185                         puts("I2C: failed to select dvi pll charge_cntl\n");
186                         return ret;
187                 }
188                 temp = I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL;
189                 ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
190                                 I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
191                 if (ret) {
192                         puts("I2C: failed to select dvi pll divider\n");
193                         return ret;
194                 }
195                 temp = I2C_DVI_PLL_FILTER_LOW_SPEED_VAL;
196                 ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
197                                 I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
198                 if (ret) {
199                         puts("I2C: failed to select dvi pll filter\n");
200                         return ret;
201                 }
202         }
203
204         temp = I2C_DVI_POWER_MGMT_VAL;
205         ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_POWER_MGMT_REG, 1,
206                         &temp, 1);
207         if (ret) {
208                 puts("I2C: failed to select dvi power mgmt\n");
209                 return ret;
210         }
211 #endif
212
213         udelay(500);
214
215         return 0;
216 }