1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright 2014 Freescale Semiconductor, Inc.
4  * Authors: Priyanka Jain <Priyanka.Jain@freescale.com>
5  *	    Wang Dongsheng <dongsheng.wang@freescale.com>
6  *
7  * This file is copied and modified from the original t1040qds/diu.c.
8  * Encoder can be used in T104x and LSx Platform.
9  */
10 
11 #include <common.h>
12 #include <stdio_dev.h>
13 #include <i2c.h>
14 
15 #define I2C_DVI_INPUT_DATA_FORMAT_REG		0x1F
16 #define I2C_DVI_PLL_CHARGE_CNTL_REG		0x33
17 #define I2C_DVI_PLL_DIVIDER_REG			0x34
18 #define I2C_DVI_PLL_SUPPLY_CNTL_REG		0x35
19 #define I2C_DVI_PLL_FILTER_REG			0x36
20 #define I2C_DVI_TEST_PATTERN_REG		0x48
21 #define I2C_DVI_POWER_MGMT_REG			0x49
22 #define I2C_DVI_LOCK_STATE_REG			0x4D
23 #define I2C_DVI_SYNC_POLARITY_REG		0x56
24 
25 /*
26  * Set VSYNC/HSYNC to active high. This is polarity of sync signals
27  * from DIU->DVI. The DIU default is active igh, so DVI is set to
28  * active high.
29  */
30 #define I2C_DVI_INPUT_DATA_FORMAT_VAL		0x98
31 
32 #define I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL	0x06
33 #define I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL	0x26
34 #define I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL	0xA0
35 #define I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL	0x08
36 #define I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL	0x16
37 #define I2C_DVI_PLL_FILTER_LOW_SPEED_VAL	0x60
38 
39 /* Clear test pattern */
40 #define I2C_DVI_TEST_PATTERN_VAL		0x18
41 /* Exit Power-down mode */
42 #define I2C_DVI_POWER_MGMT_VAL			0xC0
43 
44 /* Monitor polarity is handled via DVI Sync Polarity Register */
45 #define I2C_DVI_SYNC_POLARITY_VAL		0x00
46 
47 /* Programming of HDMI Chrontel CH7301 connector */
diu_set_dvi_encoder(unsigned int pixclock)48 int diu_set_dvi_encoder(unsigned int pixclock)
49 {
50 	int ret;
51 	u8 temp;
52 
53 	temp = I2C_DVI_TEST_PATTERN_VAL;
54 	ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_TEST_PATTERN_REG, 1,
55 			&temp, 1);
56 	if (ret) {
57 		puts("I2C: failed to select proper dvi test pattern\n");
58 		return ret;
59 	}
60 	temp = I2C_DVI_INPUT_DATA_FORMAT_VAL;
61 	ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_INPUT_DATA_FORMAT_REG,
62 			1, &temp, 1);
63 	if (ret) {
64 		puts("I2C: failed to select dvi input data format\n");
65 		return ret;
66 	}
67 
68 	/* Set Sync polarity register */
69 	temp = I2C_DVI_SYNC_POLARITY_VAL;
70 	ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_SYNC_POLARITY_REG, 1,
71 			&temp, 1);
72 	if (ret) {
73 		puts("I2C: failed to select dvi syc polarity\n");
74 		return ret;
75 	}
76 
77 	/* Set PLL registers based on pixel clock rate*/
78 	if (pixclock > 65000000) {
79 		temp = I2C_DVI_PLL_CHARGE_CNTL_HIGH_SPEED_VAL;
80 		ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
81 				I2C_DVI_PLL_CHARGE_CNTL_REG, 1,	&temp, 1);
82 		if (ret) {
83 			puts("I2C: failed to select dvi pll charge_cntl\n");
84 			return ret;
85 		}
86 		temp = I2C_DVI_PLL_DIVIDER_HIGH_SPEED_VAL;
87 		ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
88 				I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
89 		if (ret) {
90 			puts("I2C: failed to select dvi pll divider\n");
91 			return ret;
92 		}
93 		temp = I2C_DVI_PLL_FILTER_HIGH_SPEED_VAL;
94 		ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
95 				I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
96 		if (ret) {
97 			puts("I2C: failed to select dvi pll filter\n");
98 			return ret;
99 		}
100 	} else {
101 		temp = I2C_DVI_PLL_CHARGE_CNTL_LOW_SPEED_VAL;
102 		ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
103 				I2C_DVI_PLL_CHARGE_CNTL_REG, 1, &temp, 1);
104 		if (ret) {
105 			puts("I2C: failed to select dvi pll charge_cntl\n");
106 			return ret;
107 		}
108 		temp = I2C_DVI_PLL_DIVIDER_LOW_SPEED_VAL;
109 		ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
110 				I2C_DVI_PLL_DIVIDER_REG, 1, &temp, 1);
111 		if (ret) {
112 			puts("I2C: failed to select dvi pll divider\n");
113 			return ret;
114 		}
115 		temp = I2C_DVI_PLL_FILTER_LOW_SPEED_VAL;
116 		ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR,
117 				I2C_DVI_PLL_FILTER_REG, 1, &temp, 1);
118 		if (ret) {
119 			puts("I2C: failed to select dvi pll filter\n");
120 			return ret;
121 		}
122 	}
123 
124 	temp = I2C_DVI_POWER_MGMT_VAL;
125 	ret = i2c_write(CONFIG_SYS_I2C_DVI_ADDR, I2C_DVI_POWER_MGMT_REG, 1,
126 			&temp, 1);
127 	if (ret) {
128 		puts("I2C: failed to select dvi power mgmt\n");
129 		return ret;
130 	}
131 
132 	udelay(500);
133 
134 	return 0;
135 }
136