gfx_init.c revision f29dbc25
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  * This file contains routines typically used in driver initialization.
28  *
29  * Routines:
30  *
31  *       gfx_pci_config_read
32  *       gfx_cpu_config_read
33  *       gfx_detect_cpu
34  *       gfx_detect_video
35  *       gfx_get_cpu_register_base
36  *       gfx_get_frame_buffer_base
37  *       gfx_get_frame_buffer_size
38  *       gfx_get_vid_register_base
39  *       gfx_get_vip_register_base
40  * */
41
42/* CONSTANTS USED BY THE INITIALIZATION CODE */
43
44#define PCI_CONFIG_ADDR			         0x0CF8
45#define PCI_CONFIG_DATA			         0x0CFC
46#define PCI_VENDOR_DEVICE_GXM	         0x00011078
47#define PCI_VENDOR_DEVICE_REDCLOUD       0x0028100B
48#define REDCLOUD_VIDEO_PCI_VENDOR_DEVICE 0x0030100B
49
50#define GXM_CONFIG_GCR			0xB8
51#define GXM_CONFIG_CCR3			0xC3
52#define GXM_CONFIG_DIR0			0xFE
53#define GXM_CONFIG_DIR1			0xFF
54
55/* STATIC VARIABLES FOR THIS FILE */
56
57unsigned long gfx_cpu_version = 0;
58unsigned long gfx_cpu_frequency = 0;
59unsigned long gfx_vid_version = 0;
60unsigned long gfx_gx1_scratch_base = 0;
61unsigned long gfx_gx2_scratch_base = 0x7FC000;
62unsigned long gfx_pci_speed_khz = 33300;
63ChipType gfx_chip_revision = CHIP_NOT_DETECTED;
64
65ChipType gfx_detect_chip(void);
66
67/* INCLUDE SUPPORT FOR FIRST GENERATION, IF SPECIFIED. */
68
69#if GFX_INIT_GU1
70#include "init_gu1.c"
71#endif
72
73/* INCLUDE SUPPORT FOR SECOND GENERATION, IF SPECIFIED. */
74
75#if GFX_INIT_GU2
76#include "init_gu2.c"
77#endif
78
79/* THE FOLLOWING ROUTINES ARE NEVER DYNAMIC              */
80/* They are used to set the variables for future dynamic */
81/* function calls.                                       */
82
83/*----------------------------------------------------------------------------
84 * gfx_detect_chip
85 *
86 * This routine returns the name and revision of the chip. This function is
87 * only relevant to the SC1200.
88 *----------------------------------------------------------------------------
89 */
90ChipType
91gfx_detect_chip(void)
92{
93    unsigned char pid = INB(SC1200_CB_BASE_ADDR + SC1200_CB_PID);
94    unsigned char rev = INB(SC1200_CB_BASE_ADDR + SC1200_CB_REV);
95    unsigned short clk = INW(SC1200_CB_BASE_ADDR + SC1200_CB_CCFC);
96
97    gfx_chip_revision = CHIP_NOT_DETECTED;
98
99    if (pid == 0x4) {
100        switch (rev) {
101        case 0:
102            gfx_chip_revision = SC1200_REV_A;
103            break;
104        case 1:
105            gfx_chip_revision = SC1200_REV_B1_B2;
106            break;
107        case 2:
108            gfx_chip_revision = SC1200_REV_B3;
109            break;
110        case 3:
111            gfx_chip_revision = SC1200_REV_C1;
112            break;
113        case 4:
114            gfx_chip_revision = SC1200_REV_D1;
115            break;
116        case 5:
117            gfx_chip_revision = SC1200_REV_D1_1;
118            break;
119        case 6:
120            gfx_chip_revision = SC1200_REV_D2_MVD;
121            break;
122        }
123        if (rev > 0x6)
124            gfx_chip_revision = SC1200_FUTURE_REV;
125    } else if (pid == 0x5) {
126        if (rev == 0x6)
127            gfx_chip_revision = SC1200_REV_D2_MVE;
128        else if (rev > 0x6)
129            gfx_chip_revision = SC1200_FUTURE_REV;
130    }
131
132    switch ((clk >> 8) & 3) {
133    case 0:
134    default:
135        gfx_pci_speed_khz = 33300;
136        break;
137    case 1:
138        gfx_pci_speed_khz = 48000;
139        break;
140    case 2:
141        gfx_pci_speed_khz = 66600;
142        break;
143    }
144
145    return (gfx_chip_revision);
146}
147
148/*----------------------------------------------------------------------------
149 * gfx_detect_cpu
150 *
151 * This routine returns the type and revison of the CPU.  If a Geode
152 * processor is not present, the routine returns zero.
153 *
154 * The return value is as follows:
155 *     bits[24:16] = minor version
156 *     bits[15:8] = major version
157 *     bits[7:0] = type (1 = GXm, 2 = SC1200, 3 = Redcloud)
158 *
159 * A return value of 0x00020501, for example, indicates GXm version 5.2.
160 *----------------------------------------------------------------------------
161 */
162unsigned long
163gfx_detect_cpu(void)
164{
165
166    unsigned long value = 0;
167    unsigned long version = 0;
168
169    /* initialize core freq. to 0 */
170    gfx_cpu_frequency = 0;
171
172#if	GFX_INIT_GU1
173
174    value = gfx_pci_config_read(0x80000000);
175
176    if (value == PCI_VENDOR_DEVICE_GXM) {
177        unsigned char dir0 = gfx_gxm_config_read(GXM_CONFIG_DIR0) & 0xF0;
178        unsigned char dir1 = gfx_gxm_config_read(GXM_CONFIG_DIR1);
179
180        if (dir0 == 0x40) {
181            /* CHECK FOR GXLV (and GXm) (DIR1 = 0x30 THROUGH 0x82) */
182
183            if ((dir1 >= 0x30) && (dir1 <= 0x82)) {
184                /* Major version is one less than what appears in DIR1 */
185                if ((dir1 & 0xF0) < 0x70) {
186
187                    version = GFX_CPU_GXLV | (((((unsigned long)dir1 >> 4) - 1) << 8)) |        /* major - 1 */
188                        ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */
189                } else {
190                    version = GFX_CPU_GXLV | ((((unsigned long)dir1 >> 4))
191                        << 8) |        /* major */
192                        ((((unsigned long)dir1 & 0x0F)) << 16); /* minor */
193                }
194                /* Currently always CS5530 for video overlay. */
195
196#if GFX_VIDEO_DYNAMIC
197                gfx_video_type = GFX_VIDEO_TYPE_CS5530;
198#endif
199
200                /* Currently always CS5530 GPIOs for I2C access. */
201
202#if GFX_I2C_DYNAMIC
203                gfx_i2c_type = GFX_I2C_TYPE_GPIO;
204#endif
205
206#if GFX_TV_DYNAMIC
207                gfx_tv_type = GFX_TV_TYPE_FS451;
208#endif
209            }
210        } else if (dir0 == 0xB0) {
211            /* CHECK FOR SC1200 */
212
213            if ((dir1 == 0x70) || (dir1 == 0x81)) {
214                version = GFX_CPU_SC1200 | ((((unsigned long)dir1 >> 4))
215                    << 8) |            /* major */
216                    ((((unsigned long)dir1 & 0x0F)) << 16);     /* minor */
217
218                /* Detect SC1200 revision */
219
220                gfx_detect_chip();
221
222                /* SC1200 for video overlay and VIP. */
223
224#if GFX_VIDEO_DYNAMIC
225                gfx_video_type = GFX_VIDEO_TYPE_SC1200;
226#endif
227
228#if GFX_VIP_DYNAMIC
229                gfx_vip_type = GFX_VIP_TYPE_SC1200;
230#endif
231
232                /* Currently always SAA7114 decoder. */
233
234#if GFX_DECODER_DYNAMIC
235                gfx_decoder_type = GFX_DECODER_TYPE_SAA7114;
236#endif
237
238                /* SC1200 for TV encoder */
239
240#if GFX_TV_DYNAMIC
241                gfx_tv_type = GFX_TV_TYPE_SC1200;
242#endif
243
244                /* Currently always ACCESS.bus for I2C access. */
245
246#if GFX_I2C_DYNAMIC
247                gfx_i2c_type = GFX_I2C_TYPE_ACCESS;
248#endif
249            }
250        }
251
252        if (version) {
253            /* ALWAYS FIRST GENERATION GRAPHICS UNIT */
254
255#if GFX_DISPLAY_DYNAMIC
256            gfx_display_type = GFX_DISPLAY_TYPE_GU1;
257#endif
258#if GFX_2DACCEL_DYNAMIC
259            gfx_2daccel_type = GFX_2DACCEL_TYPE_GU1;
260#endif
261#if GFX_INIT_DYNAMIC
262            gfx_init_type = GFX_INIT_TYPE_GU1;
263#endif
264
265            /* READ THE CORE FREQUENCY  */
266
267            gfx_cpu_frequency = gfx_get_core_freq();
268        }
269    }
270#endif
271
272#if GFX_INIT_GU2
273
274    value = gfx_pci_config_read(0x80000800);
275
276    if (value == PCI_VENDOR_DEVICE_REDCLOUD) {
277        Q_WORD msr_value;
278        int valid, i;
279
280        /* CHECK FOR SOFT VG */
281        /* If SoftVG is not present, the base addresses for all devices */
282        /* will not be allocated.  Essentially, it is as if no Redcloud */
283        /* video hardware is present.                                   */
284
285        value = gfx_pci_config_read(0x80000900);
286
287        if (value == REDCLOUD_VIDEO_PCI_VENDOR_DEVICE) {
288            valid = 1;
289
290            /* BAR0 - BAR3 HOLD THE PERIPHERAL BASE ADDRESSES */
291
292            for (i = 0; i < 4; i++) {
293                value = gfx_pci_config_read(0x80000910 + (i << 2));
294                if (value == 0x00000000 || value == 0xFFFFFFFF) {
295                    valid = 0;
296                    break;
297                }
298            }
299
300            if (valid) {
301                /* REDCLOUD INTEGRATED VIDEO             */
302
303#if GFX_VIDEO_DYNAMIC
304                gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD;
305#endif
306
307                /* CURRENTLY, ALWAYS GPIO FOR I2C ACCESS */
308
309#if GFX_I2C_DYNAMIC
310                gfx_i2c_type = GFX_I2C_TYPE_GPIO;
311#endif
312
313                /* SECOND-GENERATION DISPLAY CONTROLLER  */
314
315#if GFX_DISPLAY_DYNAMIC
316                gfx_display_type = GFX_DISPLAY_TYPE_GU2;
317#endif
318
319                /* SECOND-GENERATION GRAPHICS UNIT       */
320
321#if GFX_2DACCEL_DYNAMIC
322                gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2;
323#endif
324
325                /* SECOND-GENERATION INITIALIZATION      */
326
327#if GFX_INIT_DYNAMIC
328                gfx_init_type = GFX_INIT_TYPE_GU2;
329#endif
330
331                /* MBUS MSR ACCESSES                     */
332
333#if GFX_MSR_DYNAMIC
334                gfx_msr_type = GFX_MSR_TYPE_REDCLOUD;
335#endif
336
337                /* CS5530 GPIO I2C */
338
339#if GFX_I2C_DYNAMIC
340                gfx_i2c_type = GFX_I2C_TYPE_GPIO;
341#endif
342
343                /* READ VERSION */
344
345                gfx_msr_init();
346
347                gfx_msr_read(RC_ID_MCP, MCP_RC_REVID, &msr_value);
348
349                /* SUBTRACT 1 FROM REV ID                                */
350                /* REDCLOUD 1.X rev id is 1 less than the reported value */
351
352                if ((msr_value.low & 0xF0) == 0x10)
353                    msr_value.low--;
354
355                version = GFX_CPU_REDCLOUD | ((msr_value.low & 0xF0) << 4) |    /* MAJOR */
356                    ((msr_value.low & 0x0F) << 16);     /* MINOR */
357
358                /* READ THE CORE FREQUENCY  */
359				/* I can't find GX implementations that need
360				 * this - we're trying to avoid virtual reads
361				 * anyway, so bail on it
362				 */
363
364				/* gfx_cpu_frequency = gfx_get_core_freq(); */
365
366                /* SET THE GP SCRATCH AREA */
367                /* Color bitmap BLTs use the last 16K of frame buffer space */
368
369                gfx_gx2_scratch_base = gfx_get_frame_buffer_size() - 0x4000;
370            }
371        }
372    }
373
374#endif
375
376    if (!version) {
377        /* ALWAYS SECOND GENERATION IF SIMULATING */
378        /* For now, that is.  This could change.  */
379
380#if GFX_DISPLAY_DYNAMIC
381        gfx_display_type = GFX_DISPLAY_TYPE_GU2;
382#endif
383#if GFX_2DACCEL_DYNAMIC
384        gfx_2daccel_type = GFX_2DACCEL_TYPE_GU2;
385#endif
386#if GFX_INIT_DYNAMIC
387        gfx_init_type = GFX_INIT_TYPE_GU2;
388#endif
389#if GFX_MSR_DYNAMIC
390        gfx_msr_type = GFX_MSR_TYPE_REDCLOUD;
391#endif
392#if GFX_VIDEO_DYNAMIC
393        gfx_video_type = GFX_VIDEO_TYPE_REDCLOUD;
394#endif
395#if GFX_I2C_DYNAMIC
396        gfx_i2c_type = GFX_I2C_TYPE_GPIO;
397#endif
398    }
399    gfx_cpu_version = version;
400
401    return (version);
402}
403
404/*----------------------------------------------------------------------------
405 * gfx_detect_video
406 *
407 * This routine returns the type of the video hardware.
408 *
409 * The return value is as follows:
410 *     bits[7:0] = type (1 = CS5530, 2 = SC1200, 3 = Redcloud)
411 *
412 * Currently this routine does not actually detect any hardware, and bases
413 * the video hardware entirely on the detected CPU.
414 *----------------------------------------------------------------------------
415 */
416unsigned long
417gfx_detect_video(void)
418{
419    unsigned long version = 0;
420
421    if ((gfx_cpu_version & 0xFF) == GFX_CPU_GXLV)
422        version = GFX_VID_CS5530;
423    else if ((gfx_cpu_version & 0xFF) == GFX_CPU_SC1200)
424        version = GFX_VID_SC1200;
425    else if ((gfx_cpu_version & 0xFF) == GFX_CPU_REDCLOUD)
426        version = GFX_VID_REDCLOUD;
427    gfx_vid_version = version;
428    return (version);
429}
430
431/*----------------------------------------------------------------------------
432 * gfx_pci_config_read
433 *
434 * This routine reads a 32-bit value from the specified location in PCI
435 * configuration space.
436 *----------------------------------------------------------------------------
437 */
438unsigned long
439gfx_pci_config_read(unsigned long address)
440{
441    unsigned long value = 0xFFFFFFFF;
442
443    OUTD(PCI_CONFIG_ADDR, address);
444    value = IND(PCI_CONFIG_DATA);
445    return (value);
446}
447
448/*----------------------------------------------------------------------------
449 * gfx_pci_config_write
450 *
451 * This routine writes a 32-bit value to the specified location in PCI
452 * configuration space.
453 *----------------------------------------------------------------------------
454 */
455void
456gfx_pci_config_write(unsigned long address, unsigned long data)
457{
458    OUTD(PCI_CONFIG_ADDR, address);
459    OUTD(PCI_CONFIG_DATA, data);
460    return;
461}
462
463/* WRAPPERS IF DYNAMIC SELECTION */
464/* Extra layer to call either first or second generation routines. */
465
466#if GFX_INIT_DYNAMIC
467
468/*----------------------------------------------------------------------------
469 * gfx_get_core_freq
470 *----------------------------------------------------------------------------
471 */
472unsigned long
473gfx_get_core_freq(void)
474{
475    unsigned long freq = 0;
476
477#if GFX_INIT_GU1
478    if (gfx_init_type & GFX_INIT_TYPE_GU1)
479        freq = gu1_get_core_freq();
480#endif
481#if GFX_INIT_GU2
482    if (gfx_init_type & GFX_INIT_TYPE_GU2)
483        freq = gu2_get_core_freq();
484#endif
485
486    return freq;
487}
488
489/*----------------------------------------------------------------------------
490 * gfx_get_cpu_register_base
491 *----------------------------------------------------------------------------
492 */
493unsigned long
494gfx_get_cpu_register_base(void)
495{
496    unsigned long base = 0;
497
498#if GFX_INIT_GU1
499    if (gfx_init_type & GFX_INIT_TYPE_GU1)
500        base = gu1_get_cpu_register_base();
501#endif
502#if GFX_INIT_GU2
503    if (gfx_init_type & GFX_INIT_TYPE_GU2)
504        base = gu2_get_cpu_register_base();
505#endif
506
507    return (base);
508}
509
510/*----------------------------------------------------------------------------
511 * gfx_get_graphics_register_base
512 *----------------------------------------------------------------------------
513 */
514unsigned long
515gfx_get_graphics_register_base(void)
516{
517    unsigned long base = 0;
518
519#if GFX_INIT_GU2
520    if (gfx_init_type & GFX_INIT_TYPE_GU2)
521        base = gu2_get_graphics_register_base();
522#endif
523
524    return (base);
525}
526
527/*----------------------------------------------------------------------------
528 * gfx_get_frame_buffer_base
529 *----------------------------------------------------------------------------
530 */
531unsigned long
532gfx_get_frame_buffer_base(void)
533{
534    unsigned long base = 0;
535
536#if GFX_INIT_GU1
537    if (gfx_init_type & GFX_INIT_TYPE_GU1)
538        base = gu1_get_frame_buffer_base();
539#endif
540#if GFX_INIT_GU2
541    if (gfx_init_type & GFX_INIT_TYPE_GU2)
542        base = gu2_get_frame_buffer_base();
543#endif
544
545    return (base);
546}
547
548/*----------------------------------------------------------------------------
549 * gfx_get_frame_buffer_size
550 *----------------------------------------------------------------------------
551 */
552unsigned long
553gfx_get_frame_buffer_size(void)
554{
555    unsigned long size = 0;
556
557#if GFX_INIT_GU1
558    if (gfx_init_type & GFX_INIT_TYPE_GU1)
559        size = gu1_get_frame_buffer_size();
560#endif
561#if GFX_INIT_GU2
562    if (gfx_init_type & GFX_INIT_TYPE_GU2)
563        size = gu2_get_frame_buffer_size();
564#endif
565
566    return size;
567}
568
569/*----------------------------------------------------------------------------
570 * gfx_get_vid_register_base
571 *----------------------------------------------------------------------------
572 */
573unsigned long
574gfx_get_vid_register_base(void)
575{
576    unsigned long base = 0;
577
578#if GFX_INIT_GU1
579    if (gfx_init_type & GFX_INIT_TYPE_GU1)
580        base = gu1_get_vid_register_base();
581#endif
582#if GFX_INIT_GU2
583    if (gfx_init_type & GFX_INIT_TYPE_GU2)
584        base = gu2_get_vid_register_base();
585#endif
586
587    return (base);
588}
589
590/*----------------------------------------------------------------------------
591 * gfx_get_vip_register_base
592 *----------------------------------------------------------------------------
593 */
594unsigned long
595gfx_get_vip_register_base(void)
596{
597    unsigned long base = 0;
598
599#if GFX_INIT_GU1
600    if (gfx_init_type & GFX_INIT_TYPE_GU1)
601        base = gu1_get_vip_register_base();
602#endif
603
604    return (base);
605}
606
607#endif
608
609/* END OF FILE */
610