1254885Sdumbbell/* 2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc. 3254885Sdumbbell * Copyright 2008 Red Hat Inc. 4254885Sdumbbell * Copyright 2009 Jerome Glisse. 5254885Sdumbbell * 6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a 7254885Sdumbbell * copy of this software and associated documentation files (the "Software"), 8254885Sdumbbell * to deal in the Software without restriction, including without limitation 9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the 11254885Sdumbbell * Software is furnished to do so, subject to the following conditions: 12254885Sdumbbell * 13254885Sdumbbell * The above copyright notice and this permission notice shall be included in 14254885Sdumbbell * all copies or substantial portions of the Software. 15254885Sdumbbell * 16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE. 23254885Sdumbbell * 24254885Sdumbbell * Authors: Dave Airlie 25254885Sdumbbell * Alex Deucher 26254885Sdumbbell * Jerome Glisse 27254885Sdumbbell */ 28254885Sdumbbell 29254885Sdumbbell#include <sys/cdefs.h> 30254885Sdumbbell__FBSDID("$FreeBSD$"); 31254885Sdumbbell 32254885Sdumbbell#include <dev/drm2/drmP.h> 33254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h> 34254885Sdumbbell#include "radeon_reg.h" 35254885Sdumbbell#include "radeon.h" 36254885Sdumbbell#include "radeon_asic.h" 37254885Sdumbbell#include "r100d.h" 38254885Sdumbbell#include "rs100d.h" 39254885Sdumbbell#include "rv200d.h" 40254885Sdumbbell#include "rv250d.h" 41254885Sdumbbell#include "atom.h" 42254885Sdumbbell 43254885Sdumbbell#include "r100_reg_safe.h" 44254885Sdumbbell#include "rn50_reg_safe.h" 45254885Sdumbbell 46254885Sdumbbell/* Firmware Names */ 47254885Sdumbbell#define FIRMWARE_R100 "radeonkmsfw_R100_cp" 48254885Sdumbbell#define FIRMWARE_R200 "radeonkmsfw_R200_cp" 49254885Sdumbbell#define FIRMWARE_R300 "radeonkmsfw_R300_cp" 50254885Sdumbbell#define FIRMWARE_R420 "radeonkmsfw_R420_cp" 51254885Sdumbbell#define FIRMWARE_RS690 "radeonkmsfw_RS690_cp" 52254885Sdumbbell#define FIRMWARE_RS600 "radeonkmsfw_RS600_cp" 53254885Sdumbbell#define FIRMWARE_R520 "radeonkmsfw_R520_cp" 54254885Sdumbbell 55254885Sdumbbell#include "r100_track.h" 56254885Sdumbbell 57254885Sdumbbell/* This files gather functions specifics to: 58254885Sdumbbell * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 59254885Sdumbbell * and others in some cases. 60254885Sdumbbell */ 61254885Sdumbbell 62254885Sdumbbell/** 63254885Sdumbbell * r100_wait_for_vblank - vblank wait asic callback. 64254885Sdumbbell * 65254885Sdumbbell * @rdev: radeon_device pointer 66254885Sdumbbell * @crtc: crtc to wait for vblank on 67254885Sdumbbell * 68254885Sdumbbell * Wait for vblank on the requested crtc (r1xx-r4xx). 69254885Sdumbbell */ 70254885Sdumbbellvoid r100_wait_for_vblank(struct radeon_device *rdev, int crtc) 71254885Sdumbbell{ 72254885Sdumbbell int i; 73254885Sdumbbell 74254885Sdumbbell if (crtc >= rdev->num_crtc) 75254885Sdumbbell return; 76254885Sdumbbell 77254885Sdumbbell if (crtc == 0) { 78254885Sdumbbell if (RREG32(RADEON_CRTC_GEN_CNTL) & RADEON_CRTC_EN) { 79254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 80254885Sdumbbell if (!(RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR)) 81254885Sdumbbell break; 82254885Sdumbbell DRM_UDELAY(1); 83254885Sdumbbell } 84254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 85254885Sdumbbell if (RREG32(RADEON_CRTC_STATUS) & RADEON_CRTC_VBLANK_CUR) 86254885Sdumbbell break; 87254885Sdumbbell DRM_UDELAY(1); 88254885Sdumbbell } 89254885Sdumbbell } 90254885Sdumbbell } else { 91254885Sdumbbell if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_EN) { 92254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 93254885Sdumbbell if (!(RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR)) 94254885Sdumbbell break; 95254885Sdumbbell DRM_UDELAY(1); 96254885Sdumbbell } 97254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 98254885Sdumbbell if (RREG32(RADEON_CRTC2_STATUS) & RADEON_CRTC2_VBLANK_CUR) 99254885Sdumbbell break; 100254885Sdumbbell DRM_UDELAY(1); 101254885Sdumbbell } 102254885Sdumbbell } 103254885Sdumbbell } 104254885Sdumbbell} 105254885Sdumbbell 106254885Sdumbbell/** 107254885Sdumbbell * r100_pre_page_flip - pre-pageflip callback. 108254885Sdumbbell * 109254885Sdumbbell * @rdev: radeon_device pointer 110254885Sdumbbell * @crtc: crtc to prepare for pageflip on 111254885Sdumbbell * 112254885Sdumbbell * Pre-pageflip callback (r1xx-r4xx). 113254885Sdumbbell * Enables the pageflip irq (vblank irq). 114254885Sdumbbell */ 115254885Sdumbbellvoid r100_pre_page_flip(struct radeon_device *rdev, int crtc) 116254885Sdumbbell{ 117254885Sdumbbell /* enable the pflip int */ 118254885Sdumbbell radeon_irq_kms_pflip_irq_get(rdev, crtc); 119254885Sdumbbell} 120254885Sdumbbell 121254885Sdumbbell/** 122254885Sdumbbell * r100_post_page_flip - pos-pageflip callback. 123254885Sdumbbell * 124254885Sdumbbell * @rdev: radeon_device pointer 125254885Sdumbbell * @crtc: crtc to cleanup pageflip on 126254885Sdumbbell * 127254885Sdumbbell * Post-pageflip callback (r1xx-r4xx). 128254885Sdumbbell * Disables the pageflip irq (vblank irq). 129254885Sdumbbell */ 130254885Sdumbbellvoid r100_post_page_flip(struct radeon_device *rdev, int crtc) 131254885Sdumbbell{ 132254885Sdumbbell /* disable the pflip int */ 133254885Sdumbbell radeon_irq_kms_pflip_irq_put(rdev, crtc); 134254885Sdumbbell} 135254885Sdumbbell 136254885Sdumbbell/** 137254885Sdumbbell * r100_page_flip - pageflip callback. 138254885Sdumbbell * 139254885Sdumbbell * @rdev: radeon_device pointer 140254885Sdumbbell * @crtc_id: crtc to cleanup pageflip on 141254885Sdumbbell * @crtc_base: new address of the crtc (GPU MC address) 142254885Sdumbbell * 143254885Sdumbbell * Does the actual pageflip (r1xx-r4xx). 144254885Sdumbbell * During vblank we take the crtc lock and wait for the update_pending 145254885Sdumbbell * bit to go high, when it does, we release the lock, and allow the 146254885Sdumbbell * double buffered update to take place. 147254885Sdumbbell * Returns the current update pending status. 148254885Sdumbbell */ 149254885Sdumbbellu32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) 150254885Sdumbbell{ 151254885Sdumbbell struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; 152254885Sdumbbell u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; 153254885Sdumbbell int i; 154254885Sdumbbell 155254885Sdumbbell /* Lock the graphics update lock */ 156254885Sdumbbell /* update the scanout addresses */ 157254885Sdumbbell WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); 158254885Sdumbbell 159254885Sdumbbell /* Wait for update_pending to go high. */ 160254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 161254885Sdumbbell if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET) 162254885Sdumbbell break; 163254885Sdumbbell DRM_UDELAY(1); 164254885Sdumbbell } 165254885Sdumbbell DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); 166254885Sdumbbell 167254885Sdumbbell /* Unlock the lock, so double-buffering can take place inside vblank */ 168254885Sdumbbell tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK; 169254885Sdumbbell WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); 170254885Sdumbbell 171254885Sdumbbell /* Return current update_pending status: */ 172254885Sdumbbell return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; 173254885Sdumbbell} 174254885Sdumbbell 175254885Sdumbbell/** 176254885Sdumbbell * r100_pm_get_dynpm_state - look up dynpm power state callback. 177254885Sdumbbell * 178254885Sdumbbell * @rdev: radeon_device pointer 179254885Sdumbbell * 180254885Sdumbbell * Look up the optimal power state based on the 181254885Sdumbbell * current state of the GPU (r1xx-r5xx). 182254885Sdumbbell * Used for dynpm only. 183254885Sdumbbell */ 184254885Sdumbbellvoid r100_pm_get_dynpm_state(struct radeon_device *rdev) 185254885Sdumbbell{ 186254885Sdumbbell int i; 187254885Sdumbbell rdev->pm.dynpm_can_upclock = true; 188254885Sdumbbell rdev->pm.dynpm_can_downclock = true; 189254885Sdumbbell 190254885Sdumbbell switch (rdev->pm.dynpm_planned_action) { 191254885Sdumbbell case DYNPM_ACTION_MINIMUM: 192254885Sdumbbell rdev->pm.requested_power_state_index = 0; 193254885Sdumbbell rdev->pm.dynpm_can_downclock = false; 194254885Sdumbbell break; 195254885Sdumbbell case DYNPM_ACTION_DOWNCLOCK: 196254885Sdumbbell if (rdev->pm.current_power_state_index == 0) { 197254885Sdumbbell rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 198254885Sdumbbell rdev->pm.dynpm_can_downclock = false; 199254885Sdumbbell } else { 200254885Sdumbbell if (rdev->pm.active_crtc_count > 1) { 201254885Sdumbbell for (i = 0; i < rdev->pm.num_power_states; i++) { 202254885Sdumbbell if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 203254885Sdumbbell continue; 204254885Sdumbbell else if (i >= rdev->pm.current_power_state_index) { 205254885Sdumbbell rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 206254885Sdumbbell break; 207254885Sdumbbell } else { 208254885Sdumbbell rdev->pm.requested_power_state_index = i; 209254885Sdumbbell break; 210254885Sdumbbell } 211254885Sdumbbell } 212254885Sdumbbell } else 213254885Sdumbbell rdev->pm.requested_power_state_index = 214254885Sdumbbell rdev->pm.current_power_state_index - 1; 215254885Sdumbbell } 216254885Sdumbbell /* don't use the power state if crtcs are active and no display flag is set */ 217254885Sdumbbell if ((rdev->pm.active_crtc_count > 0) && 218254885Sdumbbell (rdev->pm.power_state[rdev->pm.requested_power_state_index].clock_info[0].flags & 219254885Sdumbbell RADEON_PM_MODE_NO_DISPLAY)) { 220254885Sdumbbell rdev->pm.requested_power_state_index++; 221254885Sdumbbell } 222254885Sdumbbell break; 223254885Sdumbbell case DYNPM_ACTION_UPCLOCK: 224254885Sdumbbell if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { 225254885Sdumbbell rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 226254885Sdumbbell rdev->pm.dynpm_can_upclock = false; 227254885Sdumbbell } else { 228254885Sdumbbell if (rdev->pm.active_crtc_count > 1) { 229254885Sdumbbell for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { 230254885Sdumbbell if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 231254885Sdumbbell continue; 232254885Sdumbbell else if (i <= rdev->pm.current_power_state_index) { 233254885Sdumbbell rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 234254885Sdumbbell break; 235254885Sdumbbell } else { 236254885Sdumbbell rdev->pm.requested_power_state_index = i; 237254885Sdumbbell break; 238254885Sdumbbell } 239254885Sdumbbell } 240254885Sdumbbell } else 241254885Sdumbbell rdev->pm.requested_power_state_index = 242254885Sdumbbell rdev->pm.current_power_state_index + 1; 243254885Sdumbbell } 244254885Sdumbbell break; 245254885Sdumbbell case DYNPM_ACTION_DEFAULT: 246254885Sdumbbell rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; 247254885Sdumbbell rdev->pm.dynpm_can_upclock = false; 248254885Sdumbbell break; 249254885Sdumbbell case DYNPM_ACTION_NONE: 250254885Sdumbbell default: 251254885Sdumbbell DRM_ERROR("Requested mode for not defined action\n"); 252254885Sdumbbell return; 253254885Sdumbbell } 254254885Sdumbbell /* only one clock mode per power state */ 255254885Sdumbbell rdev->pm.requested_clock_mode_index = 0; 256254885Sdumbbell 257254885Sdumbbell DRM_DEBUG_DRIVER("Requested: e: %d m: %d p: %d\n", 258254885Sdumbbell rdev->pm.power_state[rdev->pm.requested_power_state_index]. 259254885Sdumbbell clock_info[rdev->pm.requested_clock_mode_index].sclk, 260254885Sdumbbell rdev->pm.power_state[rdev->pm.requested_power_state_index]. 261254885Sdumbbell clock_info[rdev->pm.requested_clock_mode_index].mclk, 262254885Sdumbbell rdev->pm.power_state[rdev->pm.requested_power_state_index]. 263254885Sdumbbell pcie_lanes); 264254885Sdumbbell} 265254885Sdumbbell 266254885Sdumbbell/** 267254885Sdumbbell * r100_pm_init_profile - Initialize power profiles callback. 268254885Sdumbbell * 269254885Sdumbbell * @rdev: radeon_device pointer 270254885Sdumbbell * 271254885Sdumbbell * Initialize the power states used in profile mode 272254885Sdumbbell * (r1xx-r3xx). 273254885Sdumbbell * Used for profile mode only. 274254885Sdumbbell */ 275254885Sdumbbellvoid r100_pm_init_profile(struct radeon_device *rdev) 276254885Sdumbbell{ 277254885Sdumbbell /* default */ 278254885Sdumbbell rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 279254885Sdumbbell rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 280254885Sdumbbell rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 281254885Sdumbbell rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 282254885Sdumbbell /* low sh */ 283254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; 284254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; 285254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 286254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 287254885Sdumbbell /* mid sh */ 288254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; 289254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0; 290254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 291254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 292254885Sdumbbell /* high sh */ 293254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; 294254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 295254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 296254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 297254885Sdumbbell /* low mh */ 298254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0; 299254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 300254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 301254885Sdumbbell rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 302254885Sdumbbell /* mid mh */ 303254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; 304254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 305254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 306254885Sdumbbell rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 307254885Sdumbbell /* high mh */ 308254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; 309254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 310254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 311254885Sdumbbell rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 312254885Sdumbbell} 313254885Sdumbbell 314254885Sdumbbell/** 315254885Sdumbbell * r100_pm_misc - set additional pm hw parameters callback. 316254885Sdumbbell * 317254885Sdumbbell * @rdev: radeon_device pointer 318254885Sdumbbell * 319254885Sdumbbell * Set non-clock parameters associated with a power state 320254885Sdumbbell * (voltage, pcie lanes, etc.) (r1xx-r4xx). 321254885Sdumbbell */ 322254885Sdumbbellvoid r100_pm_misc(struct radeon_device *rdev) 323254885Sdumbbell{ 324254885Sdumbbell int requested_index = rdev->pm.requested_power_state_index; 325254885Sdumbbell struct radeon_power_state *ps = &rdev->pm.power_state[requested_index]; 326254885Sdumbbell struct radeon_voltage *voltage = &ps->clock_info[0].voltage; 327254885Sdumbbell u32 tmp, sclk_cntl, sclk_cntl2, sclk_more_cntl; 328254885Sdumbbell 329254885Sdumbbell if ((voltage->type == VOLTAGE_GPIO) && (voltage->gpio.valid)) { 330254885Sdumbbell if (ps->misc & ATOM_PM_MISCINFO_VOLTAGE_DROP_SUPPORT) { 331254885Sdumbbell tmp = RREG32(voltage->gpio.reg); 332254885Sdumbbell if (voltage->active_high) 333254885Sdumbbell tmp |= voltage->gpio.mask; 334254885Sdumbbell else 335254885Sdumbbell tmp &= ~(voltage->gpio.mask); 336254885Sdumbbell WREG32(voltage->gpio.reg, tmp); 337254885Sdumbbell if (voltage->delay) 338254885Sdumbbell DRM_UDELAY(voltage->delay); 339254885Sdumbbell } else { 340254885Sdumbbell tmp = RREG32(voltage->gpio.reg); 341254885Sdumbbell if (voltage->active_high) 342254885Sdumbbell tmp &= ~voltage->gpio.mask; 343254885Sdumbbell else 344254885Sdumbbell tmp |= voltage->gpio.mask; 345254885Sdumbbell WREG32(voltage->gpio.reg, tmp); 346254885Sdumbbell if (voltage->delay) 347254885Sdumbbell DRM_UDELAY(voltage->delay); 348254885Sdumbbell } 349254885Sdumbbell } 350254885Sdumbbell 351254885Sdumbbell sclk_cntl = RREG32_PLL(SCLK_CNTL); 352254885Sdumbbell sclk_cntl2 = RREG32_PLL(SCLK_CNTL2); 353254885Sdumbbell sclk_cntl2 &= ~REDUCED_SPEED_SCLK_SEL(3); 354254885Sdumbbell sclk_more_cntl = RREG32_PLL(SCLK_MORE_CNTL); 355254885Sdumbbell sclk_more_cntl &= ~VOLTAGE_DELAY_SEL(3); 356254885Sdumbbell if (ps->misc & ATOM_PM_MISCINFO_ASIC_REDUCED_SPEED_SCLK_EN) { 357254885Sdumbbell sclk_more_cntl |= REDUCED_SPEED_SCLK_EN; 358254885Sdumbbell if (ps->misc & ATOM_PM_MISCINFO_DYN_CLK_3D_IDLE) 359254885Sdumbbell sclk_cntl2 |= REDUCED_SPEED_SCLK_MODE; 360254885Sdumbbell else 361254885Sdumbbell sclk_cntl2 &= ~REDUCED_SPEED_SCLK_MODE; 362254885Sdumbbell if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_2) 363254885Sdumbbell sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(0); 364254885Sdumbbell else if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_CLOCK_DIVIDER_BY_4) 365254885Sdumbbell sclk_cntl2 |= REDUCED_SPEED_SCLK_SEL(2); 366254885Sdumbbell } else 367254885Sdumbbell sclk_more_cntl &= ~REDUCED_SPEED_SCLK_EN; 368254885Sdumbbell 369254885Sdumbbell if (ps->misc & ATOM_PM_MISCINFO_ASIC_DYNAMIC_VOLTAGE_EN) { 370254885Sdumbbell sclk_more_cntl |= IO_CG_VOLTAGE_DROP; 371254885Sdumbbell if (voltage->delay) { 372254885Sdumbbell sclk_more_cntl |= VOLTAGE_DROP_SYNC; 373254885Sdumbbell switch (voltage->delay) { 374254885Sdumbbell case 33: 375254885Sdumbbell sclk_more_cntl |= VOLTAGE_DELAY_SEL(0); 376254885Sdumbbell break; 377254885Sdumbbell case 66: 378254885Sdumbbell sclk_more_cntl |= VOLTAGE_DELAY_SEL(1); 379254885Sdumbbell break; 380254885Sdumbbell case 99: 381254885Sdumbbell sclk_more_cntl |= VOLTAGE_DELAY_SEL(2); 382254885Sdumbbell break; 383254885Sdumbbell case 132: 384254885Sdumbbell sclk_more_cntl |= VOLTAGE_DELAY_SEL(3); 385254885Sdumbbell break; 386254885Sdumbbell } 387254885Sdumbbell } else 388254885Sdumbbell sclk_more_cntl &= ~VOLTAGE_DROP_SYNC; 389254885Sdumbbell } else 390254885Sdumbbell sclk_more_cntl &= ~IO_CG_VOLTAGE_DROP; 391254885Sdumbbell 392254885Sdumbbell if (ps->misc & ATOM_PM_MISCINFO_DYNAMIC_HDP_BLOCK_EN) 393254885Sdumbbell sclk_cntl &= ~FORCE_HDP; 394254885Sdumbbell else 395254885Sdumbbell sclk_cntl |= FORCE_HDP; 396254885Sdumbbell 397254885Sdumbbell WREG32_PLL(SCLK_CNTL, sclk_cntl); 398254885Sdumbbell WREG32_PLL(SCLK_CNTL2, sclk_cntl2); 399254885Sdumbbell WREG32_PLL(SCLK_MORE_CNTL, sclk_more_cntl); 400254885Sdumbbell 401254885Sdumbbell /* set pcie lanes */ 402254885Sdumbbell if ((rdev->flags & RADEON_IS_PCIE) && 403254885Sdumbbell !(rdev->flags & RADEON_IS_IGP) && 404254885Sdumbbell rdev->asic->pm.set_pcie_lanes && 405254885Sdumbbell (ps->pcie_lanes != 406254885Sdumbbell rdev->pm.power_state[rdev->pm.current_power_state_index].pcie_lanes)) { 407254885Sdumbbell radeon_set_pcie_lanes(rdev, 408254885Sdumbbell ps->pcie_lanes); 409254885Sdumbbell DRM_DEBUG_DRIVER("Setting: p: %d\n", ps->pcie_lanes); 410254885Sdumbbell } 411254885Sdumbbell} 412254885Sdumbbell 413254885Sdumbbell/** 414254885Sdumbbell * r100_pm_prepare - pre-power state change callback. 415254885Sdumbbell * 416254885Sdumbbell * @rdev: radeon_device pointer 417254885Sdumbbell * 418254885Sdumbbell * Prepare for a power state change (r1xx-r4xx). 419254885Sdumbbell */ 420254885Sdumbbellvoid r100_pm_prepare(struct radeon_device *rdev) 421254885Sdumbbell{ 422254885Sdumbbell struct drm_device *ddev = rdev->ddev; 423254885Sdumbbell struct drm_crtc *crtc; 424254885Sdumbbell struct radeon_crtc *radeon_crtc; 425254885Sdumbbell u32 tmp; 426254885Sdumbbell 427254885Sdumbbell /* disable any active CRTCs */ 428254885Sdumbbell list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { 429254885Sdumbbell radeon_crtc = to_radeon_crtc(crtc); 430254885Sdumbbell if (radeon_crtc->enabled) { 431254885Sdumbbell if (radeon_crtc->crtc_id) { 432254885Sdumbbell tmp = RREG32(RADEON_CRTC2_GEN_CNTL); 433254885Sdumbbell tmp |= RADEON_CRTC2_DISP_REQ_EN_B; 434254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, tmp); 435254885Sdumbbell } else { 436254885Sdumbbell tmp = RREG32(RADEON_CRTC_GEN_CNTL); 437254885Sdumbbell tmp |= RADEON_CRTC_DISP_REQ_EN_B; 438254885Sdumbbell WREG32(RADEON_CRTC_GEN_CNTL, tmp); 439254885Sdumbbell } 440254885Sdumbbell } 441254885Sdumbbell } 442254885Sdumbbell} 443254885Sdumbbell 444254885Sdumbbell/** 445254885Sdumbbell * r100_pm_finish - post-power state change callback. 446254885Sdumbbell * 447254885Sdumbbell * @rdev: radeon_device pointer 448254885Sdumbbell * 449254885Sdumbbell * Clean up after a power state change (r1xx-r4xx). 450254885Sdumbbell */ 451254885Sdumbbellvoid r100_pm_finish(struct radeon_device *rdev) 452254885Sdumbbell{ 453254885Sdumbbell struct drm_device *ddev = rdev->ddev; 454254885Sdumbbell struct drm_crtc *crtc; 455254885Sdumbbell struct radeon_crtc *radeon_crtc; 456254885Sdumbbell u32 tmp; 457254885Sdumbbell 458254885Sdumbbell /* enable any active CRTCs */ 459254885Sdumbbell list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) { 460254885Sdumbbell radeon_crtc = to_radeon_crtc(crtc); 461254885Sdumbbell if (radeon_crtc->enabled) { 462254885Sdumbbell if (radeon_crtc->crtc_id) { 463254885Sdumbbell tmp = RREG32(RADEON_CRTC2_GEN_CNTL); 464254885Sdumbbell tmp &= ~RADEON_CRTC2_DISP_REQ_EN_B; 465254885Sdumbbell WREG32(RADEON_CRTC2_GEN_CNTL, tmp); 466254885Sdumbbell } else { 467254885Sdumbbell tmp = RREG32(RADEON_CRTC_GEN_CNTL); 468254885Sdumbbell tmp &= ~RADEON_CRTC_DISP_REQ_EN_B; 469254885Sdumbbell WREG32(RADEON_CRTC_GEN_CNTL, tmp); 470254885Sdumbbell } 471254885Sdumbbell } 472254885Sdumbbell } 473254885Sdumbbell} 474254885Sdumbbell 475254885Sdumbbell/** 476254885Sdumbbell * r100_gui_idle - gui idle callback. 477254885Sdumbbell * 478254885Sdumbbell * @rdev: radeon_device pointer 479254885Sdumbbell * 480254885Sdumbbell * Check of the GUI (2D/3D engines) are idle (r1xx-r5xx). 481254885Sdumbbell * Returns true if idle, false if not. 482254885Sdumbbell */ 483254885Sdumbbellbool r100_gui_idle(struct radeon_device *rdev) 484254885Sdumbbell{ 485254885Sdumbbell if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) 486254885Sdumbbell return false; 487254885Sdumbbell else 488254885Sdumbbell return true; 489254885Sdumbbell} 490254885Sdumbbell 491254885Sdumbbell/* hpd for digital panel detect/disconnect */ 492254885Sdumbbell/** 493254885Sdumbbell * r100_hpd_sense - hpd sense callback. 494254885Sdumbbell * 495254885Sdumbbell * @rdev: radeon_device pointer 496254885Sdumbbell * @hpd: hpd (hotplug detect) pin 497254885Sdumbbell * 498254885Sdumbbell * Checks if a digital monitor is connected (r1xx-r4xx). 499254885Sdumbbell * Returns true if connected, false if not connected. 500254885Sdumbbell */ 501254885Sdumbbellbool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) 502254885Sdumbbell{ 503254885Sdumbbell bool connected = false; 504254885Sdumbbell 505254885Sdumbbell switch (hpd) { 506254885Sdumbbell case RADEON_HPD_1: 507254885Sdumbbell if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE) 508254885Sdumbbell connected = true; 509254885Sdumbbell break; 510254885Sdumbbell case RADEON_HPD_2: 511254885Sdumbbell if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE) 512254885Sdumbbell connected = true; 513254885Sdumbbell break; 514254885Sdumbbell default: 515254885Sdumbbell break; 516254885Sdumbbell } 517254885Sdumbbell return connected; 518254885Sdumbbell} 519254885Sdumbbell 520254885Sdumbbell/** 521254885Sdumbbell * r100_hpd_set_polarity - hpd set polarity callback. 522254885Sdumbbell * 523254885Sdumbbell * @rdev: radeon_device pointer 524254885Sdumbbell * @hpd: hpd (hotplug detect) pin 525254885Sdumbbell * 526254885Sdumbbell * Set the polarity of the hpd pin (r1xx-r4xx). 527254885Sdumbbell */ 528254885Sdumbbellvoid r100_hpd_set_polarity(struct radeon_device *rdev, 529254885Sdumbbell enum radeon_hpd_id hpd) 530254885Sdumbbell{ 531254885Sdumbbell u32 tmp; 532254885Sdumbbell bool connected = r100_hpd_sense(rdev, hpd); 533254885Sdumbbell 534254885Sdumbbell switch (hpd) { 535254885Sdumbbell case RADEON_HPD_1: 536254885Sdumbbell tmp = RREG32(RADEON_FP_GEN_CNTL); 537254885Sdumbbell if (connected) 538254885Sdumbbell tmp &= ~RADEON_FP_DETECT_INT_POL; 539254885Sdumbbell else 540254885Sdumbbell tmp |= RADEON_FP_DETECT_INT_POL; 541254885Sdumbbell WREG32(RADEON_FP_GEN_CNTL, tmp); 542254885Sdumbbell break; 543254885Sdumbbell case RADEON_HPD_2: 544254885Sdumbbell tmp = RREG32(RADEON_FP2_GEN_CNTL); 545254885Sdumbbell if (connected) 546254885Sdumbbell tmp &= ~RADEON_FP2_DETECT_INT_POL; 547254885Sdumbbell else 548254885Sdumbbell tmp |= RADEON_FP2_DETECT_INT_POL; 549254885Sdumbbell WREG32(RADEON_FP2_GEN_CNTL, tmp); 550254885Sdumbbell break; 551254885Sdumbbell default: 552254885Sdumbbell break; 553254885Sdumbbell } 554254885Sdumbbell} 555254885Sdumbbell 556254885Sdumbbell/** 557254885Sdumbbell * r100_hpd_init - hpd setup callback. 558254885Sdumbbell * 559254885Sdumbbell * @rdev: radeon_device pointer 560254885Sdumbbell * 561254885Sdumbbell * Setup the hpd pins used by the card (r1xx-r4xx). 562254885Sdumbbell * Set the polarity, and enable the hpd interrupts. 563254885Sdumbbell */ 564254885Sdumbbellvoid r100_hpd_init(struct radeon_device *rdev) 565254885Sdumbbell{ 566254885Sdumbbell struct drm_device *dev = rdev->ddev; 567254885Sdumbbell struct drm_connector *connector; 568254885Sdumbbell unsigned enable = 0; 569254885Sdumbbell 570254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 571254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 572254885Sdumbbell enable |= 1 << radeon_connector->hpd.hpd; 573254885Sdumbbell radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); 574254885Sdumbbell } 575254885Sdumbbell radeon_irq_kms_enable_hpd(rdev, enable); 576254885Sdumbbell} 577254885Sdumbbell 578254885Sdumbbell/** 579254885Sdumbbell * r100_hpd_fini - hpd tear down callback. 580254885Sdumbbell * 581254885Sdumbbell * @rdev: radeon_device pointer 582254885Sdumbbell * 583254885Sdumbbell * Tear down the hpd pins used by the card (r1xx-r4xx). 584254885Sdumbbell * Disable the hpd interrupts. 585254885Sdumbbell */ 586254885Sdumbbellvoid r100_hpd_fini(struct radeon_device *rdev) 587254885Sdumbbell{ 588254885Sdumbbell struct drm_device *dev = rdev->ddev; 589254885Sdumbbell struct drm_connector *connector; 590254885Sdumbbell unsigned disable = 0; 591254885Sdumbbell 592254885Sdumbbell list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 593254885Sdumbbell struct radeon_connector *radeon_connector = to_radeon_connector(connector); 594254885Sdumbbell disable |= 1 << radeon_connector->hpd.hpd; 595254885Sdumbbell } 596254885Sdumbbell radeon_irq_kms_disable_hpd(rdev, disable); 597254885Sdumbbell} 598254885Sdumbbell 599254885Sdumbbell/* 600254885Sdumbbell * PCI GART 601254885Sdumbbell */ 602254885Sdumbbellvoid r100_pci_gart_tlb_flush(struct radeon_device *rdev) 603254885Sdumbbell{ 604254885Sdumbbell /* TODO: can we do somethings here ? */ 605254885Sdumbbell /* It seems hw only cache one entry so we should discard this 606254885Sdumbbell * entry otherwise if first GPU GART read hit this entry it 607254885Sdumbbell * could end up in wrong address. */ 608254885Sdumbbell} 609254885Sdumbbell 610254885Sdumbbellint r100_pci_gart_init(struct radeon_device *rdev) 611254885Sdumbbell{ 612254885Sdumbbell int r; 613254885Sdumbbell 614254885Sdumbbell if (rdev->gart.ptr) { 615254885Sdumbbell DRM_ERROR("R100 PCI GART already initialized\n"); 616254885Sdumbbell return 0; 617254885Sdumbbell } 618254885Sdumbbell /* Initialize common gart structure */ 619254885Sdumbbell r = radeon_gart_init(rdev); 620254885Sdumbbell if (r) 621254885Sdumbbell return r; 622254885Sdumbbell rdev->gart.table_size = rdev->gart.num_gpu_pages * 4; 623254885Sdumbbell rdev->asic->gart.tlb_flush = &r100_pci_gart_tlb_flush; 624254885Sdumbbell rdev->asic->gart.set_page = &r100_pci_gart_set_page; 625254885Sdumbbell return radeon_gart_table_ram_alloc(rdev); 626254885Sdumbbell} 627254885Sdumbbell 628254885Sdumbbellint r100_pci_gart_enable(struct radeon_device *rdev) 629254885Sdumbbell{ 630254885Sdumbbell uint32_t tmp; 631254885Sdumbbell 632254885Sdumbbell radeon_gart_restore(rdev); 633254885Sdumbbell /* discard memory request outside of configured range */ 634254885Sdumbbell tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 635254885Sdumbbell WREG32(RADEON_AIC_CNTL, tmp); 636254885Sdumbbell /* set address range for PCI address translate */ 637254885Sdumbbell WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_start); 638254885Sdumbbell WREG32(RADEON_AIC_HI_ADDR, rdev->mc.gtt_end); 639254885Sdumbbell /* set PCI GART page-table base address */ 640254885Sdumbbell WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); 641254885Sdumbbell tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; 642254885Sdumbbell WREG32(RADEON_AIC_CNTL, tmp); 643254885Sdumbbell r100_pci_gart_tlb_flush(rdev); 644254885Sdumbbell DRM_INFO("PCI GART of %uM enabled (table at 0x%016llX).\n", 645254885Sdumbbell (unsigned)(rdev->mc.gtt_size >> 20), 646254885Sdumbbell (unsigned long long)rdev->gart.table_addr); 647254885Sdumbbell rdev->gart.ready = true; 648254885Sdumbbell return 0; 649254885Sdumbbell} 650254885Sdumbbell 651254885Sdumbbellvoid r100_pci_gart_disable(struct radeon_device *rdev) 652254885Sdumbbell{ 653254885Sdumbbell uint32_t tmp; 654254885Sdumbbell 655254885Sdumbbell /* discard memory request outside of configured range */ 656254885Sdumbbell tmp = RREG32(RADEON_AIC_CNTL) | RADEON_DIS_OUT_OF_PCI_GART_ACCESS; 657254885Sdumbbell WREG32(RADEON_AIC_CNTL, tmp & ~RADEON_PCIGART_TRANSLATE_EN); 658254885Sdumbbell WREG32(RADEON_AIC_LO_ADDR, 0); 659254885Sdumbbell WREG32(RADEON_AIC_HI_ADDR, 0); 660254885Sdumbbell} 661254885Sdumbbell 662254885Sdumbbellint r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) 663254885Sdumbbell{ 664254885Sdumbbell u32 *gtt = rdev->gart.ptr; 665254885Sdumbbell 666254885Sdumbbell if (i < 0 || i > rdev->gart.num_gpu_pages) { 667254885Sdumbbell return -EINVAL; 668254885Sdumbbell } 669254885Sdumbbell gtt[i] = cpu_to_le32(lower_32_bits(addr)); 670254885Sdumbbell return 0; 671254885Sdumbbell} 672254885Sdumbbell 673254885Sdumbbellvoid r100_pci_gart_fini(struct radeon_device *rdev) 674254885Sdumbbell{ 675254885Sdumbbell radeon_gart_fini(rdev); 676254885Sdumbbell r100_pci_gart_disable(rdev); 677254885Sdumbbell radeon_gart_table_ram_free(rdev); 678254885Sdumbbell} 679254885Sdumbbell 680254885Sdumbbellint r100_irq_set(struct radeon_device *rdev) 681254885Sdumbbell{ 682254885Sdumbbell uint32_t tmp = 0; 683254885Sdumbbell 684254885Sdumbbell if (!rdev->irq.installed) { 685254885Sdumbbell DRM_ERROR("Can't enable IRQ/MSI because no handler is installed\n"); 686254885Sdumbbell WREG32(R_000040_GEN_INT_CNTL, 0); 687254885Sdumbbell return -EINVAL; 688254885Sdumbbell } 689254885Sdumbbell if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { 690254885Sdumbbell tmp |= RADEON_SW_INT_ENABLE; 691254885Sdumbbell } 692254885Sdumbbell if (rdev->irq.crtc_vblank_int[0] || 693254885Sdumbbell atomic_read(&rdev->irq.pflip[0])) { 694254885Sdumbbell tmp |= RADEON_CRTC_VBLANK_MASK; 695254885Sdumbbell } 696254885Sdumbbell if (rdev->irq.crtc_vblank_int[1] || 697254885Sdumbbell atomic_read(&rdev->irq.pflip[1])) { 698254885Sdumbbell tmp |= RADEON_CRTC2_VBLANK_MASK; 699254885Sdumbbell } 700254885Sdumbbell if (rdev->irq.hpd[0]) { 701254885Sdumbbell tmp |= RADEON_FP_DETECT_MASK; 702254885Sdumbbell } 703254885Sdumbbell if (rdev->irq.hpd[1]) { 704254885Sdumbbell tmp |= RADEON_FP2_DETECT_MASK; 705254885Sdumbbell } 706254885Sdumbbell WREG32(RADEON_GEN_INT_CNTL, tmp); 707254885Sdumbbell return 0; 708254885Sdumbbell} 709254885Sdumbbell 710254885Sdumbbellvoid r100_irq_disable(struct radeon_device *rdev) 711254885Sdumbbell{ 712254885Sdumbbell u32 tmp; 713254885Sdumbbell 714254885Sdumbbell WREG32(R_000040_GEN_INT_CNTL, 0); 715254885Sdumbbell /* Wait and acknowledge irq */ 716254885Sdumbbell DRM_MDELAY(1); 717254885Sdumbbell tmp = RREG32(R_000044_GEN_INT_STATUS); 718254885Sdumbbell WREG32(R_000044_GEN_INT_STATUS, tmp); 719254885Sdumbbell} 720254885Sdumbbell 721254885Sdumbbellstatic uint32_t r100_irq_ack(struct radeon_device *rdev) 722254885Sdumbbell{ 723254885Sdumbbell uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); 724254885Sdumbbell uint32_t irq_mask = RADEON_SW_INT_TEST | 725254885Sdumbbell RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT | 726254885Sdumbbell RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT; 727254885Sdumbbell 728254885Sdumbbell if (irqs) { 729254885Sdumbbell WREG32(RADEON_GEN_INT_STATUS, irqs); 730254885Sdumbbell } 731254885Sdumbbell return irqs & irq_mask; 732254885Sdumbbell} 733254885Sdumbbell 734254885Sdumbbellirqreturn_t r100_irq_process(struct radeon_device *rdev) 735254885Sdumbbell{ 736254885Sdumbbell uint32_t status, msi_rearm; 737254885Sdumbbell bool queue_hotplug = false; 738254885Sdumbbell 739254885Sdumbbell status = r100_irq_ack(rdev); 740254885Sdumbbell if (!status) { 741254885Sdumbbell return IRQ_NONE; 742254885Sdumbbell } 743254885Sdumbbell if (rdev->shutdown) { 744254885Sdumbbell return IRQ_NONE; 745254885Sdumbbell } 746254885Sdumbbell while (status) { 747254885Sdumbbell /* SW interrupt */ 748254885Sdumbbell if (status & RADEON_SW_INT_TEST) { 749254885Sdumbbell radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); 750254885Sdumbbell } 751254885Sdumbbell /* Vertical blank interrupts */ 752254885Sdumbbell if (status & RADEON_CRTC_VBLANK_STAT) { 753254885Sdumbbell if (rdev->irq.crtc_vblank_int[0]) { 754254885Sdumbbell drm_handle_vblank(rdev->ddev, 0); 755254885Sdumbbell rdev->pm.vblank_sync = true; 756254885Sdumbbell DRM_WAKEUP(&rdev->irq.vblank_queue); 757254885Sdumbbell } 758254885Sdumbbell if (atomic_read(&rdev->irq.pflip[0])) 759254885Sdumbbell radeon_crtc_handle_flip(rdev, 0); 760254885Sdumbbell } 761254885Sdumbbell if (status & RADEON_CRTC2_VBLANK_STAT) { 762254885Sdumbbell if (rdev->irq.crtc_vblank_int[1]) { 763254885Sdumbbell drm_handle_vblank(rdev->ddev, 1); 764254885Sdumbbell rdev->pm.vblank_sync = true; 765254885Sdumbbell DRM_WAKEUP(&rdev->irq.vblank_queue); 766254885Sdumbbell } 767254885Sdumbbell if (atomic_read(&rdev->irq.pflip[1])) 768254885Sdumbbell radeon_crtc_handle_flip(rdev, 1); 769254885Sdumbbell } 770254885Sdumbbell if (status & RADEON_FP_DETECT_STAT) { 771254885Sdumbbell queue_hotplug = true; 772254885Sdumbbell DRM_DEBUG("HPD1\n"); 773254885Sdumbbell } 774254885Sdumbbell if (status & RADEON_FP2_DETECT_STAT) { 775254885Sdumbbell queue_hotplug = true; 776254885Sdumbbell DRM_DEBUG("HPD2\n"); 777254885Sdumbbell } 778254885Sdumbbell status = r100_irq_ack(rdev); 779254885Sdumbbell } 780254885Sdumbbell if (queue_hotplug) 781254885Sdumbbell taskqueue_enqueue(rdev->tq, &rdev->hotplug_work); 782254885Sdumbbell if (rdev->msi_enabled) { 783254885Sdumbbell switch (rdev->family) { 784254885Sdumbbell case CHIP_RS400: 785254885Sdumbbell case CHIP_RS480: 786254885Sdumbbell msi_rearm = RREG32(RADEON_AIC_CNTL) & ~RS400_MSI_REARM; 787254885Sdumbbell WREG32(RADEON_AIC_CNTL, msi_rearm); 788254885Sdumbbell WREG32(RADEON_AIC_CNTL, msi_rearm | RS400_MSI_REARM); 789254885Sdumbbell break; 790254885Sdumbbell default: 791254885Sdumbbell WREG32(RADEON_MSI_REARM_EN, RV370_MSI_REARM_EN); 792254885Sdumbbell break; 793254885Sdumbbell } 794254885Sdumbbell } 795254885Sdumbbell return IRQ_HANDLED; 796254885Sdumbbell} 797254885Sdumbbell 798254885Sdumbbellu32 r100_get_vblank_counter(struct radeon_device *rdev, int crtc) 799254885Sdumbbell{ 800254885Sdumbbell if (crtc == 0) 801254885Sdumbbell return RREG32(RADEON_CRTC_CRNT_FRAME); 802254885Sdumbbell else 803254885Sdumbbell return RREG32(RADEON_CRTC2_CRNT_FRAME); 804254885Sdumbbell} 805254885Sdumbbell 806254885Sdumbbell/* Who ever call radeon_fence_emit should call ring_lock and ask 807254885Sdumbbell * for enough space (today caller are ib schedule and buffer move) */ 808254885Sdumbbellvoid r100_fence_ring_emit(struct radeon_device *rdev, 809254885Sdumbbell struct radeon_fence *fence) 810254885Sdumbbell{ 811254885Sdumbbell struct radeon_ring *ring = &rdev->ring[fence->ring]; 812254885Sdumbbell 813254885Sdumbbell /* We have to make sure that caches are flushed before 814254885Sdumbbell * CPU might read something from VRAM. */ 815254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); 816254885Sdumbbell radeon_ring_write(ring, RADEON_RB3D_DC_FLUSH_ALL); 817254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); 818254885Sdumbbell radeon_ring_write(ring, RADEON_RB3D_ZC_FLUSH_ALL); 819254885Sdumbbell /* Wait until IDLE & CLEAN */ 820254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 821254885Sdumbbell radeon_ring_write(ring, RADEON_WAIT_2D_IDLECLEAN | RADEON_WAIT_3D_IDLECLEAN); 822254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); 823254885Sdumbbell radeon_ring_write(ring, rdev->config.r100.hdp_cntl | 824254885Sdumbbell RADEON_HDP_READ_BUFFER_INVALIDATE); 825254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0)); 826254885Sdumbbell radeon_ring_write(ring, rdev->config.r100.hdp_cntl); 827254885Sdumbbell /* Emit fence sequence & fire IRQ */ 828254885Sdumbbell radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0)); 829254885Sdumbbell radeon_ring_write(ring, fence->seq); 830254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0)); 831254885Sdumbbell radeon_ring_write(ring, RADEON_SW_INT_FIRE); 832254885Sdumbbell} 833254885Sdumbbell 834254885Sdumbbellvoid r100_semaphore_ring_emit(struct radeon_device *rdev, 835254885Sdumbbell struct radeon_ring *ring, 836254885Sdumbbell struct radeon_semaphore *semaphore, 837254885Sdumbbell bool emit_wait) 838254885Sdumbbell{ 839254885Sdumbbell /* Unused on older asics, since we don't have semaphores or multiple rings */ 840254885Sdumbbell panic("%s: Unused on older asics", __func__); 841254885Sdumbbell} 842254885Sdumbbell 843254885Sdumbbellint r100_copy_blit(struct radeon_device *rdev, 844254885Sdumbbell uint64_t src_offset, 845254885Sdumbbell uint64_t dst_offset, 846254885Sdumbbell unsigned num_gpu_pages, 847254885Sdumbbell struct radeon_fence **fence) 848254885Sdumbbell{ 849254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 850254885Sdumbbell uint32_t cur_pages; 851254885Sdumbbell uint32_t stride_bytes = RADEON_GPU_PAGE_SIZE; 852254885Sdumbbell uint32_t pitch; 853254885Sdumbbell uint32_t stride_pixels; 854254885Sdumbbell unsigned ndw; 855254885Sdumbbell int num_loops; 856254885Sdumbbell int r = 0; 857254885Sdumbbell 858254885Sdumbbell /* radeon limited to 16k stride */ 859254885Sdumbbell stride_bytes &= 0x3fff; 860254885Sdumbbell /* radeon pitch is /64 */ 861254885Sdumbbell pitch = stride_bytes / 64; 862254885Sdumbbell stride_pixels = stride_bytes / 4; 863254885Sdumbbell num_loops = DIV_ROUND_UP(num_gpu_pages, 8191); 864254885Sdumbbell 865254885Sdumbbell /* Ask for enough room for blit + flush + fence */ 866254885Sdumbbell ndw = 64 + (10 * num_loops); 867254885Sdumbbell r = radeon_ring_lock(rdev, ring, ndw); 868254885Sdumbbell if (r) { 869254885Sdumbbell DRM_ERROR("radeon: moving bo (%d) asking for %u dw.\n", r, ndw); 870254885Sdumbbell return -EINVAL; 871254885Sdumbbell } 872254885Sdumbbell while (num_gpu_pages > 0) { 873254885Sdumbbell cur_pages = num_gpu_pages; 874254885Sdumbbell if (cur_pages > 8191) { 875254885Sdumbbell cur_pages = 8191; 876254885Sdumbbell } 877254885Sdumbbell num_gpu_pages -= cur_pages; 878254885Sdumbbell 879254885Sdumbbell /* pages are in Y direction - height 880254885Sdumbbell page width in X direction - width */ 881254885Sdumbbell radeon_ring_write(ring, PACKET3(PACKET3_BITBLT_MULTI, 8)); 882254885Sdumbbell radeon_ring_write(ring, 883254885Sdumbbell RADEON_GMC_SRC_PITCH_OFFSET_CNTL | 884254885Sdumbbell RADEON_GMC_DST_PITCH_OFFSET_CNTL | 885254885Sdumbbell RADEON_GMC_SRC_CLIPPING | 886254885Sdumbbell RADEON_GMC_DST_CLIPPING | 887254885Sdumbbell RADEON_GMC_BRUSH_NONE | 888254885Sdumbbell (RADEON_COLOR_FORMAT_ARGB8888 << 8) | 889254885Sdumbbell RADEON_GMC_SRC_DATATYPE_COLOR | 890254885Sdumbbell RADEON_ROP3_S | 891254885Sdumbbell RADEON_DP_SRC_SOURCE_MEMORY | 892254885Sdumbbell RADEON_GMC_CLR_CMP_CNTL_DIS | 893254885Sdumbbell RADEON_GMC_WR_MSK_DIS); 894254885Sdumbbell radeon_ring_write(ring, (pitch << 22) | (src_offset >> 10)); 895254885Sdumbbell radeon_ring_write(ring, (pitch << 22) | (dst_offset >> 10)); 896254885Sdumbbell radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); 897254885Sdumbbell radeon_ring_write(ring, 0); 898254885Sdumbbell radeon_ring_write(ring, (0x1fff) | (0x1fff << 16)); 899254885Sdumbbell radeon_ring_write(ring, num_gpu_pages); 900254885Sdumbbell radeon_ring_write(ring, num_gpu_pages); 901254885Sdumbbell radeon_ring_write(ring, cur_pages | (stride_pixels << 16)); 902254885Sdumbbell } 903254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_DSTCACHE_CTLSTAT, 0)); 904254885Sdumbbell radeon_ring_write(ring, RADEON_RB2D_DC_FLUSH_ALL); 905254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0)); 906254885Sdumbbell radeon_ring_write(ring, 907254885Sdumbbell RADEON_WAIT_2D_IDLECLEAN | 908254885Sdumbbell RADEON_WAIT_HOST_IDLECLEAN | 909254885Sdumbbell RADEON_WAIT_DMA_GUI_IDLE); 910254885Sdumbbell if (fence) { 911254885Sdumbbell r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX); 912254885Sdumbbell } 913254885Sdumbbell radeon_ring_unlock_commit(rdev, ring); 914254885Sdumbbell return r; 915254885Sdumbbell} 916254885Sdumbbell 917254885Sdumbbellstatic int r100_cp_wait_for_idle(struct radeon_device *rdev) 918254885Sdumbbell{ 919254885Sdumbbell unsigned i; 920254885Sdumbbell u32 tmp; 921254885Sdumbbell 922254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 923254885Sdumbbell tmp = RREG32(R_000E40_RBBM_STATUS); 924254885Sdumbbell if (!G_000E40_CP_CMDSTRM_BUSY(tmp)) { 925254885Sdumbbell return 0; 926254885Sdumbbell } 927254885Sdumbbell DRM_UDELAY(1); 928254885Sdumbbell } 929254885Sdumbbell return -1; 930254885Sdumbbell} 931254885Sdumbbell 932254885Sdumbbellvoid r100_ring_start(struct radeon_device *rdev, struct radeon_ring *ring) 933254885Sdumbbell{ 934254885Sdumbbell int r; 935254885Sdumbbell 936254885Sdumbbell r = radeon_ring_lock(rdev, ring, 2); 937254885Sdumbbell if (r) { 938254885Sdumbbell return; 939254885Sdumbbell } 940254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0)); 941254885Sdumbbell radeon_ring_write(ring, 942254885Sdumbbell RADEON_ISYNC_ANY2D_IDLE3D | 943254885Sdumbbell RADEON_ISYNC_ANY3D_IDLE2D | 944254885Sdumbbell RADEON_ISYNC_WAIT_IDLEGUI | 945254885Sdumbbell RADEON_ISYNC_CPSCRATCH_IDLEGUI); 946254885Sdumbbell radeon_ring_unlock_commit(rdev, ring); 947254885Sdumbbell} 948254885Sdumbbell 949254885Sdumbbell 950254885Sdumbbell/* Load the microcode for the CP */ 951254885Sdumbbellstatic int r100_cp_init_microcode(struct radeon_device *rdev) 952254885Sdumbbell{ 953254885Sdumbbell const char *fw_name = NULL; 954254885Sdumbbell int err; 955254885Sdumbbell 956254885Sdumbbell DRM_DEBUG_KMS("\n"); 957254885Sdumbbell 958254885Sdumbbell if ((rdev->family == CHIP_R100) || (rdev->family == CHIP_RV100) || 959254885Sdumbbell (rdev->family == CHIP_RV200) || (rdev->family == CHIP_RS100) || 960254885Sdumbbell (rdev->family == CHIP_RS200)) { 961254885Sdumbbell DRM_INFO("Loading R100 Microcode\n"); 962254885Sdumbbell fw_name = FIRMWARE_R100; 963254885Sdumbbell } else if ((rdev->family == CHIP_R200) || 964254885Sdumbbell (rdev->family == CHIP_RV250) || 965254885Sdumbbell (rdev->family == CHIP_RV280) || 966254885Sdumbbell (rdev->family == CHIP_RS300)) { 967254885Sdumbbell DRM_INFO("Loading R200 Microcode\n"); 968254885Sdumbbell fw_name = FIRMWARE_R200; 969254885Sdumbbell } else if ((rdev->family == CHIP_R300) || 970254885Sdumbbell (rdev->family == CHIP_R350) || 971254885Sdumbbell (rdev->family == CHIP_RV350) || 972254885Sdumbbell (rdev->family == CHIP_RV380) || 973254885Sdumbbell (rdev->family == CHIP_RS400) || 974254885Sdumbbell (rdev->family == CHIP_RS480)) { 975254885Sdumbbell DRM_INFO("Loading R300 Microcode\n"); 976254885Sdumbbell fw_name = FIRMWARE_R300; 977254885Sdumbbell } else if ((rdev->family == CHIP_R420) || 978254885Sdumbbell (rdev->family == CHIP_R423) || 979254885Sdumbbell (rdev->family == CHIP_RV410)) { 980254885Sdumbbell DRM_INFO("Loading R400 Microcode\n"); 981254885Sdumbbell fw_name = FIRMWARE_R420; 982254885Sdumbbell } else if ((rdev->family == CHIP_RS690) || 983254885Sdumbbell (rdev->family == CHIP_RS740)) { 984254885Sdumbbell DRM_INFO("Loading RS690/RS740 Microcode\n"); 985254885Sdumbbell fw_name = FIRMWARE_RS690; 986254885Sdumbbell } else if (rdev->family == CHIP_RS600) { 987254885Sdumbbell DRM_INFO("Loading RS600 Microcode\n"); 988254885Sdumbbell fw_name = FIRMWARE_RS600; 989254885Sdumbbell } else if ((rdev->family == CHIP_RV515) || 990254885Sdumbbell (rdev->family == CHIP_R520) || 991254885Sdumbbell (rdev->family == CHIP_RV530) || 992254885Sdumbbell (rdev->family == CHIP_R580) || 993254885Sdumbbell (rdev->family == CHIP_RV560) || 994254885Sdumbbell (rdev->family == CHIP_RV570)) { 995254885Sdumbbell DRM_INFO("Loading R500 Microcode\n"); 996254885Sdumbbell fw_name = FIRMWARE_R520; 997254885Sdumbbell } 998254885Sdumbbell 999254885Sdumbbell err = 0; 1000254885Sdumbbell rdev->me_fw = firmware_get(fw_name); 1001254885Sdumbbell if (rdev->me_fw == NULL) { 1002254885Sdumbbell DRM_ERROR("radeon_cp: Failed to load firmware \"%s\"\n", 1003254885Sdumbbell fw_name); 1004254885Sdumbbell err = -ENOENT; 1005254885Sdumbbell } else if (rdev->me_fw->datasize % 8) { 1006254885Sdumbbell DRM_ERROR( 1007254885Sdumbbell "radeon_cp: Bogus length %zu in firmware \"%s\"\n", 1008254885Sdumbbell rdev->me_fw->datasize, fw_name); 1009254885Sdumbbell err = -EINVAL; 1010254885Sdumbbell firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); 1011254885Sdumbbell rdev->me_fw = NULL; 1012254885Sdumbbell } 1013254885Sdumbbell return err; 1014254885Sdumbbell} 1015254885Sdumbbell 1016254885Sdumbbell/** 1017254885Sdumbbell * r100_cp_fini_microcode - drop the firmware image reference 1018254885Sdumbbell * 1019254885Sdumbbell * @rdev: radeon_device pointer 1020254885Sdumbbell * 1021254885Sdumbbell * Drop the me firmware image reference. 1022254885Sdumbbell * Called at driver shutdown. 1023254885Sdumbbell */ 1024254885Sdumbbellstatic void r100_cp_fini_microcode (struct radeon_device *rdev) 1025254885Sdumbbell{ 1026254885Sdumbbell 1027254885Sdumbbell if (rdev->me_fw != NULL) { 1028254885Sdumbbell firmware_put(rdev->me_fw, FIRMWARE_UNLOAD); 1029254885Sdumbbell rdev->me_fw = NULL; 1030254885Sdumbbell } 1031254885Sdumbbell} 1032254885Sdumbbell 1033254885Sdumbbellstatic void r100_cp_load_microcode(struct radeon_device *rdev) 1034254885Sdumbbell{ 1035254885Sdumbbell const __be32 *fw_data; 1036254885Sdumbbell int i, size; 1037254885Sdumbbell 1038254885Sdumbbell if (r100_gui_wait_for_idle(rdev)) { 1039254885Sdumbbell DRM_ERROR("Failed to wait GUI idle while " 1040254885Sdumbbell "programming pipes. Bad things might happen.\n"); 1041254885Sdumbbell } 1042254885Sdumbbell 1043254885Sdumbbell if (rdev->me_fw) { 1044254885Sdumbbell size = rdev->me_fw->datasize / 4; 1045254885Sdumbbell fw_data = (const __be32 *)rdev->me_fw->data; 1046254885Sdumbbell WREG32(RADEON_CP_ME_RAM_ADDR, 0); 1047254885Sdumbbell for (i = 0; i < size; i += 2) { 1048254885Sdumbbell WREG32(RADEON_CP_ME_RAM_DATAH, 1049254885Sdumbbell be32_to_cpup(&fw_data[i])); 1050254885Sdumbbell WREG32(RADEON_CP_ME_RAM_DATAL, 1051254885Sdumbbell be32_to_cpup(&fw_data[i + 1])); 1052254885Sdumbbell } 1053254885Sdumbbell } 1054254885Sdumbbell} 1055254885Sdumbbell 1056254885Sdumbbellint r100_cp_init(struct radeon_device *rdev, unsigned ring_size) 1057254885Sdumbbell{ 1058254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 1059254885Sdumbbell unsigned rb_bufsz; 1060254885Sdumbbell unsigned rb_blksz; 1061254885Sdumbbell unsigned max_fetch; 1062254885Sdumbbell unsigned pre_write_timer; 1063254885Sdumbbell unsigned pre_write_limit; 1064254885Sdumbbell unsigned indirect2_start; 1065254885Sdumbbell unsigned indirect1_start; 1066254885Sdumbbell uint32_t tmp; 1067254885Sdumbbell int r; 1068254885Sdumbbell 1069254885Sdumbbell if (r100_debugfs_cp_init(rdev)) { 1070254885Sdumbbell DRM_ERROR("Failed to register debugfs file for CP !\n"); 1071254885Sdumbbell } 1072254885Sdumbbell if (!rdev->me_fw) { 1073254885Sdumbbell r = r100_cp_init_microcode(rdev); 1074254885Sdumbbell if (r) { 1075254885Sdumbbell DRM_ERROR("Failed to load firmware!\n"); 1076254885Sdumbbell return r; 1077254885Sdumbbell } 1078254885Sdumbbell } 1079254885Sdumbbell 1080254885Sdumbbell /* Align ring size */ 1081254885Sdumbbell rb_bufsz = drm_order(ring_size / 8); 1082254885Sdumbbell ring_size = (1 << (rb_bufsz + 1)) * 4; 1083254885Sdumbbell r100_cp_load_microcode(rdev); 1084254885Sdumbbell r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET, 1085254885Sdumbbell RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR, 1086254885Sdumbbell 0, 0x7fffff, RADEON_CP_PACKET2); 1087254885Sdumbbell if (r) { 1088254885Sdumbbell return r; 1089254885Sdumbbell } 1090254885Sdumbbell /* Each time the cp read 1024 bytes (16 dword/quadword) update 1091254885Sdumbbell * the rptr copy in system ram */ 1092254885Sdumbbell rb_blksz = 9; 1093254885Sdumbbell /* cp will read 128bytes at a time (4 dwords) */ 1094254885Sdumbbell max_fetch = 1; 1095254885Sdumbbell ring->align_mask = 16 - 1; 1096254885Sdumbbell /* Write to CP_RB_WPTR will be delayed for pre_write_timer clocks */ 1097254885Sdumbbell pre_write_timer = 64; 1098254885Sdumbbell /* Force CP_RB_WPTR write if written more than one time before the 1099254885Sdumbbell * delay expire 1100254885Sdumbbell */ 1101254885Sdumbbell pre_write_limit = 0; 1102254885Sdumbbell /* Setup the cp cache like this (cache size is 96 dwords) : 1103254885Sdumbbell * RING 0 to 15 1104254885Sdumbbell * INDIRECT1 16 to 79 1105254885Sdumbbell * INDIRECT2 80 to 95 1106254885Sdumbbell * So ring cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 1107254885Sdumbbell * indirect1 cache size is 64dwords (> (2 * max_fetch = 2 * 4dwords)) 1108254885Sdumbbell * indirect2 cache size is 16dwords (> (2 * max_fetch = 2 * 4dwords)) 1109254885Sdumbbell * Idea being that most of the gpu cmd will be through indirect1 buffer 1110254885Sdumbbell * so it gets the bigger cache. 1111254885Sdumbbell */ 1112254885Sdumbbell indirect2_start = 80; 1113254885Sdumbbell indirect1_start = 16; 1114254885Sdumbbell /* cp setup */ 1115254885Sdumbbell WREG32(0x718, pre_write_timer | (pre_write_limit << 28)); 1116254885Sdumbbell tmp = (REG_SET(RADEON_RB_BUFSZ, rb_bufsz) | 1117254885Sdumbbell REG_SET(RADEON_RB_BLKSZ, rb_blksz) | 1118254885Sdumbbell REG_SET(RADEON_MAX_FETCH, max_fetch)); 1119254885Sdumbbell#ifdef __BIG_ENDIAN 1120254885Sdumbbell tmp |= RADEON_BUF_SWAP_32BIT; 1121254885Sdumbbell#endif 1122254885Sdumbbell WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_NO_UPDATE); 1123254885Sdumbbell 1124254885Sdumbbell /* Set ring address */ 1125254885Sdumbbell DRM_INFO("radeon: ring at 0x%016lX\n", (unsigned long)ring->gpu_addr); 1126254885Sdumbbell WREG32(RADEON_CP_RB_BASE, ring->gpu_addr); 1127254885Sdumbbell /* Force read & write ptr to 0 */ 1128254885Sdumbbell WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA | RADEON_RB_NO_UPDATE); 1129254885Sdumbbell WREG32(RADEON_CP_RB_RPTR_WR, 0); 1130254885Sdumbbell ring->wptr = 0; 1131254885Sdumbbell WREG32(RADEON_CP_RB_WPTR, ring->wptr); 1132254885Sdumbbell 1133254885Sdumbbell /* set the wb address whether it's enabled or not */ 1134254885Sdumbbell WREG32(R_00070C_CP_RB_RPTR_ADDR, 1135254885Sdumbbell S_00070C_RB_RPTR_ADDR((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) >> 2)); 1136254885Sdumbbell WREG32(R_000774_SCRATCH_ADDR, rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET); 1137254885Sdumbbell 1138254885Sdumbbell if (rdev->wb.enabled) 1139254885Sdumbbell WREG32(R_000770_SCRATCH_UMSK, 0xff); 1140254885Sdumbbell else { 1141254885Sdumbbell tmp |= RADEON_RB_NO_UPDATE; 1142254885Sdumbbell WREG32(R_000770_SCRATCH_UMSK, 0); 1143254885Sdumbbell } 1144254885Sdumbbell 1145254885Sdumbbell WREG32(RADEON_CP_RB_CNTL, tmp); 1146254885Sdumbbell DRM_UDELAY(10); 1147254885Sdumbbell ring->rptr = RREG32(RADEON_CP_RB_RPTR); 1148254885Sdumbbell /* Set cp mode to bus mastering & enable cp*/ 1149254885Sdumbbell WREG32(RADEON_CP_CSQ_MODE, 1150254885Sdumbbell REG_SET(RADEON_INDIRECT2_START, indirect2_start) | 1151254885Sdumbbell REG_SET(RADEON_INDIRECT1_START, indirect1_start)); 1152254885Sdumbbell WREG32(RADEON_CP_RB_WPTR_DELAY, 0); 1153254885Sdumbbell WREG32(RADEON_CP_CSQ_MODE, 0x00004D4D); 1154254885Sdumbbell WREG32(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM); 1155254885Sdumbbell 1156254885Sdumbbell /* at this point everything should be setup correctly to enable master */ 1157254885Sdumbbell pci_enable_busmaster(rdev->dev); 1158254885Sdumbbell 1159254885Sdumbbell radeon_ring_start(rdev, RADEON_RING_TYPE_GFX_INDEX, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); 1160254885Sdumbbell r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); 1161254885Sdumbbell if (r) { 1162254885Sdumbbell DRM_ERROR("radeon: cp isn't working (%d).\n", r); 1163254885Sdumbbell return r; 1164254885Sdumbbell } 1165254885Sdumbbell ring->ready = true; 1166254885Sdumbbell radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); 1167254885Sdumbbell 1168254885Sdumbbell if (!ring->rptr_save_reg /* not resuming from suspend */ 1169254885Sdumbbell && radeon_ring_supports_scratch_reg(rdev, ring)) { 1170254885Sdumbbell r = radeon_scratch_get(rdev, &ring->rptr_save_reg); 1171254885Sdumbbell if (r) { 1172254885Sdumbbell DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); 1173254885Sdumbbell ring->rptr_save_reg = 0; 1174254885Sdumbbell } 1175254885Sdumbbell } 1176254885Sdumbbell return 0; 1177254885Sdumbbell} 1178254885Sdumbbell 1179254885Sdumbbellvoid r100_cp_fini(struct radeon_device *rdev) 1180254885Sdumbbell{ 1181254885Sdumbbell if (r100_cp_wait_for_idle(rdev)) { 1182254885Sdumbbell DRM_ERROR("Wait for CP idle timeout, shutting down CP.\n"); 1183254885Sdumbbell } 1184254885Sdumbbell /* Disable ring */ 1185254885Sdumbbell r100_cp_disable(rdev); 1186254885Sdumbbell radeon_scratch_free(rdev, rdev->ring[RADEON_RING_TYPE_GFX_INDEX].rptr_save_reg); 1187254885Sdumbbell radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); 1188254885Sdumbbell DRM_INFO("radeon: cp finalized\n"); 1189254885Sdumbbell} 1190254885Sdumbbell 1191254885Sdumbbellvoid r100_cp_disable(struct radeon_device *rdev) 1192254885Sdumbbell{ 1193254885Sdumbbell /* Disable ring */ 1194254885Sdumbbell radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); 1195254885Sdumbbell rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; 1196254885Sdumbbell WREG32(RADEON_CP_CSQ_MODE, 0); 1197254885Sdumbbell WREG32(RADEON_CP_CSQ_CNTL, 0); 1198254885Sdumbbell WREG32(R_000770_SCRATCH_UMSK, 0); 1199254885Sdumbbell if (r100_gui_wait_for_idle(rdev)) { 1200254885Sdumbbell DRM_ERROR("Failed to wait GUI idle while " 1201254885Sdumbbell "programming pipes. Bad things might happen.\n"); 1202254885Sdumbbell } 1203254885Sdumbbell} 1204254885Sdumbbell 1205254885Sdumbbell/* 1206254885Sdumbbell * CS functions 1207254885Sdumbbell */ 1208254885Sdumbbellint r100_reloc_pitch_offset(struct radeon_cs_parser *p, 1209254885Sdumbbell struct radeon_cs_packet *pkt, 1210254885Sdumbbell unsigned idx, 1211254885Sdumbbell unsigned reg) 1212254885Sdumbbell{ 1213254885Sdumbbell int r; 1214254885Sdumbbell u32 tile_flags = 0; 1215254885Sdumbbell u32 tmp; 1216254885Sdumbbell struct radeon_cs_reloc *reloc; 1217254885Sdumbbell u32 value; 1218254885Sdumbbell 1219254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1220254885Sdumbbell if (r) { 1221254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1222254885Sdumbbell idx, reg); 1223254885Sdumbbell r100_cs_dump_packet(p, pkt); 1224254885Sdumbbell return r; 1225254885Sdumbbell } 1226254885Sdumbbell 1227254885Sdumbbell value = radeon_get_ib_value(p, idx); 1228254885Sdumbbell tmp = value & 0x003fffff; 1229254885Sdumbbell tmp += (((u32)reloc->lobj.gpu_offset) >> 10); 1230254885Sdumbbell 1231254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1232254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1233254885Sdumbbell tile_flags |= RADEON_DST_TILE_MACRO; 1234254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { 1235254885Sdumbbell if (reg == RADEON_SRC_PITCH_OFFSET) { 1236254885Sdumbbell DRM_ERROR("Cannot src blit from microtiled surface\n"); 1237254885Sdumbbell r100_cs_dump_packet(p, pkt); 1238254885Sdumbbell return -EINVAL; 1239254885Sdumbbell } 1240254885Sdumbbell tile_flags |= RADEON_DST_TILE_MICRO; 1241254885Sdumbbell } 1242254885Sdumbbell 1243254885Sdumbbell tmp |= tile_flags; 1244254885Sdumbbell p->ib.ptr[idx] = (value & 0x3fc00000) | tmp; 1245254885Sdumbbell } else 1246254885Sdumbbell p->ib.ptr[idx] = (value & 0xffc00000) | tmp; 1247254885Sdumbbell return 0; 1248254885Sdumbbell} 1249254885Sdumbbell 1250254885Sdumbbellint r100_packet3_load_vbpntr(struct radeon_cs_parser *p, 1251254885Sdumbbell struct radeon_cs_packet *pkt, 1252254885Sdumbbell int idx) 1253254885Sdumbbell{ 1254254885Sdumbbell unsigned c, i; 1255254885Sdumbbell struct radeon_cs_reloc *reloc; 1256254885Sdumbbell struct r100_cs_track *track; 1257254885Sdumbbell int r = 0; 1258254885Sdumbbell volatile uint32_t *ib; 1259254885Sdumbbell u32 idx_value; 1260254885Sdumbbell 1261254885Sdumbbell ib = p->ib.ptr; 1262254885Sdumbbell track = (struct r100_cs_track *)p->track; 1263254885Sdumbbell c = radeon_get_ib_value(p, idx++) & 0x1F; 1264254885Sdumbbell if (c > 16) { 1265254885Sdumbbell DRM_ERROR("Only 16 vertex buffers are allowed %d\n", 1266254885Sdumbbell pkt->opcode); 1267254885Sdumbbell r100_cs_dump_packet(p, pkt); 1268254885Sdumbbell return -EINVAL; 1269254885Sdumbbell } 1270254885Sdumbbell track->num_arrays = c; 1271254885Sdumbbell for (i = 0; i < (c - 1); i+=2, idx+=3) { 1272254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1273254885Sdumbbell if (r) { 1274254885Sdumbbell DRM_ERROR("No reloc for packet3 %d\n", 1275254885Sdumbbell pkt->opcode); 1276254885Sdumbbell r100_cs_dump_packet(p, pkt); 1277254885Sdumbbell return r; 1278254885Sdumbbell } 1279254885Sdumbbell idx_value = radeon_get_ib_value(p, idx); 1280254885Sdumbbell ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); 1281254885Sdumbbell 1282254885Sdumbbell track->arrays[i + 0].esize = idx_value >> 8; 1283254885Sdumbbell track->arrays[i + 0].robj = reloc->robj; 1284254885Sdumbbell track->arrays[i + 0].esize &= 0x7F; 1285254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1286254885Sdumbbell if (r) { 1287254885Sdumbbell DRM_ERROR("No reloc for packet3 %d\n", 1288254885Sdumbbell pkt->opcode); 1289254885Sdumbbell r100_cs_dump_packet(p, pkt); 1290254885Sdumbbell return r; 1291254885Sdumbbell } 1292254885Sdumbbell ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); 1293254885Sdumbbell track->arrays[i + 1].robj = reloc->robj; 1294254885Sdumbbell track->arrays[i + 1].esize = idx_value >> 24; 1295254885Sdumbbell track->arrays[i + 1].esize &= 0x7F; 1296254885Sdumbbell } 1297254885Sdumbbell if (c & 1) { 1298254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1299254885Sdumbbell if (r) { 1300254885Sdumbbell DRM_ERROR("No reloc for packet3 %d\n", 1301254885Sdumbbell pkt->opcode); 1302254885Sdumbbell r100_cs_dump_packet(p, pkt); 1303254885Sdumbbell return r; 1304254885Sdumbbell } 1305254885Sdumbbell idx_value = radeon_get_ib_value(p, idx); 1306254885Sdumbbell ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); 1307254885Sdumbbell track->arrays[i + 0].robj = reloc->robj; 1308254885Sdumbbell track->arrays[i + 0].esize = idx_value >> 8; 1309254885Sdumbbell track->arrays[i + 0].esize &= 0x7F; 1310254885Sdumbbell } 1311254885Sdumbbell return r; 1312254885Sdumbbell} 1313254885Sdumbbell 1314254885Sdumbbellint r100_cs_parse_packet0(struct radeon_cs_parser *p, 1315254885Sdumbbell struct radeon_cs_packet *pkt, 1316254885Sdumbbell const unsigned *auth, unsigned n, 1317254885Sdumbbell radeon_packet0_check_t check) 1318254885Sdumbbell{ 1319254885Sdumbbell unsigned reg; 1320254885Sdumbbell unsigned i, j, m; 1321254885Sdumbbell unsigned idx; 1322254885Sdumbbell int r; 1323254885Sdumbbell 1324254885Sdumbbell idx = pkt->idx + 1; 1325254885Sdumbbell reg = pkt->reg; 1326254885Sdumbbell /* Check that register fall into register range 1327254885Sdumbbell * determined by the number of entry (n) in the 1328254885Sdumbbell * safe register bitmap. 1329254885Sdumbbell */ 1330254885Sdumbbell if (pkt->one_reg_wr) { 1331254885Sdumbbell if ((reg >> 7) > n) { 1332254885Sdumbbell return -EINVAL; 1333254885Sdumbbell } 1334254885Sdumbbell } else { 1335254885Sdumbbell if (((reg + (pkt->count << 2)) >> 7) > n) { 1336254885Sdumbbell return -EINVAL; 1337254885Sdumbbell } 1338254885Sdumbbell } 1339254885Sdumbbell for (i = 0; i <= pkt->count; i++, idx++) { 1340254885Sdumbbell j = (reg >> 7); 1341254885Sdumbbell m = 1 << ((reg >> 2) & 31); 1342254885Sdumbbell if (auth[j] & m) { 1343254885Sdumbbell r = check(p, pkt, idx, reg); 1344254885Sdumbbell if (r) { 1345254885Sdumbbell return r; 1346254885Sdumbbell } 1347254885Sdumbbell } 1348254885Sdumbbell if (pkt->one_reg_wr) { 1349254885Sdumbbell if (!(auth[j] & m)) { 1350254885Sdumbbell break; 1351254885Sdumbbell } 1352254885Sdumbbell } else { 1353254885Sdumbbell reg += 4; 1354254885Sdumbbell } 1355254885Sdumbbell } 1356254885Sdumbbell return 0; 1357254885Sdumbbell} 1358254885Sdumbbell 1359254885Sdumbbellvoid r100_cs_dump_packet(struct radeon_cs_parser *p, 1360254885Sdumbbell struct radeon_cs_packet *pkt) 1361254885Sdumbbell{ 1362254885Sdumbbell volatile uint32_t *ib; 1363254885Sdumbbell unsigned i; 1364254885Sdumbbell unsigned idx; 1365254885Sdumbbell 1366254885Sdumbbell ib = p->ib.ptr; 1367254885Sdumbbell idx = pkt->idx; 1368254885Sdumbbell for (i = 0; i <= (pkt->count + 1); i++, idx++) { 1369254885Sdumbbell DRM_INFO("ib[%d]=0x%08X\n", idx, ib[idx]); 1370254885Sdumbbell } 1371254885Sdumbbell} 1372254885Sdumbbell 1373254885Sdumbbell/** 1374254885Sdumbbell * r100_cs_packet_parse() - parse cp packet and point ib index to next packet 1375254885Sdumbbell * @parser: parser structure holding parsing context. 1376254885Sdumbbell * @pkt: where to store packet informations 1377254885Sdumbbell * 1378254885Sdumbbell * Assume that chunk_ib_index is properly set. Will return -EINVAL 1379254885Sdumbbell * if packet is bigger than remaining ib size. or if packets is unknown. 1380254885Sdumbbell **/ 1381254885Sdumbbellint r100_cs_packet_parse(struct radeon_cs_parser *p, 1382254885Sdumbbell struct radeon_cs_packet *pkt, 1383254885Sdumbbell unsigned idx) 1384254885Sdumbbell{ 1385254885Sdumbbell struct radeon_cs_chunk *ib_chunk = &p->chunks[p->chunk_ib_idx]; 1386254885Sdumbbell uint32_t header; 1387254885Sdumbbell 1388254885Sdumbbell if (idx >= ib_chunk->length_dw) { 1389254885Sdumbbell DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 1390254885Sdumbbell idx, ib_chunk->length_dw); 1391254885Sdumbbell return -EINVAL; 1392254885Sdumbbell } 1393254885Sdumbbell header = radeon_get_ib_value(p, idx); 1394254885Sdumbbell pkt->idx = idx; 1395254885Sdumbbell pkt->type = CP_PACKET_GET_TYPE(header); 1396254885Sdumbbell pkt->count = CP_PACKET_GET_COUNT(header); 1397254885Sdumbbell switch (pkt->type) { 1398254885Sdumbbell case PACKET_TYPE0: 1399254885Sdumbbell pkt->reg = CP_PACKET0_GET_REG(header); 1400254885Sdumbbell pkt->one_reg_wr = CP_PACKET0_GET_ONE_REG_WR(header); 1401254885Sdumbbell break; 1402254885Sdumbbell case PACKET_TYPE3: 1403254885Sdumbbell pkt->opcode = CP_PACKET3_GET_OPCODE(header); 1404254885Sdumbbell break; 1405254885Sdumbbell case PACKET_TYPE2: 1406254885Sdumbbell pkt->count = -1; 1407254885Sdumbbell break; 1408254885Sdumbbell default: 1409254885Sdumbbell DRM_ERROR("Unknown packet type %d at %d !\n", pkt->type, idx); 1410254885Sdumbbell return -EINVAL; 1411254885Sdumbbell } 1412254885Sdumbbell if ((pkt->count + 1 + pkt->idx) >= ib_chunk->length_dw) { 1413254885Sdumbbell DRM_ERROR("Packet (%d:%d:%d) end after CS buffer (%d) !\n", 1414254885Sdumbbell pkt->idx, pkt->type, pkt->count, ib_chunk->length_dw); 1415254885Sdumbbell return -EINVAL; 1416254885Sdumbbell } 1417254885Sdumbbell return 0; 1418254885Sdumbbell} 1419254885Sdumbbell 1420254885Sdumbbell/** 1421254885Sdumbbell * r100_cs_packet_next_vline() - parse userspace VLINE packet 1422254885Sdumbbell * @parser: parser structure holding parsing context. 1423254885Sdumbbell * 1424254885Sdumbbell * Userspace sends a special sequence for VLINE waits. 1425254885Sdumbbell * PACKET0 - VLINE_START_END + value 1426254885Sdumbbell * PACKET0 - WAIT_UNTIL +_value 1427254885Sdumbbell * RELOC (P3) - crtc_id in reloc. 1428254885Sdumbbell * 1429254885Sdumbbell * This function parses this and relocates the VLINE START END 1430254885Sdumbbell * and WAIT UNTIL packets to the correct crtc. 1431254885Sdumbbell * It also detects a switched off crtc and nulls out the 1432254885Sdumbbell * wait in that case. 1433254885Sdumbbell */ 1434254885Sdumbbellint r100_cs_packet_parse_vline(struct radeon_cs_parser *p) 1435254885Sdumbbell{ 1436254885Sdumbbell struct drm_mode_object *obj; 1437254885Sdumbbell struct drm_crtc *crtc; 1438254885Sdumbbell struct radeon_crtc *radeon_crtc; 1439254885Sdumbbell struct radeon_cs_packet p3reloc, waitreloc; 1440254885Sdumbbell int crtc_id; 1441254885Sdumbbell int r; 1442254885Sdumbbell uint32_t header, h_idx, reg; 1443254885Sdumbbell volatile uint32_t *ib; 1444254885Sdumbbell 1445254885Sdumbbell ib = p->ib.ptr; 1446254885Sdumbbell 1447254885Sdumbbell /* parse the wait until */ 1448254885Sdumbbell r = r100_cs_packet_parse(p, &waitreloc, p->idx); 1449254885Sdumbbell if (r) 1450254885Sdumbbell return r; 1451254885Sdumbbell 1452254885Sdumbbell /* check its a wait until and only 1 count */ 1453254885Sdumbbell if (waitreloc.reg != RADEON_WAIT_UNTIL || 1454254885Sdumbbell waitreloc.count != 0) { 1455254885Sdumbbell DRM_ERROR("vline wait had illegal wait until segment\n"); 1456254885Sdumbbell return -EINVAL; 1457254885Sdumbbell } 1458254885Sdumbbell 1459254885Sdumbbell if (radeon_get_ib_value(p, waitreloc.idx + 1) != RADEON_WAIT_CRTC_VLINE) { 1460254885Sdumbbell DRM_ERROR("vline wait had illegal wait until\n"); 1461254885Sdumbbell return -EINVAL; 1462254885Sdumbbell } 1463254885Sdumbbell 1464254885Sdumbbell /* jump over the NOP */ 1465254885Sdumbbell r = r100_cs_packet_parse(p, &p3reloc, p->idx + waitreloc.count + 2); 1466254885Sdumbbell if (r) 1467254885Sdumbbell return r; 1468254885Sdumbbell 1469254885Sdumbbell h_idx = p->idx - 2; 1470254885Sdumbbell p->idx += waitreloc.count + 2; 1471254885Sdumbbell p->idx += p3reloc.count + 2; 1472254885Sdumbbell 1473254885Sdumbbell header = radeon_get_ib_value(p, h_idx); 1474254885Sdumbbell crtc_id = radeon_get_ib_value(p, h_idx + 5); 1475254885Sdumbbell reg = CP_PACKET0_GET_REG(header); 1476254885Sdumbbell obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC); 1477254885Sdumbbell if (!obj) { 1478254885Sdumbbell DRM_ERROR("cannot find crtc %d\n", crtc_id); 1479254885Sdumbbell return -EINVAL; 1480254885Sdumbbell } 1481254885Sdumbbell crtc = obj_to_crtc(obj); 1482254885Sdumbbell radeon_crtc = to_radeon_crtc(crtc); 1483254885Sdumbbell crtc_id = radeon_crtc->crtc_id; 1484254885Sdumbbell 1485254885Sdumbbell if (!crtc->enabled) { 1486254885Sdumbbell /* if the CRTC isn't enabled - we need to nop out the wait until */ 1487254885Sdumbbell ib[h_idx + 2] = PACKET2(0); 1488254885Sdumbbell ib[h_idx + 3] = PACKET2(0); 1489254885Sdumbbell } else if (crtc_id == 1) { 1490254885Sdumbbell switch (reg) { 1491254885Sdumbbell case AVIVO_D1MODE_VLINE_START_END: 1492254885Sdumbbell header &= ~R300_CP_PACKET0_REG_MASK; 1493254885Sdumbbell header |= AVIVO_D2MODE_VLINE_START_END >> 2; 1494254885Sdumbbell break; 1495254885Sdumbbell case RADEON_CRTC_GUI_TRIG_VLINE: 1496254885Sdumbbell header &= ~R300_CP_PACKET0_REG_MASK; 1497254885Sdumbbell header |= RADEON_CRTC2_GUI_TRIG_VLINE >> 2; 1498254885Sdumbbell break; 1499254885Sdumbbell default: 1500254885Sdumbbell DRM_ERROR("unknown crtc reloc\n"); 1501254885Sdumbbell return -EINVAL; 1502254885Sdumbbell } 1503254885Sdumbbell ib[h_idx] = header; 1504254885Sdumbbell ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1; 1505254885Sdumbbell } 1506254885Sdumbbell 1507254885Sdumbbell return 0; 1508254885Sdumbbell} 1509254885Sdumbbell 1510254885Sdumbbell/** 1511254885Sdumbbell * r100_cs_packet_next_reloc() - parse next packet which should be reloc packet3 1512254885Sdumbbell * @parser: parser structure holding parsing context. 1513254885Sdumbbell * @data: pointer to relocation data 1514254885Sdumbbell * @offset_start: starting offset 1515254885Sdumbbell * @offset_mask: offset mask (to align start offset on) 1516254885Sdumbbell * @reloc: reloc informations 1517254885Sdumbbell * 1518254885Sdumbbell * Check next packet is relocation packet3, do bo validation and compute 1519254885Sdumbbell * GPU offset using the provided start. 1520254885Sdumbbell **/ 1521254885Sdumbbellint r100_cs_packet_next_reloc(struct radeon_cs_parser *p, 1522254885Sdumbbell struct radeon_cs_reloc **cs_reloc) 1523254885Sdumbbell{ 1524254885Sdumbbell struct radeon_cs_chunk *relocs_chunk; 1525254885Sdumbbell struct radeon_cs_packet p3reloc; 1526254885Sdumbbell unsigned idx; 1527254885Sdumbbell int r; 1528254885Sdumbbell 1529254885Sdumbbell if (p->chunk_relocs_idx == -1) { 1530254885Sdumbbell DRM_ERROR("No relocation chunk !\n"); 1531254885Sdumbbell return -EINVAL; 1532254885Sdumbbell } 1533254885Sdumbbell *cs_reloc = NULL; 1534254885Sdumbbell relocs_chunk = &p->chunks[p->chunk_relocs_idx]; 1535254885Sdumbbell r = r100_cs_packet_parse(p, &p3reloc, p->idx); 1536254885Sdumbbell if (r) { 1537254885Sdumbbell return r; 1538254885Sdumbbell } 1539254885Sdumbbell p->idx += p3reloc.count + 2; 1540254885Sdumbbell if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { 1541254885Sdumbbell DRM_ERROR("No packet3 for relocation for packet at %d.\n", 1542254885Sdumbbell p3reloc.idx); 1543254885Sdumbbell r100_cs_dump_packet(p, &p3reloc); 1544254885Sdumbbell return -EINVAL; 1545254885Sdumbbell } 1546254885Sdumbbell idx = radeon_get_ib_value(p, p3reloc.idx + 1); 1547254885Sdumbbell if (idx >= relocs_chunk->length_dw) { 1548254885Sdumbbell DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", 1549254885Sdumbbell idx, relocs_chunk->length_dw); 1550254885Sdumbbell r100_cs_dump_packet(p, &p3reloc); 1551254885Sdumbbell return -EINVAL; 1552254885Sdumbbell } 1553254885Sdumbbell /* FIXME: we assume reloc size is 4 dwords */ 1554254885Sdumbbell *cs_reloc = p->relocs_ptr[(idx / 4)]; 1555254885Sdumbbell return 0; 1556254885Sdumbbell} 1557254885Sdumbbell 1558254885Sdumbbellstatic int r100_get_vtx_size(uint32_t vtx_fmt) 1559254885Sdumbbell{ 1560254885Sdumbbell int vtx_size; 1561254885Sdumbbell vtx_size = 2; 1562254885Sdumbbell /* ordered according to bits in spec */ 1563254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_W0) 1564254885Sdumbbell vtx_size++; 1565254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_FPCOLOR) 1566254885Sdumbbell vtx_size += 3; 1567254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_FPALPHA) 1568254885Sdumbbell vtx_size++; 1569254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_PKCOLOR) 1570254885Sdumbbell vtx_size++; 1571254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_FPSPEC) 1572254885Sdumbbell vtx_size += 3; 1573254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_FPFOG) 1574254885Sdumbbell vtx_size++; 1575254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_PKSPEC) 1576254885Sdumbbell vtx_size++; 1577254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_ST0) 1578254885Sdumbbell vtx_size += 2; 1579254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_ST1) 1580254885Sdumbbell vtx_size += 2; 1581254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_Q1) 1582254885Sdumbbell vtx_size++; 1583254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_ST2) 1584254885Sdumbbell vtx_size += 2; 1585254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_Q2) 1586254885Sdumbbell vtx_size++; 1587254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_ST3) 1588254885Sdumbbell vtx_size += 2; 1589254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_Q3) 1590254885Sdumbbell vtx_size++; 1591254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_Q0) 1592254885Sdumbbell vtx_size++; 1593254885Sdumbbell /* blend weight */ 1594254885Sdumbbell if (vtx_fmt & (0x7 << 15)) 1595254885Sdumbbell vtx_size += (vtx_fmt >> 15) & 0x7; 1596254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_N0) 1597254885Sdumbbell vtx_size += 3; 1598254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_XY1) 1599254885Sdumbbell vtx_size += 2; 1600254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_Z1) 1601254885Sdumbbell vtx_size++; 1602254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_W1) 1603254885Sdumbbell vtx_size++; 1604254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_N1) 1605254885Sdumbbell vtx_size++; 1606254885Sdumbbell if (vtx_fmt & RADEON_SE_VTX_FMT_Z) 1607254885Sdumbbell vtx_size++; 1608254885Sdumbbell return vtx_size; 1609254885Sdumbbell} 1610254885Sdumbbell 1611254885Sdumbbellstatic int r100_packet0_check(struct radeon_cs_parser *p, 1612254885Sdumbbell struct radeon_cs_packet *pkt, 1613254885Sdumbbell unsigned idx, unsigned reg) 1614254885Sdumbbell{ 1615254885Sdumbbell struct radeon_cs_reloc *reloc; 1616254885Sdumbbell struct r100_cs_track *track; 1617254885Sdumbbell volatile uint32_t *ib; 1618254885Sdumbbell uint32_t tmp; 1619254885Sdumbbell int r; 1620254885Sdumbbell int i, face; 1621254885Sdumbbell u32 tile_flags = 0; 1622254885Sdumbbell u32 idx_value; 1623254885Sdumbbell 1624254885Sdumbbell ib = p->ib.ptr; 1625254885Sdumbbell track = (struct r100_cs_track *)p->track; 1626254885Sdumbbell 1627254885Sdumbbell idx_value = radeon_get_ib_value(p, idx); 1628254885Sdumbbell 1629254885Sdumbbell switch (reg) { 1630254885Sdumbbell case RADEON_CRTC_GUI_TRIG_VLINE: 1631254885Sdumbbell r = r100_cs_packet_parse_vline(p); 1632254885Sdumbbell if (r) { 1633254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1634254885Sdumbbell idx, reg); 1635254885Sdumbbell r100_cs_dump_packet(p, pkt); 1636254885Sdumbbell return r; 1637254885Sdumbbell } 1638254885Sdumbbell break; 1639254885Sdumbbell /* FIXME: only allow PACKET3 blit? easier to check for out of 1640254885Sdumbbell * range access */ 1641254885Sdumbbell case RADEON_DST_PITCH_OFFSET: 1642254885Sdumbbell case RADEON_SRC_PITCH_OFFSET: 1643254885Sdumbbell r = r100_reloc_pitch_offset(p, pkt, idx, reg); 1644254885Sdumbbell if (r) 1645254885Sdumbbell return r; 1646254885Sdumbbell break; 1647254885Sdumbbell case RADEON_RB3D_DEPTHOFFSET: 1648254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1649254885Sdumbbell if (r) { 1650254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1651254885Sdumbbell idx, reg); 1652254885Sdumbbell r100_cs_dump_packet(p, pkt); 1653254885Sdumbbell return r; 1654254885Sdumbbell } 1655254885Sdumbbell track->zb.robj = reloc->robj; 1656254885Sdumbbell track->zb.offset = idx_value; 1657254885Sdumbbell track->zb_dirty = true; 1658254885Sdumbbell ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); 1659254885Sdumbbell break; 1660254885Sdumbbell case RADEON_RB3D_COLOROFFSET: 1661254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1662254885Sdumbbell if (r) { 1663254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1664254885Sdumbbell idx, reg); 1665254885Sdumbbell r100_cs_dump_packet(p, pkt); 1666254885Sdumbbell return r; 1667254885Sdumbbell } 1668254885Sdumbbell track->cb[0].robj = reloc->robj; 1669254885Sdumbbell track->cb[0].offset = idx_value; 1670254885Sdumbbell track->cb_dirty = true; 1671254885Sdumbbell ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); 1672254885Sdumbbell break; 1673254885Sdumbbell case RADEON_PP_TXOFFSET_0: 1674254885Sdumbbell case RADEON_PP_TXOFFSET_1: 1675254885Sdumbbell case RADEON_PP_TXOFFSET_2: 1676254885Sdumbbell i = (reg - RADEON_PP_TXOFFSET_0) / 24; 1677254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1678254885Sdumbbell if (r) { 1679254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1680254885Sdumbbell idx, reg); 1681254885Sdumbbell r100_cs_dump_packet(p, pkt); 1682254885Sdumbbell return r; 1683254885Sdumbbell } 1684254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1685254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1686254885Sdumbbell tile_flags |= RADEON_TXO_MACRO_TILE; 1687254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) 1688254885Sdumbbell tile_flags |= RADEON_TXO_MICRO_TILE_X2; 1689254885Sdumbbell 1690254885Sdumbbell tmp = idx_value & ~(0x7 << 2); 1691254885Sdumbbell tmp |= tile_flags; 1692254885Sdumbbell ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset); 1693254885Sdumbbell } else 1694254885Sdumbbell ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); 1695254885Sdumbbell track->textures[i].robj = reloc->robj; 1696254885Sdumbbell track->tex_dirty = true; 1697254885Sdumbbell break; 1698254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T0_0: 1699254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T0_1: 1700254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T0_2: 1701254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T0_3: 1702254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T0_4: 1703254885Sdumbbell i = (reg - RADEON_PP_CUBIC_OFFSET_T0_0) / 4; 1704254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1705254885Sdumbbell if (r) { 1706254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1707254885Sdumbbell idx, reg); 1708254885Sdumbbell r100_cs_dump_packet(p, pkt); 1709254885Sdumbbell return r; 1710254885Sdumbbell } 1711254885Sdumbbell track->textures[0].cube_info[i].offset = idx_value; 1712254885Sdumbbell ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); 1713254885Sdumbbell track->textures[0].cube_info[i].robj = reloc->robj; 1714254885Sdumbbell track->tex_dirty = true; 1715254885Sdumbbell break; 1716254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T1_0: 1717254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T1_1: 1718254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T1_2: 1719254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T1_3: 1720254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T1_4: 1721254885Sdumbbell i = (reg - RADEON_PP_CUBIC_OFFSET_T1_0) / 4; 1722254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1723254885Sdumbbell if (r) { 1724254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1725254885Sdumbbell idx, reg); 1726254885Sdumbbell r100_cs_dump_packet(p, pkt); 1727254885Sdumbbell return r; 1728254885Sdumbbell } 1729254885Sdumbbell track->textures[1].cube_info[i].offset = idx_value; 1730254885Sdumbbell ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); 1731254885Sdumbbell track->textures[1].cube_info[i].robj = reloc->robj; 1732254885Sdumbbell track->tex_dirty = true; 1733254885Sdumbbell break; 1734254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T2_0: 1735254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T2_1: 1736254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T2_2: 1737254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T2_3: 1738254885Sdumbbell case RADEON_PP_CUBIC_OFFSET_T2_4: 1739254885Sdumbbell i = (reg - RADEON_PP_CUBIC_OFFSET_T2_0) / 4; 1740254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1741254885Sdumbbell if (r) { 1742254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1743254885Sdumbbell idx, reg); 1744254885Sdumbbell r100_cs_dump_packet(p, pkt); 1745254885Sdumbbell return r; 1746254885Sdumbbell } 1747254885Sdumbbell track->textures[2].cube_info[i].offset = idx_value; 1748254885Sdumbbell ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); 1749254885Sdumbbell track->textures[2].cube_info[i].robj = reloc->robj; 1750254885Sdumbbell track->tex_dirty = true; 1751254885Sdumbbell break; 1752254885Sdumbbell case RADEON_RE_WIDTH_HEIGHT: 1753254885Sdumbbell track->maxy = ((idx_value >> 16) & 0x7FF); 1754254885Sdumbbell track->cb_dirty = true; 1755254885Sdumbbell track->zb_dirty = true; 1756254885Sdumbbell break; 1757254885Sdumbbell case RADEON_RB3D_COLORPITCH: 1758254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1759254885Sdumbbell if (r) { 1760254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1761254885Sdumbbell idx, reg); 1762254885Sdumbbell r100_cs_dump_packet(p, pkt); 1763254885Sdumbbell return r; 1764254885Sdumbbell } 1765254885Sdumbbell if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 1766254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) 1767254885Sdumbbell tile_flags |= RADEON_COLOR_TILE_ENABLE; 1768254885Sdumbbell if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) 1769254885Sdumbbell tile_flags |= RADEON_COLOR_MICROTILE_ENABLE; 1770254885Sdumbbell 1771254885Sdumbbell tmp = idx_value & ~(0x7 << 16); 1772254885Sdumbbell tmp |= tile_flags; 1773254885Sdumbbell ib[idx] = tmp; 1774254885Sdumbbell } else 1775254885Sdumbbell ib[idx] = idx_value; 1776254885Sdumbbell 1777254885Sdumbbell track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK; 1778254885Sdumbbell track->cb_dirty = true; 1779254885Sdumbbell break; 1780254885Sdumbbell case RADEON_RB3D_DEPTHPITCH: 1781254885Sdumbbell track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK; 1782254885Sdumbbell track->zb_dirty = true; 1783254885Sdumbbell break; 1784254885Sdumbbell case RADEON_RB3D_CNTL: 1785254885Sdumbbell switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) { 1786254885Sdumbbell case 7: 1787254885Sdumbbell case 8: 1788254885Sdumbbell case 9: 1789254885Sdumbbell case 11: 1790254885Sdumbbell case 12: 1791254885Sdumbbell track->cb[0].cpp = 1; 1792254885Sdumbbell break; 1793254885Sdumbbell case 3: 1794254885Sdumbbell case 4: 1795254885Sdumbbell case 15: 1796254885Sdumbbell track->cb[0].cpp = 2; 1797254885Sdumbbell break; 1798254885Sdumbbell case 6: 1799254885Sdumbbell track->cb[0].cpp = 4; 1800254885Sdumbbell break; 1801254885Sdumbbell default: 1802254885Sdumbbell DRM_ERROR("Invalid color buffer format (%d) !\n", 1803254885Sdumbbell ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f)); 1804254885Sdumbbell return -EINVAL; 1805254885Sdumbbell } 1806254885Sdumbbell track->z_enabled = !!(idx_value & RADEON_Z_ENABLE); 1807254885Sdumbbell track->cb_dirty = true; 1808254885Sdumbbell track->zb_dirty = true; 1809254885Sdumbbell break; 1810254885Sdumbbell case RADEON_RB3D_ZSTENCILCNTL: 1811254885Sdumbbell switch (idx_value & 0xf) { 1812254885Sdumbbell case 0: 1813254885Sdumbbell track->zb.cpp = 2; 1814254885Sdumbbell break; 1815254885Sdumbbell case 2: 1816254885Sdumbbell case 3: 1817254885Sdumbbell case 4: 1818254885Sdumbbell case 5: 1819254885Sdumbbell case 9: 1820254885Sdumbbell case 11: 1821254885Sdumbbell track->zb.cpp = 4; 1822254885Sdumbbell break; 1823254885Sdumbbell default: 1824254885Sdumbbell break; 1825254885Sdumbbell } 1826254885Sdumbbell track->zb_dirty = true; 1827254885Sdumbbell break; 1828254885Sdumbbell case RADEON_RB3D_ZPASS_ADDR: 1829254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1830254885Sdumbbell if (r) { 1831254885Sdumbbell DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 1832254885Sdumbbell idx, reg); 1833254885Sdumbbell r100_cs_dump_packet(p, pkt); 1834254885Sdumbbell return r; 1835254885Sdumbbell } 1836254885Sdumbbell ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); 1837254885Sdumbbell break; 1838254885Sdumbbell case RADEON_PP_CNTL: 1839254885Sdumbbell { 1840254885Sdumbbell uint32_t temp = idx_value >> 4; 1841254885Sdumbbell for (i = 0; i < track->num_texture; i++) 1842254885Sdumbbell track->textures[i].enabled = !!(temp & (1 << i)); 1843254885Sdumbbell track->tex_dirty = true; 1844254885Sdumbbell } 1845254885Sdumbbell break; 1846254885Sdumbbell case RADEON_SE_VF_CNTL: 1847254885Sdumbbell track->vap_vf_cntl = idx_value; 1848254885Sdumbbell break; 1849254885Sdumbbell case RADEON_SE_VTX_FMT: 1850254885Sdumbbell track->vtx_size = r100_get_vtx_size(idx_value); 1851254885Sdumbbell break; 1852254885Sdumbbell case RADEON_PP_TEX_SIZE_0: 1853254885Sdumbbell case RADEON_PP_TEX_SIZE_1: 1854254885Sdumbbell case RADEON_PP_TEX_SIZE_2: 1855254885Sdumbbell i = (reg - RADEON_PP_TEX_SIZE_0) / 8; 1856254885Sdumbbell track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1; 1857254885Sdumbbell track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1; 1858254885Sdumbbell track->tex_dirty = true; 1859254885Sdumbbell break; 1860254885Sdumbbell case RADEON_PP_TEX_PITCH_0: 1861254885Sdumbbell case RADEON_PP_TEX_PITCH_1: 1862254885Sdumbbell case RADEON_PP_TEX_PITCH_2: 1863254885Sdumbbell i = (reg - RADEON_PP_TEX_PITCH_0) / 8; 1864254885Sdumbbell track->textures[i].pitch = idx_value + 32; 1865254885Sdumbbell track->tex_dirty = true; 1866254885Sdumbbell break; 1867254885Sdumbbell case RADEON_PP_TXFILTER_0: 1868254885Sdumbbell case RADEON_PP_TXFILTER_1: 1869254885Sdumbbell case RADEON_PP_TXFILTER_2: 1870254885Sdumbbell i = (reg - RADEON_PP_TXFILTER_0) / 24; 1871254885Sdumbbell track->textures[i].num_levels = ((idx_value & RADEON_MAX_MIP_LEVEL_MASK) 1872254885Sdumbbell >> RADEON_MAX_MIP_LEVEL_SHIFT); 1873254885Sdumbbell tmp = (idx_value >> 23) & 0x7; 1874254885Sdumbbell if (tmp == 2 || tmp == 6) 1875254885Sdumbbell track->textures[i].roundup_w = false; 1876254885Sdumbbell tmp = (idx_value >> 27) & 0x7; 1877254885Sdumbbell if (tmp == 2 || tmp == 6) 1878254885Sdumbbell track->textures[i].roundup_h = false; 1879254885Sdumbbell track->tex_dirty = true; 1880254885Sdumbbell break; 1881254885Sdumbbell case RADEON_PP_TXFORMAT_0: 1882254885Sdumbbell case RADEON_PP_TXFORMAT_1: 1883254885Sdumbbell case RADEON_PP_TXFORMAT_2: 1884254885Sdumbbell i = (reg - RADEON_PP_TXFORMAT_0) / 24; 1885254885Sdumbbell if (idx_value & RADEON_TXFORMAT_NON_POWER2) { 1886254885Sdumbbell track->textures[i].use_pitch = 1; 1887254885Sdumbbell } else { 1888254885Sdumbbell track->textures[i].use_pitch = 0; 1889254885Sdumbbell track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK); 1890254885Sdumbbell track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK); 1891254885Sdumbbell } 1892254885Sdumbbell if (idx_value & RADEON_TXFORMAT_CUBIC_MAP_ENABLE) 1893254885Sdumbbell track->textures[i].tex_coord_type = 2; 1894254885Sdumbbell switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) { 1895254885Sdumbbell case RADEON_TXFORMAT_I8: 1896254885Sdumbbell case RADEON_TXFORMAT_RGB332: 1897254885Sdumbbell case RADEON_TXFORMAT_Y8: 1898254885Sdumbbell track->textures[i].cpp = 1; 1899254885Sdumbbell track->textures[i].compress_format = R100_TRACK_COMP_NONE; 1900254885Sdumbbell break; 1901254885Sdumbbell case RADEON_TXFORMAT_AI88: 1902254885Sdumbbell case RADEON_TXFORMAT_ARGB1555: 1903254885Sdumbbell case RADEON_TXFORMAT_RGB565: 1904254885Sdumbbell case RADEON_TXFORMAT_ARGB4444: 1905254885Sdumbbell case RADEON_TXFORMAT_VYUY422: 1906254885Sdumbbell case RADEON_TXFORMAT_YVYU422: 1907254885Sdumbbell case RADEON_TXFORMAT_SHADOW16: 1908254885Sdumbbell case RADEON_TXFORMAT_LDUDV655: 1909254885Sdumbbell case RADEON_TXFORMAT_DUDV88: 1910254885Sdumbbell track->textures[i].cpp = 2; 1911254885Sdumbbell track->textures[i].compress_format = R100_TRACK_COMP_NONE; 1912254885Sdumbbell break; 1913254885Sdumbbell case RADEON_TXFORMAT_ARGB8888: 1914254885Sdumbbell case RADEON_TXFORMAT_RGBA8888: 1915254885Sdumbbell case RADEON_TXFORMAT_SHADOW32: 1916254885Sdumbbell case RADEON_TXFORMAT_LDUDUV8888: 1917254885Sdumbbell track->textures[i].cpp = 4; 1918254885Sdumbbell track->textures[i].compress_format = R100_TRACK_COMP_NONE; 1919254885Sdumbbell break; 1920254885Sdumbbell case RADEON_TXFORMAT_DXT1: 1921254885Sdumbbell track->textures[i].cpp = 1; 1922254885Sdumbbell track->textures[i].compress_format = R100_TRACK_COMP_DXT1; 1923254885Sdumbbell break; 1924254885Sdumbbell case RADEON_TXFORMAT_DXT23: 1925254885Sdumbbell case RADEON_TXFORMAT_DXT45: 1926254885Sdumbbell track->textures[i].cpp = 1; 1927254885Sdumbbell track->textures[i].compress_format = R100_TRACK_COMP_DXT35; 1928254885Sdumbbell break; 1929254885Sdumbbell } 1930254885Sdumbbell track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf); 1931254885Sdumbbell track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf); 1932254885Sdumbbell track->tex_dirty = true; 1933254885Sdumbbell break; 1934254885Sdumbbell case RADEON_PP_CUBIC_FACES_0: 1935254885Sdumbbell case RADEON_PP_CUBIC_FACES_1: 1936254885Sdumbbell case RADEON_PP_CUBIC_FACES_2: 1937254885Sdumbbell tmp = idx_value; 1938254885Sdumbbell i = (reg - RADEON_PP_CUBIC_FACES_0) / 4; 1939254885Sdumbbell for (face = 0; face < 4; face++) { 1940254885Sdumbbell track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf); 1941254885Sdumbbell track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf); 1942254885Sdumbbell } 1943254885Sdumbbell track->tex_dirty = true; 1944254885Sdumbbell break; 1945254885Sdumbbell default: 1946254885Sdumbbell DRM_ERROR("Forbidden register 0x%04X in cs at %d\n", 1947254885Sdumbbell reg, idx); 1948254885Sdumbbell return -EINVAL; 1949254885Sdumbbell } 1950254885Sdumbbell return 0; 1951254885Sdumbbell} 1952254885Sdumbbell 1953254885Sdumbbellint r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, 1954254885Sdumbbell struct radeon_cs_packet *pkt, 1955254885Sdumbbell struct radeon_bo *robj) 1956254885Sdumbbell{ 1957254885Sdumbbell unsigned idx; 1958254885Sdumbbell u32 value; 1959254885Sdumbbell idx = pkt->idx + 1; 1960254885Sdumbbell value = radeon_get_ib_value(p, idx + 2); 1961254885Sdumbbell if ((value + 1) > radeon_bo_size(robj)) { 1962254885Sdumbbell DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " 1963254885Sdumbbell "(need %u have %lu) !\n", 1964254885Sdumbbell value + 1, 1965254885Sdumbbell radeon_bo_size(robj)); 1966254885Sdumbbell return -EINVAL; 1967254885Sdumbbell } 1968254885Sdumbbell return 0; 1969254885Sdumbbell} 1970254885Sdumbbell 1971254885Sdumbbellstatic int r100_packet3_check(struct radeon_cs_parser *p, 1972254885Sdumbbell struct radeon_cs_packet *pkt) 1973254885Sdumbbell{ 1974254885Sdumbbell struct radeon_cs_reloc *reloc; 1975254885Sdumbbell struct r100_cs_track *track; 1976254885Sdumbbell unsigned idx; 1977254885Sdumbbell volatile uint32_t *ib; 1978254885Sdumbbell int r; 1979254885Sdumbbell 1980254885Sdumbbell ib = p->ib.ptr; 1981254885Sdumbbell idx = pkt->idx + 1; 1982254885Sdumbbell track = (struct r100_cs_track *)p->track; 1983254885Sdumbbell switch (pkt->opcode) { 1984254885Sdumbbell case PACKET3_3D_LOAD_VBPNTR: 1985254885Sdumbbell r = r100_packet3_load_vbpntr(p, pkt, idx); 1986254885Sdumbbell if (r) 1987254885Sdumbbell return r; 1988254885Sdumbbell break; 1989254885Sdumbbell case PACKET3_INDX_BUFFER: 1990254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 1991254885Sdumbbell if (r) { 1992254885Sdumbbell DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 1993254885Sdumbbell r100_cs_dump_packet(p, pkt); 1994254885Sdumbbell return r; 1995254885Sdumbbell } 1996254885Sdumbbell ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset); 1997254885Sdumbbell r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj); 1998254885Sdumbbell if (r) { 1999254885Sdumbbell return r; 2000254885Sdumbbell } 2001254885Sdumbbell break; 2002254885Sdumbbell case 0x23: 2003254885Sdumbbell /* 3D_RNDR_GEN_INDX_PRIM on r100/r200 */ 2004254885Sdumbbell r = r100_cs_packet_next_reloc(p, &reloc); 2005254885Sdumbbell if (r) { 2006254885Sdumbbell DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode); 2007254885Sdumbbell r100_cs_dump_packet(p, pkt); 2008254885Sdumbbell return r; 2009254885Sdumbbell } 2010254885Sdumbbell ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset); 2011254885Sdumbbell track->num_arrays = 1; 2012254885Sdumbbell track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 2)); 2013254885Sdumbbell 2014254885Sdumbbell track->arrays[0].robj = reloc->robj; 2015254885Sdumbbell track->arrays[0].esize = track->vtx_size; 2016254885Sdumbbell 2017254885Sdumbbell track->max_indx = radeon_get_ib_value(p, idx+1); 2018254885Sdumbbell 2019254885Sdumbbell track->vap_vf_cntl = radeon_get_ib_value(p, idx+3); 2020254885Sdumbbell track->immd_dwords = pkt->count - 1; 2021254885Sdumbbell r = r100_cs_track_check(p->rdev, track); 2022254885Sdumbbell if (r) 2023254885Sdumbbell return r; 2024254885Sdumbbell break; 2025254885Sdumbbell case PACKET3_3D_DRAW_IMMD: 2026254885Sdumbbell if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) { 2027254885Sdumbbell DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); 2028254885Sdumbbell return -EINVAL; 2029254885Sdumbbell } 2030254885Sdumbbell track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0)); 2031254885Sdumbbell track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 2032254885Sdumbbell track->immd_dwords = pkt->count - 1; 2033254885Sdumbbell r = r100_cs_track_check(p->rdev, track); 2034254885Sdumbbell if (r) 2035254885Sdumbbell return r; 2036254885Sdumbbell break; 2037254885Sdumbbell /* triggers drawing using in-packet vertex data */ 2038254885Sdumbbell case PACKET3_3D_DRAW_IMMD_2: 2039254885Sdumbbell if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) { 2040254885Sdumbbell DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); 2041254885Sdumbbell return -EINVAL; 2042254885Sdumbbell } 2043254885Sdumbbell track->vap_vf_cntl = radeon_get_ib_value(p, idx); 2044254885Sdumbbell track->immd_dwords = pkt->count; 2045254885Sdumbbell r = r100_cs_track_check(p->rdev, track); 2046254885Sdumbbell if (r) 2047254885Sdumbbell return r; 2048254885Sdumbbell break; 2049254885Sdumbbell /* triggers drawing using in-packet vertex data */ 2050254885Sdumbbell case PACKET3_3D_DRAW_VBUF_2: 2051254885Sdumbbell track->vap_vf_cntl = radeon_get_ib_value(p, idx); 2052254885Sdumbbell r = r100_cs_track_check(p->rdev, track); 2053254885Sdumbbell if (r) 2054254885Sdumbbell return r; 2055254885Sdumbbell break; 2056254885Sdumbbell /* triggers drawing of vertex buffers setup elsewhere */ 2057254885Sdumbbell case PACKET3_3D_DRAW_INDX_2: 2058254885Sdumbbell track->vap_vf_cntl = radeon_get_ib_value(p, idx); 2059254885Sdumbbell r = r100_cs_track_check(p->rdev, track); 2060254885Sdumbbell if (r) 2061254885Sdumbbell return r; 2062254885Sdumbbell break; 2063254885Sdumbbell /* triggers drawing using indices to vertex buffer */ 2064254885Sdumbbell case PACKET3_3D_DRAW_VBUF: 2065254885Sdumbbell track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 2066254885Sdumbbell r = r100_cs_track_check(p->rdev, track); 2067254885Sdumbbell if (r) 2068254885Sdumbbell return r; 2069254885Sdumbbell break; 2070254885Sdumbbell /* triggers drawing of vertex buffers setup elsewhere */ 2071254885Sdumbbell case PACKET3_3D_DRAW_INDX: 2072254885Sdumbbell track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); 2073254885Sdumbbell r = r100_cs_track_check(p->rdev, track); 2074254885Sdumbbell if (r) 2075254885Sdumbbell return r; 2076254885Sdumbbell break; 2077254885Sdumbbell /* triggers drawing using indices to vertex buffer */ 2078254885Sdumbbell case PACKET3_3D_CLEAR_HIZ: 2079254885Sdumbbell case PACKET3_3D_CLEAR_ZMASK: 2080254885Sdumbbell if (p->rdev->hyperz_filp != p->filp) 2081254885Sdumbbell return -EINVAL; 2082254885Sdumbbell break; 2083254885Sdumbbell case PACKET3_NOP: 2084254885Sdumbbell break; 2085254885Sdumbbell default: 2086254885Sdumbbell DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 2087254885Sdumbbell return -EINVAL; 2088254885Sdumbbell } 2089254885Sdumbbell return 0; 2090254885Sdumbbell} 2091254885Sdumbbell 2092254885Sdumbbellint r100_cs_parse(struct radeon_cs_parser *p) 2093254885Sdumbbell{ 2094254885Sdumbbell struct radeon_cs_packet pkt; 2095254885Sdumbbell struct r100_cs_track *track; 2096254885Sdumbbell int r; 2097254885Sdumbbell 2098254885Sdumbbell track = malloc(sizeof(*track), DRM_MEM_DRIVER, M_ZERO | M_WAITOK); 2099254885Sdumbbell if (!track) 2100254885Sdumbbell return -ENOMEM; 2101254885Sdumbbell r100_cs_track_clear(p->rdev, track); 2102254885Sdumbbell p->track = track; 2103254885Sdumbbell do { 2104254885Sdumbbell r = r100_cs_packet_parse(p, &pkt, p->idx); 2105254885Sdumbbell if (r) { 2106254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2107254885Sdumbbell p->track = NULL; 2108254885Sdumbbell return r; 2109254885Sdumbbell } 2110254885Sdumbbell p->idx += pkt.count + 2; 2111254885Sdumbbell switch (pkt.type) { 2112254885Sdumbbell case PACKET_TYPE0: 2113254885Sdumbbell if (p->rdev->family >= CHIP_R200) 2114254885Sdumbbell r = r100_cs_parse_packet0(p, &pkt, 2115254885Sdumbbell p->rdev->config.r100.reg_safe_bm, 2116254885Sdumbbell p->rdev->config.r100.reg_safe_bm_size, 2117254885Sdumbbell &r200_packet0_check); 2118254885Sdumbbell else 2119254885Sdumbbell r = r100_cs_parse_packet0(p, &pkt, 2120254885Sdumbbell p->rdev->config.r100.reg_safe_bm, 2121254885Sdumbbell p->rdev->config.r100.reg_safe_bm_size, 2122254885Sdumbbell &r100_packet0_check); 2123254885Sdumbbell break; 2124254885Sdumbbell case PACKET_TYPE2: 2125254885Sdumbbell break; 2126254885Sdumbbell case PACKET_TYPE3: 2127254885Sdumbbell r = r100_packet3_check(p, &pkt); 2128254885Sdumbbell break; 2129254885Sdumbbell default: 2130254885Sdumbbell DRM_ERROR("Unknown packet type %d !\n", 2131254885Sdumbbell pkt.type); 2132254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2133254885Sdumbbell p->track = NULL; 2134254885Sdumbbell return -EINVAL; 2135254885Sdumbbell } 2136254885Sdumbbell if (r) { 2137254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2138254885Sdumbbell p->track = NULL; 2139254885Sdumbbell return r; 2140254885Sdumbbell } 2141254885Sdumbbell } while (p->idx < p->chunks[p->chunk_ib_idx].length_dw); 2142254885Sdumbbell free(p->track, DRM_MEM_DRIVER); 2143254885Sdumbbell p->track = NULL; 2144254885Sdumbbell return 0; 2145254885Sdumbbell} 2146254885Sdumbbell 2147254885Sdumbbellstatic void r100_cs_track_texture_print(struct r100_cs_track_texture *t) 2148254885Sdumbbell{ 2149254885Sdumbbell DRM_ERROR("pitch %d\n", t->pitch); 2150254885Sdumbbell DRM_ERROR("use_pitch %d\n", t->use_pitch); 2151254885Sdumbbell DRM_ERROR("width %d\n", t->width); 2152254885Sdumbbell DRM_ERROR("width_11 %d\n", t->width_11); 2153254885Sdumbbell DRM_ERROR("height %d\n", t->height); 2154254885Sdumbbell DRM_ERROR("height_11 %d\n", t->height_11); 2155254885Sdumbbell DRM_ERROR("num levels %d\n", t->num_levels); 2156254885Sdumbbell DRM_ERROR("depth %d\n", t->txdepth); 2157254885Sdumbbell DRM_ERROR("bpp %d\n", t->cpp); 2158254885Sdumbbell DRM_ERROR("coordinate type %d\n", t->tex_coord_type); 2159254885Sdumbbell DRM_ERROR("width round to power of 2 %d\n", t->roundup_w); 2160254885Sdumbbell DRM_ERROR("height round to power of 2 %d\n", t->roundup_h); 2161254885Sdumbbell DRM_ERROR("compress format %d\n", t->compress_format); 2162254885Sdumbbell} 2163254885Sdumbbell 2164254885Sdumbbellstatic int r100_track_compress_size(int compress_format, int w, int h) 2165254885Sdumbbell{ 2166254885Sdumbbell int block_width, block_height, block_bytes; 2167254885Sdumbbell int wblocks, hblocks; 2168254885Sdumbbell int min_wblocks; 2169254885Sdumbbell int sz; 2170254885Sdumbbell 2171254885Sdumbbell block_width = 4; 2172254885Sdumbbell block_height = 4; 2173254885Sdumbbell 2174254885Sdumbbell switch (compress_format) { 2175254885Sdumbbell case R100_TRACK_COMP_DXT1: 2176254885Sdumbbell block_bytes = 8; 2177254885Sdumbbell min_wblocks = 4; 2178254885Sdumbbell break; 2179254885Sdumbbell default: 2180254885Sdumbbell case R100_TRACK_COMP_DXT35: 2181254885Sdumbbell block_bytes = 16; 2182254885Sdumbbell min_wblocks = 2; 2183254885Sdumbbell break; 2184254885Sdumbbell } 2185254885Sdumbbell 2186254885Sdumbbell hblocks = (h + block_height - 1) / block_height; 2187254885Sdumbbell wblocks = (w + block_width - 1) / block_width; 2188254885Sdumbbell if (wblocks < min_wblocks) 2189254885Sdumbbell wblocks = min_wblocks; 2190254885Sdumbbell sz = wblocks * hblocks * block_bytes; 2191254885Sdumbbell return sz; 2192254885Sdumbbell} 2193254885Sdumbbell 2194254885Sdumbbellstatic int r100_cs_track_cube(struct radeon_device *rdev, 2195254885Sdumbbell struct r100_cs_track *track, unsigned idx) 2196254885Sdumbbell{ 2197254885Sdumbbell unsigned face, w, h; 2198254885Sdumbbell struct radeon_bo *cube_robj; 2199254885Sdumbbell unsigned long size; 2200254885Sdumbbell unsigned compress_format = track->textures[idx].compress_format; 2201254885Sdumbbell 2202254885Sdumbbell for (face = 0; face < 5; face++) { 2203254885Sdumbbell cube_robj = track->textures[idx].cube_info[face].robj; 2204254885Sdumbbell w = track->textures[idx].cube_info[face].width; 2205254885Sdumbbell h = track->textures[idx].cube_info[face].height; 2206254885Sdumbbell 2207254885Sdumbbell if (compress_format) { 2208254885Sdumbbell size = r100_track_compress_size(compress_format, w, h); 2209254885Sdumbbell } else 2210254885Sdumbbell size = w * h; 2211254885Sdumbbell size *= track->textures[idx].cpp; 2212254885Sdumbbell 2213254885Sdumbbell size += track->textures[idx].cube_info[face].offset; 2214254885Sdumbbell 2215254885Sdumbbell if (size > radeon_bo_size(cube_robj)) { 2216254885Sdumbbell DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", 2217254885Sdumbbell size, radeon_bo_size(cube_robj)); 2218254885Sdumbbell r100_cs_track_texture_print(&track->textures[idx]); 2219254885Sdumbbell return -1; 2220254885Sdumbbell } 2221254885Sdumbbell } 2222254885Sdumbbell return 0; 2223254885Sdumbbell} 2224254885Sdumbbell 2225254885Sdumbbellstatic int r100_cs_track_texture_check(struct radeon_device *rdev, 2226254885Sdumbbell struct r100_cs_track *track) 2227254885Sdumbbell{ 2228254885Sdumbbell struct radeon_bo *robj; 2229254885Sdumbbell unsigned long size; 2230254885Sdumbbell unsigned u, i, w, h, d; 2231254885Sdumbbell int ret; 2232254885Sdumbbell 2233254885Sdumbbell for (u = 0; u < track->num_texture; u++) { 2234254885Sdumbbell if (!track->textures[u].enabled) 2235254885Sdumbbell continue; 2236254885Sdumbbell if (track->textures[u].lookup_disable) 2237254885Sdumbbell continue; 2238254885Sdumbbell robj = track->textures[u].robj; 2239254885Sdumbbell if (robj == NULL) { 2240254885Sdumbbell DRM_ERROR("No texture bound to unit %u\n", u); 2241254885Sdumbbell return -EINVAL; 2242254885Sdumbbell } 2243254885Sdumbbell size = 0; 2244254885Sdumbbell for (i = 0; i <= track->textures[u].num_levels; i++) { 2245254885Sdumbbell if (track->textures[u].use_pitch) { 2246254885Sdumbbell if (rdev->family < CHIP_R300) 2247254885Sdumbbell w = (track->textures[u].pitch / track->textures[u].cpp) / (1 << i); 2248254885Sdumbbell else 2249254885Sdumbbell w = track->textures[u].pitch / (1 << i); 2250254885Sdumbbell } else { 2251254885Sdumbbell w = track->textures[u].width; 2252254885Sdumbbell if (rdev->family >= CHIP_RV515) 2253254885Sdumbbell w |= track->textures[u].width_11; 2254254885Sdumbbell w = w / (1 << i); 2255254885Sdumbbell if (track->textures[u].roundup_w) 2256254885Sdumbbell w = roundup_pow_of_two(w); 2257254885Sdumbbell } 2258254885Sdumbbell h = track->textures[u].height; 2259254885Sdumbbell if (rdev->family >= CHIP_RV515) 2260254885Sdumbbell h |= track->textures[u].height_11; 2261254885Sdumbbell h = h / (1 << i); 2262254885Sdumbbell if (track->textures[u].roundup_h) 2263254885Sdumbbell h = roundup_pow_of_two(h); 2264254885Sdumbbell if (track->textures[u].tex_coord_type == 1) { 2265254885Sdumbbell d = (1 << track->textures[u].txdepth) / (1 << i); 2266254885Sdumbbell if (!d) 2267254885Sdumbbell d = 1; 2268254885Sdumbbell } else { 2269254885Sdumbbell d = 1; 2270254885Sdumbbell } 2271254885Sdumbbell if (track->textures[u].compress_format) { 2272254885Sdumbbell 2273254885Sdumbbell size += r100_track_compress_size(track->textures[u].compress_format, w, h) * d; 2274254885Sdumbbell /* compressed textures are block based */ 2275254885Sdumbbell } else 2276254885Sdumbbell size += w * h * d; 2277254885Sdumbbell } 2278254885Sdumbbell size *= track->textures[u].cpp; 2279254885Sdumbbell 2280254885Sdumbbell switch (track->textures[u].tex_coord_type) { 2281254885Sdumbbell case 0: 2282254885Sdumbbell case 1: 2283254885Sdumbbell break; 2284254885Sdumbbell case 2: 2285254885Sdumbbell if (track->separate_cube) { 2286254885Sdumbbell ret = r100_cs_track_cube(rdev, track, u); 2287254885Sdumbbell if (ret) 2288254885Sdumbbell return ret; 2289254885Sdumbbell } else 2290254885Sdumbbell size *= 6; 2291254885Sdumbbell break; 2292254885Sdumbbell default: 2293254885Sdumbbell DRM_ERROR("Invalid texture coordinate type %u for unit " 2294254885Sdumbbell "%u\n", track->textures[u].tex_coord_type, u); 2295254885Sdumbbell return -EINVAL; 2296254885Sdumbbell } 2297254885Sdumbbell if (size > radeon_bo_size(robj)) { 2298254885Sdumbbell DRM_ERROR("Texture of unit %u needs %lu bytes but is " 2299254885Sdumbbell "%lu\n", u, size, radeon_bo_size(robj)); 2300254885Sdumbbell r100_cs_track_texture_print(&track->textures[u]); 2301254885Sdumbbell return -EINVAL; 2302254885Sdumbbell } 2303254885Sdumbbell } 2304254885Sdumbbell return 0; 2305254885Sdumbbell} 2306254885Sdumbbell 2307254885Sdumbbellint r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) 2308254885Sdumbbell{ 2309254885Sdumbbell unsigned i; 2310254885Sdumbbell unsigned long size; 2311254885Sdumbbell unsigned prim_walk; 2312254885Sdumbbell unsigned nverts; 2313254885Sdumbbell unsigned num_cb = track->cb_dirty ? track->num_cb : 0; 2314254885Sdumbbell 2315254885Sdumbbell if (num_cb && !track->zb_cb_clear && !track->color_channel_mask && 2316254885Sdumbbell !track->blend_read_enable) 2317254885Sdumbbell num_cb = 0; 2318254885Sdumbbell 2319254885Sdumbbell for (i = 0; i < num_cb; i++) { 2320254885Sdumbbell if (track->cb[i].robj == NULL) { 2321254885Sdumbbell DRM_ERROR("[drm] No buffer for color buffer %d !\n", i); 2322254885Sdumbbell return -EINVAL; 2323254885Sdumbbell } 2324254885Sdumbbell size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; 2325254885Sdumbbell size += track->cb[i].offset; 2326254885Sdumbbell if (size > radeon_bo_size(track->cb[i].robj)) { 2327254885Sdumbbell DRM_ERROR("[drm] Buffer too small for color buffer %d " 2328254885Sdumbbell "(need %lu have %lu) !\n", i, size, 2329254885Sdumbbell radeon_bo_size(track->cb[i].robj)); 2330254885Sdumbbell DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", 2331254885Sdumbbell i, track->cb[i].pitch, track->cb[i].cpp, 2332254885Sdumbbell track->cb[i].offset, track->maxy); 2333254885Sdumbbell return -EINVAL; 2334254885Sdumbbell } 2335254885Sdumbbell } 2336254885Sdumbbell track->cb_dirty = false; 2337254885Sdumbbell 2338254885Sdumbbell if (track->zb_dirty && track->z_enabled) { 2339254885Sdumbbell if (track->zb.robj == NULL) { 2340254885Sdumbbell DRM_ERROR("[drm] No buffer for z buffer !\n"); 2341254885Sdumbbell return -EINVAL; 2342254885Sdumbbell } 2343254885Sdumbbell size = track->zb.pitch * track->zb.cpp * track->maxy; 2344254885Sdumbbell size += track->zb.offset; 2345254885Sdumbbell if (size > radeon_bo_size(track->zb.robj)) { 2346254885Sdumbbell DRM_ERROR("[drm] Buffer too small for z buffer " 2347254885Sdumbbell "(need %lu have %lu) !\n", size, 2348254885Sdumbbell radeon_bo_size(track->zb.robj)); 2349254885Sdumbbell DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", 2350254885Sdumbbell track->zb.pitch, track->zb.cpp, 2351254885Sdumbbell track->zb.offset, track->maxy); 2352254885Sdumbbell return -EINVAL; 2353254885Sdumbbell } 2354254885Sdumbbell } 2355254885Sdumbbell track->zb_dirty = false; 2356254885Sdumbbell 2357254885Sdumbbell if (track->aa_dirty && track->aaresolve) { 2358254885Sdumbbell if (track->aa.robj == NULL) { 2359254885Sdumbbell DRM_ERROR("[drm] No buffer for AA resolve buffer %d !\n", i); 2360254885Sdumbbell return -EINVAL; 2361254885Sdumbbell } 2362254885Sdumbbell /* I believe the format comes from colorbuffer0. */ 2363254885Sdumbbell size = track->aa.pitch * track->cb[0].cpp * track->maxy; 2364254885Sdumbbell size += track->aa.offset; 2365254885Sdumbbell if (size > radeon_bo_size(track->aa.robj)) { 2366254885Sdumbbell DRM_ERROR("[drm] Buffer too small for AA resolve buffer %d " 2367254885Sdumbbell "(need %lu have %lu) !\n", i, size, 2368254885Sdumbbell radeon_bo_size(track->aa.robj)); 2369254885Sdumbbell DRM_ERROR("[drm] AA resolve buffer %d (%u %u %u %u)\n", 2370254885Sdumbbell i, track->aa.pitch, track->cb[0].cpp, 2371254885Sdumbbell track->aa.offset, track->maxy); 2372254885Sdumbbell return -EINVAL; 2373254885Sdumbbell } 2374254885Sdumbbell } 2375254885Sdumbbell track->aa_dirty = false; 2376254885Sdumbbell 2377254885Sdumbbell prim_walk = (track->vap_vf_cntl >> 4) & 0x3; 2378254885Sdumbbell if (track->vap_vf_cntl & (1 << 14)) { 2379254885Sdumbbell nverts = track->vap_alt_nverts; 2380254885Sdumbbell } else { 2381254885Sdumbbell nverts = (track->vap_vf_cntl >> 16) & 0xFFFF; 2382254885Sdumbbell } 2383254885Sdumbbell switch (prim_walk) { 2384254885Sdumbbell case 1: 2385254885Sdumbbell for (i = 0; i < track->num_arrays; i++) { 2386254885Sdumbbell size = track->arrays[i].esize * track->max_indx * 4; 2387254885Sdumbbell if (track->arrays[i].robj == NULL) { 2388254885Sdumbbell DRM_ERROR("(PW %u) Vertex array %u no buffer " 2389254885Sdumbbell "bound\n", prim_walk, i); 2390254885Sdumbbell return -EINVAL; 2391254885Sdumbbell } 2392254885Sdumbbell if (size > radeon_bo_size(track->arrays[i].robj)) { 2393254885Sdumbbell dev_err(rdev->dev, "(PW %u) Vertex array %u " 2394254885Sdumbbell "need %lu dwords have %lu dwords\n", 2395254885Sdumbbell prim_walk, i, size >> 2, 2396254885Sdumbbell radeon_bo_size(track->arrays[i].robj) 2397254885Sdumbbell >> 2); 2398254885Sdumbbell DRM_ERROR("Max indices %u\n", track->max_indx); 2399254885Sdumbbell return -EINVAL; 2400254885Sdumbbell } 2401254885Sdumbbell } 2402254885Sdumbbell break; 2403254885Sdumbbell case 2: 2404254885Sdumbbell for (i = 0; i < track->num_arrays; i++) { 2405254885Sdumbbell size = track->arrays[i].esize * (nverts - 1) * 4; 2406254885Sdumbbell if (track->arrays[i].robj == NULL) { 2407254885Sdumbbell DRM_ERROR("(PW %u) Vertex array %u no buffer " 2408254885Sdumbbell "bound\n", prim_walk, i); 2409254885Sdumbbell return -EINVAL; 2410254885Sdumbbell } 2411254885Sdumbbell if (size > radeon_bo_size(track->arrays[i].robj)) { 2412254885Sdumbbell dev_err(rdev->dev, "(PW %u) Vertex array %u " 2413254885Sdumbbell "need %lu dwords have %lu dwords\n", 2414254885Sdumbbell prim_walk, i, size >> 2, 2415254885Sdumbbell radeon_bo_size(track->arrays[i].robj) 2416254885Sdumbbell >> 2); 2417254885Sdumbbell return -EINVAL; 2418254885Sdumbbell } 2419254885Sdumbbell } 2420254885Sdumbbell break; 2421254885Sdumbbell case 3: 2422254885Sdumbbell size = track->vtx_size * nverts; 2423254885Sdumbbell if (size != track->immd_dwords) { 2424254885Sdumbbell DRM_ERROR("IMMD draw %u dwors but needs %lu dwords\n", 2425254885Sdumbbell track->immd_dwords, size); 2426254885Sdumbbell DRM_ERROR("VAP_VF_CNTL.NUM_VERTICES %u, VTX_SIZE %u\n", 2427254885Sdumbbell nverts, track->vtx_size); 2428254885Sdumbbell return -EINVAL; 2429254885Sdumbbell } 2430254885Sdumbbell break; 2431254885Sdumbbell default: 2432254885Sdumbbell DRM_ERROR("[drm] Invalid primitive walk %d for VAP_VF_CNTL\n", 2433254885Sdumbbell prim_walk); 2434254885Sdumbbell return -EINVAL; 2435254885Sdumbbell } 2436254885Sdumbbell 2437254885Sdumbbell if (track->tex_dirty) { 2438254885Sdumbbell track->tex_dirty = false; 2439254885Sdumbbell return r100_cs_track_texture_check(rdev, track); 2440254885Sdumbbell } 2441254885Sdumbbell return 0; 2442254885Sdumbbell} 2443254885Sdumbbell 2444254885Sdumbbellvoid r100_cs_track_clear(struct radeon_device *rdev, struct r100_cs_track *track) 2445254885Sdumbbell{ 2446254885Sdumbbell unsigned i, face; 2447254885Sdumbbell 2448254885Sdumbbell track->cb_dirty = true; 2449254885Sdumbbell track->zb_dirty = true; 2450254885Sdumbbell track->tex_dirty = true; 2451254885Sdumbbell track->aa_dirty = true; 2452254885Sdumbbell 2453254885Sdumbbell if (rdev->family < CHIP_R300) { 2454254885Sdumbbell track->num_cb = 1; 2455254885Sdumbbell if (rdev->family <= CHIP_RS200) 2456254885Sdumbbell track->num_texture = 3; 2457254885Sdumbbell else 2458254885Sdumbbell track->num_texture = 6; 2459254885Sdumbbell track->maxy = 2048; 2460254885Sdumbbell track->separate_cube = 1; 2461254885Sdumbbell } else { 2462254885Sdumbbell track->num_cb = 4; 2463254885Sdumbbell track->num_texture = 16; 2464254885Sdumbbell track->maxy = 4096; 2465254885Sdumbbell track->separate_cube = 0; 2466254885Sdumbbell track->aaresolve = false; 2467254885Sdumbbell track->aa.robj = NULL; 2468254885Sdumbbell } 2469254885Sdumbbell 2470254885Sdumbbell for (i = 0; i < track->num_cb; i++) { 2471254885Sdumbbell track->cb[i].robj = NULL; 2472254885Sdumbbell track->cb[i].pitch = 8192; 2473254885Sdumbbell track->cb[i].cpp = 16; 2474254885Sdumbbell track->cb[i].offset = 0; 2475254885Sdumbbell } 2476254885Sdumbbell track->z_enabled = true; 2477254885Sdumbbell track->zb.robj = NULL; 2478254885Sdumbbell track->zb.pitch = 8192; 2479254885Sdumbbell track->zb.cpp = 4; 2480254885Sdumbbell track->zb.offset = 0; 2481254885Sdumbbell track->vtx_size = 0x7F; 2482254885Sdumbbell track->immd_dwords = 0xFFFFFFFFUL; 2483254885Sdumbbell track->num_arrays = 11; 2484254885Sdumbbell track->max_indx = 0x00FFFFFFUL; 2485254885Sdumbbell for (i = 0; i < track->num_arrays; i++) { 2486254885Sdumbbell track->arrays[i].robj = NULL; 2487254885Sdumbbell track->arrays[i].esize = 0x7F; 2488254885Sdumbbell } 2489254885Sdumbbell for (i = 0; i < track->num_texture; i++) { 2490254885Sdumbbell track->textures[i].compress_format = R100_TRACK_COMP_NONE; 2491254885Sdumbbell track->textures[i].pitch = 16536; 2492254885Sdumbbell track->textures[i].width = 16536; 2493254885Sdumbbell track->textures[i].height = 16536; 2494254885Sdumbbell track->textures[i].width_11 = 1 << 11; 2495254885Sdumbbell track->textures[i].height_11 = 1 << 11; 2496254885Sdumbbell track->textures[i].num_levels = 12; 2497254885Sdumbbell if (rdev->family <= CHIP_RS200) { 2498254885Sdumbbell track->textures[i].tex_coord_type = 0; 2499254885Sdumbbell track->textures[i].txdepth = 0; 2500254885Sdumbbell } else { 2501254885Sdumbbell track->textures[i].txdepth = 16; 2502254885Sdumbbell track->textures[i].tex_coord_type = 1; 2503254885Sdumbbell } 2504254885Sdumbbell track->textures[i].cpp = 64; 2505254885Sdumbbell track->textures[i].robj = NULL; 2506254885Sdumbbell /* CS IB emission code makes sure texture unit are disabled */ 2507254885Sdumbbell track->textures[i].enabled = false; 2508254885Sdumbbell track->textures[i].lookup_disable = false; 2509254885Sdumbbell track->textures[i].roundup_w = true; 2510254885Sdumbbell track->textures[i].roundup_h = true; 2511254885Sdumbbell if (track->separate_cube) 2512254885Sdumbbell for (face = 0; face < 5; face++) { 2513254885Sdumbbell track->textures[i].cube_info[face].robj = NULL; 2514254885Sdumbbell track->textures[i].cube_info[face].width = 16536; 2515254885Sdumbbell track->textures[i].cube_info[face].height = 16536; 2516254885Sdumbbell track->textures[i].cube_info[face].offset = 0; 2517254885Sdumbbell } 2518254885Sdumbbell } 2519254885Sdumbbell} 2520254885Sdumbbell 2521254885Sdumbbell/* 2522254885Sdumbbell * Global GPU functions 2523254885Sdumbbell */ 2524254885Sdumbbellstatic void r100_errata(struct radeon_device *rdev) 2525254885Sdumbbell{ 2526254885Sdumbbell rdev->pll_errata = 0; 2527254885Sdumbbell 2528254885Sdumbbell if (rdev->family == CHIP_RV200 || rdev->family == CHIP_RS200) { 2529254885Sdumbbell rdev->pll_errata |= CHIP_ERRATA_PLL_DUMMYREADS; 2530254885Sdumbbell } 2531254885Sdumbbell 2532254885Sdumbbell if (rdev->family == CHIP_RV100 || 2533254885Sdumbbell rdev->family == CHIP_RS100 || 2534254885Sdumbbell rdev->family == CHIP_RS200) { 2535254885Sdumbbell rdev->pll_errata |= CHIP_ERRATA_PLL_DELAY; 2536254885Sdumbbell } 2537254885Sdumbbell} 2538254885Sdumbbell 2539254885Sdumbbellstatic int r100_rbbm_fifo_wait_for_entry(struct radeon_device *rdev, unsigned n) 2540254885Sdumbbell{ 2541254885Sdumbbell unsigned i; 2542254885Sdumbbell uint32_t tmp; 2543254885Sdumbbell 2544254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 2545254885Sdumbbell tmp = RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK; 2546254885Sdumbbell if (tmp >= n) { 2547254885Sdumbbell return 0; 2548254885Sdumbbell } 2549254885Sdumbbell DRM_UDELAY(1); 2550254885Sdumbbell } 2551254885Sdumbbell return -1; 2552254885Sdumbbell} 2553254885Sdumbbell 2554254885Sdumbbellint r100_gui_wait_for_idle(struct radeon_device *rdev) 2555254885Sdumbbell{ 2556254885Sdumbbell unsigned i; 2557254885Sdumbbell uint32_t tmp; 2558254885Sdumbbell 2559254885Sdumbbell if (r100_rbbm_fifo_wait_for_entry(rdev, 64)) { 2560254885Sdumbbell DRM_ERROR("radeon: wait for empty RBBM fifo failed !" 2561254885Sdumbbell " Bad things might happen.\n"); 2562254885Sdumbbell } 2563254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 2564254885Sdumbbell tmp = RREG32(RADEON_RBBM_STATUS); 2565254885Sdumbbell if (!(tmp & RADEON_RBBM_ACTIVE)) { 2566254885Sdumbbell return 0; 2567254885Sdumbbell } 2568254885Sdumbbell DRM_UDELAY(1); 2569254885Sdumbbell } 2570254885Sdumbbell return -1; 2571254885Sdumbbell} 2572254885Sdumbbell 2573254885Sdumbbellint r100_mc_wait_for_idle(struct radeon_device *rdev) 2574254885Sdumbbell{ 2575254885Sdumbbell unsigned i; 2576254885Sdumbbell uint32_t tmp; 2577254885Sdumbbell 2578254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 2579254885Sdumbbell /* read MC_STATUS */ 2580254885Sdumbbell tmp = RREG32(RADEON_MC_STATUS); 2581254885Sdumbbell if (tmp & RADEON_MC_IDLE) { 2582254885Sdumbbell return 0; 2583254885Sdumbbell } 2584254885Sdumbbell DRM_UDELAY(1); 2585254885Sdumbbell } 2586254885Sdumbbell return -1; 2587254885Sdumbbell} 2588254885Sdumbbell 2589254885Sdumbbellbool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) 2590254885Sdumbbell{ 2591254885Sdumbbell u32 rbbm_status; 2592254885Sdumbbell 2593254885Sdumbbell rbbm_status = RREG32(R_000E40_RBBM_STATUS); 2594254885Sdumbbell if (!G_000E40_GUI_ACTIVE(rbbm_status)) { 2595254885Sdumbbell radeon_ring_lockup_update(ring); 2596254885Sdumbbell return false; 2597254885Sdumbbell } 2598254885Sdumbbell /* force CP activities */ 2599254885Sdumbbell radeon_ring_force_activity(rdev, ring); 2600254885Sdumbbell return radeon_ring_test_lockup(rdev, ring); 2601254885Sdumbbell} 2602254885Sdumbbell 2603254885Sdumbbell/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ 2604254885Sdumbbellvoid r100_enable_bm(struct radeon_device *rdev) 2605254885Sdumbbell{ 2606254885Sdumbbell uint32_t tmp; 2607254885Sdumbbell /* Enable bus mastering */ 2608254885Sdumbbell tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; 2609254885Sdumbbell WREG32(RADEON_BUS_CNTL, tmp); 2610254885Sdumbbell} 2611254885Sdumbbell 2612254885Sdumbbellvoid r100_bm_disable(struct radeon_device *rdev) 2613254885Sdumbbell{ 2614254885Sdumbbell u32 tmp; 2615254885Sdumbbell 2616254885Sdumbbell /* disable bus mastering */ 2617254885Sdumbbell tmp = RREG32(R_000030_BUS_CNTL); 2618254885Sdumbbell WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000044); 2619254885Sdumbbell DRM_MDELAY(1); 2620254885Sdumbbell WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000042); 2621254885Sdumbbell DRM_MDELAY(1); 2622254885Sdumbbell WREG32(R_000030_BUS_CNTL, (tmp & 0xFFFFFFFF) | 0x00000040); 2623254885Sdumbbell tmp = RREG32(RADEON_BUS_CNTL); 2624254885Sdumbbell DRM_MDELAY(1); 2625254885Sdumbbell pci_disable_busmaster(rdev->dev); 2626254885Sdumbbell DRM_MDELAY(1); 2627254885Sdumbbell} 2628254885Sdumbbell 2629254885Sdumbbellint r100_asic_reset(struct radeon_device *rdev) 2630254885Sdumbbell{ 2631254885Sdumbbell struct r100_mc_save save; 2632254885Sdumbbell u32 status, tmp; 2633254885Sdumbbell int ret = 0; 2634254885Sdumbbell 2635254885Sdumbbell status = RREG32(R_000E40_RBBM_STATUS); 2636254885Sdumbbell if (!G_000E40_GUI_ACTIVE(status)) { 2637254885Sdumbbell return 0; 2638254885Sdumbbell } 2639254885Sdumbbell r100_mc_stop(rdev, &save); 2640254885Sdumbbell status = RREG32(R_000E40_RBBM_STATUS); 2641254885Sdumbbell dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 2642254885Sdumbbell /* stop CP */ 2643254885Sdumbbell WREG32(RADEON_CP_CSQ_CNTL, 0); 2644254885Sdumbbell tmp = RREG32(RADEON_CP_RB_CNTL); 2645254885Sdumbbell WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA); 2646254885Sdumbbell WREG32(RADEON_CP_RB_RPTR_WR, 0); 2647254885Sdumbbell WREG32(RADEON_CP_RB_WPTR, 0); 2648254885Sdumbbell WREG32(RADEON_CP_RB_CNTL, tmp); 2649254885Sdumbbell /* save PCI state */ 2650263170Sdumbbell pci_save_state(device_get_parent(rdev->dev)); 2651254885Sdumbbell /* disable bus mastering */ 2652254885Sdumbbell r100_bm_disable(rdev); 2653254885Sdumbbell WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_SE(1) | 2654254885Sdumbbell S_0000F0_SOFT_RESET_RE(1) | 2655254885Sdumbbell S_0000F0_SOFT_RESET_PP(1) | 2656254885Sdumbbell S_0000F0_SOFT_RESET_RB(1)); 2657254885Sdumbbell RREG32(R_0000F0_RBBM_SOFT_RESET); 2658254885Sdumbbell DRM_MDELAY(500); 2659254885Sdumbbell WREG32(R_0000F0_RBBM_SOFT_RESET, 0); 2660254885Sdumbbell DRM_MDELAY(1); 2661254885Sdumbbell status = RREG32(R_000E40_RBBM_STATUS); 2662254885Sdumbbell dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 2663254885Sdumbbell /* reset CP */ 2664254885Sdumbbell WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1)); 2665254885Sdumbbell RREG32(R_0000F0_RBBM_SOFT_RESET); 2666254885Sdumbbell DRM_MDELAY(500); 2667254885Sdumbbell WREG32(R_0000F0_RBBM_SOFT_RESET, 0); 2668254885Sdumbbell DRM_MDELAY(1); 2669254885Sdumbbell status = RREG32(R_000E40_RBBM_STATUS); 2670254885Sdumbbell dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status); 2671254885Sdumbbell /* restore PCI & busmastering */ 2672263170Sdumbbell pci_restore_state(device_get_parent(rdev->dev)); 2673254885Sdumbbell r100_enable_bm(rdev); 2674254885Sdumbbell /* Check if GPU is idle */ 2675254885Sdumbbell if (G_000E40_SE_BUSY(status) || G_000E40_RE_BUSY(status) || 2676254885Sdumbbell G_000E40_TAM_BUSY(status) || G_000E40_PB_BUSY(status)) { 2677254885Sdumbbell dev_err(rdev->dev, "failed to reset GPU\n"); 2678254885Sdumbbell ret = -1; 2679254885Sdumbbell } else 2680254885Sdumbbell dev_info(rdev->dev, "GPU reset succeed\n"); 2681254885Sdumbbell r100_mc_resume(rdev, &save); 2682254885Sdumbbell return ret; 2683254885Sdumbbell} 2684254885Sdumbbell 2685254885Sdumbbellvoid r100_set_common_regs(struct radeon_device *rdev) 2686254885Sdumbbell{ 2687254885Sdumbbell struct drm_device *dev = rdev->ddev; 2688254885Sdumbbell bool force_dac2 = false; 2689254885Sdumbbell u32 tmp; 2690254885Sdumbbell 2691254885Sdumbbell /* set these so they don't interfere with anything */ 2692254885Sdumbbell WREG32(RADEON_OV0_SCALE_CNTL, 0); 2693254885Sdumbbell WREG32(RADEON_SUBPIC_CNTL, 0); 2694254885Sdumbbell WREG32(RADEON_VIPH_CONTROL, 0); 2695254885Sdumbbell WREG32(RADEON_I2C_CNTL_1, 0); 2696254885Sdumbbell WREG32(RADEON_DVI_I2C_CNTL_1, 0); 2697254885Sdumbbell WREG32(RADEON_CAP0_TRIG_CNTL, 0); 2698254885Sdumbbell WREG32(RADEON_CAP1_TRIG_CNTL, 0); 2699254885Sdumbbell 2700254885Sdumbbell /* always set up dac2 on rn50 and some rv100 as lots 2701254885Sdumbbell * of servers seem to wire it up to a VGA port but 2702254885Sdumbbell * don't report it in the bios connector 2703254885Sdumbbell * table. 2704254885Sdumbbell */ 2705254885Sdumbbell switch (dev->pci_device) { 2706254885Sdumbbell /* RN50 */ 2707254885Sdumbbell case 0x515e: 2708254885Sdumbbell case 0x5969: 2709254885Sdumbbell force_dac2 = true; 2710254885Sdumbbell break; 2711254885Sdumbbell /* RV100*/ 2712254885Sdumbbell case 0x5159: 2713254885Sdumbbell case 0x515a: 2714254885Sdumbbell /* DELL triple head servers */ 2715254885Sdumbbell if ((dev->pci_subvendor == 0x1028 /* DELL */) && 2716254885Sdumbbell ((dev->pci_subdevice == 0x016c) || 2717254885Sdumbbell (dev->pci_subdevice == 0x016d) || 2718254885Sdumbbell (dev->pci_subdevice == 0x016e) || 2719254885Sdumbbell (dev->pci_subdevice == 0x016f) || 2720254885Sdumbbell (dev->pci_subdevice == 0x0170) || 2721254885Sdumbbell (dev->pci_subdevice == 0x017d) || 2722254885Sdumbbell (dev->pci_subdevice == 0x017e) || 2723254885Sdumbbell (dev->pci_subdevice == 0x0183) || 2724254885Sdumbbell (dev->pci_subdevice == 0x018a) || 2725254885Sdumbbell (dev->pci_subdevice == 0x019a))) 2726254885Sdumbbell force_dac2 = true; 2727254885Sdumbbell break; 2728254885Sdumbbell } 2729254885Sdumbbell 2730254885Sdumbbell if (force_dac2) { 2731254885Sdumbbell u32 disp_hw_debug = RREG32(RADEON_DISP_HW_DEBUG); 2732254885Sdumbbell u32 tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); 2733254885Sdumbbell u32 dac2_cntl = RREG32(RADEON_DAC_CNTL2); 2734254885Sdumbbell 2735254885Sdumbbell /* For CRT on DAC2, don't turn it on if BIOS didn't 2736254885Sdumbbell enable it, even it's detected. 2737254885Sdumbbell */ 2738254885Sdumbbell 2739254885Sdumbbell /* force it to crtc0 */ 2740254885Sdumbbell dac2_cntl &= ~RADEON_DAC2_DAC_CLK_SEL; 2741254885Sdumbbell dac2_cntl |= RADEON_DAC2_DAC2_CLK_SEL; 2742254885Sdumbbell disp_hw_debug |= RADEON_CRT2_DISP1_SEL; 2743254885Sdumbbell 2744254885Sdumbbell /* set up the TV DAC */ 2745254885Sdumbbell tv_dac_cntl &= ~(RADEON_TV_DAC_PEDESTAL | 2746254885Sdumbbell RADEON_TV_DAC_STD_MASK | 2747254885Sdumbbell RADEON_TV_DAC_RDACPD | 2748254885Sdumbbell RADEON_TV_DAC_GDACPD | 2749254885Sdumbbell RADEON_TV_DAC_BDACPD | 2750254885Sdumbbell RADEON_TV_DAC_BGADJ_MASK | 2751254885Sdumbbell RADEON_TV_DAC_DACADJ_MASK); 2752254885Sdumbbell tv_dac_cntl |= (RADEON_TV_DAC_NBLANK | 2753254885Sdumbbell RADEON_TV_DAC_NHOLD | 2754254885Sdumbbell RADEON_TV_DAC_STD_PS2 | 2755254885Sdumbbell (0x58 << 16)); 2756254885Sdumbbell 2757254885Sdumbbell WREG32(RADEON_TV_DAC_CNTL, tv_dac_cntl); 2758254885Sdumbbell WREG32(RADEON_DISP_HW_DEBUG, disp_hw_debug); 2759254885Sdumbbell WREG32(RADEON_DAC_CNTL2, dac2_cntl); 2760254885Sdumbbell } 2761254885Sdumbbell 2762254885Sdumbbell /* switch PM block to ACPI mode */ 2763254885Sdumbbell tmp = RREG32_PLL(RADEON_PLL_PWRMGT_CNTL); 2764254885Sdumbbell tmp &= ~RADEON_PM_MODE_SEL; 2765254885Sdumbbell WREG32_PLL(RADEON_PLL_PWRMGT_CNTL, tmp); 2766254885Sdumbbell 2767254885Sdumbbell} 2768254885Sdumbbell 2769254885Sdumbbell/* 2770254885Sdumbbell * VRAM info 2771254885Sdumbbell */ 2772254885Sdumbbellstatic void r100_vram_get_type(struct radeon_device *rdev) 2773254885Sdumbbell{ 2774254885Sdumbbell uint32_t tmp; 2775254885Sdumbbell 2776254885Sdumbbell rdev->mc.vram_is_ddr = false; 2777254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) 2778254885Sdumbbell rdev->mc.vram_is_ddr = true; 2779254885Sdumbbell else if (RREG32(RADEON_MEM_SDRAM_MODE_REG) & RADEON_MEM_CFG_TYPE_DDR) 2780254885Sdumbbell rdev->mc.vram_is_ddr = true; 2781254885Sdumbbell if ((rdev->family == CHIP_RV100) || 2782254885Sdumbbell (rdev->family == CHIP_RS100) || 2783254885Sdumbbell (rdev->family == CHIP_RS200)) { 2784254885Sdumbbell tmp = RREG32(RADEON_MEM_CNTL); 2785254885Sdumbbell if (tmp & RV100_HALF_MODE) { 2786254885Sdumbbell rdev->mc.vram_width = 32; 2787254885Sdumbbell } else { 2788254885Sdumbbell rdev->mc.vram_width = 64; 2789254885Sdumbbell } 2790254885Sdumbbell if (rdev->flags & RADEON_SINGLE_CRTC) { 2791254885Sdumbbell rdev->mc.vram_width /= 4; 2792254885Sdumbbell rdev->mc.vram_is_ddr = true; 2793254885Sdumbbell } 2794254885Sdumbbell } else if (rdev->family <= CHIP_RV280) { 2795254885Sdumbbell tmp = RREG32(RADEON_MEM_CNTL); 2796254885Sdumbbell if (tmp & RADEON_MEM_NUM_CHANNELS_MASK) { 2797254885Sdumbbell rdev->mc.vram_width = 128; 2798254885Sdumbbell } else { 2799254885Sdumbbell rdev->mc.vram_width = 64; 2800254885Sdumbbell } 2801254885Sdumbbell } else { 2802254885Sdumbbell /* newer IGPs */ 2803254885Sdumbbell rdev->mc.vram_width = 128; 2804254885Sdumbbell } 2805254885Sdumbbell} 2806254885Sdumbbell 2807254885Sdumbbellstatic u32 r100_get_accessible_vram(struct radeon_device *rdev) 2808254885Sdumbbell{ 2809254885Sdumbbell u32 aper_size; 2810254885Sdumbbell u8 byte; 2811254885Sdumbbell 2812254885Sdumbbell aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 2813254885Sdumbbell 2814254885Sdumbbell /* Set HDP_APER_CNTL only on cards that are known not to be broken, 2815254885Sdumbbell * that is has the 2nd generation multifunction PCI interface 2816254885Sdumbbell */ 2817254885Sdumbbell if (rdev->family == CHIP_RV280 || 2818254885Sdumbbell rdev->family >= CHIP_RV350) { 2819254885Sdumbbell WREG32_P(RADEON_HOST_PATH_CNTL, RADEON_HDP_APER_CNTL, 2820254885Sdumbbell ~RADEON_HDP_APER_CNTL); 2821254885Sdumbbell DRM_INFO("Generation 2 PCI interface, using max accessible memory\n"); 2822254885Sdumbbell return aper_size * 2; 2823254885Sdumbbell } 2824254885Sdumbbell 2825254885Sdumbbell /* Older cards have all sorts of funny issues to deal with. First 2826254885Sdumbbell * check if it's a multifunction card by reading the PCI config 2827254885Sdumbbell * header type... Limit those to one aperture size 2828254885Sdumbbell */ 2829254885Sdumbbell byte = pci_read_config(rdev->dev, 0xe, 1); 2830254885Sdumbbell if (byte & 0x80) { 2831254885Sdumbbell DRM_INFO("Generation 1 PCI interface in multifunction mode\n"); 2832254885Sdumbbell DRM_INFO("Limiting VRAM to one aperture\n"); 2833254885Sdumbbell return aper_size; 2834254885Sdumbbell } 2835254885Sdumbbell 2836254885Sdumbbell /* Single function older card. We read HDP_APER_CNTL to see how the BIOS 2837254885Sdumbbell * have set it up. We don't write this as it's broken on some ASICs but 2838254885Sdumbbell * we expect the BIOS to have done the right thing (might be too optimistic...) 2839254885Sdumbbell */ 2840254885Sdumbbell if (RREG32(RADEON_HOST_PATH_CNTL) & RADEON_HDP_APER_CNTL) 2841254885Sdumbbell return aper_size * 2; 2842254885Sdumbbell return aper_size; 2843254885Sdumbbell} 2844254885Sdumbbell 2845254885Sdumbbellvoid r100_vram_init_sizes(struct radeon_device *rdev) 2846254885Sdumbbell{ 2847254885Sdumbbell u64 config_aper_size; 2848254885Sdumbbell 2849254885Sdumbbell /* work out accessible VRAM */ 2850254885Sdumbbell rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); 2851254885Sdumbbell rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); 2852254885Sdumbbell rdev->mc.visible_vram_size = r100_get_accessible_vram(rdev); 2853254885Sdumbbell /* FIXME we don't use the second aperture yet when we could use it */ 2854254885Sdumbbell if (rdev->mc.visible_vram_size > rdev->mc.aper_size) 2855254885Sdumbbell rdev->mc.visible_vram_size = rdev->mc.aper_size; 2856254885Sdumbbell config_aper_size = RREG32(RADEON_CONFIG_APER_SIZE); 2857254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) { 2858254885Sdumbbell uint32_t tom; 2859254885Sdumbbell /* read NB_TOM to get the amount of ram stolen for the GPU */ 2860254885Sdumbbell tom = RREG32(RADEON_NB_TOM); 2861254885Sdumbbell rdev->mc.real_vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16); 2862254885Sdumbbell WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 2863254885Sdumbbell rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 2864254885Sdumbbell } else { 2865254885Sdumbbell rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE); 2866254885Sdumbbell /* Some production boards of m6 will report 0 2867254885Sdumbbell * if it's 8 MB 2868254885Sdumbbell */ 2869254885Sdumbbell if (rdev->mc.real_vram_size == 0) { 2870254885Sdumbbell rdev->mc.real_vram_size = 8192 * 1024; 2871254885Sdumbbell WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size); 2872254885Sdumbbell } 2873254885Sdumbbell /* Fix for RN50, M6, M7 with 8/16/32(??) MBs of VRAM - 2874254885Sdumbbell * Novell bug 204882 + along with lots of ubuntu ones 2875254885Sdumbbell */ 2876254885Sdumbbell if (rdev->mc.aper_size > config_aper_size) 2877254885Sdumbbell config_aper_size = rdev->mc.aper_size; 2878254885Sdumbbell 2879254885Sdumbbell if (config_aper_size > rdev->mc.real_vram_size) 2880254885Sdumbbell rdev->mc.mc_vram_size = config_aper_size; 2881254885Sdumbbell else 2882254885Sdumbbell rdev->mc.mc_vram_size = rdev->mc.real_vram_size; 2883254885Sdumbbell } 2884254885Sdumbbell} 2885254885Sdumbbell 2886254885Sdumbbellvoid r100_vga_set_state(struct radeon_device *rdev, bool state) 2887254885Sdumbbell{ 2888254885Sdumbbell uint32_t temp; 2889254885Sdumbbell 2890254885Sdumbbell temp = RREG32(RADEON_CONFIG_CNTL); 2891254885Sdumbbell if (state == false) { 2892254885Sdumbbell temp &= ~RADEON_CFG_VGA_RAM_EN; 2893254885Sdumbbell temp |= RADEON_CFG_VGA_IO_DIS; 2894254885Sdumbbell } else { 2895254885Sdumbbell temp &= ~RADEON_CFG_VGA_IO_DIS; 2896254885Sdumbbell } 2897254885Sdumbbell WREG32(RADEON_CONFIG_CNTL, temp); 2898254885Sdumbbell} 2899254885Sdumbbell 2900254885Sdumbbellstatic void r100_mc_init(struct radeon_device *rdev) 2901254885Sdumbbell{ 2902254885Sdumbbell u64 base; 2903254885Sdumbbell 2904254885Sdumbbell r100_vram_get_type(rdev); 2905254885Sdumbbell r100_vram_init_sizes(rdev); 2906254885Sdumbbell base = rdev->mc.aper_base; 2907254885Sdumbbell if (rdev->flags & RADEON_IS_IGP) 2908254885Sdumbbell base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16; 2909254885Sdumbbell radeon_vram_location(rdev, &rdev->mc, base); 2910254885Sdumbbell rdev->mc.gtt_base_align = 0; 2911254885Sdumbbell if (!(rdev->flags & RADEON_IS_AGP)) 2912254885Sdumbbell radeon_gtt_location(rdev, &rdev->mc); 2913254885Sdumbbell radeon_update_bandwidth_info(rdev); 2914254885Sdumbbell} 2915254885Sdumbbell 2916254885Sdumbbell 2917254885Sdumbbell/* 2918254885Sdumbbell * Indirect registers accessor 2919254885Sdumbbell */ 2920254885Sdumbbellvoid r100_pll_errata_after_index(struct radeon_device *rdev) 2921254885Sdumbbell{ 2922254885Sdumbbell if (rdev->pll_errata & CHIP_ERRATA_PLL_DUMMYREADS) { 2923254885Sdumbbell (void)RREG32(RADEON_CLOCK_CNTL_DATA); 2924254885Sdumbbell (void)RREG32(RADEON_CRTC_GEN_CNTL); 2925254885Sdumbbell } 2926254885Sdumbbell} 2927254885Sdumbbell 2928254885Sdumbbellstatic void r100_pll_errata_after_data(struct radeon_device *rdev) 2929254885Sdumbbell{ 2930254885Sdumbbell /* This workarounds is necessary on RV100, RS100 and RS200 chips 2931254885Sdumbbell * or the chip could hang on a subsequent access 2932254885Sdumbbell */ 2933254885Sdumbbell if (rdev->pll_errata & CHIP_ERRATA_PLL_DELAY) { 2934254885Sdumbbell DRM_MDELAY(5); 2935254885Sdumbbell } 2936254885Sdumbbell 2937254885Sdumbbell /* This function is required to workaround a hardware bug in some (all?) 2938254885Sdumbbell * revisions of the R300. This workaround should be called after every 2939254885Sdumbbell * CLOCK_CNTL_INDEX register access. If not, register reads afterward 2940254885Sdumbbell * may not be correct. 2941254885Sdumbbell */ 2942254885Sdumbbell if (rdev->pll_errata & CHIP_ERRATA_R300_CG) { 2943254885Sdumbbell uint32_t save, tmp; 2944254885Sdumbbell 2945254885Sdumbbell save = RREG32(RADEON_CLOCK_CNTL_INDEX); 2946254885Sdumbbell tmp = save & ~(0x3f | RADEON_PLL_WR_EN); 2947254885Sdumbbell WREG32(RADEON_CLOCK_CNTL_INDEX, tmp); 2948254885Sdumbbell tmp = RREG32(RADEON_CLOCK_CNTL_DATA); 2949254885Sdumbbell WREG32(RADEON_CLOCK_CNTL_INDEX, save); 2950254885Sdumbbell } 2951254885Sdumbbell} 2952254885Sdumbbell 2953254885Sdumbbelluint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg) 2954254885Sdumbbell{ 2955254885Sdumbbell uint32_t data; 2956254885Sdumbbell 2957254885Sdumbbell WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f); 2958254885Sdumbbell r100_pll_errata_after_index(rdev); 2959254885Sdumbbell data = RREG32(RADEON_CLOCK_CNTL_DATA); 2960254885Sdumbbell r100_pll_errata_after_data(rdev); 2961254885Sdumbbell return data; 2962254885Sdumbbell} 2963254885Sdumbbell 2964254885Sdumbbellvoid r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 2965254885Sdumbbell{ 2966254885Sdumbbell WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN)); 2967254885Sdumbbell r100_pll_errata_after_index(rdev); 2968254885Sdumbbell WREG32(RADEON_CLOCK_CNTL_DATA, v); 2969254885Sdumbbell r100_pll_errata_after_data(rdev); 2970254885Sdumbbell} 2971254885Sdumbbell 2972254885Sdumbbellstatic void r100_set_safe_registers(struct radeon_device *rdev) 2973254885Sdumbbell{ 2974254885Sdumbbell if (ASIC_IS_RN50(rdev)) { 2975254885Sdumbbell rdev->config.r100.reg_safe_bm = rn50_reg_safe_bm; 2976254885Sdumbbell rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(rn50_reg_safe_bm); 2977254885Sdumbbell } else if (rdev->family < CHIP_R200) { 2978254885Sdumbbell rdev->config.r100.reg_safe_bm = r100_reg_safe_bm; 2979254885Sdumbbell rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(r100_reg_safe_bm); 2980254885Sdumbbell } else { 2981254885Sdumbbell r200_set_safe_registers(rdev); 2982254885Sdumbbell } 2983254885Sdumbbell} 2984254885Sdumbbell 2985254885Sdumbbell/* 2986254885Sdumbbell * Debugfs info 2987254885Sdumbbell */ 2988254885Sdumbbell#if defined(CONFIG_DEBUG_FS) 2989254885Sdumbbellstatic int r100_debugfs_rbbm_info(struct seq_file *m, void *data) 2990254885Sdumbbell{ 2991254885Sdumbbell struct drm_info_node *node = (struct drm_info_node *) m->private; 2992254885Sdumbbell struct drm_device *dev = node->minor->dev; 2993254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 2994254885Sdumbbell uint32_t reg, value; 2995254885Sdumbbell unsigned i; 2996254885Sdumbbell 2997254885Sdumbbell seq_printf(m, "RBBM_STATUS 0x%08x\n", RREG32(RADEON_RBBM_STATUS)); 2998254885Sdumbbell seq_printf(m, "RBBM_CMDFIFO_STAT 0x%08x\n", RREG32(0xE7C)); 2999254885Sdumbbell seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 3000254885Sdumbbell for (i = 0; i < 64; i++) { 3001254885Sdumbbell WREG32(RADEON_RBBM_CMDFIFO_ADDR, i | 0x100); 3002254885Sdumbbell reg = (RREG32(RADEON_RBBM_CMDFIFO_DATA) - 1) >> 2; 3003254885Sdumbbell WREG32(RADEON_RBBM_CMDFIFO_ADDR, i); 3004254885Sdumbbell value = RREG32(RADEON_RBBM_CMDFIFO_DATA); 3005254885Sdumbbell seq_printf(m, "[0x%03X] 0x%04X=0x%08X\n", i, reg, value); 3006254885Sdumbbell } 3007254885Sdumbbell return 0; 3008254885Sdumbbell} 3009254885Sdumbbell 3010254885Sdumbbellstatic int r100_debugfs_cp_ring_info(struct seq_file *m, void *data) 3011254885Sdumbbell{ 3012254885Sdumbbell struct drm_info_node *node = (struct drm_info_node *) m->private; 3013254885Sdumbbell struct drm_device *dev = node->minor->dev; 3014254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 3015254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 3016254885Sdumbbell uint32_t rdp, wdp; 3017254885Sdumbbell unsigned count, i, j; 3018254885Sdumbbell 3019254885Sdumbbell radeon_ring_free_size(rdev, ring); 3020254885Sdumbbell rdp = RREG32(RADEON_CP_RB_RPTR); 3021254885Sdumbbell wdp = RREG32(RADEON_CP_RB_WPTR); 3022254885Sdumbbell count = (rdp + ring->ring_size - wdp) & ring->ptr_mask; 3023254885Sdumbbell seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 3024254885Sdumbbell seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp); 3025254885Sdumbbell seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp); 3026254885Sdumbbell seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); 3027254885Sdumbbell seq_printf(m, "%u dwords in ring\n", count); 3028254885Sdumbbell for (j = 0; j <= count; j++) { 3029254885Sdumbbell i = (rdp + j) & ring->ptr_mask; 3030254885Sdumbbell seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]); 3031254885Sdumbbell } 3032254885Sdumbbell return 0; 3033254885Sdumbbell} 3034254885Sdumbbell 3035254885Sdumbbell 3036254885Sdumbbellstatic int r100_debugfs_cp_csq_fifo(struct seq_file *m, void *data) 3037254885Sdumbbell{ 3038254885Sdumbbell struct drm_info_node *node = (struct drm_info_node *) m->private; 3039254885Sdumbbell struct drm_device *dev = node->minor->dev; 3040254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 3041254885Sdumbbell uint32_t csq_stat, csq2_stat, tmp; 3042254885Sdumbbell unsigned r_rptr, r_wptr, ib1_rptr, ib1_wptr, ib2_rptr, ib2_wptr; 3043254885Sdumbbell unsigned i; 3044254885Sdumbbell 3045254885Sdumbbell seq_printf(m, "CP_STAT 0x%08x\n", RREG32(RADEON_CP_STAT)); 3046254885Sdumbbell seq_printf(m, "CP_CSQ_MODE 0x%08x\n", RREG32(RADEON_CP_CSQ_MODE)); 3047254885Sdumbbell csq_stat = RREG32(RADEON_CP_CSQ_STAT); 3048254885Sdumbbell csq2_stat = RREG32(RADEON_CP_CSQ2_STAT); 3049254885Sdumbbell r_rptr = (csq_stat >> 0) & 0x3ff; 3050254885Sdumbbell r_wptr = (csq_stat >> 10) & 0x3ff; 3051254885Sdumbbell ib1_rptr = (csq_stat >> 20) & 0x3ff; 3052254885Sdumbbell ib1_wptr = (csq2_stat >> 0) & 0x3ff; 3053254885Sdumbbell ib2_rptr = (csq2_stat >> 10) & 0x3ff; 3054254885Sdumbbell ib2_wptr = (csq2_stat >> 20) & 0x3ff; 3055254885Sdumbbell seq_printf(m, "CP_CSQ_STAT 0x%08x\n", csq_stat); 3056254885Sdumbbell seq_printf(m, "CP_CSQ2_STAT 0x%08x\n", csq2_stat); 3057254885Sdumbbell seq_printf(m, "Ring rptr %u\n", r_rptr); 3058254885Sdumbbell seq_printf(m, "Ring wptr %u\n", r_wptr); 3059254885Sdumbbell seq_printf(m, "Indirect1 rptr %u\n", ib1_rptr); 3060254885Sdumbbell seq_printf(m, "Indirect1 wptr %u\n", ib1_wptr); 3061254885Sdumbbell seq_printf(m, "Indirect2 rptr %u\n", ib2_rptr); 3062254885Sdumbbell seq_printf(m, "Indirect2 wptr %u\n", ib2_wptr); 3063254885Sdumbbell /* FIXME: 0, 128, 640 depends on fifo setup see cp_init_kms 3064254885Sdumbbell * 128 = indirect1_start * 8 & 640 = indirect2_start * 8 */ 3065254885Sdumbbell seq_printf(m, "Ring fifo:\n"); 3066254885Sdumbbell for (i = 0; i < 256; i++) { 3067254885Sdumbbell WREG32(RADEON_CP_CSQ_ADDR, i << 2); 3068254885Sdumbbell tmp = RREG32(RADEON_CP_CSQ_DATA); 3069254885Sdumbbell seq_printf(m, "rfifo[%04d]=0x%08X\n", i, tmp); 3070254885Sdumbbell } 3071254885Sdumbbell seq_printf(m, "Indirect1 fifo:\n"); 3072254885Sdumbbell for (i = 256; i <= 512; i++) { 3073254885Sdumbbell WREG32(RADEON_CP_CSQ_ADDR, i << 2); 3074254885Sdumbbell tmp = RREG32(RADEON_CP_CSQ_DATA); 3075254885Sdumbbell seq_printf(m, "ib1fifo[%04d]=0x%08X\n", i, tmp); 3076254885Sdumbbell } 3077254885Sdumbbell seq_printf(m, "Indirect2 fifo:\n"); 3078254885Sdumbbell for (i = 640; i < ib1_wptr; i++) { 3079254885Sdumbbell WREG32(RADEON_CP_CSQ_ADDR, i << 2); 3080254885Sdumbbell tmp = RREG32(RADEON_CP_CSQ_DATA); 3081254885Sdumbbell seq_printf(m, "ib2fifo[%04d]=0x%08X\n", i, tmp); 3082254885Sdumbbell } 3083254885Sdumbbell return 0; 3084254885Sdumbbell} 3085254885Sdumbbell 3086254885Sdumbbellstatic int r100_debugfs_mc_info(struct seq_file *m, void *data) 3087254885Sdumbbell{ 3088254885Sdumbbell struct drm_info_node *node = (struct drm_info_node *) m->private; 3089254885Sdumbbell struct drm_device *dev = node->minor->dev; 3090254885Sdumbbell struct radeon_device *rdev = dev->dev_private; 3091254885Sdumbbell uint32_t tmp; 3092254885Sdumbbell 3093254885Sdumbbell tmp = RREG32(RADEON_CONFIG_MEMSIZE); 3094254885Sdumbbell seq_printf(m, "CONFIG_MEMSIZE 0x%08x\n", tmp); 3095254885Sdumbbell tmp = RREG32(RADEON_MC_FB_LOCATION); 3096254885Sdumbbell seq_printf(m, "MC_FB_LOCATION 0x%08x\n", tmp); 3097254885Sdumbbell tmp = RREG32(RADEON_BUS_CNTL); 3098254885Sdumbbell seq_printf(m, "BUS_CNTL 0x%08x\n", tmp); 3099254885Sdumbbell tmp = RREG32(RADEON_MC_AGP_LOCATION); 3100254885Sdumbbell seq_printf(m, "MC_AGP_LOCATION 0x%08x\n", tmp); 3101254885Sdumbbell tmp = RREG32(RADEON_AGP_BASE); 3102254885Sdumbbell seq_printf(m, "AGP_BASE 0x%08x\n", tmp); 3103254885Sdumbbell tmp = RREG32(RADEON_HOST_PATH_CNTL); 3104254885Sdumbbell seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp); 3105254885Sdumbbell tmp = RREG32(0x01D0); 3106254885Sdumbbell seq_printf(m, "AIC_CTRL 0x%08x\n", tmp); 3107254885Sdumbbell tmp = RREG32(RADEON_AIC_LO_ADDR); 3108254885Sdumbbell seq_printf(m, "AIC_LO_ADDR 0x%08x\n", tmp); 3109254885Sdumbbell tmp = RREG32(RADEON_AIC_HI_ADDR); 3110254885Sdumbbell seq_printf(m, "AIC_HI_ADDR 0x%08x\n", tmp); 3111254885Sdumbbell tmp = RREG32(0x01E4); 3112254885Sdumbbell seq_printf(m, "AIC_TLB_ADDR 0x%08x\n", tmp); 3113254885Sdumbbell return 0; 3114254885Sdumbbell} 3115254885Sdumbbell 3116254885Sdumbbellstatic struct drm_info_list r100_debugfs_rbbm_list[] = { 3117254885Sdumbbell {"r100_rbbm_info", r100_debugfs_rbbm_info, 0, NULL}, 3118254885Sdumbbell}; 3119254885Sdumbbell 3120254885Sdumbbellstatic struct drm_info_list r100_debugfs_cp_list[] = { 3121254885Sdumbbell {"r100_cp_ring_info", r100_debugfs_cp_ring_info, 0, NULL}, 3122254885Sdumbbell {"r100_cp_csq_fifo", r100_debugfs_cp_csq_fifo, 0, NULL}, 3123254885Sdumbbell}; 3124254885Sdumbbell 3125254885Sdumbbellstatic struct drm_info_list r100_debugfs_mc_info_list[] = { 3126254885Sdumbbell {"r100_mc_info", r100_debugfs_mc_info, 0, NULL}, 3127254885Sdumbbell}; 3128254885Sdumbbell#endif 3129254885Sdumbbell 3130254885Sdumbbellint r100_debugfs_rbbm_init(struct radeon_device *rdev) 3131254885Sdumbbell{ 3132254885Sdumbbell#if defined(CONFIG_DEBUG_FS) 3133254885Sdumbbell return radeon_debugfs_add_files(rdev, r100_debugfs_rbbm_list, 1); 3134254885Sdumbbell#else 3135254885Sdumbbell return 0; 3136254885Sdumbbell#endif 3137254885Sdumbbell} 3138254885Sdumbbell 3139254885Sdumbbellint r100_debugfs_cp_init(struct radeon_device *rdev) 3140254885Sdumbbell{ 3141254885Sdumbbell#if defined(CONFIG_DEBUG_FS) 3142254885Sdumbbell return radeon_debugfs_add_files(rdev, r100_debugfs_cp_list, 2); 3143254885Sdumbbell#else 3144254885Sdumbbell return 0; 3145254885Sdumbbell#endif 3146254885Sdumbbell} 3147254885Sdumbbell 3148254885Sdumbbellint r100_debugfs_mc_info_init(struct radeon_device *rdev) 3149254885Sdumbbell{ 3150254885Sdumbbell#if defined(CONFIG_DEBUG_FS) 3151254885Sdumbbell return radeon_debugfs_add_files(rdev, r100_debugfs_mc_info_list, 1); 3152254885Sdumbbell#else 3153254885Sdumbbell return 0; 3154254885Sdumbbell#endif 3155254885Sdumbbell} 3156254885Sdumbbell 3157254885Sdumbbellint r100_set_surface_reg(struct radeon_device *rdev, int reg, 3158254885Sdumbbell uint32_t tiling_flags, uint32_t pitch, 3159254885Sdumbbell uint32_t offset, uint32_t obj_size) 3160254885Sdumbbell{ 3161254885Sdumbbell int surf_index = reg * 16; 3162254885Sdumbbell int flags = 0; 3163254885Sdumbbell 3164254885Sdumbbell if (rdev->family <= CHIP_RS200) { 3165254885Sdumbbell if ((tiling_flags & (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 3166254885Sdumbbell == (RADEON_TILING_MACRO|RADEON_TILING_MICRO)) 3167254885Sdumbbell flags |= RADEON_SURF_TILE_COLOR_BOTH; 3168254885Sdumbbell if (tiling_flags & RADEON_TILING_MACRO) 3169254885Sdumbbell flags |= RADEON_SURF_TILE_COLOR_MACRO; 3170254885Sdumbbell } else if (rdev->family <= CHIP_RV280) { 3171254885Sdumbbell if (tiling_flags & (RADEON_TILING_MACRO)) 3172254885Sdumbbell flags |= R200_SURF_TILE_COLOR_MACRO; 3173254885Sdumbbell if (tiling_flags & RADEON_TILING_MICRO) 3174254885Sdumbbell flags |= R200_SURF_TILE_COLOR_MICRO; 3175254885Sdumbbell } else { 3176254885Sdumbbell if (tiling_flags & RADEON_TILING_MACRO) 3177254885Sdumbbell flags |= R300_SURF_TILE_MACRO; 3178254885Sdumbbell if (tiling_flags & RADEON_TILING_MICRO) 3179254885Sdumbbell flags |= R300_SURF_TILE_MICRO; 3180254885Sdumbbell } 3181254885Sdumbbell 3182254885Sdumbbell if (tiling_flags & RADEON_TILING_SWAP_16BIT) 3183254885Sdumbbell flags |= RADEON_SURF_AP0_SWP_16BPP | RADEON_SURF_AP1_SWP_16BPP; 3184254885Sdumbbell if (tiling_flags & RADEON_TILING_SWAP_32BIT) 3185254885Sdumbbell flags |= RADEON_SURF_AP0_SWP_32BPP | RADEON_SURF_AP1_SWP_32BPP; 3186254885Sdumbbell 3187254885Sdumbbell /* when we aren't tiling the pitch seems to needs to be furtherdivided down. - tested on power5 + rn50 server */ 3188254885Sdumbbell if (tiling_flags & (RADEON_TILING_SWAP_16BIT | RADEON_TILING_SWAP_32BIT)) { 3189254885Sdumbbell if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) 3190254885Sdumbbell if (ASIC_IS_RN50(rdev)) 3191254885Sdumbbell pitch /= 16; 3192254885Sdumbbell } 3193254885Sdumbbell 3194254885Sdumbbell /* r100/r200 divide by 16 */ 3195254885Sdumbbell if (rdev->family < CHIP_R300) 3196254885Sdumbbell flags |= pitch / 16; 3197254885Sdumbbell else 3198254885Sdumbbell flags |= pitch / 8; 3199254885Sdumbbell 3200254885Sdumbbell 3201254885Sdumbbell DRM_DEBUG_KMS("writing surface %d %d %x %x\n", reg, flags, offset, offset+obj_size-1); 3202254885Sdumbbell WREG32(RADEON_SURFACE0_INFO + surf_index, flags); 3203254885Sdumbbell WREG32(RADEON_SURFACE0_LOWER_BOUND + surf_index, offset); 3204254885Sdumbbell WREG32(RADEON_SURFACE0_UPPER_BOUND + surf_index, offset + obj_size - 1); 3205254885Sdumbbell return 0; 3206254885Sdumbbell} 3207254885Sdumbbell 3208254885Sdumbbellvoid r100_clear_surface_reg(struct radeon_device *rdev, int reg) 3209254885Sdumbbell{ 3210254885Sdumbbell int surf_index = reg * 16; 3211254885Sdumbbell WREG32(RADEON_SURFACE0_INFO + surf_index, 0); 3212254885Sdumbbell} 3213254885Sdumbbell 3214254885Sdumbbellvoid r100_bandwidth_update(struct radeon_device *rdev) 3215254885Sdumbbell{ 3216254885Sdumbbell fixed20_12 trcd_ff, trp_ff, tras_ff, trbs_ff, tcas_ff; 3217254885Sdumbbell fixed20_12 sclk_ff, mclk_ff, sclk_eff_ff, sclk_delay_ff; 3218254885Sdumbbell fixed20_12 peak_disp_bw, mem_bw, pix_clk, pix_clk2, temp_ff, crit_point_ff; 3219254885Sdumbbell uint32_t temp, data, mem_trcd, mem_trp, mem_tras; 3220254885Sdumbbell fixed20_12 memtcas_ff[8] = { 3221254885Sdumbbell dfixed_init(1), 3222254885Sdumbbell dfixed_init(2), 3223254885Sdumbbell dfixed_init(3), 3224254885Sdumbbell dfixed_init(0), 3225254885Sdumbbell dfixed_init_half(1), 3226254885Sdumbbell dfixed_init_half(2), 3227254885Sdumbbell dfixed_init(0), 3228254885Sdumbbell }; 3229254885Sdumbbell fixed20_12 memtcas_rs480_ff[8] = { 3230254885Sdumbbell dfixed_init(0), 3231254885Sdumbbell dfixed_init(1), 3232254885Sdumbbell dfixed_init(2), 3233254885Sdumbbell dfixed_init(3), 3234254885Sdumbbell dfixed_init(0), 3235254885Sdumbbell dfixed_init_half(1), 3236254885Sdumbbell dfixed_init_half(2), 3237254885Sdumbbell dfixed_init_half(3), 3238254885Sdumbbell }; 3239254885Sdumbbell fixed20_12 memtcas2_ff[8] = { 3240254885Sdumbbell dfixed_init(0), 3241254885Sdumbbell dfixed_init(1), 3242254885Sdumbbell dfixed_init(2), 3243254885Sdumbbell dfixed_init(3), 3244254885Sdumbbell dfixed_init(4), 3245254885Sdumbbell dfixed_init(5), 3246254885Sdumbbell dfixed_init(6), 3247254885Sdumbbell dfixed_init(7), 3248254885Sdumbbell }; 3249254885Sdumbbell fixed20_12 memtrbs[8] = { 3250254885Sdumbbell dfixed_init(1), 3251254885Sdumbbell dfixed_init_half(1), 3252254885Sdumbbell dfixed_init(2), 3253254885Sdumbbell dfixed_init_half(2), 3254254885Sdumbbell dfixed_init(3), 3255254885Sdumbbell dfixed_init_half(3), 3256254885Sdumbbell dfixed_init(4), 3257254885Sdumbbell dfixed_init_half(4) 3258254885Sdumbbell }; 3259254885Sdumbbell fixed20_12 memtrbs_r4xx[8] = { 3260254885Sdumbbell dfixed_init(4), 3261254885Sdumbbell dfixed_init(5), 3262254885Sdumbbell dfixed_init(6), 3263254885Sdumbbell dfixed_init(7), 3264254885Sdumbbell dfixed_init(8), 3265254885Sdumbbell dfixed_init(9), 3266254885Sdumbbell dfixed_init(10), 3267254885Sdumbbell dfixed_init(11) 3268254885Sdumbbell }; 3269254885Sdumbbell fixed20_12 min_mem_eff; 3270254885Sdumbbell fixed20_12 mc_latency_sclk, mc_latency_mclk, k1; 3271254885Sdumbbell fixed20_12 cur_latency_mclk, cur_latency_sclk; 3272254885Sdumbbell fixed20_12 disp_latency, disp_latency_overhead, disp_drain_rate, 3273254885Sdumbbell disp_drain_rate2, read_return_rate; 3274254885Sdumbbell fixed20_12 time_disp1_drop_priority; 3275254885Sdumbbell int c; 3276254885Sdumbbell int cur_size = 16; /* in octawords */ 3277254885Sdumbbell int critical_point = 0, critical_point2; 3278254885Sdumbbell/* uint32_t read_return_rate, time_disp1_drop_priority; */ 3279254885Sdumbbell int stop_req, max_stop_req; 3280254885Sdumbbell struct drm_display_mode *mode1 = NULL; 3281254885Sdumbbell struct drm_display_mode *mode2 = NULL; 3282254885Sdumbbell uint32_t pixel_bytes1 = 0; 3283254885Sdumbbell uint32_t pixel_bytes2 = 0; 3284254885Sdumbbell 3285254885Sdumbbell radeon_update_display_priority(rdev); 3286254885Sdumbbell 3287254885Sdumbbell if (rdev->mode_info.crtcs[0]->base.enabled) { 3288254885Sdumbbell mode1 = &rdev->mode_info.crtcs[0]->base.mode; 3289254885Sdumbbell pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; 3290254885Sdumbbell } 3291254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 3292254885Sdumbbell if (rdev->mode_info.crtcs[1]->base.enabled) { 3293254885Sdumbbell mode2 = &rdev->mode_info.crtcs[1]->base.mode; 3294254885Sdumbbell pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; 3295254885Sdumbbell } 3296254885Sdumbbell } 3297254885Sdumbbell 3298254885Sdumbbell min_mem_eff.full = dfixed_const_8(0); 3299254885Sdumbbell /* get modes */ 3300254885Sdumbbell if ((rdev->disp_priority == 2) && ASIC_IS_R300(rdev)) { 3301254885Sdumbbell uint32_t mc_init_misc_lat_timer = RREG32(R300_MC_INIT_MISC_LAT_TIMER); 3302254885Sdumbbell mc_init_misc_lat_timer &= ~(R300_MC_DISP1R_INIT_LAT_MASK << R300_MC_DISP1R_INIT_LAT_SHIFT); 3303254885Sdumbbell mc_init_misc_lat_timer &= ~(R300_MC_DISP0R_INIT_LAT_MASK << R300_MC_DISP0R_INIT_LAT_SHIFT); 3304254885Sdumbbell /* check crtc enables */ 3305254885Sdumbbell if (mode2) 3306254885Sdumbbell mc_init_misc_lat_timer |= (1 << R300_MC_DISP1R_INIT_LAT_SHIFT); 3307254885Sdumbbell if (mode1) 3308254885Sdumbbell mc_init_misc_lat_timer |= (1 << R300_MC_DISP0R_INIT_LAT_SHIFT); 3309254885Sdumbbell WREG32(R300_MC_INIT_MISC_LAT_TIMER, mc_init_misc_lat_timer); 3310254885Sdumbbell } 3311254885Sdumbbell 3312254885Sdumbbell /* 3313254885Sdumbbell * determine is there is enough bw for current mode 3314254885Sdumbbell */ 3315254885Sdumbbell sclk_ff = rdev->pm.sclk; 3316254885Sdumbbell mclk_ff = rdev->pm.mclk; 3317254885Sdumbbell 3318254885Sdumbbell temp = (rdev->mc.vram_width / 8) * (rdev->mc.vram_is_ddr ? 2 : 1); 3319254885Sdumbbell temp_ff.full = dfixed_const(temp); 3320254885Sdumbbell mem_bw.full = dfixed_mul(mclk_ff, temp_ff); 3321254885Sdumbbell 3322254885Sdumbbell pix_clk.full = 0; 3323254885Sdumbbell pix_clk2.full = 0; 3324254885Sdumbbell peak_disp_bw.full = 0; 3325254885Sdumbbell if (mode1) { 3326254885Sdumbbell temp_ff.full = dfixed_const(1000); 3327254885Sdumbbell pix_clk.full = dfixed_const(mode1->clock); /* convert to fixed point */ 3328254885Sdumbbell pix_clk.full = dfixed_div(pix_clk, temp_ff); 3329254885Sdumbbell temp_ff.full = dfixed_const(pixel_bytes1); 3330254885Sdumbbell peak_disp_bw.full += dfixed_mul(pix_clk, temp_ff); 3331254885Sdumbbell } 3332254885Sdumbbell if (mode2) { 3333254885Sdumbbell temp_ff.full = dfixed_const(1000); 3334254885Sdumbbell pix_clk2.full = dfixed_const(mode2->clock); /* convert to fixed point */ 3335254885Sdumbbell pix_clk2.full = dfixed_div(pix_clk2, temp_ff); 3336254885Sdumbbell temp_ff.full = dfixed_const(pixel_bytes2); 3337254885Sdumbbell peak_disp_bw.full += dfixed_mul(pix_clk2, temp_ff); 3338254885Sdumbbell } 3339254885Sdumbbell 3340254885Sdumbbell mem_bw.full = dfixed_mul(mem_bw, min_mem_eff); 3341254885Sdumbbell if (peak_disp_bw.full >= mem_bw.full) { 3342254885Sdumbbell DRM_ERROR("You may not have enough display bandwidth for current mode\n" 3343254885Sdumbbell "If you have flickering problem, try to lower resolution, refresh rate, or color depth\n"); 3344254885Sdumbbell } 3345254885Sdumbbell 3346254885Sdumbbell /* Get values from the EXT_MEM_CNTL register...converting its contents. */ 3347254885Sdumbbell temp = RREG32(RADEON_MEM_TIMING_CNTL); 3348254885Sdumbbell if ((rdev->family == CHIP_RV100) || (rdev->flags & RADEON_IS_IGP)) { /* RV100, M6, IGPs */ 3349254885Sdumbbell mem_trcd = ((temp >> 2) & 0x3) + 1; 3350254885Sdumbbell mem_trp = ((temp & 0x3)) + 1; 3351254885Sdumbbell mem_tras = ((temp & 0x70) >> 4) + 1; 3352254885Sdumbbell } else if (rdev->family == CHIP_R300 || 3353254885Sdumbbell rdev->family == CHIP_R350) { /* r300, r350 */ 3354254885Sdumbbell mem_trcd = (temp & 0x7) + 1; 3355254885Sdumbbell mem_trp = ((temp >> 8) & 0x7) + 1; 3356254885Sdumbbell mem_tras = ((temp >> 11) & 0xf) + 4; 3357254885Sdumbbell } else if (rdev->family == CHIP_RV350 || 3358254885Sdumbbell rdev->family <= CHIP_RV380) { 3359254885Sdumbbell /* rv3x0 */ 3360254885Sdumbbell mem_trcd = (temp & 0x7) + 3; 3361254885Sdumbbell mem_trp = ((temp >> 8) & 0x7) + 3; 3362254885Sdumbbell mem_tras = ((temp >> 11) & 0xf) + 6; 3363254885Sdumbbell } else if (rdev->family == CHIP_R420 || 3364254885Sdumbbell rdev->family == CHIP_R423 || 3365254885Sdumbbell rdev->family == CHIP_RV410) { 3366254885Sdumbbell /* r4xx */ 3367254885Sdumbbell mem_trcd = (temp & 0xf) + 3; 3368254885Sdumbbell if (mem_trcd > 15) 3369254885Sdumbbell mem_trcd = 15; 3370254885Sdumbbell mem_trp = ((temp >> 8) & 0xf) + 3; 3371254885Sdumbbell if (mem_trp > 15) 3372254885Sdumbbell mem_trp = 15; 3373254885Sdumbbell mem_tras = ((temp >> 12) & 0x1f) + 6; 3374254885Sdumbbell if (mem_tras > 31) 3375254885Sdumbbell mem_tras = 31; 3376254885Sdumbbell } else { /* RV200, R200 */ 3377254885Sdumbbell mem_trcd = (temp & 0x7) + 1; 3378254885Sdumbbell mem_trp = ((temp >> 8) & 0x7) + 1; 3379254885Sdumbbell mem_tras = ((temp >> 12) & 0xf) + 4; 3380254885Sdumbbell } 3381254885Sdumbbell /* convert to FF */ 3382254885Sdumbbell trcd_ff.full = dfixed_const(mem_trcd); 3383254885Sdumbbell trp_ff.full = dfixed_const(mem_trp); 3384254885Sdumbbell tras_ff.full = dfixed_const(mem_tras); 3385254885Sdumbbell 3386254885Sdumbbell /* Get values from the MEM_SDRAM_MODE_REG register...converting its */ 3387254885Sdumbbell temp = RREG32(RADEON_MEM_SDRAM_MODE_REG); 3388254885Sdumbbell data = (temp & (7 << 20)) >> 20; 3389254885Sdumbbell if ((rdev->family == CHIP_RV100) || rdev->flags & RADEON_IS_IGP) { 3390254885Sdumbbell if (rdev->family == CHIP_RS480) /* don't think rs400 */ 3391254885Sdumbbell tcas_ff = memtcas_rs480_ff[data]; 3392254885Sdumbbell else 3393254885Sdumbbell tcas_ff = memtcas_ff[data]; 3394254885Sdumbbell } else 3395254885Sdumbbell tcas_ff = memtcas2_ff[data]; 3396254885Sdumbbell 3397254885Sdumbbell if (rdev->family == CHIP_RS400 || 3398254885Sdumbbell rdev->family == CHIP_RS480) { 3399254885Sdumbbell /* extra cas latency stored in bits 23-25 0-4 clocks */ 3400254885Sdumbbell data = (temp >> 23) & 0x7; 3401254885Sdumbbell if (data < 5) 3402254885Sdumbbell tcas_ff.full += dfixed_const(data); 3403254885Sdumbbell } 3404254885Sdumbbell 3405254885Sdumbbell if (ASIC_IS_R300(rdev) && !(rdev->flags & RADEON_IS_IGP)) { 3406254885Sdumbbell /* on the R300, Tcas is included in Trbs. 3407254885Sdumbbell */ 3408254885Sdumbbell temp = RREG32(RADEON_MEM_CNTL); 3409254885Sdumbbell data = (R300_MEM_NUM_CHANNELS_MASK & temp); 3410254885Sdumbbell if (data == 1) { 3411254885Sdumbbell if (R300_MEM_USE_CD_CH_ONLY & temp) { 3412254885Sdumbbell temp = RREG32(R300_MC_IND_INDEX); 3413254885Sdumbbell temp &= ~R300_MC_IND_ADDR_MASK; 3414254885Sdumbbell temp |= R300_MC_READ_CNTL_CD_mcind; 3415254885Sdumbbell WREG32(R300_MC_IND_INDEX, temp); 3416254885Sdumbbell temp = RREG32(R300_MC_IND_DATA); 3417254885Sdumbbell data = (R300_MEM_RBS_POSITION_C_MASK & temp); 3418254885Sdumbbell } else { 3419254885Sdumbbell temp = RREG32(R300_MC_READ_CNTL_AB); 3420254885Sdumbbell data = (R300_MEM_RBS_POSITION_A_MASK & temp); 3421254885Sdumbbell } 3422254885Sdumbbell } else { 3423254885Sdumbbell temp = RREG32(R300_MC_READ_CNTL_AB); 3424254885Sdumbbell data = (R300_MEM_RBS_POSITION_A_MASK & temp); 3425254885Sdumbbell } 3426254885Sdumbbell if (rdev->family == CHIP_RV410 || 3427254885Sdumbbell rdev->family == CHIP_R420 || 3428254885Sdumbbell rdev->family == CHIP_R423) 3429254885Sdumbbell trbs_ff = memtrbs_r4xx[data]; 3430254885Sdumbbell else 3431254885Sdumbbell trbs_ff = memtrbs[data]; 3432254885Sdumbbell tcas_ff.full += trbs_ff.full; 3433254885Sdumbbell } 3434254885Sdumbbell 3435254885Sdumbbell sclk_eff_ff.full = sclk_ff.full; 3436254885Sdumbbell 3437254885Sdumbbell if (rdev->flags & RADEON_IS_AGP) { 3438254885Sdumbbell fixed20_12 agpmode_ff; 3439254885Sdumbbell agpmode_ff.full = dfixed_const(radeon_agpmode); 3440254885Sdumbbell temp_ff.full = dfixed_const_666(16); 3441254885Sdumbbell sclk_eff_ff.full -= dfixed_mul(agpmode_ff, temp_ff); 3442254885Sdumbbell } 3443254885Sdumbbell /* TODO PCIE lanes may affect this - agpmode == 16?? */ 3444254885Sdumbbell 3445254885Sdumbbell if (ASIC_IS_R300(rdev)) { 3446254885Sdumbbell sclk_delay_ff.full = dfixed_const(250); 3447254885Sdumbbell } else { 3448254885Sdumbbell if ((rdev->family == CHIP_RV100) || 3449254885Sdumbbell rdev->flags & RADEON_IS_IGP) { 3450254885Sdumbbell if (rdev->mc.vram_is_ddr) 3451254885Sdumbbell sclk_delay_ff.full = dfixed_const(41); 3452254885Sdumbbell else 3453254885Sdumbbell sclk_delay_ff.full = dfixed_const(33); 3454254885Sdumbbell } else { 3455254885Sdumbbell if (rdev->mc.vram_width == 128) 3456254885Sdumbbell sclk_delay_ff.full = dfixed_const(57); 3457254885Sdumbbell else 3458254885Sdumbbell sclk_delay_ff.full = dfixed_const(41); 3459254885Sdumbbell } 3460254885Sdumbbell } 3461254885Sdumbbell 3462254885Sdumbbell mc_latency_sclk.full = dfixed_div(sclk_delay_ff, sclk_eff_ff); 3463254885Sdumbbell 3464254885Sdumbbell if (rdev->mc.vram_is_ddr) { 3465254885Sdumbbell if (rdev->mc.vram_width == 32) { 3466254885Sdumbbell k1.full = dfixed_const(40); 3467254885Sdumbbell c = 3; 3468254885Sdumbbell } else { 3469254885Sdumbbell k1.full = dfixed_const(20); 3470254885Sdumbbell c = 1; 3471254885Sdumbbell } 3472254885Sdumbbell } else { 3473254885Sdumbbell k1.full = dfixed_const(40); 3474254885Sdumbbell c = 3; 3475254885Sdumbbell } 3476254885Sdumbbell 3477254885Sdumbbell temp_ff.full = dfixed_const(2); 3478254885Sdumbbell mc_latency_mclk.full = dfixed_mul(trcd_ff, temp_ff); 3479254885Sdumbbell temp_ff.full = dfixed_const(c); 3480254885Sdumbbell mc_latency_mclk.full += dfixed_mul(tcas_ff, temp_ff); 3481254885Sdumbbell temp_ff.full = dfixed_const(4); 3482254885Sdumbbell mc_latency_mclk.full += dfixed_mul(tras_ff, temp_ff); 3483254885Sdumbbell mc_latency_mclk.full += dfixed_mul(trp_ff, temp_ff); 3484254885Sdumbbell mc_latency_mclk.full += k1.full; 3485254885Sdumbbell 3486254885Sdumbbell mc_latency_mclk.full = dfixed_div(mc_latency_mclk, mclk_ff); 3487254885Sdumbbell mc_latency_mclk.full += dfixed_div(temp_ff, sclk_eff_ff); 3488254885Sdumbbell 3489254885Sdumbbell /* 3490254885Sdumbbell HW cursor time assuming worst case of full size colour cursor. 3491254885Sdumbbell */ 3492254885Sdumbbell temp_ff.full = dfixed_const((2 * (cur_size - (rdev->mc.vram_is_ddr + 1)))); 3493254885Sdumbbell temp_ff.full += trcd_ff.full; 3494254885Sdumbbell if (temp_ff.full < tras_ff.full) 3495254885Sdumbbell temp_ff.full = tras_ff.full; 3496254885Sdumbbell cur_latency_mclk.full = dfixed_div(temp_ff, mclk_ff); 3497254885Sdumbbell 3498254885Sdumbbell temp_ff.full = dfixed_const(cur_size); 3499254885Sdumbbell cur_latency_sclk.full = dfixed_div(temp_ff, sclk_eff_ff); 3500254885Sdumbbell /* 3501254885Sdumbbell Find the total latency for the display data. 3502254885Sdumbbell */ 3503254885Sdumbbell disp_latency_overhead.full = dfixed_const(8); 3504254885Sdumbbell disp_latency_overhead.full = dfixed_div(disp_latency_overhead, sclk_ff); 3505254885Sdumbbell mc_latency_mclk.full += disp_latency_overhead.full + cur_latency_mclk.full; 3506254885Sdumbbell mc_latency_sclk.full += disp_latency_overhead.full + cur_latency_sclk.full; 3507254885Sdumbbell 3508254885Sdumbbell if (mc_latency_mclk.full > mc_latency_sclk.full) 3509254885Sdumbbell disp_latency.full = mc_latency_mclk.full; 3510254885Sdumbbell else 3511254885Sdumbbell disp_latency.full = mc_latency_sclk.full; 3512254885Sdumbbell 3513254885Sdumbbell /* setup Max GRPH_STOP_REQ default value */ 3514254885Sdumbbell if (ASIC_IS_RV100(rdev)) 3515254885Sdumbbell max_stop_req = 0x5c; 3516254885Sdumbbell else 3517254885Sdumbbell max_stop_req = 0x7c; 3518254885Sdumbbell 3519254885Sdumbbell if (mode1) { 3520254885Sdumbbell /* CRTC1 3521254885Sdumbbell Set GRPH_BUFFER_CNTL register using h/w defined optimal values. 3522254885Sdumbbell GRPH_STOP_REQ <= MIN[ 0x7C, (CRTC_H_DISP + 1) * (bit depth) / 0x10 ] 3523254885Sdumbbell */ 3524254885Sdumbbell stop_req = mode1->hdisplay * pixel_bytes1 / 16; 3525254885Sdumbbell 3526254885Sdumbbell if (stop_req > max_stop_req) 3527254885Sdumbbell stop_req = max_stop_req; 3528254885Sdumbbell 3529254885Sdumbbell /* 3530254885Sdumbbell Find the drain rate of the display buffer. 3531254885Sdumbbell */ 3532254885Sdumbbell temp_ff.full = dfixed_const((16/pixel_bytes1)); 3533254885Sdumbbell disp_drain_rate.full = dfixed_div(pix_clk, temp_ff); 3534254885Sdumbbell 3535254885Sdumbbell /* 3536254885Sdumbbell Find the critical point of the display buffer. 3537254885Sdumbbell */ 3538254885Sdumbbell crit_point_ff.full = dfixed_mul(disp_drain_rate, disp_latency); 3539254885Sdumbbell crit_point_ff.full += dfixed_const_half(0); 3540254885Sdumbbell 3541254885Sdumbbell critical_point = dfixed_trunc(crit_point_ff); 3542254885Sdumbbell 3543254885Sdumbbell if (rdev->disp_priority == 2) { 3544254885Sdumbbell critical_point = 0; 3545254885Sdumbbell } 3546254885Sdumbbell 3547254885Sdumbbell /* 3548254885Sdumbbell The critical point should never be above max_stop_req-4. Setting 3549254885Sdumbbell GRPH_CRITICAL_CNTL = 0 will thus force high priority all the time. 3550254885Sdumbbell */ 3551254885Sdumbbell if (max_stop_req - critical_point < 4) 3552254885Sdumbbell critical_point = 0; 3553254885Sdumbbell 3554254885Sdumbbell if (critical_point == 0 && mode2 && rdev->family == CHIP_R300) { 3555254885Sdumbbell /* some R300 cards have problem with this set to 0, when CRTC2 is enabled.*/ 3556254885Sdumbbell critical_point = 0x10; 3557254885Sdumbbell } 3558254885Sdumbbell 3559254885Sdumbbell temp = RREG32(RADEON_GRPH_BUFFER_CNTL); 3560254885Sdumbbell temp &= ~(RADEON_GRPH_STOP_REQ_MASK); 3561254885Sdumbbell temp |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 3562254885Sdumbbell temp &= ~(RADEON_GRPH_START_REQ_MASK); 3563254885Sdumbbell if ((rdev->family == CHIP_R350) && 3564254885Sdumbbell (stop_req > 0x15)) { 3565254885Sdumbbell stop_req -= 0x10; 3566254885Sdumbbell } 3567254885Sdumbbell temp |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 3568254885Sdumbbell temp |= RADEON_GRPH_BUFFER_SIZE; 3569254885Sdumbbell temp &= ~(RADEON_GRPH_CRITICAL_CNTL | 3570254885Sdumbbell RADEON_GRPH_CRITICAL_AT_SOF | 3571254885Sdumbbell RADEON_GRPH_STOP_CNTL); 3572254885Sdumbbell /* 3573254885Sdumbbell Write the result into the register. 3574254885Sdumbbell */ 3575254885Sdumbbell WREG32(RADEON_GRPH_BUFFER_CNTL, ((temp & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 3576254885Sdumbbell (critical_point << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 3577254885Sdumbbell 3578254885Sdumbbell#if 0 3579254885Sdumbbell if ((rdev->family == CHIP_RS400) || 3580254885Sdumbbell (rdev->family == CHIP_RS480)) { 3581254885Sdumbbell /* attempt to program RS400 disp regs correctly ??? */ 3582254885Sdumbbell temp = RREG32(RS400_DISP1_REG_CNTL); 3583254885Sdumbbell temp &= ~(RS400_DISP1_START_REQ_LEVEL_MASK | 3584254885Sdumbbell RS400_DISP1_STOP_REQ_LEVEL_MASK); 3585254885Sdumbbell WREG32(RS400_DISP1_REQ_CNTL1, (temp | 3586254885Sdumbbell (critical_point << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 3587254885Sdumbbell (critical_point << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 3588254885Sdumbbell temp = RREG32(RS400_DMIF_MEM_CNTL1); 3589254885Sdumbbell temp &= ~(RS400_DISP1_CRITICAL_POINT_START_MASK | 3590254885Sdumbbell RS400_DISP1_CRITICAL_POINT_STOP_MASK); 3591254885Sdumbbell WREG32(RS400_DMIF_MEM_CNTL1, (temp | 3592254885Sdumbbell (critical_point << RS400_DISP1_CRITICAL_POINT_START_SHIFT) | 3593254885Sdumbbell (critical_point << RS400_DISP1_CRITICAL_POINT_STOP_SHIFT))); 3594254885Sdumbbell } 3595254885Sdumbbell#endif 3596254885Sdumbbell 3597254885Sdumbbell DRM_DEBUG_KMS("GRPH_BUFFER_CNTL from to %x\n", 3598254885Sdumbbell /* (unsigned int)info->SavedReg->grph_buffer_cntl, */ 3599254885Sdumbbell (unsigned int)RREG32(RADEON_GRPH_BUFFER_CNTL)); 3600254885Sdumbbell } 3601254885Sdumbbell 3602254885Sdumbbell if (mode2) { 3603254885Sdumbbell u32 grph2_cntl; 3604254885Sdumbbell stop_req = mode2->hdisplay * pixel_bytes2 / 16; 3605254885Sdumbbell 3606254885Sdumbbell if (stop_req > max_stop_req) 3607254885Sdumbbell stop_req = max_stop_req; 3608254885Sdumbbell 3609254885Sdumbbell /* 3610254885Sdumbbell Find the drain rate of the display buffer. 3611254885Sdumbbell */ 3612254885Sdumbbell temp_ff.full = dfixed_const((16/pixel_bytes2)); 3613254885Sdumbbell disp_drain_rate2.full = dfixed_div(pix_clk2, temp_ff); 3614254885Sdumbbell 3615254885Sdumbbell grph2_cntl = RREG32(RADEON_GRPH2_BUFFER_CNTL); 3616254885Sdumbbell grph2_cntl &= ~(RADEON_GRPH_STOP_REQ_MASK); 3617254885Sdumbbell grph2_cntl |= (stop_req << RADEON_GRPH_STOP_REQ_SHIFT); 3618254885Sdumbbell grph2_cntl &= ~(RADEON_GRPH_START_REQ_MASK); 3619254885Sdumbbell if ((rdev->family == CHIP_R350) && 3620254885Sdumbbell (stop_req > 0x15)) { 3621254885Sdumbbell stop_req -= 0x10; 3622254885Sdumbbell } 3623254885Sdumbbell grph2_cntl |= (stop_req << RADEON_GRPH_START_REQ_SHIFT); 3624254885Sdumbbell grph2_cntl |= RADEON_GRPH_BUFFER_SIZE; 3625254885Sdumbbell grph2_cntl &= ~(RADEON_GRPH_CRITICAL_CNTL | 3626254885Sdumbbell RADEON_GRPH_CRITICAL_AT_SOF | 3627254885Sdumbbell RADEON_GRPH_STOP_CNTL); 3628254885Sdumbbell 3629254885Sdumbbell if ((rdev->family == CHIP_RS100) || 3630254885Sdumbbell (rdev->family == CHIP_RS200)) 3631254885Sdumbbell critical_point2 = 0; 3632254885Sdumbbell else { 3633254885Sdumbbell temp = (rdev->mc.vram_width * rdev->mc.vram_is_ddr + 1)/128; 3634254885Sdumbbell temp_ff.full = dfixed_const(temp); 3635254885Sdumbbell temp_ff.full = dfixed_mul(mclk_ff, temp_ff); 3636254885Sdumbbell if (sclk_ff.full < temp_ff.full) 3637254885Sdumbbell temp_ff.full = sclk_ff.full; 3638254885Sdumbbell 3639254885Sdumbbell read_return_rate.full = temp_ff.full; 3640254885Sdumbbell 3641254885Sdumbbell if (mode1) { 3642254885Sdumbbell temp_ff.full = read_return_rate.full - disp_drain_rate.full; 3643254885Sdumbbell time_disp1_drop_priority.full = dfixed_div(crit_point_ff, temp_ff); 3644254885Sdumbbell } else { 3645254885Sdumbbell time_disp1_drop_priority.full = 0; 3646254885Sdumbbell } 3647254885Sdumbbell crit_point_ff.full = disp_latency.full + time_disp1_drop_priority.full + disp_latency.full; 3648254885Sdumbbell crit_point_ff.full = dfixed_mul(crit_point_ff, disp_drain_rate2); 3649254885Sdumbbell crit_point_ff.full += dfixed_const_half(0); 3650254885Sdumbbell 3651254885Sdumbbell critical_point2 = dfixed_trunc(crit_point_ff); 3652254885Sdumbbell 3653254885Sdumbbell if (rdev->disp_priority == 2) { 3654254885Sdumbbell critical_point2 = 0; 3655254885Sdumbbell } 3656254885Sdumbbell 3657254885Sdumbbell if (max_stop_req - critical_point2 < 4) 3658254885Sdumbbell critical_point2 = 0; 3659254885Sdumbbell 3660254885Sdumbbell } 3661254885Sdumbbell 3662254885Sdumbbell if (critical_point2 == 0 && rdev->family == CHIP_R300) { 3663254885Sdumbbell /* some R300 cards have problem with this set to 0 */ 3664254885Sdumbbell critical_point2 = 0x10; 3665254885Sdumbbell } 3666254885Sdumbbell 3667254885Sdumbbell WREG32(RADEON_GRPH2_BUFFER_CNTL, ((grph2_cntl & ~RADEON_GRPH_CRITICAL_POINT_MASK) | 3668254885Sdumbbell (critical_point2 << RADEON_GRPH_CRITICAL_POINT_SHIFT))); 3669254885Sdumbbell 3670254885Sdumbbell if ((rdev->family == CHIP_RS400) || 3671254885Sdumbbell (rdev->family == CHIP_RS480)) { 3672254885Sdumbbell#if 0 3673254885Sdumbbell /* attempt to program RS400 disp2 regs correctly ??? */ 3674254885Sdumbbell temp = RREG32(RS400_DISP2_REQ_CNTL1); 3675254885Sdumbbell temp &= ~(RS400_DISP2_START_REQ_LEVEL_MASK | 3676254885Sdumbbell RS400_DISP2_STOP_REQ_LEVEL_MASK); 3677254885Sdumbbell WREG32(RS400_DISP2_REQ_CNTL1, (temp | 3678254885Sdumbbell (critical_point2 << RS400_DISP1_START_REQ_LEVEL_SHIFT) | 3679254885Sdumbbell (critical_point2 << RS400_DISP1_STOP_REQ_LEVEL_SHIFT))); 3680254885Sdumbbell temp = RREG32(RS400_DISP2_REQ_CNTL2); 3681254885Sdumbbell temp &= ~(RS400_DISP2_CRITICAL_POINT_START_MASK | 3682254885Sdumbbell RS400_DISP2_CRITICAL_POINT_STOP_MASK); 3683254885Sdumbbell WREG32(RS400_DISP2_REQ_CNTL2, (temp | 3684254885Sdumbbell (critical_point2 << RS400_DISP2_CRITICAL_POINT_START_SHIFT) | 3685254885Sdumbbell (critical_point2 << RS400_DISP2_CRITICAL_POINT_STOP_SHIFT))); 3686254885Sdumbbell#endif 3687254885Sdumbbell WREG32(RS400_DISP2_REQ_CNTL1, 0x105DC1CC); 3688254885Sdumbbell WREG32(RS400_DISP2_REQ_CNTL2, 0x2749D000); 3689254885Sdumbbell WREG32(RS400_DMIF_MEM_CNTL1, 0x29CA71DC); 3690254885Sdumbbell WREG32(RS400_DISP1_REQ_CNTL1, 0x28FBC3AC); 3691254885Sdumbbell } 3692254885Sdumbbell 3693254885Sdumbbell DRM_DEBUG_KMS("GRPH2_BUFFER_CNTL from to %x\n", 3694254885Sdumbbell (unsigned int)RREG32(RADEON_GRPH2_BUFFER_CNTL)); 3695254885Sdumbbell } 3696254885Sdumbbell} 3697254885Sdumbbell 3698254885Sdumbbellint r100_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) 3699254885Sdumbbell{ 3700254885Sdumbbell uint32_t scratch; 3701254885Sdumbbell uint32_t tmp = 0; 3702254885Sdumbbell unsigned i; 3703254885Sdumbbell int r; 3704254885Sdumbbell 3705254885Sdumbbell r = radeon_scratch_get(rdev, &scratch); 3706254885Sdumbbell if (r) { 3707254885Sdumbbell DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); 3708254885Sdumbbell return r; 3709254885Sdumbbell } 3710254885Sdumbbell WREG32(scratch, 0xCAFEDEAD); 3711254885Sdumbbell r = radeon_ring_lock(rdev, ring, 2); 3712254885Sdumbbell if (r) { 3713254885Sdumbbell DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); 3714254885Sdumbbell radeon_scratch_free(rdev, scratch); 3715254885Sdumbbell return r; 3716254885Sdumbbell } 3717254885Sdumbbell radeon_ring_write(ring, PACKET0(scratch, 0)); 3718254885Sdumbbell radeon_ring_write(ring, 0xDEADBEEF); 3719254885Sdumbbell radeon_ring_unlock_commit(rdev, ring); 3720254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 3721254885Sdumbbell tmp = RREG32(scratch); 3722254885Sdumbbell if (tmp == 0xDEADBEEF) { 3723254885Sdumbbell break; 3724254885Sdumbbell } 3725254885Sdumbbell DRM_UDELAY(1); 3726254885Sdumbbell } 3727254885Sdumbbell if (i < rdev->usec_timeout) { 3728254885Sdumbbell DRM_INFO("ring test succeeded in %d usecs\n", i); 3729254885Sdumbbell } else { 3730254885Sdumbbell DRM_ERROR("radeon: ring test failed (scratch(0x%04X)=0x%08X)\n", 3731254885Sdumbbell scratch, tmp); 3732254885Sdumbbell r = -EINVAL; 3733254885Sdumbbell } 3734254885Sdumbbell radeon_scratch_free(rdev, scratch); 3735254885Sdumbbell return r; 3736254885Sdumbbell} 3737254885Sdumbbell 3738254885Sdumbbellvoid r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) 3739254885Sdumbbell{ 3740254885Sdumbbell struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 3741254885Sdumbbell 3742254885Sdumbbell if (ring->rptr_save_reg) { 3743254885Sdumbbell u32 next_rptr = ring->wptr + 2 + 3; 3744254885Sdumbbell radeon_ring_write(ring, PACKET0(ring->rptr_save_reg, 0)); 3745254885Sdumbbell radeon_ring_write(ring, next_rptr); 3746254885Sdumbbell } 3747254885Sdumbbell 3748254885Sdumbbell radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); 3749254885Sdumbbell radeon_ring_write(ring, ib->gpu_addr); 3750254885Sdumbbell radeon_ring_write(ring, ib->length_dw); 3751254885Sdumbbell} 3752254885Sdumbbell 3753254885Sdumbbellint r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) 3754254885Sdumbbell{ 3755254885Sdumbbell struct radeon_ib ib; 3756254885Sdumbbell uint32_t scratch; 3757254885Sdumbbell uint32_t tmp = 0; 3758254885Sdumbbell unsigned i; 3759254885Sdumbbell int r; 3760254885Sdumbbell 3761254885Sdumbbell r = radeon_scratch_get(rdev, &scratch); 3762254885Sdumbbell if (r) { 3763254885Sdumbbell DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); 3764254885Sdumbbell return r; 3765254885Sdumbbell } 3766254885Sdumbbell WREG32(scratch, 0xCAFEDEAD); 3767254885Sdumbbell r = radeon_ib_get(rdev, RADEON_RING_TYPE_GFX_INDEX, &ib, NULL, 256); 3768254885Sdumbbell if (r) { 3769254885Sdumbbell DRM_ERROR("radeon: failed to get ib (%d).\n", r); 3770254885Sdumbbell goto free_scratch; 3771254885Sdumbbell } 3772254885Sdumbbell ib.ptr[0] = PACKET0(scratch, 0); 3773254885Sdumbbell ib.ptr[1] = 0xDEADBEEF; 3774254885Sdumbbell ib.ptr[2] = PACKET2(0); 3775254885Sdumbbell ib.ptr[3] = PACKET2(0); 3776254885Sdumbbell ib.ptr[4] = PACKET2(0); 3777254885Sdumbbell ib.ptr[5] = PACKET2(0); 3778254885Sdumbbell ib.ptr[6] = PACKET2(0); 3779254885Sdumbbell ib.ptr[7] = PACKET2(0); 3780254885Sdumbbell ib.length_dw = 8; 3781254885Sdumbbell r = radeon_ib_schedule(rdev, &ib, NULL); 3782254885Sdumbbell if (r) { 3783254885Sdumbbell DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); 3784254885Sdumbbell goto free_ib; 3785254885Sdumbbell } 3786254885Sdumbbell r = radeon_fence_wait(ib.fence, false); 3787254885Sdumbbell if (r) { 3788254885Sdumbbell DRM_ERROR("radeon: fence wait failed (%d).\n", r); 3789254885Sdumbbell goto free_ib; 3790254885Sdumbbell } 3791254885Sdumbbell for (i = 0; i < rdev->usec_timeout; i++) { 3792254885Sdumbbell tmp = RREG32(scratch); 3793254885Sdumbbell if (tmp == 0xDEADBEEF) { 3794254885Sdumbbell break; 3795254885Sdumbbell } 3796254885Sdumbbell DRM_UDELAY(1); 3797254885Sdumbbell } 3798254885Sdumbbell if (i < rdev->usec_timeout) { 3799254885Sdumbbell DRM_INFO("ib test succeeded in %u usecs\n", i); 3800254885Sdumbbell } else { 3801254885Sdumbbell DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", 3802254885Sdumbbell scratch, tmp); 3803254885Sdumbbell r = -EINVAL; 3804254885Sdumbbell } 3805254885Sdumbbellfree_ib: 3806254885Sdumbbell radeon_ib_free(rdev, &ib); 3807254885Sdumbbellfree_scratch: 3808254885Sdumbbell radeon_scratch_free(rdev, scratch); 3809254885Sdumbbell return r; 3810254885Sdumbbell} 3811254885Sdumbbell 3812254885Sdumbbellvoid r100_mc_stop(struct radeon_device *rdev, struct r100_mc_save *save) 3813254885Sdumbbell{ 3814254885Sdumbbell /* Shutdown CP we shouldn't need to do that but better be safe than 3815254885Sdumbbell * sorry 3816254885Sdumbbell */ 3817254885Sdumbbell rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; 3818254885Sdumbbell WREG32(R_000740_CP_CSQ_CNTL, 0); 3819254885Sdumbbell 3820254885Sdumbbell /* Save few CRTC registers */ 3821254885Sdumbbell save->GENMO_WT = RREG8(R_0003C2_GENMO_WT); 3822254885Sdumbbell save->CRTC_EXT_CNTL = RREG32(R_000054_CRTC_EXT_CNTL); 3823254885Sdumbbell save->CRTC_GEN_CNTL = RREG32(R_000050_CRTC_GEN_CNTL); 3824254885Sdumbbell save->CUR_OFFSET = RREG32(R_000260_CUR_OFFSET); 3825254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 3826254885Sdumbbell save->CRTC2_GEN_CNTL = RREG32(R_0003F8_CRTC2_GEN_CNTL); 3827254885Sdumbbell save->CUR2_OFFSET = RREG32(R_000360_CUR2_OFFSET); 3828254885Sdumbbell } 3829254885Sdumbbell 3830254885Sdumbbell /* Disable VGA aperture access */ 3831254885Sdumbbell WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & save->GENMO_WT); 3832254885Sdumbbell /* Disable cursor, overlay, crtc */ 3833254885Sdumbbell WREG32(R_000260_CUR_OFFSET, save->CUR_OFFSET | S_000260_CUR_LOCK(1)); 3834254885Sdumbbell WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL | 3835254885Sdumbbell S_000054_CRTC_DISPLAY_DIS(1)); 3836254885Sdumbbell WREG32(R_000050_CRTC_GEN_CNTL, 3837254885Sdumbbell (C_000050_CRTC_CUR_EN & save->CRTC_GEN_CNTL) | 3838254885Sdumbbell S_000050_CRTC_DISP_REQ_EN_B(1)); 3839254885Sdumbbell WREG32(R_000420_OV0_SCALE_CNTL, 3840254885Sdumbbell C_000420_OV0_OVERLAY_EN & RREG32(R_000420_OV0_SCALE_CNTL)); 3841254885Sdumbbell WREG32(R_000260_CUR_OFFSET, C_000260_CUR_LOCK & save->CUR_OFFSET); 3842254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 3843254885Sdumbbell WREG32(R_000360_CUR2_OFFSET, save->CUR2_OFFSET | 3844254885Sdumbbell S_000360_CUR2_LOCK(1)); 3845254885Sdumbbell WREG32(R_0003F8_CRTC2_GEN_CNTL, 3846254885Sdumbbell (C_0003F8_CRTC2_CUR_EN & save->CRTC2_GEN_CNTL) | 3847254885Sdumbbell S_0003F8_CRTC2_DISPLAY_DIS(1) | 3848254885Sdumbbell S_0003F8_CRTC2_DISP_REQ_EN_B(1)); 3849254885Sdumbbell WREG32(R_000360_CUR2_OFFSET, 3850254885Sdumbbell C_000360_CUR2_LOCK & save->CUR2_OFFSET); 3851254885Sdumbbell } 3852254885Sdumbbell} 3853254885Sdumbbell 3854254885Sdumbbellvoid r100_mc_resume(struct radeon_device *rdev, struct r100_mc_save *save) 3855254885Sdumbbell{ 3856254885Sdumbbell /* Update base address for crtc */ 3857254885Sdumbbell WREG32(R_00023C_DISPLAY_BASE_ADDR, rdev->mc.vram_start); 3858254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 3859254885Sdumbbell WREG32(R_00033C_CRTC2_DISPLAY_BASE_ADDR, rdev->mc.vram_start); 3860254885Sdumbbell } 3861254885Sdumbbell /* Restore CRTC registers */ 3862254885Sdumbbell WREG8(R_0003C2_GENMO_WT, save->GENMO_WT); 3863254885Sdumbbell WREG32(R_000054_CRTC_EXT_CNTL, save->CRTC_EXT_CNTL); 3864254885Sdumbbell WREG32(R_000050_CRTC_GEN_CNTL, save->CRTC_GEN_CNTL); 3865254885Sdumbbell if (!(rdev->flags & RADEON_SINGLE_CRTC)) { 3866254885Sdumbbell WREG32(R_0003F8_CRTC2_GEN_CNTL, save->CRTC2_GEN_CNTL); 3867254885Sdumbbell } 3868254885Sdumbbell} 3869254885Sdumbbell 3870254885Sdumbbellvoid r100_vga_render_disable(struct radeon_device *rdev) 3871254885Sdumbbell{ 3872254885Sdumbbell u32 tmp; 3873254885Sdumbbell 3874254885Sdumbbell tmp = RREG8(R_0003C2_GENMO_WT); 3875254885Sdumbbell WREG8(R_0003C2_GENMO_WT, C_0003C2_VGA_RAM_EN & tmp); 3876254885Sdumbbell} 3877254885Sdumbbell 3878254885Sdumbbellstatic void r100_debugfs(struct radeon_device *rdev) 3879254885Sdumbbell{ 3880254885Sdumbbell int r; 3881254885Sdumbbell 3882254885Sdumbbell r = r100_debugfs_mc_info_init(rdev); 3883254885Sdumbbell if (r) 3884254885Sdumbbell dev_warn(rdev->dev, "Failed to create r100_mc debugfs file.\n"); 3885254885Sdumbbell} 3886254885Sdumbbell 3887254885Sdumbbellstatic void r100_mc_program(struct radeon_device *rdev) 3888254885Sdumbbell{ 3889254885Sdumbbell struct r100_mc_save save; 3890254885Sdumbbell 3891254885Sdumbbell /* Stops all mc clients */ 3892254885Sdumbbell r100_mc_stop(rdev, &save); 3893254885Sdumbbell if (rdev->flags & RADEON_IS_AGP) { 3894254885Sdumbbell WREG32(R_00014C_MC_AGP_LOCATION, 3895254885Sdumbbell S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) | 3896254885Sdumbbell S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16)); 3897254885Sdumbbell WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base)); 3898254885Sdumbbell if (rdev->family > CHIP_RV200) 3899254885Sdumbbell WREG32(R_00015C_AGP_BASE_2, 3900254885Sdumbbell upper_32_bits(rdev->mc.agp_base) & 0xff); 3901254885Sdumbbell } else { 3902254885Sdumbbell WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF); 3903254885Sdumbbell WREG32(R_000170_AGP_BASE, 0); 3904254885Sdumbbell if (rdev->family > CHIP_RV200) 3905254885Sdumbbell WREG32(R_00015C_AGP_BASE_2, 0); 3906254885Sdumbbell } 3907254885Sdumbbell /* Wait for mc idle */ 3908254885Sdumbbell if (r100_mc_wait_for_idle(rdev)) 3909254885Sdumbbell dev_warn(rdev->dev, "Wait for MC idle timeout.\n"); 3910254885Sdumbbell /* Program MC, should be a 32bits limited address space */ 3911254885Sdumbbell WREG32(R_000148_MC_FB_LOCATION, 3912254885Sdumbbell S_000148_MC_FB_START(rdev->mc.vram_start >> 16) | 3913254885Sdumbbell S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16)); 3914254885Sdumbbell r100_mc_resume(rdev, &save); 3915254885Sdumbbell} 3916254885Sdumbbell 3917254885Sdumbbellstatic void r100_clock_startup(struct radeon_device *rdev) 3918254885Sdumbbell{ 3919254885Sdumbbell u32 tmp; 3920254885Sdumbbell 3921254885Sdumbbell if (radeon_dynclks != -1 && radeon_dynclks) 3922254885Sdumbbell radeon_legacy_set_clock_gating(rdev, 1); 3923254885Sdumbbell /* We need to force on some of the block */ 3924254885Sdumbbell tmp = RREG32_PLL(R_00000D_SCLK_CNTL); 3925254885Sdumbbell tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1); 3926254885Sdumbbell if ((rdev->family == CHIP_RV250) || (rdev->family == CHIP_RV280)) 3927254885Sdumbbell tmp |= S_00000D_FORCE_DISP1(1) | S_00000D_FORCE_DISP2(1); 3928254885Sdumbbell WREG32_PLL(R_00000D_SCLK_CNTL, tmp); 3929254885Sdumbbell} 3930254885Sdumbbell 3931254885Sdumbbellstatic int r100_startup(struct radeon_device *rdev) 3932254885Sdumbbell{ 3933254885Sdumbbell int r; 3934254885Sdumbbell 3935254885Sdumbbell /* set common regs */ 3936254885Sdumbbell r100_set_common_regs(rdev); 3937254885Sdumbbell /* program mc */ 3938254885Sdumbbell r100_mc_program(rdev); 3939254885Sdumbbell /* Resume clock */ 3940254885Sdumbbell r100_clock_startup(rdev); 3941254885Sdumbbell /* Initialize GART (initialize after TTM so we can allocate 3942254885Sdumbbell * memory through TTM but finalize after TTM) */ 3943254885Sdumbbell r100_enable_bm(rdev); 3944254885Sdumbbell if (rdev->flags & RADEON_IS_PCI) { 3945254885Sdumbbell r = r100_pci_gart_enable(rdev); 3946254885Sdumbbell if (r) 3947254885Sdumbbell return r; 3948254885Sdumbbell } 3949254885Sdumbbell 3950254885Sdumbbell /* allocate wb buffer */ 3951254885Sdumbbell r = radeon_wb_init(rdev); 3952254885Sdumbbell if (r) 3953254885Sdumbbell return r; 3954254885Sdumbbell 3955254885Sdumbbell r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 3956254885Sdumbbell if (r) { 3957254885Sdumbbell dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 3958254885Sdumbbell return r; 3959254885Sdumbbell } 3960254885Sdumbbell 3961254885Sdumbbell /* Enable IRQ */ 3962254885Sdumbbell r100_irq_set(rdev); 3963254885Sdumbbell rdev->config.r100.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL); 3964254885Sdumbbell /* 1M ring buffer */ 3965254885Sdumbbell r = r100_cp_init(rdev, 1024 * 1024); 3966254885Sdumbbell if (r) { 3967254885Sdumbbell dev_err(rdev->dev, "failed initializing CP (%d).\n", r); 3968254885Sdumbbell return r; 3969254885Sdumbbell } 3970254885Sdumbbell 3971254885Sdumbbell r = radeon_ib_pool_init(rdev); 3972254885Sdumbbell if (r) { 3973254885Sdumbbell dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 3974254885Sdumbbell return r; 3975254885Sdumbbell } 3976254885Sdumbbell 3977254885Sdumbbell return 0; 3978254885Sdumbbell} 3979254885Sdumbbell 3980254885Sdumbbellint r100_resume(struct radeon_device *rdev) 3981254885Sdumbbell{ 3982254885Sdumbbell int r; 3983254885Sdumbbell 3984254885Sdumbbell /* Make sur GART are not working */ 3985254885Sdumbbell if (rdev->flags & RADEON_IS_PCI) 3986254885Sdumbbell r100_pci_gart_disable(rdev); 3987254885Sdumbbell /* Resume clock before doing reset */ 3988254885Sdumbbell r100_clock_startup(rdev); 3989254885Sdumbbell /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 3990254885Sdumbbell if (radeon_asic_reset(rdev)) { 3991254885Sdumbbell dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 3992254885Sdumbbell RREG32(R_000E40_RBBM_STATUS), 3993254885Sdumbbell RREG32(R_0007C0_CP_STAT)); 3994254885Sdumbbell } 3995254885Sdumbbell /* post */ 3996254885Sdumbbell radeon_combios_asic_init(rdev->ddev); 3997254885Sdumbbell /* Resume clock after posting */ 3998254885Sdumbbell r100_clock_startup(rdev); 3999254885Sdumbbell /* Initialize surface registers */ 4000254885Sdumbbell radeon_surface_init(rdev); 4001254885Sdumbbell 4002254885Sdumbbell rdev->accel_working = true; 4003254885Sdumbbell r = r100_startup(rdev); 4004254885Sdumbbell if (r) { 4005254885Sdumbbell rdev->accel_working = false; 4006254885Sdumbbell } 4007254885Sdumbbell return r; 4008254885Sdumbbell} 4009254885Sdumbbell 4010254885Sdumbbellint r100_suspend(struct radeon_device *rdev) 4011254885Sdumbbell{ 4012254885Sdumbbell r100_cp_disable(rdev); 4013254885Sdumbbell radeon_wb_disable(rdev); 4014254885Sdumbbell r100_irq_disable(rdev); 4015254885Sdumbbell if (rdev->flags & RADEON_IS_PCI) 4016254885Sdumbbell r100_pci_gart_disable(rdev); 4017254885Sdumbbell return 0; 4018254885Sdumbbell} 4019254885Sdumbbell 4020254885Sdumbbellvoid r100_fini(struct radeon_device *rdev) 4021254885Sdumbbell{ 4022254885Sdumbbell r100_cp_fini(rdev); 4023254885Sdumbbell radeon_wb_fini(rdev); 4024254885Sdumbbell radeon_ib_pool_fini(rdev); 4025254885Sdumbbell radeon_gem_fini(rdev); 4026254885Sdumbbell if (rdev->flags & RADEON_IS_PCI) 4027254885Sdumbbell r100_pci_gart_fini(rdev); 4028254885Sdumbbell radeon_agp_fini(rdev); 4029254885Sdumbbell radeon_irq_kms_fini(rdev); 4030254885Sdumbbell radeon_fence_driver_fini(rdev); 4031254885Sdumbbell radeon_bo_fini(rdev); 4032254885Sdumbbell radeon_atombios_fini(rdev); 4033254885Sdumbbell r100_cp_fini_microcode(rdev); 4034254885Sdumbbell free(rdev->bios, DRM_MEM_DRIVER); 4035254885Sdumbbell rdev->bios = NULL; 4036254885Sdumbbell} 4037254885Sdumbbell 4038254885Sdumbbell/* 4039254885Sdumbbell * Due to how kexec works, it can leave the hw fully initialised when it 4040254885Sdumbbell * boots the new kernel. However doing our init sequence with the CP and 4041254885Sdumbbell * WB stuff setup causes GPU hangs on the RN50 at least. So at startup 4042254885Sdumbbell * do some quick sanity checks and restore sane values to avoid this 4043254885Sdumbbell * problem. 4044254885Sdumbbell */ 4045254885Sdumbbellvoid r100_restore_sanity(struct radeon_device *rdev) 4046254885Sdumbbell{ 4047254885Sdumbbell u32 tmp; 4048254885Sdumbbell 4049254885Sdumbbell tmp = RREG32(RADEON_CP_CSQ_CNTL); 4050254885Sdumbbell if (tmp) { 4051254885Sdumbbell WREG32(RADEON_CP_CSQ_CNTL, 0); 4052254885Sdumbbell } 4053254885Sdumbbell tmp = RREG32(RADEON_CP_RB_CNTL); 4054254885Sdumbbell if (tmp) { 4055254885Sdumbbell WREG32(RADEON_CP_RB_CNTL, 0); 4056254885Sdumbbell } 4057254885Sdumbbell tmp = RREG32(RADEON_SCRATCH_UMSK); 4058254885Sdumbbell if (tmp) { 4059254885Sdumbbell WREG32(RADEON_SCRATCH_UMSK, 0); 4060254885Sdumbbell } 4061254885Sdumbbell} 4062254885Sdumbbell 4063254885Sdumbbellint r100_init(struct radeon_device *rdev) 4064254885Sdumbbell{ 4065254885Sdumbbell int r; 4066254885Sdumbbell 4067254885Sdumbbell /* Register debugfs file specific to this group of asics */ 4068254885Sdumbbell r100_debugfs(rdev); 4069254885Sdumbbell /* Disable VGA */ 4070254885Sdumbbell r100_vga_render_disable(rdev); 4071254885Sdumbbell /* Initialize scratch registers */ 4072254885Sdumbbell radeon_scratch_init(rdev); 4073254885Sdumbbell /* Initialize surface registers */ 4074254885Sdumbbell radeon_surface_init(rdev); 4075254885Sdumbbell /* sanity check some register to avoid hangs like after kexec */ 4076254885Sdumbbell r100_restore_sanity(rdev); 4077254885Sdumbbell /* TODO: disable VGA need to use VGA request */ 4078254885Sdumbbell /* BIOS*/ 4079254885Sdumbbell if (!radeon_get_bios(rdev)) { 4080254885Sdumbbell if (ASIC_IS_AVIVO(rdev)) 4081254885Sdumbbell return -EINVAL; 4082254885Sdumbbell } 4083254885Sdumbbell if (rdev->is_atom_bios) { 4084254885Sdumbbell dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n"); 4085254885Sdumbbell return -EINVAL; 4086254885Sdumbbell } else { 4087254885Sdumbbell r = radeon_combios_init(rdev); 4088254885Sdumbbell if (r) 4089254885Sdumbbell return r; 4090254885Sdumbbell } 4091254885Sdumbbell /* Reset gpu before posting otherwise ATOM will enter infinite loop */ 4092254885Sdumbbell if (radeon_asic_reset(rdev)) { 4093254885Sdumbbell dev_warn(rdev->dev, 4094254885Sdumbbell "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n", 4095254885Sdumbbell RREG32(R_000E40_RBBM_STATUS), 4096254885Sdumbbell RREG32(R_0007C0_CP_STAT)); 4097254885Sdumbbell } 4098254885Sdumbbell /* check if cards are posted or not */ 4099254885Sdumbbell if (radeon_boot_test_post_card(rdev) == false) 4100254885Sdumbbell return -EINVAL; 4101254885Sdumbbell /* Set asic errata */ 4102254885Sdumbbell r100_errata(rdev); 4103254885Sdumbbell /* Initialize clocks */ 4104254885Sdumbbell radeon_get_clock_info(rdev->ddev); 4105254885Sdumbbell /* initialize AGP */ 4106254885Sdumbbell if (rdev->flags & RADEON_IS_AGP) { 4107254885Sdumbbell r = radeon_agp_init(rdev); 4108254885Sdumbbell if (r) { 4109254885Sdumbbell radeon_agp_disable(rdev); 4110254885Sdumbbell } 4111254885Sdumbbell } 4112254885Sdumbbell /* initialize VRAM */ 4113254885Sdumbbell r100_mc_init(rdev); 4114254885Sdumbbell /* Fence driver */ 4115254885Sdumbbell r = radeon_fence_driver_init(rdev); 4116254885Sdumbbell if (r) 4117254885Sdumbbell return r; 4118254885Sdumbbell r = radeon_irq_kms_init(rdev); 4119254885Sdumbbell if (r) 4120254885Sdumbbell return r; 4121254885Sdumbbell /* Memory manager */ 4122254885Sdumbbell r = radeon_bo_init(rdev); 4123254885Sdumbbell if (r) 4124254885Sdumbbell return r; 4125254885Sdumbbell if (rdev->flags & RADEON_IS_PCI) { 4126254885Sdumbbell r = r100_pci_gart_init(rdev); 4127254885Sdumbbell if (r) 4128254885Sdumbbell return r; 4129254885Sdumbbell } 4130254885Sdumbbell r100_set_safe_registers(rdev); 4131254885Sdumbbell 4132254885Sdumbbell rdev->accel_working = true; 4133254885Sdumbbell r = r100_startup(rdev); 4134254885Sdumbbell if (r) { 4135254885Sdumbbell /* Somethings want wront with the accel init stop accel */ 4136254885Sdumbbell dev_err(rdev->dev, "Disabling GPU acceleration\n"); 4137254885Sdumbbell r100_cp_fini(rdev); 4138254885Sdumbbell radeon_wb_fini(rdev); 4139254885Sdumbbell radeon_ib_pool_fini(rdev); 4140254885Sdumbbell radeon_irq_kms_fini(rdev); 4141254885Sdumbbell if (rdev->flags & RADEON_IS_PCI) 4142254885Sdumbbell r100_pci_gart_fini(rdev); 4143254885Sdumbbell rdev->accel_working = false; 4144254885Sdumbbell } 4145254885Sdumbbell return 0; 4146254885Sdumbbell} 4147254885Sdumbbell 4148254885Sdumbbelluint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg, 4149254885Sdumbbell bool always_indirect) 4150254885Sdumbbell{ 4151254885Sdumbbell if (reg < rdev->rmmio_size && !always_indirect) 4152254885Sdumbbell return bus_read_4(rdev->rmmio, reg); 4153254885Sdumbbell else { 4154254885Sdumbbell unsigned long flags; 4155254885Sdumbbell uint32_t ret; 4156254885Sdumbbell 4157254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->mmio_idx_lock, flags); 4158254885Sdumbbell bus_write_4(rdev->rmmio, RADEON_MM_INDEX, reg); 4159254885Sdumbbell ret = bus_read_4(rdev->rmmio, RADEON_MM_DATA); 4160254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->mmio_idx_lock, flags); 4161254885Sdumbbell 4162254885Sdumbbell return ret; 4163254885Sdumbbell } 4164254885Sdumbbell} 4165254885Sdumbbell 4166254885Sdumbbellvoid r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v, 4167254885Sdumbbell bool always_indirect) 4168254885Sdumbbell{ 4169254885Sdumbbell if (reg < rdev->rmmio_size && !always_indirect) 4170254885Sdumbbell bus_write_4(rdev->rmmio, reg, v); 4171254885Sdumbbell else { 4172254885Sdumbbell unsigned long flags; 4173254885Sdumbbell 4174254885Sdumbbell DRM_SPINLOCK_IRQSAVE(&rdev->mmio_idx_lock, flags); 4175254885Sdumbbell bus_write_4(rdev->rmmio, RADEON_MM_INDEX, reg); 4176254885Sdumbbell bus_write_4(rdev->rmmio, RADEON_MM_DATA, v); 4177254885Sdumbbell DRM_SPINUNLOCK_IRQRESTORE(&rdev->mmio_idx_lock, flags); 4178254885Sdumbbell } 4179254885Sdumbbell} 4180254885Sdumbbell 4181254885Sdumbbellu32 r100_io_rreg(struct radeon_device *rdev, u32 reg) 4182254885Sdumbbell{ 4183254885Sdumbbell if (reg < rdev->rio_mem_size) 4184254885Sdumbbell return bus_read_4(rdev->rio_mem, reg); 4185254885Sdumbbell else { 4186254885Sdumbbell /* XXX No locking? -- dumbbell@ */ 4187254885Sdumbbell bus_write_4(rdev->rio_mem, RADEON_MM_INDEX, reg); 4188254885Sdumbbell return bus_read_4(rdev->rio_mem, RADEON_MM_DATA); 4189254885Sdumbbell } 4190254885Sdumbbell} 4191254885Sdumbbell 4192254885Sdumbbellvoid r100_io_wreg(struct radeon_device *rdev, u32 reg, u32 v) 4193254885Sdumbbell{ 4194254885Sdumbbell if (reg < rdev->rio_mem_size) 4195254885Sdumbbell bus_write_4(rdev->rio_mem, reg, v); 4196254885Sdumbbell else { 4197254885Sdumbbell /* XXX No locking? -- dumbbell@ */ 4198254885Sdumbbell bus_write_4(rdev->rio_mem, RADEON_MM_INDEX, reg); 4199254885Sdumbbell bus_write_4(rdev->rio_mem, RADEON_MM_DATA, v); 4200254885Sdumbbell } 4201254885Sdumbbell} 4202