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