linux/drivers/gpu/drm/radeon/r420.c
<<
>>
Prefs
   1/*
   2 * Copyright 2008 Advanced Micro Devices, Inc.
   3 * Copyright 2008 Red Hat Inc.
   4 * Copyright 2009 Jerome Glisse.
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a
   7 * copy of this software and associated documentation files (the "Software"),
   8 * to deal in the Software without restriction, including without limitation
   9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  10 * and/or sell copies of the Software, and to permit persons to whom the
  11 * Software is furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  22 * OTHER DEALINGS IN THE SOFTWARE.
  23 *
  24 * Authors: Dave Airlie
  25 *          Alex Deucher
  26 *          Jerome Glisse
  27 */
  28#include <linux/seq_file.h>
  29#include "drmP.h"
  30#include "radeon_reg.h"
  31#include "radeon.h"
  32#include "atom.h"
  33#include "r420d.h"
  34
  35int r420_mc_init(struct radeon_device *rdev)
  36{
  37        int r;
  38
  39        /* Setup GPU memory space */
  40        rdev->mc.vram_location = 0xFFFFFFFFUL;
  41        rdev->mc.gtt_location = 0xFFFFFFFFUL;
  42        if (rdev->flags & RADEON_IS_AGP) {
  43                r = radeon_agp_init(rdev);
  44                if (r) {
  45                        printk(KERN_WARNING "[drm] Disabling AGP\n");
  46                        rdev->flags &= ~RADEON_IS_AGP;
  47                        rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024;
  48                } else {
  49                        rdev->mc.gtt_location = rdev->mc.agp_base;
  50                }
  51        }
  52        r = radeon_mc_setup(rdev);
  53        if (r) {
  54                return r;
  55        }
  56        return 0;
  57}
  58
  59void r420_pipes_init(struct radeon_device *rdev)
  60{
  61        unsigned tmp;
  62        unsigned gb_pipe_select;
  63        unsigned num_pipes;
  64
  65        /* GA_ENHANCE workaround TCL deadlock issue */
  66        WREG32(0x4274, (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3));
  67        /* add idle wait as per freedesktop.org bug 24041 */
  68        if (r100_gui_wait_for_idle(rdev)) {
  69                printk(KERN_WARNING "Failed to wait GUI idle while "
  70                       "programming pipes. Bad things might happen.\n");
  71        }
  72        /* get max number of pipes */
  73        gb_pipe_select = RREG32(0x402C);
  74        num_pipes = ((gb_pipe_select >> 12) & 3) + 1;
  75        rdev->num_gb_pipes = num_pipes;
  76        tmp = 0;
  77        switch (num_pipes) {
  78        default:
  79                /* force to 1 pipe */
  80                num_pipes = 1;
  81        case 1:
  82                tmp = (0 << 1);
  83                break;
  84        case 2:
  85                tmp = (3 << 1);
  86                break;
  87        case 3:
  88                tmp = (6 << 1);
  89                break;
  90        case 4:
  91                tmp = (7 << 1);
  92                break;
  93        }
  94        WREG32(0x42C8, (1 << num_pipes) - 1);
  95        /* Sub pixel 1/12 so we can have 4K rendering according to doc */
  96        tmp |= (1 << 4) | (1 << 0);
  97        WREG32(0x4018, tmp);
  98        if (r100_gui_wait_for_idle(rdev)) {
  99                printk(KERN_WARNING "Failed to wait GUI idle while "
 100                       "programming pipes. Bad things might happen.\n");
 101        }
 102
 103        tmp = RREG32(0x170C);
 104        WREG32(0x170C, tmp | (1 << 31));
 105
 106        WREG32(R300_RB2D_DSTCACHE_MODE,
 107               RREG32(R300_RB2D_DSTCACHE_MODE) |
 108               R300_DC_AUTOFLUSH_ENABLE |
 109               R300_DC_DC_DISABLE_IGNORE_PE);
 110
 111        if (r100_gui_wait_for_idle(rdev)) {
 112                printk(KERN_WARNING "Failed to wait GUI idle while "
 113                       "programming pipes. Bad things might happen.\n");
 114        }
 115
 116        if (rdev->family == CHIP_RV530) {
 117                tmp = RREG32(RV530_GB_PIPE_SELECT2);
 118                if ((tmp & 3) == 3)
 119                        rdev->num_z_pipes = 2;
 120                else
 121                        rdev->num_z_pipes = 1;
 122        } else
 123                rdev->num_z_pipes = 1;
 124
 125        DRM_INFO("radeon: %d quad pipes, %d z pipes initialized.\n",
 126                 rdev->num_gb_pipes, rdev->num_z_pipes);
 127}
 128
 129u32 r420_mc_rreg(struct radeon_device *rdev, u32 reg)
 130{
 131        u32 r;
 132
 133        WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg));
 134        r = RREG32(R_0001FC_MC_IND_DATA);
 135        return r;
 136}
 137
 138void r420_mc_wreg(struct radeon_device *rdev, u32 reg, u32 v)
 139{
 140        WREG32(R_0001F8_MC_IND_INDEX, S_0001F8_MC_IND_ADDR(reg) |
 141                S_0001F8_MC_IND_WR_EN(1));
 142        WREG32(R_0001FC_MC_IND_DATA, v);
 143}
 144
 145static void r420_debugfs(struct radeon_device *rdev)
 146{
 147        if (r100_debugfs_rbbm_init(rdev)) {
 148                DRM_ERROR("Failed to register debugfs file for RBBM !\n");
 149        }
 150        if (r420_debugfs_pipes_info_init(rdev)) {
 151                DRM_ERROR("Failed to register debugfs file for pipes !\n");
 152        }
 153}
 154
 155static void r420_clock_resume(struct radeon_device *rdev)
 156{
 157        u32 sclk_cntl;
 158
 159        if (radeon_dynclks != -1 && radeon_dynclks)
 160                radeon_atom_set_clock_gating(rdev, 1);
 161        sclk_cntl = RREG32_PLL(R_00000D_SCLK_CNTL);
 162        sclk_cntl |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1);
 163        if (rdev->family == CHIP_R420)
 164                sclk_cntl |= S_00000D_FORCE_PX(1) | S_00000D_FORCE_TX(1);
 165        WREG32_PLL(R_00000D_SCLK_CNTL, sclk_cntl);
 166}
 167
 168static int r420_startup(struct radeon_device *rdev)
 169{
 170        int r;
 171
 172        r300_mc_program(rdev);
 173        /* Resume clock */
 174        r420_clock_resume(rdev);
 175        /* Initialize GART (initialize after TTM so we can allocate
 176         * memory through TTM but finalize after TTM) */
 177        if (rdev->flags & RADEON_IS_PCIE) {
 178                r = rv370_pcie_gart_enable(rdev);
 179                if (r)
 180                        return r;
 181        }
 182        if (rdev->flags & RADEON_IS_PCI) {
 183                r = r100_pci_gart_enable(rdev);
 184                if (r)
 185                        return r;
 186        }
 187        r420_pipes_init(rdev);
 188        /* Enable IRQ */
 189        rdev->irq.sw_int = true;
 190        r100_irq_set(rdev);
 191        /* 1M ring buffer */
 192        r = r100_cp_init(rdev, 1024 * 1024);
 193        if (r) {
 194                dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
 195                return r;
 196        }
 197        r = r100_wb_init(rdev);
 198        if (r) {
 199                dev_err(rdev->dev, "failled initializing WB (%d).\n", r);
 200        }
 201        r = r100_ib_init(rdev);
 202        if (r) {
 203                dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
 204                return r;
 205        }
 206        return 0;
 207}
 208
 209int r420_resume(struct radeon_device *rdev)
 210{
 211        /* Make sur GART are not working */
 212        if (rdev->flags & RADEON_IS_PCIE)
 213                rv370_pcie_gart_disable(rdev);
 214        if (rdev->flags & RADEON_IS_PCI)
 215                r100_pci_gart_disable(rdev);
 216        /* Resume clock before doing reset */
 217        r420_clock_resume(rdev);
 218        /* Reset gpu before posting otherwise ATOM will enter infinite loop */
 219        if (radeon_gpu_reset(rdev)) {
 220                dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
 221                        RREG32(R_000E40_RBBM_STATUS),
 222                        RREG32(R_0007C0_CP_STAT));
 223        }
 224        /* check if cards are posted or not */
 225        if (rdev->is_atom_bios) {
 226                atom_asic_init(rdev->mode_info.atom_context);
 227        } else {
 228                radeon_combios_asic_init(rdev->ddev);
 229        }
 230        /* Resume clock after posting */
 231        r420_clock_resume(rdev);
 232
 233        return r420_startup(rdev);
 234}
 235
 236int r420_suspend(struct radeon_device *rdev)
 237{
 238        r100_cp_disable(rdev);
 239        r100_wb_disable(rdev);
 240        r100_irq_disable(rdev);
 241        if (rdev->flags & RADEON_IS_PCIE)
 242                rv370_pcie_gart_disable(rdev);
 243        if (rdev->flags & RADEON_IS_PCI)
 244                r100_pci_gart_disable(rdev);
 245        return 0;
 246}
 247
 248void r420_fini(struct radeon_device *rdev)
 249{
 250        r100_cp_fini(rdev);
 251        r100_wb_fini(rdev);
 252        r100_ib_fini(rdev);
 253        radeon_gem_fini(rdev);
 254        if (rdev->flags & RADEON_IS_PCIE)
 255                rv370_pcie_gart_fini(rdev);
 256        if (rdev->flags & RADEON_IS_PCI)
 257                r100_pci_gart_fini(rdev);
 258        radeon_agp_fini(rdev);
 259        radeon_irq_kms_fini(rdev);
 260        radeon_fence_driver_fini(rdev);
 261        radeon_object_fini(rdev);
 262        if (rdev->is_atom_bios) {
 263                radeon_atombios_fini(rdev);
 264        } else {
 265                radeon_combios_fini(rdev);
 266        }
 267        kfree(rdev->bios);
 268        rdev->bios = NULL;
 269}
 270
 271int r420_init(struct radeon_device *rdev)
 272{
 273        int r;
 274
 275        /* Initialize scratch registers */
 276        radeon_scratch_init(rdev);
 277        /* Initialize surface registers */
 278        radeon_surface_init(rdev);
 279        /* TODO: disable VGA need to use VGA request */
 280        /* BIOS*/
 281        if (!radeon_get_bios(rdev)) {
 282                if (ASIC_IS_AVIVO(rdev))
 283                        return -EINVAL;
 284        }
 285        if (rdev->is_atom_bios) {
 286                r = radeon_atombios_init(rdev);
 287                if (r) {
 288                        return r;
 289                }
 290        } else {
 291                r = radeon_combios_init(rdev);
 292                if (r) {
 293                        return r;
 294                }
 295        }
 296        /* Reset gpu before posting otherwise ATOM will enter infinite loop */
 297        if (radeon_gpu_reset(rdev)) {
 298                dev_warn(rdev->dev,
 299                        "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
 300                        RREG32(R_000E40_RBBM_STATUS),
 301                        RREG32(R_0007C0_CP_STAT));
 302        }
 303        /* check if cards are posted or not */
 304        if (!radeon_card_posted(rdev) && rdev->bios) {
 305                DRM_INFO("GPU not posted. posting now...\n");
 306                if (rdev->is_atom_bios) {
 307                        atom_asic_init(rdev->mode_info.atom_context);
 308                } else {
 309                        radeon_combios_asic_init(rdev->ddev);
 310                }
 311        }
 312        /* Initialize clocks */
 313        radeon_get_clock_info(rdev->ddev);
 314        /* Initialize power management */
 315        radeon_pm_init(rdev);
 316        /* Get vram informations */
 317        r300_vram_info(rdev);
 318        /* Initialize memory controller (also test AGP) */
 319        r = r420_mc_init(rdev);
 320        if (r) {
 321                return r;
 322        }
 323        r420_debugfs(rdev);
 324        /* Fence driver */
 325        r = radeon_fence_driver_init(rdev);
 326        if (r) {
 327                return r;
 328        }
 329        r = radeon_irq_kms_init(rdev);
 330        if (r) {
 331                return r;
 332        }
 333        /* Memory manager */
 334        r = radeon_object_init(rdev);
 335        if (r) {
 336                return r;
 337        }
 338        if (rdev->flags & RADEON_IS_PCIE) {
 339                r = rv370_pcie_gart_init(rdev);
 340                if (r)
 341                        return r;
 342        }
 343        if (rdev->flags & RADEON_IS_PCI) {
 344                r = r100_pci_gart_init(rdev);
 345                if (r)
 346                        return r;
 347        }
 348        r300_set_reg_safe(rdev);
 349        rdev->accel_working = true;
 350        r = r420_startup(rdev);
 351        if (r) {
 352                /* Somethings want wront with the accel init stop accel */
 353                dev_err(rdev->dev, "Disabling GPU acceleration\n");
 354                r420_suspend(rdev);
 355                r100_cp_fini(rdev);
 356                r100_wb_fini(rdev);
 357                r100_ib_fini(rdev);
 358                if (rdev->flags & RADEON_IS_PCIE)
 359                        rv370_pcie_gart_fini(rdev);
 360                if (rdev->flags & RADEON_IS_PCI)
 361                        r100_pci_gart_fini(rdev);
 362                radeon_agp_fini(rdev);
 363                radeon_irq_kms_fini(rdev);
 364                rdev->accel_working = false;
 365        }
 366        return 0;
 367}
 368
 369/*
 370 * Debugfs info
 371 */
 372#if defined(CONFIG_DEBUG_FS)
 373static int r420_debugfs_pipes_info(struct seq_file *m, void *data)
 374{
 375        struct drm_info_node *node = (struct drm_info_node *) m->private;
 376        struct drm_device *dev = node->minor->dev;
 377        struct radeon_device *rdev = dev->dev_private;
 378        uint32_t tmp;
 379
 380        tmp = RREG32(R400_GB_PIPE_SELECT);
 381        seq_printf(m, "GB_PIPE_SELECT 0x%08x\n", tmp);
 382        tmp = RREG32(R300_GB_TILE_CONFIG);
 383        seq_printf(m, "GB_TILE_CONFIG 0x%08x\n", tmp);
 384        tmp = RREG32(R300_DST_PIPE_CONFIG);
 385        seq_printf(m, "DST_PIPE_CONFIG 0x%08x\n", tmp);
 386        return 0;
 387}
 388
 389static struct drm_info_list r420_pipes_info_list[] = {
 390        {"r420_pipes_info", r420_debugfs_pipes_info, 0, NULL},
 391};
 392#endif
 393
 394int r420_debugfs_pipes_info_init(struct radeon_device *rdev)
 395{
 396#if defined(CONFIG_DEBUG_FS)
 397        return radeon_debugfs_add_files(rdev, r420_pipes_info_list, 1);
 398#else
 399        return 0;
 400#endif
 401}
 402
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.