dora9211.c revision 04007eba
1/* Copyright (c) 2005 Advanced Micro Devices, Inc.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 *
21 * Neither the name of the Advanced Micro Devices, Inc. nor the names of its
22 * contributors may be used to endorse or promote products derived from this
23 * software without specific prior written permission.
24 * */
25
26/*
27 * File Contents:   This file contains the panel functions to interface
28 *                  the dorado platform.
29 *
30 * SubModule:       Geode FlatPanel library
31 * */
32
33#include "dora9211.h"
34
35void
36Dorado_Get_9211_Details(unsigned long flags, Pnl_PanelParams * pParam)
37{
38    unsigned long DPanelType;
39    int i;
40
41    for (i = 0; i < 0x7fff; i++) {
42    }
43
44    Dorado9211GpioInit();
45
46    for (i = 0; i < 5; i++)
47        toggle_Centaurus_9211_clock();
48
49    if (flags & PNL_PANELCHIP) {
50        DPanelType = Dorado9211ReadReg(0x430);
51
52        if ((DPanelType & 0xFFFF0000) == 0x92110000) {  /* found 9211 */
53            /* check the values for revision ID */
54            if (DPanelType >= 0x92110301)
55                pParam->PanelChip = PNL_9211_C;
56            else if ((DPanelType >= 0x92110101) && (DPanelType < 0x92110301))
57                pParam->PanelChip = PNL_9211_A;
58            else
59                pParam->PanelChip = PNL_UNKNOWN_CHIP;
60        }
61        else {                  /* no 9211 present */
62            pParam->PanelChip = PNL_UNKNOWN_CHIP;
63        }
64    }
65
66    if ((pParam->PanelChip != PNL_UNKNOWN_CHIP) && (flags & PNL_PANELSTAT)) {
67        unsigned long PanelTypeOrg;
68        unsigned char Panel_2Byte;
69
70        DPanelType = Dorado9211ReadReg(0x438);
71        DPanelType &= 0x00e8e8e8;
72        DPanelType |= 0x00170000;
73        Dorado9211WriteReg(0x438, DPanelType);
74        DPanelType = 0;
75
76        DPanelType = Dorado9211ReadReg(0x434);
77        DPanelType = (DPanelType >> (DRD_LCDRESGPIO1 + 1));
78        PanelTypeOrg = DPanelType >> 8;
79        Panel_2Byte = (unsigned char) PanelTypeOrg;
80        Panel_2Byte = (Panel_2Byte >> (DRD_LCDRESGPIO2 - DRD_LCDRESGPIO1 - 1));
81        DPanelType = (DPanelType | ((unsigned int) Panel_2Byte << 8));
82        DPanelType = DPanelType >> 1;
83        PanelTypeOrg = DPanelType >> 8;
84        Panel_2Byte = (unsigned char) PanelTypeOrg;
85        Panel_2Byte = (Panel_2Byte >> (DRD_LCDRESGPIO3 - DRD_LCDRESGPIO2 - 1));
86        DPanelType = (DPanelType | ((unsigned int) Panel_2Byte << 8));
87        DPanelType = DPanelType >> 1;
88        PanelTypeOrg = DPanelType >> 8;
89        Panel_2Byte = (unsigned char) PanelTypeOrg;
90        Panel_2Byte = (Panel_2Byte >> (DRD_LCDRESGPIO4 - DRD_LCDRESGPIO3 - 1));
91        DPanelType = (DPanelType | ((unsigned int) Panel_2Byte << 8));
92        DPanelType = DPanelType >> 5;
93        DPanelType &= 0xf;
94
95        switch (DPanelType) {
96        case 8:
97            pParam->PanelStat.XRes = 800;
98            pParam->PanelStat.YRes = 600;
99            pParam->PanelStat.Depth = 18;
100            pParam->PanelStat.MonoColor = PNL_COLOR_PANEL;
101            pParam->PanelStat.Type = PNL_TFT;
102            break;
103
104        case 9:
105            pParam->PanelStat.XRes = 640;
106            pParam->PanelStat.YRes = 480;
107            pParam->PanelStat.Depth = 8;
108            pParam->PanelStat.MonoColor = PNL_COLOR_PANEL;
109            pParam->PanelStat.Type = PNL_SSTN;
110            break;
111
112        case 10:
113            pParam->PanelStat.XRes = 1024;
114            pParam->PanelStat.YRes = 768;
115            pParam->PanelStat.Depth = 18;
116            pParam->PanelStat.MonoColor = PNL_COLOR_PANEL;
117            pParam->PanelStat.Type = PNL_TFT;
118            break;
119        case 0:
120        case 1:
121        case 2:
122        case 3:
123        case 4:
124        case 5:
125        case 6:
126        case 7:
127        case 11:
128            pParam->PanelStat.XRes = 640;
129            pParam->PanelStat.YRes = 480;
130            pParam->PanelStat.Depth = 16;
131            pParam->PanelStat.MonoColor = PNL_COLOR_PANEL;
132            pParam->PanelStat.Type = PNL_DSTN;
133            break;
134        case 12:
135            pParam->PanelStat.XRes = 640;
136            pParam->PanelStat.YRes = 480;
137            pParam->PanelStat.Depth = 18;
138            pParam->PanelStat.MonoColor = PNL_COLOR_PANEL;
139            pParam->PanelStat.Type = PNL_TFT;
140            break;
141        case 13:
142            pParam->PanelStat.XRes = 1024;
143            pParam->PanelStat.YRes = 768;
144            pParam->PanelStat.Depth = 24;
145            pParam->PanelStat.MonoColor = PNL_COLOR_PANEL;
146            pParam->PanelStat.Type = PNL_DSTN;
147            break;
148        case 14:
149            pParam->PanelStat.XRes = 640;
150            pParam->PanelStat.YRes = 480;
151            pParam->PanelStat.Depth = 8;
152            pParam->PanelStat.MonoColor = PNL_MONO_PANEL;
153            pParam->PanelStat.Type = PNL_DSTN;
154            break;
155        case 15:
156            pParam->PanelStat.XRes = 800;
157            pParam->PanelStat.YRes = 600;
158            pParam->PanelStat.Depth = 16;
159            pParam->PanelStat.MonoColor = PNL_COLOR_PANEL;
160            pParam->PanelStat.Type = PNL_DSTN;
161            break;
162        default:
163            break;
164        }
165    }
166    /* if block end */
167}
168
169void
170Dorado9211Init(Pnl_PanelStat * pstat)
171{
172    int mode;
173    unsigned long orig_value, pm_value;
174
175    gfx_delay_milliseconds(100);
176    Dorado9211GpioInit();
177
178    Dorado9211ToggleClock();
179    Dorado9211ToggleClock();
180    Dorado9211ToggleClock();
181    Dorado9211ToggleClock();
182    Dorado9211ToggleClock();
183
184    gfx_delay_milliseconds(100);
185
186    Dorado9211ToggleClock();
187    Dorado9211ToggleClock();
188    Dorado9211ToggleClock();
189    Dorado9211ToggleClock();
190    Dorado9211ToggleClock();
191
192    Dorado9211WriteReg(CS92xx_LCD_PWR_MAN, 0x0);
193
194    gfx_delay_milliseconds(100);
195    gfx_delay_milliseconds(100);
196
197    /* LOOP THROUGH THE AVAILABLE MODES TO FIND A MATCH */
198    for (mode = 0; mode < NUM_92XX_MODES; mode++) {
199        if ((FPModeParams[mode].xres == pstat->XRes) &&
200            (FPModeParams[mode].yres == pstat->YRes) &&
201            (FPModeParams[mode].bpp == pstat->Depth) &&
202            (FPModeParams[mode].panel_type == pstat->Type) &&
203            (FPModeParams[mode].color_type == pstat->MonoColor)) {
204
205            /* SET THE 92xx FOR THE SELECTED MODE */
206            CS92xx_MODE *pMode = &FPModeParams[mode];
207
208            Dorado9211WriteReg(CS92xx_LCD_PAN_TIMING1, pMode->panel_timing1);
209            Dorado9211WriteReg(CS92xx_LCD_PAN_TIMING2, pMode->panel_timing2);
210            Dorado9211WriteReg(CS92xx_LCD_DITH_FR_CNTRL,
211                               pMode->rev_C_dither_frc);
212            Dorado9211WriteReg(CS92xx_BLUE_LSFR_SEED, pMode->blue_lsfr_seed);
213            Dorado9211WriteReg(CS92xx_RED_GREEN_LSFR_SEED,
214                               pMode->red_green_lsfr_seed);
215            DoradoProgramFRMload();
216            Dorado9211WriteReg(CS92xx_LCD_MEM_CNTRL, pMode->memory_control);
217            Dorado9211WriteReg(CS92xx_LCD_PWR_MAN, pMode->power_management);
218            gfx_delay_milliseconds(100);
219            gfx_delay_milliseconds(100);
220            Dorado9211ClearCS();
221
222            /* This code is added to take care of Panel initialization.
223             * Irrespective of Xpressrom is enabling the panel or not.
224             */
225            orig_value = READ_VID32(0X04);
226            WRITE_VID32(0x04, 0x00200141);
227            gfx_delay_milliseconds(21);
228            pm_value = gfx_ind(0x9030);
229
230            pm_value |= 0x400;
231            gfx_outd(0x9030, pm_value);
232            gfx_delay_milliseconds(4);
233            orig_value &= 0xfff1ffff;
234            WRITE_VID32(0X4, orig_value);
235            return;
236        }                       /*end if() */
237    }                           /*end for() */
238
239}
240
241void
242Dorado9211SetCS(void)
243{
244    unsigned long value;
245
246    value = gfx_ind(DRD_CSP9211IN);
247    gfx_outd(DRD_CSP9211OUT, value | DRD_CS9211);
248}
249
250void
251Dorado9211ClearCS(void)
252{
253    unsigned long value;
254
255    value = gfx_ind(DRD_CSP9211IN);
256    gfx_outd(DRD_CSP9211OUT, value & (~DRD_CS9211));
257}
258
259void
260Dorado9211SetDataOut(void)
261{
262    unsigned long value;
263
264    value = gfx_ind(DRD_DATAOUTP9211IN);
265    gfx_outd(DRD_DATAOUTP9211OUT, value | DRD_DATAIN9211);
266}
267
268void
269Dorado9211ClearDataOut(void)
270{
271    unsigned long value;
272
273    value = gfx_ind(DRD_DATAOUTP9211IN);
274    gfx_outd(DRD_DATAOUTP9211OUT, value & (~DRD_DATAIN9211));
275}
276
277unsigned char
278Dorado9211ReadDataIn(void)
279{
280    unsigned char readdata = 0;
281    unsigned long value;
282
283    /* why to read 4 times ??? */
284    value = gfx_ind(DRD_DATAINP9211IN);
285    value = gfx_ind(DRD_DATAINP9211IN);
286    value = gfx_ind(DRD_DATAINP9211IN);
287    value = gfx_ind(DRD_DATAINP9211IN);
288    if (value & DRD_DATAOUT9211)
289        readdata = 1;
290    return (readdata);
291}
292
293void
294Dorado9211ToggleClock(void)
295{
296    Dorado9211SetClock();
297    Dorado9211ClearClock();
298}
299
300void
301Dorado9211SetClock(void)
302{
303    unsigned long value;
304
305    value = gfx_ind(DRD_CLOCKP9211IN);
306    gfx_outd(DRD_CLOCKP9211OUT, value | DRD_CLOCK9211);
307}
308
309void
310Dorado9211ClearClock(void)
311{
312    unsigned long value;
313
314    value = gfx_ind(DRD_CLOCKP9211IN);
315    gfx_outd(DRD_CLOCKP9211OUT, value & (~DRD_CLOCK9211));
316}
317
318void
319Dorado9211GpioInit(void)
320{
321    unsigned long value;
322
323    /* set output enable on gpio 7, 9, 11 */
324    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_SEL), DRD_CLOCK9211CFG);
325    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_CFG), 3);
326    /* set output enable on gpio 7, 9, 11 */
327    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_SEL), DRD_CS9211CFG);
328    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_CFG), 3);
329    /* set output enable on gpio 7, 9, 18 */
330    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_SEL), DRD_DATAIN9211CFG);
331    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_CFG), 3);
332    /* disable on gpio 11 - This is the output from the 9211 */
333    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_SEL), DRD_DATAOUT9211CFG);
334    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPPIN_CFG), 0);
335    /* Set all PINS low */
336    value = gfx_ind(DRD_GEODE_GPIO_BASE + DRD_GEODE_GPDI0);
337    value &= ~(DRD_CS9211 | DRD_CLOCK9211 | DRD_DATAIN9211);
338    gfx_outd((DRD_GEODE_GPIO_BASE + DRD_GEODE_GPDO0), value);
339}
340
341unsigned long
342Dorado9211ReadReg(unsigned short index)
343{
344
345    unsigned char i, readbit;
346    unsigned long data;
347
348    Dorado9211ClearDataOut();
349
350    Dorado9211SetCS();
351    Dorado9211ToggleClock();
352
353    Dorado9211SetDataOut();
354    Dorado9211ToggleClock();
355
356    for (i = 0; i < 12; i++) {
357        if (index & 0x1) {
358            Dorado9211SetDataOut();
359        }
360        else {
361            Dorado9211ClearDataOut();
362        }
363        Dorado9211ToggleClock();
364        index >>= 1;
365    }
366
367    Dorado9211ClearDataOut();
368    Dorado9211ToggleClock();
369
370    /* Idle clock, 7 clocks, no data set */
371
372    Dorado9211ToggleClock();
373    Dorado9211ToggleClock();
374    Dorado9211ToggleClock();
375    Dorado9211ToggleClock();
376    Dorado9211ToggleClock();
377    Dorado9211ToggleClock();
378    Dorado9211ToggleClock();
379
380    data = 0;
381    for (i = 0; i < 32; i++) {
382        Dorado9211ToggleClock();
383        readbit = Dorado9211ReadDataIn();
384        data |= (((unsigned long) readbit) << i);
385    }
386
387    Dorado9211ClearCS();
388    Dorado9211ToggleClock();
389    return (data);
390
391}
392
393void
394Dorado9211WriteReg(unsigned short index, unsigned long data)
395{
396
397    unsigned char i;
398
399    Dorado9211ClearDataOut();
400    Dorado9211SetDataOut();
401    Dorado9211SetCS();
402    Dorado9211ToggleClock();
403    Dorado9211SetDataOut();
404    Dorado9211ToggleClock();
405
406    for (i = 0; i < 12; i++) {
407        if (index & 0x1) {
408            Dorado9211SetDataOut();
409        }
410        else {
411            Dorado9211ClearDataOut();
412        }
413        Dorado9211ToggleClock();
414        index >>= 1;
415    }
416
417    Dorado9211SetDataOut();
418    Dorado9211ToggleClock();
419
420    for (i = 0; i < 32; i++) {
421        if (data & 0x1) {
422            Dorado9211SetDataOut();
423        }
424        else {
425            Dorado9211ClearDataOut();
426        }
427        Dorado9211ToggleClock();
428        data >>= 1;
429    }
430
431    Dorado9211ClearCS();
432
433    Dorado9211ToggleClock();
434    Dorado9211ToggleClock();
435    Dorado9211ToggleClock();
436    Dorado9211ToggleClock();
437}
438
439void
440DoradoProgramFRMload(void)
441{
442    unsigned long DoradoFRMtable[] = {
443
444        0x00000000,
445        0x00000000,
446        0x01000100,
447        0x01000100,
448        0x01010101,
449        0x01010101,
450        0x02081041,
451        0x02081041,
452        0x10111111,
453        0x11111101,
454        0x49249241,
455        0x12412492,
456        0x92244891,
457        0x92244891,
458        0x22252525,
459        0x22252525,
460        0x528294a5,
461        0x2528494a,
462        0x294a5295,
463        0x294a5295,
464        0x54a54a95,
465        0x2952a52a,
466        0x2a552a55,
467        0x2a552a55,
468        0x554aa955,
469        0x2a9552aa,
470        0x2aaa5555,
471        0x2aaa5555,
472        0x55555555,
473        0x2aaaaaaa,
474        0x55555555,
475        0x55555555,
476        0xaaaaaaab,
477        0x55555555,
478        0x5555aaab,
479        0x5555aaab,
480        0xaab556ab,
481        0x556aad55,
482        0x55ab55ab,
483        0x55ab55ab,
484        0xab5ab56b,
485        0x56ad5ad5,
486        0x56b5ad6b,
487        0x56b5ad6b,
488        0xad6d6b5b,
489        0x5ad6b6b6,
490        0x5b5b5b5b,
491        0x5b5b5b5b,
492        0x5F6db6db,
493        0x5F6db6db,
494        0xF776F776,
495        0xF776F776,
496        0xFBDEFBDE,
497        0xFBDEFBDE,
498        0x7eFFBFF7,
499        0x7eFFBFF7,
500        0xFF7FF7F7,
501        0xFF7FF7F7,
502        0xFF7FFF7F,
503        0xFF7FFF7F,
504        0xFFF7FFFF,
505        0xFFF7FFFF,
506        0xFFFFFFFF,
507        0xFFFFFFFF,
508    };
509
510    unsigned char i;
511    unsigned short index;
512    unsigned long data;
513
514    Dorado9211WriteReg(CS92xx_FRM_MEMORY_INDEX, 0);
515    index = CS92xx_FRM_MEMORY_DATA;
516    for (i = 0; i < 64; i += 2) {
517        data = DoradoFRMtable[i];
518        Dorado9211WriteReg(index, data);
519        data = DoradoFRMtable[i + 1];
520        Dorado9211WriteReg(index, data);
521    }
522
523/*
524 * The first FRM location (64 bits) does not program correctly.
525 * This location always reads back with the last value programmed.
526 * ie. If 32 64-bit values are programmed, location 0 reads back as the 32nd
527 * If 30 locations are programmed, location 0 reads back as the 30th, etc.
528 * Fix this by re-writing location 0 after programming all 64 in the writeFRM
529 * loop in RevCFrmload() in CS9211.
530 */
531
532    Dorado9211WriteReg(CS92xx_FRM_MEMORY_INDEX, 0);
533    Dorado9211WriteReg(CS92xx_FRM_MEMORY_DATA, 0);
534    Dorado9211WriteReg(CS92xx_FRM_MEMORY_DATA, 0);
535
536}
537
538/*****************************************************************************
539 * void Dorado_Enable_Power((void);
540 * Enables the power of the CX9211 on Dorado board.
541 *****************************************************************************
542 */
543
544void
545Dorado_Power_Up(void)
546{
547    Dorado9211WriteReg(CS92xx_LCD_PWR_MAN, 0x01000000);
548    return;
549
550}                               /* disable_Centaurus_Power */
551
552/*****************************************************************************
553 * void Dorado_Disable_Power((void);
554 * Disables the power of the CX9211 on Dorado board.
555 *****************************************************************************
556 */
557
558void
559Dorado_Power_Down(void)
560{
561    Dorado9211WriteReg(CS92xx_LCD_PWR_MAN, 0x0);
562    return;
563
564}                               /* disable_Centaurus_Power */
565
566void
567Dorado_Save_Panel_State(void)
568{
569
570    /* set 9211 registers using the desired panel settings     */
571    cs9211_regs.panel_timing1 = Dorado9211ReadReg(CS92xx_LCD_PAN_TIMING1);
572    cs9211_regs.panel_timing2 = Dorado9211ReadReg(CS92xx_LCD_PAN_TIMING2);
573
574    cs9211_regs.dither_frc_ctrl = Dorado9211ReadReg(CS92xx_LCD_DITH_FR_CNTRL);
575    cs9211_regs.blue_lsfr_seed = Dorado9211ReadReg(CS92xx_BLUE_LSFR_SEED);
576    cs9211_regs.red_green_lsfr_seed =
577        Dorado9211ReadReg(CS92xx_RED_GREEN_LSFR_SEED);
578
579    /* CentaurusProgramFRMload(); */
580    cs9211_regs.memory_control = Dorado9211ReadReg(CS92xx_LCD_MEM_CNTRL);
581
582    /* Set the power register last. This will turn the panel on at the 9211 */
583    cs9211_regs.power_management = Dorado9211ReadReg(CS92xx_LCD_PWR_MAN);
584    cs9211_regs.panel_state = cs9211_regs.power_management;
585}
586
587void
588Dorado_Restore_Panel_State(void)
589{
590    unsigned long off_data = 0;
591
592    /* Before restoring the 9211 registers, power off the 9211. */
593
594    Dorado9211WriteReg(CS92xx_LCD_PWR_MAN, off_data);
595
596    /* set 9211 registers using the desired panel settings    */
597    Dorado9211WriteReg(CS92xx_LCD_PAN_TIMING1, cs9211_regs.panel_timing1);
598    Dorado9211WriteReg(CS92xx_LCD_PAN_TIMING2, cs9211_regs.panel_timing2);
599    /* load the LSFR seeds */
600    Dorado9211WriteReg(CS92xx_LCD_DITH_FR_CNTRL, cs9211_regs.dither_frc_ctrl);
601    Dorado9211WriteReg(CS92xx_BLUE_LSFR_SEED, cs9211_regs.blue_lsfr_seed);
602    Dorado9211WriteReg(CS92xx_RED_GREEN_LSFR_SEED,
603                       cs9211_regs.red_green_lsfr_seed);
604
605    Dorado9211WriteReg(CS92xx_LCD_MEM_CNTRL, cs9211_regs.memory_control);
606    /* Set the power register last. This will turn the panel on at the 9211 */
607    Dorado9211WriteReg(CS92xx_LCD_PWR_MAN, cs9211_regs.power_management);
608}
609