1*a3f9d6c7SDirk Eibach /*
2*a3f9d6c7SDirk Eibach * (C) Copyright 2014
3*a3f9d6c7SDirk Eibach * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
4*a3f9d6c7SDirk Eibach *
5*a3f9d6c7SDirk Eibach * SPDX-License-Identifier: GPL-2.0+
6*a3f9d6c7SDirk Eibach */
7*a3f9d6c7SDirk Eibach
8*a3f9d6c7SDirk Eibach #include <common.h>
9*a3f9d6c7SDirk Eibach #include <i2c.h>
10*a3f9d6c7SDirk Eibach
11*a3f9d6c7SDirk Eibach #define ADV7611_I2C_ADDR 0x4c
12*a3f9d6c7SDirk Eibach #define ADV7611_RDINFO 0x2051
13*a3f9d6c7SDirk Eibach
14*a3f9d6c7SDirk Eibach /*
15*a3f9d6c7SDirk Eibach * ADV7611 I2C Addresses in u-boot notation
16*a3f9d6c7SDirk Eibach */
17*a3f9d6c7SDirk Eibach enum {
18*a3f9d6c7SDirk Eibach CP_I2C_ADDR = 0x22,
19*a3f9d6c7SDirk Eibach DPLL_I2C_ADDR = 0x26,
20*a3f9d6c7SDirk Eibach KSV_I2C_ADDR = 0x32,
21*a3f9d6c7SDirk Eibach HDMI_I2C_ADDR = 0x34,
22*a3f9d6c7SDirk Eibach EDID_I2C_ADDR = 0x36,
23*a3f9d6c7SDirk Eibach INFOFRAME_I2C_ADDR = 0x3e,
24*a3f9d6c7SDirk Eibach CEC_I2C_ADDR = 0x40,
25*a3f9d6c7SDirk Eibach IO_I2C_ADDR = ADV7611_I2C_ADDR,
26*a3f9d6c7SDirk Eibach };
27*a3f9d6c7SDirk Eibach
28*a3f9d6c7SDirk Eibach /*
29*a3f9d6c7SDirk Eibach * Global Control Registers
30*a3f9d6c7SDirk Eibach */
31*a3f9d6c7SDirk Eibach enum {
32*a3f9d6c7SDirk Eibach IO_RD_INFO_MSB = 0xea,
33*a3f9d6c7SDirk Eibach IO_RD_INFO_LSB = 0xeb,
34*a3f9d6c7SDirk Eibach IO_CEC_ADDR = 0xf4,
35*a3f9d6c7SDirk Eibach IO_INFOFRAME_ADDR = 0xf5,
36*a3f9d6c7SDirk Eibach IO_DPLL_ADDR = 0xf8,
37*a3f9d6c7SDirk Eibach IO_KSV_ADDR = 0xf9,
38*a3f9d6c7SDirk Eibach IO_EDID_ADDR = 0xfa,
39*a3f9d6c7SDirk Eibach IO_HDMI_ADDR = 0xfb,
40*a3f9d6c7SDirk Eibach IO_CP_ADDR = 0xfd,
41*a3f9d6c7SDirk Eibach };
42*a3f9d6c7SDirk Eibach
43*a3f9d6c7SDirk Eibach int adv7611_i2c[] = CONFIG_SYS_ADV7611_I2C;
44*a3f9d6c7SDirk Eibach
adv7611_probe(unsigned int screen)45*a3f9d6c7SDirk Eibach int adv7611_probe(unsigned int screen)
46*a3f9d6c7SDirk Eibach {
47*a3f9d6c7SDirk Eibach int old_bus = i2c_get_bus_num();
48*a3f9d6c7SDirk Eibach unsigned int rd_info;
49*a3f9d6c7SDirk Eibach int res = 0;
50*a3f9d6c7SDirk Eibach
51*a3f9d6c7SDirk Eibach i2c_set_bus_num(adv7611_i2c[screen]);
52*a3f9d6c7SDirk Eibach
53*a3f9d6c7SDirk Eibach rd_info = (i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_MSB) << 8)
54*a3f9d6c7SDirk Eibach | i2c_reg_read(IO_I2C_ADDR, IO_RD_INFO_LSB);
55*a3f9d6c7SDirk Eibach
56*a3f9d6c7SDirk Eibach if (rd_info != ADV7611_RDINFO) {
57*a3f9d6c7SDirk Eibach res = -1;
58*a3f9d6c7SDirk Eibach goto out;
59*a3f9d6c7SDirk Eibach }
60*a3f9d6c7SDirk Eibach
61*a3f9d6c7SDirk Eibach /*
62*a3f9d6c7SDirk Eibach * set I2C addresses to default values
63*a3f9d6c7SDirk Eibach */
64*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, IO_CEC_ADDR, CEC_I2C_ADDR << 1);
65*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, IO_INFOFRAME_ADDR, INFOFRAME_I2C_ADDR << 1);
66*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, IO_DPLL_ADDR, DPLL_I2C_ADDR << 1);
67*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, IO_KSV_ADDR, KSV_I2C_ADDR << 1);
68*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, IO_EDID_ADDR, EDID_I2C_ADDR << 1);
69*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, IO_HDMI_ADDR, HDMI_I2C_ADDR << 1);
70*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, IO_CP_ADDR, CP_I2C_ADDR << 1);
71*a3f9d6c7SDirk Eibach
72*a3f9d6c7SDirk Eibach /*
73*a3f9d6c7SDirk Eibach * do magic initialization sequence from
74*a3f9d6c7SDirk Eibach * "ADV7611 Register Settings Recommendations Revision 1.5"
75*a3f9d6c7SDirk Eibach * with most registers undocumented
76*a3f9d6c7SDirk Eibach */
77*a3f9d6c7SDirk Eibach i2c_reg_write(CP_I2C_ADDR, 0x6c, 0x00);
78*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x9b, 0x03);
79*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x6f, 0x08);
80*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x85, 0x1f);
81*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x87, 0x70);
82*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x57, 0xda);
83*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x58, 0x01);
84*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x03, 0x98);
85*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x4c, 0x44);
86*a3f9d6c7SDirk Eibach
87*a3f9d6c7SDirk Eibach /*
88*a3f9d6c7SDirk Eibach * IO_REG_02, default 0xf0
89*a3f9d6c7SDirk Eibach *
90*a3f9d6c7SDirk Eibach * INP_COLOR_SPACE (IO, Address 0x02[7:4])
91*a3f9d6c7SDirk Eibach * default: 0b1111 auto
92*a3f9d6c7SDirk Eibach * set to : 0b0001 force RGB (range 0 to 255) input
93*a3f9d6c7SDirk Eibach *
94*a3f9d6c7SDirk Eibach * RGB_OUT (IO, Address 0x02[1])
95*a3f9d6c7SDirk Eibach * default: 0 YPbPr color space output
96*a3f9d6c7SDirk Eibach * set to : 1 RGB color space output
97*a3f9d6c7SDirk Eibach */
98*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, 0x02, 0x12);
99*a3f9d6c7SDirk Eibach
100*a3f9d6c7SDirk Eibach /*
101*a3f9d6c7SDirk Eibach * IO_REG_03, default 0x00
102*a3f9d6c7SDirk Eibach *
103*a3f9d6c7SDirk Eibach * OP_FORMAT_SEL (IO, Address 0x03[7:0])
104*a3f9d6c7SDirk Eibach * default: 0x00 8-bit SDR ITU-656 mode
105*a3f9d6c7SDirk Eibach * set to : 0x40 24-bit 4:4:4 SDR mode
106*a3f9d6c7SDirk Eibach */
107*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, 0x03, 0x40);
108*a3f9d6c7SDirk Eibach
109*a3f9d6c7SDirk Eibach /*
110*a3f9d6c7SDirk Eibach * IO_REG_05, default 0x2c
111*a3f9d6c7SDirk Eibach *
112*a3f9d6c7SDirk Eibach * AVCODE_INSERT_EN (IO, Address 0x05[2])
113*a3f9d6c7SDirk Eibach * default: 1 insert AV codes into data stream
114*a3f9d6c7SDirk Eibach * set to : 0 do not insert AV codes into data stream
115*a3f9d6c7SDirk Eibach */
116*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, 0x05, 0x28);
117*a3f9d6c7SDirk Eibach
118*a3f9d6c7SDirk Eibach /*
119*a3f9d6c7SDirk Eibach * IO_REG_0C, default 0x62
120*a3f9d6c7SDirk Eibach *
121*a3f9d6c7SDirk Eibach * POWER_DOWN (IO, Address 0x0C[5])
122*a3f9d6c7SDirk Eibach * default: 1 chip is powered down
123*a3f9d6c7SDirk Eibach * set to : 0 chip is operational
124*a3f9d6c7SDirk Eibach */
125*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, 0x0c, 0x42);
126*a3f9d6c7SDirk Eibach
127*a3f9d6c7SDirk Eibach /*
128*a3f9d6c7SDirk Eibach * IO_REG_15, default 0xbe
129*a3f9d6c7SDirk Eibach *
130*a3f9d6c7SDirk Eibach * TRI_SYNCS (IO, Address 0x15[3)
131*a3f9d6c7SDirk Eibach * TRI_LLC (IO, Address 0x15[2])
132*a3f9d6c7SDirk Eibach * TRI_PIX (IO, Address 0x15[1])
133*a3f9d6c7SDirk Eibach * default: 1 video output pins are tristate
134*a3f9d6c7SDirk Eibach * set to : 0 video output pins are active
135*a3f9d6c7SDirk Eibach */
136*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, 0x15, 0xb0);
137*a3f9d6c7SDirk Eibach
138*a3f9d6c7SDirk Eibach /*
139*a3f9d6c7SDirk Eibach * HDMI_REGISTER_02H, default 0xff
140*a3f9d6c7SDirk Eibach *
141*a3f9d6c7SDirk Eibach * CLOCK_TERMA_DISABLE (HDMI, Address 0x83[0])
142*a3f9d6c7SDirk Eibach * default: 1 disable termination
143*a3f9d6c7SDirk Eibach * set to : 0 enable termination
144*a3f9d6c7SDirk Eibach * Future options are:
145*a3f9d6c7SDirk Eibach * - use the chips automatic termination control
146*a3f9d6c7SDirk Eibach * - set this manually on cable detect
147*a3f9d6c7SDirk Eibach * but at the moment this seems a safe default.
148*a3f9d6c7SDirk Eibach */
149*a3f9d6c7SDirk Eibach i2c_reg_write(HDMI_I2C_ADDR, 0x83, 0xfe);
150*a3f9d6c7SDirk Eibach
151*a3f9d6c7SDirk Eibach /*
152*a3f9d6c7SDirk Eibach * HDMI_CP_CNTRL_1, default 0x01
153*a3f9d6c7SDirk Eibach *
154*a3f9d6c7SDirk Eibach * HDMI_FRUN_EN (CP, Address 0xBA[0])
155*a3f9d6c7SDirk Eibach * default: 1 Enable the free run feature in HDMI mode
156*a3f9d6c7SDirk Eibach * set to : 0 Disable the free run feature in HDMI mode
157*a3f9d6c7SDirk Eibach */
158*a3f9d6c7SDirk Eibach i2c_reg_write(CP_I2C_ADDR, 0xba, 0x00);
159*a3f9d6c7SDirk Eibach
160*a3f9d6c7SDirk Eibach /*
161*a3f9d6c7SDirk Eibach * INT1_CONFIGURATION, default 0x20
162*a3f9d6c7SDirk Eibach *
163*a3f9d6c7SDirk Eibach * INTRQ_DUR_SEL[1:0] (IO, Address 0x40[7:6])
164*a3f9d6c7SDirk Eibach * default: 00 Interrupt signal is active for 4 Xtal periods
165*a3f9d6c7SDirk Eibach * set to : 11 Active until cleared
166*a3f9d6c7SDirk Eibach *
167*a3f9d6c7SDirk Eibach * INTRQ_OP_SEL[1:0] (IO, Address 0x40[1:0])
168*a3f9d6c7SDirk Eibach * default: 00 Open drain
169*a3f9d6c7SDirk Eibach * set to : 10 Drives high when active
170*a3f9d6c7SDirk Eibach */
171*a3f9d6c7SDirk Eibach i2c_reg_write(IO_I2C_ADDR, 0x40, 0xc2);
172*a3f9d6c7SDirk Eibach
173*a3f9d6c7SDirk Eibach out:
174*a3f9d6c7SDirk Eibach i2c_set_bus_num(old_bus);
175*a3f9d6c7SDirk Eibach
176*a3f9d6c7SDirk Eibach return res;
177*a3f9d6c7SDirk Eibach }
178