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