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