uboot/drivers/video/ati_radeon_fb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * ATI Radeon Video card Framebuffer driver.
   4 *
   5 * Copyright 2007 Freescale Semiconductor, Inc.
   6 * Zhang Wei <wei.zhang@freescale.com>
   7 * Jason Jin <jason.jin@freescale.com>
   8 *
   9 * Some codes of this file is partly ported from Linux kernel
  10 * ATI video framebuffer driver.
  11 *
  12 * Now the driver is tested on below ATI chips:
  13 *   9200
  14 *   X300
  15 *   X700
  16 */
  17
  18#include <common.h>
  19#include <linux/delay.h>
  20
  21#include <command.h>
  22#include <bios_emul.h>
  23#include <env.h>
  24#include <pci.h>
  25#include <asm/processor.h>
  26#include <linux/errno.h>
  27#include <asm/io.h>
  28#include <malloc.h>
  29#include <video_fb.h>
  30#include "videomodes.h"
  31
  32#include <radeon.h>
  33#include "ati_ids.h"
  34#include "ati_radeon_fb.h"
  35
  36#undef DEBUG
  37
  38#ifdef DEBUG
  39#define DPRINT(x...) printf(x)
  40#else
  41#define DPRINT(x...) do{}while(0)
  42#endif
  43
  44#define MAX_MAPPED_VRAM (2048*2048*4)
  45#define MIN_MAPPED_VRAM (1024*768*1)
  46
  47#define RADEON_BUFFER_ALIGN             0x00000fff
  48#define SURF_UPPER_BOUND(x,y,bpp)       (((((x) * (((y) + 15) & ~15) * (bpp)/8) + RADEON_BUFFER_ALIGN) \
  49                                          & ~RADEON_BUFFER_ALIGN) - 1)
  50#define RADEON_CRT_PITCH(width, bpp)    ((((width) * (bpp) + ((bpp) * 8 - 1)) / ((bpp) * 8)) | \
  51                                         ((((width) * (bpp) + ((bpp) * 8 - 1)) / ((bpp) * 8)) << 16))
  52
  53#define CRTC_H_TOTAL_DISP_VAL(htotal, hdisp) \
  54                (((((htotal) / 8) - 1) & 0x3ff) | (((((hdisp) / 8) - 1) & 0x1ff) << 16))
  55#define CRTC_HSYNC_STRT_WID_VAL(hsync_srtr, hsync_wid) \
  56                (((hsync_srtr) & 0x1fff) | (((hsync_wid) & 0x3f) << 16))
  57#define CRTC_V_TOTAL_DISP_VAL(vtotal, vdisp) \
  58                ((((vtotal) - 1) & 0xffff) | (((vdisp) - 1) << 16))
  59#define CRTC_VSYNC_STRT_WID_VAL(vsync_srtr, vsync_wid) \
  60                ((((vsync_srtr) - 1) & 0xfff) | (((vsync_wid) & 0x1f) << 16))
  61
  62/*#define PCI_VENDOR_ID_ATI*/
  63#define PCI_CHIP_RV280_5960             0x5960
  64#define PCI_CHIP_RV280_5961             0x5961
  65#define PCI_CHIP_RV280_5962             0x5962
  66#define PCI_CHIP_RV280_5964             0x5964
  67#define PCI_CHIP_RV280_5C63             0x5C63
  68#define PCI_CHIP_RV370_5B60             0x5B60
  69#define PCI_CHIP_RV380_5657             0x5657
  70#define PCI_CHIP_R420_554d              0x554d
  71
  72static struct pci_device_id ati_radeon_pci_ids[] = {
  73        {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5960},
  74        {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5961},
  75        {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5962},
  76        {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5964},
  77        {PCI_VENDOR_ID_ATI, PCI_CHIP_RV280_5C63},
  78        {PCI_VENDOR_ID_ATI, PCI_CHIP_RV370_5B60},
  79        {PCI_VENDOR_ID_ATI, PCI_CHIP_RV380_5657},
  80        {PCI_VENDOR_ID_ATI, PCI_CHIP_R420_554d},
  81        {0, 0}
  82};
  83
  84static u16 ati_radeon_id_family_table[][2] = {
  85        {PCI_CHIP_RV280_5960, CHIP_FAMILY_RV280},
  86        {PCI_CHIP_RV280_5961, CHIP_FAMILY_RV280},
  87        {PCI_CHIP_RV280_5962, CHIP_FAMILY_RV280},
  88        {PCI_CHIP_RV280_5964, CHIP_FAMILY_RV280},
  89        {PCI_CHIP_RV280_5C63, CHIP_FAMILY_RV280},
  90        {PCI_CHIP_RV370_5B60, CHIP_FAMILY_RV380},
  91        {PCI_CHIP_RV380_5657, CHIP_FAMILY_RV380},
  92        {PCI_CHIP_R420_554d,  CHIP_FAMILY_R420},
  93        {0, 0}
  94};
  95
  96u16 get_radeon_id_family(u16 device)
  97{
  98        int i;
  99        for (i=0; ati_radeon_id_family_table[0][i]; i+=2)
 100                if (ati_radeon_id_family_table[0][i] == device)
 101                        return ati_radeon_id_family_table[0][i + 1];
 102        return 0;
 103}
 104
 105struct radeonfb_info *rinfo;
 106
 107static void radeon_identify_vram(struct radeonfb_info *rinfo)
 108{
 109        u32 tmp;
 110
 111        /* framebuffer size */
 112        if ((rinfo->family == CHIP_FAMILY_RS100) ||
 113                (rinfo->family == CHIP_FAMILY_RS200) ||
 114                (rinfo->family == CHIP_FAMILY_RS300)) {
 115                u32 tom = INREG(NB_TOM);
 116                tmp = ((((tom >> 16) - (tom & 0xffff) + 1) << 6) * 1024);
 117
 118                radeon_fifo_wait(6);
 119                OUTREG(MC_FB_LOCATION, tom);
 120                OUTREG(DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
 121                OUTREG(CRTC2_DISPLAY_BASE_ADDR, (tom & 0xffff) << 16);
 122                OUTREG(OV0_BASE_ADDR, (tom & 0xffff) << 16);
 123
 124                /* This is supposed to fix the crtc2 noise problem. */
 125                OUTREG(GRPH2_BUFFER_CNTL, INREG(GRPH2_BUFFER_CNTL) & ~0x7f0000);
 126
 127                if ((rinfo->family == CHIP_FAMILY_RS100) ||
 128                        (rinfo->family == CHIP_FAMILY_RS200)) {
 129                /* This is to workaround the asic bug for RMX, some versions
 130                   of BIOS dosen't have this register initialized correctly.
 131                */
 132                        OUTREGP(CRTC_MORE_CNTL, CRTC_H_CUTOFF_ACTIVE_EN,
 133                                ~CRTC_H_CUTOFF_ACTIVE_EN);
 134                }
 135        } else {
 136                tmp = INREG(CONFIG_MEMSIZE);
 137        }
 138
 139        /* mem size is bits [28:0], mask off the rest */
 140        rinfo->video_ram = tmp & CONFIG_MEMSIZE_MASK;
 141
 142        /*
 143         * Hack to get around some busted production M6's
 144         * reporting no ram
 145         */
 146        if (rinfo->video_ram == 0) {
 147                switch (rinfo->pdev.device) {
 148                case PCI_CHIP_RADEON_LY:
 149                case PCI_CHIP_RADEON_LZ:
 150                        rinfo->video_ram = 8192 * 1024;
 151                        break;
 152                default:
 153                        break;
 154                }
 155        }
 156
 157        /*
 158         * Now try to identify VRAM type
 159         */
 160        if ((rinfo->family >= CHIP_FAMILY_R300) ||
 161            (INREG(MEM_SDRAM_MODE_REG) & (1<<30)))
 162                rinfo->vram_ddr = 1;
 163        else
 164                rinfo->vram_ddr = 0;
 165
 166        tmp = INREG(MEM_CNTL);
 167        if (IS_R300_VARIANT(rinfo)) {
 168                tmp &=  R300_MEM_NUM_CHANNELS_MASK;
 169                switch (tmp) {
 170                case 0:  rinfo->vram_width = 64; break;
 171                case 1:  rinfo->vram_width = 128; break;
 172                case 2:  rinfo->vram_width = 256; break;
 173                default: rinfo->vram_width = 128; break;
 174                }
 175        } else if ((rinfo->family == CHIP_FAMILY_RV100) ||
 176                   (rinfo->family == CHIP_FAMILY_RS100) ||
 177                   (rinfo->family == CHIP_FAMILY_RS200)){
 178                if (tmp & RV100_MEM_HALF_MODE)
 179                        rinfo->vram_width = 32;
 180                else
 181                        rinfo->vram_width = 64;
 182        } else {
 183                if (tmp & MEM_NUM_CHANNELS_MASK)
 184                        rinfo->vram_width = 128;
 185                else
 186                        rinfo->vram_width = 64;
 187        }
 188
 189        /* This may not be correct, as some cards can have half of channel disabled
 190         * ToDo: identify these cases
 191         */
 192
 193        DPRINT("radeonfb: Found %dk of %s %d bits wide videoram\n",
 194               rinfo->video_ram / 1024,
 195               rinfo->vram_ddr ? "DDR" : "SDRAM",
 196               rinfo->vram_width);
 197
 198}
 199
 200static void radeon_write_pll_regs(struct radeonfb_info *rinfo, struct radeon_regs *mode)
 201{
 202        int i;
 203
 204        radeon_fifo_wait(20);
 205
 206#if 0
 207        /* Workaround from XFree */
 208        if (rinfo->is_mobility) {
 209                /* A temporal workaround for the occational blanking on certain laptop
 210                 * panels. This appears to related to the PLL divider registers
 211                 * (fail to lock?). It occurs even when all dividers are the same
 212                 * with their old settings. In this case we really don't need to
 213                 * fiddle with PLL registers. By doing this we can avoid the blanking
 214                 * problem with some panels.
 215                 */
 216                if ((mode->ppll_ref_div == (INPLL(PPLL_REF_DIV) & PPLL_REF_DIV_MASK)) &&
 217                    (mode->ppll_div_3 == (INPLL(PPLL_DIV_3) &
 218                                          (PPLL_POST3_DIV_MASK | PPLL_FB3_DIV_MASK)))) {
 219                        /* We still have to force a switch to selected PPLL div thanks to
 220                         * an XFree86 driver bug which will switch it away in some cases
 221                         * even when using UseFDev */
 222                        OUTREGP(CLOCK_CNTL_INDEX,
 223                                mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
 224                                ~PPLL_DIV_SEL_MASK);
 225                        radeon_pll_errata_after_index(rinfo);
 226                        radeon_pll_errata_after_data(rinfo);
 227                        return;
 228                }
 229        }
 230#endif
 231        if(rinfo->pdev.device == PCI_CHIP_RV370_5B60) return;
 232
 233        /* Swich VCKL clock input to CPUCLK so it stays fed while PPLL updates*/
 234        OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_CPUCLK, ~VCLK_SRC_SEL_MASK);
 235
 236        /* Reset PPLL & enable atomic update */
 237        OUTPLLP(PPLL_CNTL,
 238                PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN,
 239                ~(PPLL_RESET | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
 240
 241        /* Switch to selected PPLL divider */
 242        OUTREGP(CLOCK_CNTL_INDEX,
 243                mode->clk_cntl_index & PPLL_DIV_SEL_MASK,
 244                ~PPLL_DIV_SEL_MASK);
 245
 246        /* Set PPLL ref. div */
 247        if (rinfo->family == CHIP_FAMILY_R300 ||
 248            rinfo->family == CHIP_FAMILY_RS300 ||
 249            rinfo->family == CHIP_FAMILY_R350 ||
 250            rinfo->family == CHIP_FAMILY_RV350) {
 251                if (mode->ppll_ref_div & R300_PPLL_REF_DIV_ACC_MASK) {
 252                        /* When restoring console mode, use saved PPLL_REF_DIV
 253                         * setting.
 254                         */
 255                        OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, 0);
 256                } else {
 257                        /* R300 uses ref_div_acc field as real ref divider */
 258                        OUTPLLP(PPLL_REF_DIV,
 259                                (mode->ppll_ref_div << R300_PPLL_REF_DIV_ACC_SHIFT),
 260                                ~R300_PPLL_REF_DIV_ACC_MASK);
 261                }
 262        } else
 263                OUTPLLP(PPLL_REF_DIV, mode->ppll_ref_div, ~PPLL_REF_DIV_MASK);
 264
 265        /* Set PPLL divider 3 & post divider*/
 266        OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_FB3_DIV_MASK);
 267        OUTPLLP(PPLL_DIV_3, mode->ppll_div_3, ~PPLL_POST3_DIV_MASK);
 268
 269        /* Write update */
 270        while (INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R)
 271                ;
 272        OUTPLLP(PPLL_REF_DIV, PPLL_ATOMIC_UPDATE_W, ~PPLL_ATOMIC_UPDATE_W);
 273
 274        /* Wait read update complete */
 275        /* FIXME: Certain revisions of R300 can't recover here.  Not sure of
 276           the cause yet, but this workaround will mask the problem for now.
 277           Other chips usually will pass at the very first test, so the
 278           workaround shouldn't have any effect on them. */
 279        for (i = 0; (i < 10000 && INPLL(PPLL_REF_DIV) & PPLL_ATOMIC_UPDATE_R); i++)
 280                ;
 281
 282        OUTPLL(HTOTAL_CNTL, 0);
 283
 284        /* Clear reset & atomic update */
 285        OUTPLLP(PPLL_CNTL, 0,
 286                ~(PPLL_RESET | PPLL_SLEEP | PPLL_ATOMIC_UPDATE_EN | PPLL_VGA_ATOMIC_UPDATE_EN));
 287
 288        /* We may want some locking ... oh well */
 289        udelay(5000);
 290
 291        /* Switch back VCLK source to PPLL */
 292        OUTPLLP(VCLK_ECP_CNTL, VCLK_SRC_SEL_PPLLCLK, ~VCLK_SRC_SEL_MASK);
 293}
 294
 295typedef struct {
 296        u16 reg;
 297        u32 val;
 298} reg_val;
 299
 300#if 0   /* unused ? -> scheduled for removal */
 301/* these common regs are cleared before mode setting so they do not
 302 * interfere with anything
 303 */
 304static reg_val common_regs[] = {
 305        { OVR_CLR, 0 },
 306        { OVR_WID_LEFT_RIGHT, 0 },
 307        { OVR_WID_TOP_BOTTOM, 0 },
 308        { OV0_SCALE_CNTL, 0 },
 309        { SUBPIC_CNTL, 0 },
 310        { VIPH_CONTROL, 0 },
 311        { I2C_CNTL_1, 0 },
 312        { GEN_INT_CNTL, 0 },
 313        { CAP0_TRIG_CNTL, 0 },
 314        { CAP1_TRIG_CNTL, 0 },
 315};
 316#endif /* 0 */
 317
 318void radeon_setmode(void)
 319{
 320        struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
 321
 322        mode->crtc_gen_cntl = 0x03000200;
 323        mode->crtc_ext_cntl = 0x00008048;
 324        mode->dac_cntl = 0xff002100;
 325        mode->crtc_h_total_disp = 0x4f0063;
 326        mode->crtc_h_sync_strt_wid = 0x8c02a2;
 327        mode->crtc_v_total_disp = 0x01df020c;
 328        mode->crtc_v_sync_strt_wid = 0x8201ea;
 329        mode->crtc_pitch = 0x00500050;
 330
 331        OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
 332        OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
 333                ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
 334        OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
 335        OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
 336        OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
 337        OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
 338        OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
 339        OUTREG(CRTC_OFFSET, 0);
 340        OUTREG(CRTC_OFFSET_CNTL, 0);
 341        OUTREG(CRTC_PITCH, mode->crtc_pitch);
 342
 343        mode->clk_cntl_index = 0x300;
 344        mode->ppll_ref_div = 0xc;
 345        mode->ppll_div_3 = 0x00030059;
 346
 347        radeon_write_pll_regs(rinfo, mode);
 348}
 349
 350static void set_pal(void)
 351{
 352        int idx, val = 0;
 353
 354        for (idx = 0; idx < 256; idx++) {
 355                OUTREG8(PALETTE_INDEX, idx);
 356                OUTREG(PALETTE_DATA, val);
 357                val += 0x00010101;
 358        }
 359}
 360
 361void radeon_setmode_9200(int vesa_idx, int bpp)
 362{
 363        struct radeon_regs *mode = malloc(sizeof(struct radeon_regs));
 364
 365        mode->crtc_gen_cntl = CRTC_EN | CRTC_EXT_DISP_EN;
 366        mode->crtc_ext_cntl = VGA_ATI_LINEAR | XCRT_CNT_EN | CRTC_CRT_ON;
 367        mode->dac_cntl = DAC_MASK_ALL | DAC_VGA_ADR_EN | DAC_8BIT_EN;
 368        mode->crtc_offset_cntl = CRTC_OFFSET_CNTL__CRTC_TILE_EN;
 369
 370        switch (bpp) {
 371        case 24:
 372                mode->crtc_gen_cntl |= 0x6 << 8; /* x888 */
 373#if defined(__BIG_ENDIAN)
 374                mode->surface_cntl = NONSURF_AP0_SWP_32BPP | NONSURF_AP1_SWP_32BPP;
 375                mode->surf_info[0] = NONSURF_AP0_SWP_32BPP | NONSURF_AP1_SWP_32BPP;
 376#endif
 377                break;
 378        case 16:
 379                mode->crtc_gen_cntl |= 0x4 << 8; /* 565 */
 380#if defined(__BIG_ENDIAN)
 381                mode->surface_cntl = NONSURF_AP0_SWP_16BPP | NONSURF_AP1_SWP_16BPP;
 382                mode->surf_info[0] = NONSURF_AP0_SWP_16BPP | NONSURF_AP1_SWP_16BPP;
 383#endif
 384                break;
 385        default:
 386                mode->crtc_gen_cntl |= 0x2 << 8; /* palette */
 387                mode->surface_cntl = 0x00000000;
 388                break;
 389        }
 390
 391        switch (vesa_idx) {
 392        case RES_MODE_1280x1024:
 393                mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1688,1280);
 394                mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(1066,1024);
 395                mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(1025,3);
 396#if defined(CONFIG_RADEON_VREFRESH_75HZ)
 397                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1288,18);
 398                mode->ppll_div_3 = 0x00010078;
 399#else /* default @ 60 Hz */
 400                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1320,14);
 401                mode->ppll_div_3 = 0x00010060;
 402#endif
 403                /*
 404                 * for this mode pitch expands to the same value for 32, 16 and 8 bpp,
 405                 * so we set it here once only.
 406                 */
 407                mode->crtc_pitch = RADEON_CRT_PITCH(1280,32);
 408                switch (bpp) {
 409                case 24:
 410                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1280 * 4 / 16);
 411                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,32);
 412                        break;
 413                case 16:
 414                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1280 * 2 / 16);
 415                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,16);
 416                        break;
 417                default: /* 8 bpp */
 418                        mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1280 * 1 / 16);
 419                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1280,1024,8);
 420                        break;
 421                }
 422                break;
 423        case RES_MODE_1024x768:
 424#if defined(CONFIG_RADEON_VREFRESH_75HZ)
 425                mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1312,1024);
 426                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1032,12);
 427                mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(800,768);
 428                mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(769,3);
 429                mode->ppll_div_3 = 0x0002008c;
 430#else /* @ 60 Hz */
 431                mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1344,1024);
 432                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(1040,17) | CRTC_H_SYNC_POL;
 433                mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(806,768);
 434                mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(771,6) | CRTC_V_SYNC_POL;
 435                mode->ppll_div_3 = 0x00020074;
 436#endif
 437                /* also same pitch value for 32, 16 and 8 bpp */
 438                mode->crtc_pitch = RADEON_CRT_PITCH(1024,32);
 439                switch (bpp) {
 440                case 24:
 441                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1024 * 4 / 16);
 442                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,32);
 443                        break;
 444                case 16:
 445                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (1024 * 2 / 16);
 446                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,16);
 447                        break;
 448                default: /* 8 bpp */
 449                        mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1024 * 1 / 16);
 450                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,768,8);
 451                        break;
 452                }
 453                break;
 454        case RES_MODE_800x600:
 455                mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(1056,800);
 456#if defined(CONFIG_RADEON_VREFRESH_75HZ)
 457                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(808,10);
 458                mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(625,600);
 459                mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(601,3);
 460                mode->ppll_div_3 = 0x000300b0;
 461#else /* @ 60 Hz */
 462                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(832,16);
 463                mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(628,600);
 464                mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(601,4);
 465                mode->ppll_div_3 = 0x0003008e;
 466#endif
 467                switch (bpp) {
 468                case 24:
 469                        mode->crtc_pitch = RADEON_CRT_PITCH(832,32);
 470                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (832 * 4 / 16);
 471                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(832,600,32);
 472                        break;
 473                case 16:
 474                        mode->crtc_pitch = RADEON_CRT_PITCH(896,16);
 475                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (896 * 2 / 16);
 476                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(896,600,16);
 477                        break;
 478                default: /* 8 bpp */
 479                        mode->crtc_pitch = RADEON_CRT_PITCH(1024,8);
 480                        mode->surf_info[0] = R200_SURF_TILE_COLOR_MACRO | (1024 * 1 / 16);
 481                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(1024,600,8);
 482                        break;
 483                }
 484                break;
 485        default: /* RES_MODE_640x480 */
 486#if defined(CONFIG_RADEON_VREFRESH_75HZ)
 487                mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(840,640);
 488                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(648,8) | CRTC_H_SYNC_POL;
 489                mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(500,480);
 490                mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(481,3) | CRTC_V_SYNC_POL;
 491                mode->ppll_div_3 = 0x00030070;
 492#else /* @ 60 Hz */
 493                mode->crtc_h_total_disp = CRTC_H_TOTAL_DISP_VAL(800,640);
 494                mode->crtc_h_sync_strt_wid = CRTC_HSYNC_STRT_WID_VAL(674,12) | CRTC_H_SYNC_POL;
 495                mode->crtc_v_total_disp = CRTC_V_TOTAL_DISP_VAL(525,480);
 496                mode->crtc_v_sync_strt_wid = CRTC_VSYNC_STRT_WID_VAL(491,2) | CRTC_V_SYNC_POL;
 497                mode->ppll_div_3 = 0x00030059;
 498#endif
 499                /* also same pitch value for 32, 16 and 8 bpp */
 500                mode->crtc_pitch = RADEON_CRT_PITCH(640,32);
 501                switch (bpp) {
 502                case 24:
 503                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (640 * 4 / 16);
 504                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(640,480,32);
 505                        break;
 506                case 16:
 507                        mode->surf_info[0] |= R200_SURF_TILE_COLOR_MACRO | (640 * 2 / 16);
 508                        mode->surf_upper_bound[0] = SURF_UPPER_BOUND(640,480,16);
 509                        break;
 510                default: /* 8 bpp */
 511                        mode->crtc_offset_cntl = 0x00000000;
 512                        break;
 513                }
 514                break;
 515        }
 516
 517        OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl | CRTC_DISP_REQ_EN_B);
 518        OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
 519                (CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
 520        OUTREGP(DAC_CNTL, mode->dac_cntl, DAC_RANGE_CNTL | DAC_BLANKING);
 521        OUTREG(CRTC_H_TOTAL_DISP, mode->crtc_h_total_disp);
 522        OUTREG(CRTC_H_SYNC_STRT_WID, mode->crtc_h_sync_strt_wid);
 523        OUTREG(CRTC_V_TOTAL_DISP, mode->crtc_v_total_disp);
 524        OUTREG(CRTC_V_SYNC_STRT_WID, mode->crtc_v_sync_strt_wid);
 525        OUTREG(CRTC_OFFSET, 0);
 526        OUTREG(CRTC_OFFSET_CNTL, mode->crtc_offset_cntl);
 527        OUTREG(CRTC_PITCH, mode->crtc_pitch);
 528        OUTREG(CRTC_GEN_CNTL, mode->crtc_gen_cntl);
 529
 530        mode->clk_cntl_index = 0x300;
 531        mode->ppll_ref_div = 0xc;
 532
 533        radeon_write_pll_regs(rinfo, mode);
 534
 535        OUTREGP(CRTC_EXT_CNTL, mode->crtc_ext_cntl,
 536                ~(CRTC_HSYNC_DIS | CRTC_VSYNC_DIS | CRTC_DISPLAY_DIS));
 537        OUTREG(SURFACE0_INFO, mode->surf_info[0]);
 538        OUTREG(SURFACE0_LOWER_BOUND, 0);
 539        OUTREG(SURFACE0_UPPER_BOUND, mode->surf_upper_bound[0]);
 540        OUTREG(SURFACE_CNTL, mode->surface_cntl);
 541
 542        if (bpp > 8)
 543                set_pal();
 544
 545        free(mode);
 546}
 547
 548#include "../bios_emulator/include/biosemu.h"
 549
 550int radeon_probe(struct radeonfb_info *rinfo)
 551{
 552        pci_dev_t pdev;
 553        u16 did;
 554
 555        pdev = pci_find_devices(ati_radeon_pci_ids, 0);
 556
 557        if (pdev != -1) {
 558                pci_read_config_word(pdev, PCI_DEVICE_ID, &did);
 559                printf("ATI Radeon video card (%04x, %04x) found @(%d:%d:%d)\n",
 560                                PCI_VENDOR_ID_ATI, did, (pdev >> 16) & 0xff,
 561                                (pdev >> 11) & 0x1f, (pdev >> 8) & 0x7);
 562
 563                strcpy(rinfo->name, "ATI Radeon");
 564                rinfo->pdev.vendor = PCI_VENDOR_ID_ATI;
 565                rinfo->pdev.device = did;
 566                rinfo->family = get_radeon_id_family(rinfo->pdev.device);
 567                pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0,
 568                                &rinfo->fb_base_bus);
 569                pci_read_config_dword(pdev, PCI_BASE_ADDRESS_2,
 570                                &rinfo->mmio_base_bus);
 571                rinfo->fb_base_bus &= 0xfffff000;
 572                rinfo->mmio_base_bus &= ~0x04;
 573
 574                rinfo->mmio_base = pci_bus_to_virt(pdev, rinfo->mmio_base_bus,
 575                                        PCI_REGION_MEM, 0, MAP_NOCACHE);
 576                DPRINT("rinfo->mmio_base = 0x%p bus=0x%x\n",
 577                       rinfo->mmio_base, rinfo->mmio_base_bus);
 578                rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16;
 579                DPRINT("rinfo->fb_local_base = 0x%x\n",rinfo->fb_local_base);
 580                /* PostBIOS with x86 emulater */
 581                if (!BootVideoCardBIOS(pdev, NULL, 0))
 582                        return -1;
 583
 584                /*
 585                 * Check for errata
 586                 * (These will be added in the future for the chipfamily
 587                 * R300, RV200, RS200, RV100, RS100.)
 588                 */
 589
 590                /* Get VRAM size and type */
 591                radeon_identify_vram(rinfo);
 592
 593                rinfo->mapped_vram = min_t(unsigned long, MAX_MAPPED_VRAM,
 594                                rinfo->video_ram);
 595                rinfo->fb_base = pci_bus_to_virt(pdev, rinfo->fb_base_bus,
 596                                        PCI_REGION_MEM, 0, MAP_NOCACHE);
 597                DPRINT("Radeon: framebuffer base address 0x%08x, "
 598                       "bus address 0x%08x\n"
 599                       "MMIO base address 0x%08x, bus address 0x%08x, "
 600                       "framebuffer local base 0x%08x.\n ",
 601                       (u32)rinfo->fb_base, rinfo->fb_base_bus,
 602                       (u32)rinfo->mmio_base, rinfo->mmio_base_bus,
 603                       rinfo->fb_local_base);
 604                return 0;
 605        }
 606        return -1;
 607}
 608
 609/*
 610 * The Graphic Device
 611 */
 612GraphicDevice ctfb;
 613
 614#define CURSOR_SIZE     0x1000  /* in KByte for HW Cursor */
 615#define PATTERN_ADR     (pGD->dprBase + CURSOR_SIZE)    /* pattern Memory after Cursor Memory */
 616#define PATTERN_SIZE    8*8*4   /* 4 Bytes per Pixel 8 x 8 Pixel */
 617#define ACCELMEMORY     (CURSOR_SIZE + PATTERN_SIZE)    /* reserved Memory for BITBlt and hw cursor */
 618
 619void *video_hw_init(void)
 620{
 621        GraphicDevice *pGD = (GraphicDevice *) & ctfb;
 622        u32 *vm;
 623        char *penv;
 624        unsigned long t1, hsynch, vsynch;
 625        int bits_per_pixel, i, tmp, vesa_idx = 0, videomode;
 626        struct ctfb_res_modes *res_mode;
 627        struct ctfb_res_modes var_mode;
 628
 629        rinfo = malloc(sizeof(struct radeonfb_info));
 630
 631        printf("Video: ");
 632        if(radeon_probe(rinfo)) {
 633                printf("No radeon video card found!\n");
 634                return NULL;
 635        }
 636
 637        tmp = 0;
 638
 639        videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE;
 640        /* get video mode via environment */
 641        penv = env_get("videomode");
 642        if (penv) {
 643                /* deceide if it is a string */
 644                if (penv[0] <= '9') {
 645                        videomode = (int) simple_strtoul (penv, NULL, 16);
 646                        tmp = 1;
 647                }
 648        } else {
 649                tmp = 1;
 650        }
 651        if (tmp) {
 652                /* parameter are vesa modes */
 653                /* search params */
 654                for (i = 0; i < VESA_MODES_COUNT; i++) {
 655                        if (vesa_modes[i].vesanr == videomode)
 656                                break;
 657                }
 658                if (i == VESA_MODES_COUNT) {
 659                        printf ("no VESA Mode found, switching to mode 0x%x ", CONFIG_SYS_DEFAULT_VIDEO_MODE);
 660                        i = 0;
 661                }
 662                res_mode = (struct ctfb_res_modes *) &res_mode_init[vesa_modes[i].resindex];
 663                bits_per_pixel = vesa_modes[i].bits_per_pixel;
 664                vesa_idx = vesa_modes[i].resindex;
 665        } else {
 666                res_mode = (struct ctfb_res_modes *) &var_mode;
 667                bits_per_pixel = video_get_params (res_mode, penv);
 668        }
 669
 670        /* calculate hsynch and vsynch freq (info only) */
 671        t1 = (res_mode->left_margin + res_mode->xres +
 672              res_mode->right_margin + res_mode->hsync_len) / 8;
 673        t1 *= 8;
 674        t1 *= res_mode->pixclock;
 675        t1 /= 1000;
 676        hsynch = 1000000000L / t1;
 677        t1 *= (res_mode->upper_margin + res_mode->yres +
 678               res_mode->lower_margin + res_mode->vsync_len);
 679        t1 /= 1000;
 680        vsynch = 1000000000L / t1;
 681
 682        /* fill in Graphic device struct */
 683        sprintf (pGD->modeIdent, "%dx%dx%d %ldkHz %ldHz", res_mode->xres,
 684                 res_mode->yres, bits_per_pixel, (hsynch / 1000),
 685                 (vsynch / 1000));
 686        printf ("%s\n", pGD->modeIdent);
 687        pGD->winSizeX = res_mode->xres;
 688        pGD->winSizeY = res_mode->yres;
 689        pGD->plnSizeX = res_mode->xres;
 690        pGD->plnSizeY = res_mode->yres;
 691
 692        switch (bits_per_pixel) {
 693        case 24:
 694                pGD->gdfBytesPP = 4;
 695                pGD->gdfIndex = GDF_32BIT_X888RGB;
 696                if (res_mode->xres == 800) {
 697                        pGD->winSizeX = 832;
 698                        pGD->plnSizeX = 832;
 699                }
 700                break;
 701        case 16:
 702                pGD->gdfBytesPP = 2;
 703                pGD->gdfIndex = GDF_16BIT_565RGB;
 704                if (res_mode->xres == 800) {
 705                        pGD->winSizeX = 896;
 706                        pGD->plnSizeX = 896;
 707                }
 708                break;
 709        default:
 710                if (res_mode->xres == 800) {
 711                        pGD->winSizeX = 1024;
 712                        pGD->plnSizeX = 1024;
 713                }
 714                pGD->gdfBytesPP = 1;
 715                pGD->gdfIndex = GDF__8BIT_INDEX;
 716                break;
 717        }
 718
 719        pGD->isaBase = CONFIG_SYS_ISA_IO_BASE_ADDRESS;
 720        pGD->pciBase = (unsigned int)rinfo->fb_base;
 721        pGD->frameAdrs = (unsigned int)rinfo->fb_base;
 722        pGD->memSize = 64 * 1024 * 1024;
 723
 724        /* Cursor Start Address */
 725        pGD->dprBase = (pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP) +
 726                (unsigned int)rinfo->fb_base;
 727        if ((pGD->dprBase & 0x0fff) != 0) {
 728                /* allign it */
 729                pGD->dprBase &= 0xfffff000;
 730                pGD->dprBase += 0x00001000;
 731        }
 732        DPRINT ("Cursor Start %x Pattern Start %x\n", pGD->dprBase,
 733                PATTERN_ADR);
 734        pGD->vprBase = (unsigned int)rinfo->fb_base;    /* Dummy */
 735        pGD->cprBase = (unsigned int)rinfo->fb_base;    /* Dummy */
 736        /* set up Hardware */
 737
 738        /* Clear video memory (only visible screen area) */
 739        i = pGD->winSizeX * pGD->winSizeY * pGD->gdfBytesPP / 4;
 740        vm = (unsigned int *) pGD->pciBase;
 741        while (i--)
 742                *vm++ = 0;
 743        /*SetDrawingEngine (bits_per_pixel);*/
 744
 745        if (rinfo->family == CHIP_FAMILY_RV280)
 746                radeon_setmode_9200(vesa_idx, bits_per_pixel);
 747        else
 748                radeon_setmode();
 749
 750        return ((void *) pGD);
 751}
 752
 753void video_set_lut (unsigned int index, /* color number */
 754               unsigned char r, /* red */
 755               unsigned char g, /* green */
 756               unsigned char b  /* blue */
 757               )
 758{
 759        OUTREG(PALETTE_INDEX, index);
 760        OUTREG(PALETTE_DATA, (r << 16) | (g << 8) | b);
 761}
 762