1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * (C) Copyright 2010
3*4882a593Smuzhiyun * Dirk Eibach, Guntermann & Drunck GmbH, eibach@gdsys.de
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * SPDX-License-Identifier: GPL-2.0+
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <i2c.h>
10*4882a593Smuzhiyun #include <malloc.h>
11*4882a593Smuzhiyun
12*4882a593Smuzhiyun #include "ch7301.h"
13*4882a593Smuzhiyun #include "dp501.h"
14*4882a593Smuzhiyun #include <gdsys_fpga.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #define ICS8N3QV01_I2C_ADDR 0x6E
17*4882a593Smuzhiyun #define ICS8N3QV01_FREF 114285000
18*4882a593Smuzhiyun #define ICS8N3QV01_FREF_LL 114285000LL
19*4882a593Smuzhiyun #define ICS8N3QV01_F_DEFAULT_0 156250000LL
20*4882a593Smuzhiyun #define ICS8N3QV01_F_DEFAULT_1 125000000LL
21*4882a593Smuzhiyun #define ICS8N3QV01_F_DEFAULT_2 100000000LL
22*4882a593Smuzhiyun #define ICS8N3QV01_F_DEFAULT_3 25175000LL
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #define SIL1178_MASTER_I2C_ADDRESS 0x38
25*4882a593Smuzhiyun #define SIL1178_SLAVE_I2C_ADDRESS 0x39
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define PIXCLK_640_480_60 25180000
28*4882a593Smuzhiyun #define MAX_X_CHARS 53
29*4882a593Smuzhiyun #define MAX_Y_CHARS 26
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun #ifdef CONFIG_SYS_OSD_DH
32*4882a593Smuzhiyun #define MAX_OSD_SCREEN 8
33*4882a593Smuzhiyun #define OSD_DH_BASE 4
34*4882a593Smuzhiyun #else
35*4882a593Smuzhiyun #define MAX_OSD_SCREEN 4
36*4882a593Smuzhiyun #endif
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun #ifdef CONFIG_SYS_OSD_DH
39*4882a593Smuzhiyun #define OSD_SET_REG(screen, fld, val) \
40*4882a593Smuzhiyun do { \
41*4882a593Smuzhiyun if (screen >= OSD_DH_BASE) \
42*4882a593Smuzhiyun FPGA_SET_REG(screen - OSD_DH_BASE, osd1.fld, val); \
43*4882a593Smuzhiyun else \
44*4882a593Smuzhiyun FPGA_SET_REG(screen, osd0.fld, val); \
45*4882a593Smuzhiyun } while (0)
46*4882a593Smuzhiyun #else
47*4882a593Smuzhiyun #define OSD_SET_REG(screen, fld, val) \
48*4882a593Smuzhiyun FPGA_SET_REG(screen, osd0.fld, val)
49*4882a593Smuzhiyun #endif
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun #ifdef CONFIG_SYS_OSD_DH
52*4882a593Smuzhiyun #define OSD_GET_REG(screen, fld, val) \
53*4882a593Smuzhiyun do { \
54*4882a593Smuzhiyun if (screen >= OSD_DH_BASE) \
55*4882a593Smuzhiyun FPGA_GET_REG(screen - OSD_DH_BASE, osd1.fld, val); \
56*4882a593Smuzhiyun else \
57*4882a593Smuzhiyun FPGA_GET_REG(screen, osd0.fld, val); \
58*4882a593Smuzhiyun } while (0)
59*4882a593Smuzhiyun #else
60*4882a593Smuzhiyun #define OSD_GET_REG(screen, fld, val) \
61*4882a593Smuzhiyun FPGA_GET_REG(screen, osd0.fld, val)
62*4882a593Smuzhiyun #endif
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun unsigned int base_width;
65*4882a593Smuzhiyun unsigned int base_height;
66*4882a593Smuzhiyun size_t bufsize;
67*4882a593Smuzhiyun u16 *buf;
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun unsigned int osd_screen_mask = 0;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #ifdef CONFIG_SYS_ICS8N3QV01_I2C
72*4882a593Smuzhiyun int ics8n3qv01_i2c[] = CONFIG_SYS_ICS8N3QV01_I2C;
73*4882a593Smuzhiyun #endif
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun #ifdef CONFIG_SYS_SIL1178_I2C
76*4882a593Smuzhiyun int sil1178_i2c[] = CONFIG_SYS_SIL1178_I2C;
77*4882a593Smuzhiyun #endif
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun #ifdef CONFIG_SYS_MPC92469AC
mpc92469ac_calc_parameters(unsigned int fout,unsigned int * post_div,unsigned int * feedback_div)80*4882a593Smuzhiyun static void mpc92469ac_calc_parameters(unsigned int fout,
81*4882a593Smuzhiyun unsigned int *post_div, unsigned int *feedback_div)
82*4882a593Smuzhiyun {
83*4882a593Smuzhiyun unsigned int n = *post_div;
84*4882a593Smuzhiyun unsigned int m = *feedback_div;
85*4882a593Smuzhiyun unsigned int a;
86*4882a593Smuzhiyun unsigned int b = 14745600 / 16;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun if (fout < 50169600)
89*4882a593Smuzhiyun n = 8;
90*4882a593Smuzhiyun else if (fout < 100339199)
91*4882a593Smuzhiyun n = 4;
92*4882a593Smuzhiyun else if (fout < 200678399)
93*4882a593Smuzhiyun n = 2;
94*4882a593Smuzhiyun else
95*4882a593Smuzhiyun n = 1;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun a = fout * n + (b / 2); /* add b/2 for proper rounding */
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun m = a / b;
100*4882a593Smuzhiyun
101*4882a593Smuzhiyun *post_div = n;
102*4882a593Smuzhiyun *feedback_div = m;
103*4882a593Smuzhiyun }
104*4882a593Smuzhiyun
mpc92469ac_set(unsigned screen,unsigned int fout)105*4882a593Smuzhiyun static void mpc92469ac_set(unsigned screen, unsigned int fout)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun unsigned int n;
108*4882a593Smuzhiyun unsigned int m;
109*4882a593Smuzhiyun unsigned int bitval = 0;
110*4882a593Smuzhiyun mpc92469ac_calc_parameters(fout, &n, &m);
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun switch (n) {
113*4882a593Smuzhiyun case 1:
114*4882a593Smuzhiyun bitval = 0x00;
115*4882a593Smuzhiyun break;
116*4882a593Smuzhiyun case 2:
117*4882a593Smuzhiyun bitval = 0x01;
118*4882a593Smuzhiyun break;
119*4882a593Smuzhiyun case 4:
120*4882a593Smuzhiyun bitval = 0x02;
121*4882a593Smuzhiyun break;
122*4882a593Smuzhiyun case 8:
123*4882a593Smuzhiyun bitval = 0x03;
124*4882a593Smuzhiyun break;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun FPGA_SET_REG(screen, mpc3w_control, (bitval << 9) | m);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun #endif
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun #ifdef CONFIG_SYS_ICS8N3QV01_I2C
132*4882a593Smuzhiyun
ics8n3qv01_get_fout_calc(unsigned index)133*4882a593Smuzhiyun static unsigned int ics8n3qv01_get_fout_calc(unsigned index)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun unsigned long long n;
136*4882a593Smuzhiyun unsigned long long mint;
137*4882a593Smuzhiyun unsigned long long mfrac;
138*4882a593Smuzhiyun u8 reg_a, reg_b, reg_c, reg_d, reg_f;
139*4882a593Smuzhiyun unsigned long long fout_calc;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun if (index > 3)
142*4882a593Smuzhiyun return 0;
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun reg_a = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 0 + index);
145*4882a593Smuzhiyun reg_b = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 4 + index);
146*4882a593Smuzhiyun reg_c = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 8 + index);
147*4882a593Smuzhiyun reg_d = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 12 + index);
148*4882a593Smuzhiyun reg_f = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 20 + index);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun mint = ((reg_a >> 1) & 0x1f) | (reg_f & 0x20);
151*4882a593Smuzhiyun mfrac = ((reg_a & 0x01) << 17) | (reg_b << 9) | (reg_c << 1)
152*4882a593Smuzhiyun | (reg_d >> 7);
153*4882a593Smuzhiyun n = reg_d & 0x7f;
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun fout_calc = (mint * ICS8N3QV01_FREF_LL
156*4882a593Smuzhiyun + mfrac * ICS8N3QV01_FREF_LL / 262144LL
157*4882a593Smuzhiyun + ICS8N3QV01_FREF_LL / 524288LL
158*4882a593Smuzhiyun + n / 2)
159*4882a593Smuzhiyun / n
160*4882a593Smuzhiyun * 1000000
161*4882a593Smuzhiyun / (1000000 - 100);
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun return fout_calc;
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun
166*4882a593Smuzhiyun
ics8n3qv01_calc_parameters(unsigned int fout,unsigned int * _mint,unsigned int * _mfrac,unsigned int * _n)167*4882a593Smuzhiyun static void ics8n3qv01_calc_parameters(unsigned int fout,
168*4882a593Smuzhiyun unsigned int *_mint, unsigned int *_mfrac,
169*4882a593Smuzhiyun unsigned int *_n)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun unsigned int n;
172*4882a593Smuzhiyun unsigned int foutiic;
173*4882a593Smuzhiyun unsigned int fvcoiic;
174*4882a593Smuzhiyun unsigned int mint;
175*4882a593Smuzhiyun unsigned long long mfrac;
176*4882a593Smuzhiyun
177*4882a593Smuzhiyun n = (2215000000U + fout / 2) / fout;
178*4882a593Smuzhiyun if ((n & 1) && (n > 5))
179*4882a593Smuzhiyun n -= 1;
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun foutiic = fout - (fout / 10000);
182*4882a593Smuzhiyun fvcoiic = foutiic * n;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun mint = fvcoiic / 114285000;
185*4882a593Smuzhiyun if ((mint < 17) || (mint > 63))
186*4882a593Smuzhiyun printf("ics8n3qv01_calc_parameters: cannot determine mint\n");
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun mfrac = ((unsigned long long)fvcoiic % 114285000LL) * 262144LL
189*4882a593Smuzhiyun / 114285000LL;
190*4882a593Smuzhiyun
191*4882a593Smuzhiyun *_mint = mint;
192*4882a593Smuzhiyun *_mfrac = mfrac;
193*4882a593Smuzhiyun *_n = n;
194*4882a593Smuzhiyun }
195*4882a593Smuzhiyun
ics8n3qv01_set(unsigned int fout)196*4882a593Smuzhiyun static void ics8n3qv01_set(unsigned int fout)
197*4882a593Smuzhiyun {
198*4882a593Smuzhiyun unsigned int n;
199*4882a593Smuzhiyun unsigned int mint;
200*4882a593Smuzhiyun unsigned int mfrac;
201*4882a593Smuzhiyun unsigned int fout_calc;
202*4882a593Smuzhiyun unsigned long long fout_prog;
203*4882a593Smuzhiyun long long off_ppm;
204*4882a593Smuzhiyun u8 reg0, reg4, reg8, reg12, reg18, reg20;
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun fout_calc = ics8n3qv01_get_fout_calc(1);
207*4882a593Smuzhiyun off_ppm = (fout_calc - ICS8N3QV01_F_DEFAULT_1) * 1000000
208*4882a593Smuzhiyun / ICS8N3QV01_F_DEFAULT_1;
209*4882a593Smuzhiyun printf(" PLL is off by %lld ppm\n", off_ppm);
210*4882a593Smuzhiyun fout_prog = (unsigned long long)fout * (unsigned long long)fout_calc
211*4882a593Smuzhiyun / ICS8N3QV01_F_DEFAULT_1;
212*4882a593Smuzhiyun ics8n3qv01_calc_parameters(fout_prog, &mint, &mfrac, &n);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun reg0 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 0) & 0xc0;
215*4882a593Smuzhiyun reg0 |= (mint & 0x1f) << 1;
216*4882a593Smuzhiyun reg0 |= (mfrac >> 17) & 0x01;
217*4882a593Smuzhiyun i2c_reg_write(ICS8N3QV01_I2C_ADDR, 0, reg0);
218*4882a593Smuzhiyun
219*4882a593Smuzhiyun reg4 = mfrac >> 9;
220*4882a593Smuzhiyun i2c_reg_write(ICS8N3QV01_I2C_ADDR, 4, reg4);
221*4882a593Smuzhiyun
222*4882a593Smuzhiyun reg8 = mfrac >> 1;
223*4882a593Smuzhiyun i2c_reg_write(ICS8N3QV01_I2C_ADDR, 8, reg8);
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun reg12 = mfrac << 7;
226*4882a593Smuzhiyun reg12 |= n & 0x7f;
227*4882a593Smuzhiyun i2c_reg_write(ICS8N3QV01_I2C_ADDR, 12, reg12);
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun reg18 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 18) & 0x03;
230*4882a593Smuzhiyun reg18 |= 0x20;
231*4882a593Smuzhiyun i2c_reg_write(ICS8N3QV01_I2C_ADDR, 18, reg18);
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun reg20 = i2c_reg_read(ICS8N3QV01_I2C_ADDR, 20) & 0x1f;
234*4882a593Smuzhiyun reg20 |= mint & (1 << 5);
235*4882a593Smuzhiyun i2c_reg_write(ICS8N3QV01_I2C_ADDR, 20, reg20);
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun #endif
238*4882a593Smuzhiyun
osd_write_videomem(unsigned screen,unsigned offset,u16 * data,size_t charcount)239*4882a593Smuzhiyun static int osd_write_videomem(unsigned screen, unsigned offset,
240*4882a593Smuzhiyun u16 *data, size_t charcount)
241*4882a593Smuzhiyun {
242*4882a593Smuzhiyun unsigned int k;
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun for (k = 0; k < charcount; ++k) {
245*4882a593Smuzhiyun if (offset + k >= bufsize)
246*4882a593Smuzhiyun return -1;
247*4882a593Smuzhiyun #ifdef CONFIG_SYS_OSD_DH
248*4882a593Smuzhiyun if (screen >= OSD_DH_BASE)
249*4882a593Smuzhiyun FPGA_SET_REG(screen - OSD_DH_BASE,
250*4882a593Smuzhiyun videomem1[offset + k], data[k]);
251*4882a593Smuzhiyun else
252*4882a593Smuzhiyun FPGA_SET_REG(screen, videomem0[offset + k], data[k]);
253*4882a593Smuzhiyun #else
254*4882a593Smuzhiyun FPGA_SET_REG(screen, videomem0[offset + k], data[k]);
255*4882a593Smuzhiyun #endif
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun return charcount;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun
osd_print(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])261*4882a593Smuzhiyun static int osd_print(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
262*4882a593Smuzhiyun {
263*4882a593Smuzhiyun unsigned screen;
264*4882a593Smuzhiyun
265*4882a593Smuzhiyun if (argc < 5) {
266*4882a593Smuzhiyun cmd_usage(cmdtp);
267*4882a593Smuzhiyun return 1;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun
270*4882a593Smuzhiyun for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
271*4882a593Smuzhiyun unsigned x;
272*4882a593Smuzhiyun unsigned y;
273*4882a593Smuzhiyun unsigned charcount;
274*4882a593Smuzhiyun unsigned len;
275*4882a593Smuzhiyun u8 color;
276*4882a593Smuzhiyun unsigned int k;
277*4882a593Smuzhiyun char *text;
278*4882a593Smuzhiyun int res;
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun if (!(osd_screen_mask & (1 << screen)))
281*4882a593Smuzhiyun continue;
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun x = simple_strtoul(argv[1], NULL, 16);
284*4882a593Smuzhiyun y = simple_strtoul(argv[2], NULL, 16);
285*4882a593Smuzhiyun color = simple_strtoul(argv[3], NULL, 16);
286*4882a593Smuzhiyun text = argv[4];
287*4882a593Smuzhiyun charcount = strlen(text);
288*4882a593Smuzhiyun len = (charcount > bufsize) ? bufsize : charcount;
289*4882a593Smuzhiyun
290*4882a593Smuzhiyun for (k = 0; k < len; ++k)
291*4882a593Smuzhiyun buf[k] = (text[k] << 8) | color;
292*4882a593Smuzhiyun
293*4882a593Smuzhiyun res = osd_write_videomem(screen, y * base_width + x, buf, len);
294*4882a593Smuzhiyun if (res < 0)
295*4882a593Smuzhiyun return res;
296*4882a593Smuzhiyun
297*4882a593Smuzhiyun OSD_SET_REG(screen, control, 0x0049);
298*4882a593Smuzhiyun }
299*4882a593Smuzhiyun
300*4882a593Smuzhiyun return 0;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
osd_probe(unsigned screen)303*4882a593Smuzhiyun int osd_probe(unsigned screen)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun u16 version;
306*4882a593Smuzhiyun u16 features;
307*4882a593Smuzhiyun int old_bus = i2c_get_bus_num();
308*4882a593Smuzhiyun bool pixclock_present = false;
309*4882a593Smuzhiyun bool output_driver_present = false;
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun OSD_GET_REG(0, version, &version);
312*4882a593Smuzhiyun OSD_GET_REG(0, features, &features);
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun base_width = ((features & 0x3f00) >> 8) + 1;
315*4882a593Smuzhiyun base_height = (features & 0x001f) + 1;
316*4882a593Smuzhiyun bufsize = base_width * base_height;
317*4882a593Smuzhiyun buf = malloc(sizeof(u16) * bufsize);
318*4882a593Smuzhiyun if (!buf)
319*4882a593Smuzhiyun return -1;
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun #ifdef CONFIG_SYS_OSD_DH
322*4882a593Smuzhiyun printf("OSD%d-%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n",
323*4882a593Smuzhiyun (screen >= OSD_DH_BASE) ? (screen - OSD_DH_BASE) : screen,
324*4882a593Smuzhiyun (screen > 3) ? 1 : 0, version/100, version%100, base_width,
325*4882a593Smuzhiyun base_height);
326*4882a593Smuzhiyun #else
327*4882a593Smuzhiyun printf("OSD%d: Digital-OSD version %01d.%02d, %d" "x%d characters\n",
328*4882a593Smuzhiyun screen, version/100, version%100, base_width, base_height);
329*4882a593Smuzhiyun #endif
330*4882a593Smuzhiyun /* setup pixclock */
331*4882a593Smuzhiyun
332*4882a593Smuzhiyun #ifdef CONFIG_SYS_MPC92469AC
333*4882a593Smuzhiyun pixclock_present = true;
334*4882a593Smuzhiyun mpc92469ac_set(screen, PIXCLK_640_480_60);
335*4882a593Smuzhiyun #endif
336*4882a593Smuzhiyun
337*4882a593Smuzhiyun #ifdef CONFIG_SYS_ICS8N3QV01_I2C
338*4882a593Smuzhiyun i2c_set_bus_num(ics8n3qv01_i2c[screen]);
339*4882a593Smuzhiyun if (!i2c_probe(ICS8N3QV01_I2C_ADDR)) {
340*4882a593Smuzhiyun ics8n3qv01_set(PIXCLK_640_480_60);
341*4882a593Smuzhiyun pixclock_present = true;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun #endif
344*4882a593Smuzhiyun
345*4882a593Smuzhiyun if (!pixclock_present)
346*4882a593Smuzhiyun printf(" no pixelclock found\n");
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun /* setup output driver */
349*4882a593Smuzhiyun
350*4882a593Smuzhiyun #ifdef CONFIG_SYS_CH7301_I2C
351*4882a593Smuzhiyun if (!ch7301_probe(screen, true))
352*4882a593Smuzhiyun output_driver_present = true;
353*4882a593Smuzhiyun #endif
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun #ifdef CONFIG_SYS_SIL1178_I2C
356*4882a593Smuzhiyun i2c_set_bus_num(sil1178_i2c[screen]);
357*4882a593Smuzhiyun if (!i2c_probe(SIL1178_SLAVE_I2C_ADDRESS)) {
358*4882a593Smuzhiyun if (i2c_reg_read(SIL1178_SLAVE_I2C_ADDRESS, 0x02) == 0x06) {
359*4882a593Smuzhiyun /*
360*4882a593Smuzhiyun * magic initialization sequence,
361*4882a593Smuzhiyun * adapted from datasheet
362*4882a593Smuzhiyun */
363*4882a593Smuzhiyun i2c_reg_write(SIL1178_SLAVE_I2C_ADDRESS, 0x08, 0x36);
364*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0f, 0x44);
365*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0f, 0x4c);
366*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0e, 0x10);
367*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0a, 0x80);
368*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x09, 0x30);
369*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0c, 0x89);
370*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x0d, 0x60);
371*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x08, 0x36);
372*4882a593Smuzhiyun i2c_reg_write(SIL1178_MASTER_I2C_ADDRESS, 0x08, 0x37);
373*4882a593Smuzhiyun output_driver_present = true;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun #endif
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun #ifdef CONFIG_SYS_DP501_I2C
379*4882a593Smuzhiyun if (!dp501_probe(screen, true))
380*4882a593Smuzhiyun output_driver_present = true;
381*4882a593Smuzhiyun #endif
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun if (!output_driver_present)
384*4882a593Smuzhiyun printf(" no output driver found\n");
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun OSD_SET_REG(screen, xy_size, ((32 - 1) << 8) | (16 - 1));
387*4882a593Smuzhiyun OSD_SET_REG(screen, x_pos, 0x007f);
388*4882a593Smuzhiyun OSD_SET_REG(screen, y_pos, 0x005f);
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun if (pixclock_present && output_driver_present)
391*4882a593Smuzhiyun osd_screen_mask |= 1 << screen;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun i2c_set_bus_num(old_bus);
394*4882a593Smuzhiyun
395*4882a593Smuzhiyun return 0;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
osd_write(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])398*4882a593Smuzhiyun int osd_write(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
399*4882a593Smuzhiyun {
400*4882a593Smuzhiyun unsigned screen;
401*4882a593Smuzhiyun
402*4882a593Smuzhiyun if ((argc < 4) || (strlen(argv[3]) % 4)) {
403*4882a593Smuzhiyun cmd_usage(cmdtp);
404*4882a593Smuzhiyun return 1;
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
408*4882a593Smuzhiyun unsigned x;
409*4882a593Smuzhiyun unsigned y;
410*4882a593Smuzhiyun unsigned k;
411*4882a593Smuzhiyun u16 buffer[base_width];
412*4882a593Smuzhiyun char *rp;
413*4882a593Smuzhiyun u16 *wp = buffer;
414*4882a593Smuzhiyun unsigned count = (argc > 4) ?
415*4882a593Smuzhiyun simple_strtoul(argv[4], NULL, 16) : 1;
416*4882a593Smuzhiyun
417*4882a593Smuzhiyun if (!(osd_screen_mask & (1 << screen)))
418*4882a593Smuzhiyun continue;
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun x = simple_strtoul(argv[1], NULL, 16);
421*4882a593Smuzhiyun y = simple_strtoul(argv[2], NULL, 16);
422*4882a593Smuzhiyun rp = argv[3];
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun
425*4882a593Smuzhiyun while (*rp) {
426*4882a593Smuzhiyun char substr[5];
427*4882a593Smuzhiyun
428*4882a593Smuzhiyun memcpy(substr, rp, 4);
429*4882a593Smuzhiyun substr[4] = 0;
430*4882a593Smuzhiyun *wp = simple_strtoul(substr, NULL, 16);
431*4882a593Smuzhiyun
432*4882a593Smuzhiyun rp += 4;
433*4882a593Smuzhiyun wp++;
434*4882a593Smuzhiyun if (wp - buffer > base_width)
435*4882a593Smuzhiyun break;
436*4882a593Smuzhiyun }
437*4882a593Smuzhiyun
438*4882a593Smuzhiyun for (k = 0; k < count; ++k) {
439*4882a593Smuzhiyun unsigned offset =
440*4882a593Smuzhiyun y * base_width + x + k * (wp - buffer);
441*4882a593Smuzhiyun osd_write_videomem(screen, offset, buffer,
442*4882a593Smuzhiyun wp - buffer);
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun
445*4882a593Smuzhiyun OSD_SET_REG(screen, control, 0x0049);
446*4882a593Smuzhiyun }
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun return 0;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
osd_size(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])451*4882a593Smuzhiyun int osd_size(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
452*4882a593Smuzhiyun {
453*4882a593Smuzhiyun unsigned screen;
454*4882a593Smuzhiyun unsigned x;
455*4882a593Smuzhiyun unsigned y;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun if (argc < 3) {
458*4882a593Smuzhiyun cmd_usage(cmdtp);
459*4882a593Smuzhiyun return 1;
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun x = simple_strtoul(argv[1], NULL, 16);
463*4882a593Smuzhiyun y = simple_strtoul(argv[2], NULL, 16);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun if (!x || (x > 64) || (x > MAX_X_CHARS) ||
466*4882a593Smuzhiyun !y || (y > 32) || (y > MAX_Y_CHARS)) {
467*4882a593Smuzhiyun cmd_usage(cmdtp);
468*4882a593Smuzhiyun return 1;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun for (screen = 0; screen < MAX_OSD_SCREEN; ++screen) {
472*4882a593Smuzhiyun if (!(osd_screen_mask & (1 << screen)))
473*4882a593Smuzhiyun continue;
474*4882a593Smuzhiyun
475*4882a593Smuzhiyun OSD_SET_REG(screen, xy_size, ((x - 1) << 8) | (y - 1));
476*4882a593Smuzhiyun OSD_SET_REG(screen, x_pos, 32767 * (640 - 12 * x) / 65535);
477*4882a593Smuzhiyun OSD_SET_REG(screen, y_pos, 32767 * (480 - 18 * y) / 65535);
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun return 0;
481*4882a593Smuzhiyun }
482*4882a593Smuzhiyun
483*4882a593Smuzhiyun U_BOOT_CMD(
484*4882a593Smuzhiyun osdw, 5, 0, osd_write,
485*4882a593Smuzhiyun "write 16-bit hex encoded buffer to osd memory",
486*4882a593Smuzhiyun "pos_x pos_y buffer count\n"
487*4882a593Smuzhiyun );
488*4882a593Smuzhiyun
489*4882a593Smuzhiyun U_BOOT_CMD(
490*4882a593Smuzhiyun osdp, 5, 0, osd_print,
491*4882a593Smuzhiyun "write ASCII buffer to osd memory",
492*4882a593Smuzhiyun "pos_x pos_y color text\n"
493*4882a593Smuzhiyun );
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun U_BOOT_CMD(
496*4882a593Smuzhiyun osdsize, 3, 0, osd_size,
497*4882a593Smuzhiyun "set OSD XY size in characters",
498*4882a593Smuzhiyun "size_x(max. " __stringify(MAX_X_CHARS)
499*4882a593Smuzhiyun ") size_y(max. " __stringify(MAX_Y_CHARS) ")\n"
500*4882a593Smuzhiyun );
501