Commit b68bdc1b authored by Dave Airlie's avatar Dave Airlie

Merge branch 'next' of git://people.freedesktop.org/~deathsimple/linux into drm-next

This contains all the radeon documentation rebased on top of the ib fixes.

* 'next' of git://people.freedesktop.org/~deathsimple/linux:
  drm/radeon: fix SS setup for DCPLL
  drm/radeon: fix up pll selection on DCE5/6
  drm/radeon: start to document evergreen.c
  drm/radeon: start to document the functions r100.c
  drm/radeon: document VM functions in radeon_gart.c (v3)
  drm/radeon: document non-VM functions in radeon_gart.c (v2)
  drm/radeon: document radeon_ring.c (v4)
  drm/radeon: document radeon_fence.c (v2)
  drm/radeon: document radeon_asic.c
  drm/radeon: document radeon_irq_kms.c
  drm/radeon: document radeon_kms.c
  drm/radeon: document radeon_device.c (v2)
  drm/radeon: add rptr save support for r1xx-r5xx
  drm/radeon: update rptr saving logic for memory buffers
  drm/radeon: remove radeon_ring_index()
  drm/radeon: update ib_execute for SI (v2)
  drm/radeon: fix const IB handling v2
  drm/radeon: let sa manager block for fences to wait for v2
  drm/radeon: return an error if there is nothing to wait for
parents 29935554 f312f093
...@@ -457,22 +457,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, ...@@ -457,22 +457,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
switch (pll_id) { switch (pll_id) {
case ATOM_PPLL1: case ATOM_PPLL1:
args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL; args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P1PLL;
args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
break; break;
case ATOM_PPLL2: case ATOM_PPLL2:
args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL; args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_P2PLL;
args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
break; break;
case ATOM_DCPLL: case ATOM_DCPLL:
args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL; args.v3.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V3_DCPLL;
args.v3.usSpreadSpectrumAmount = cpu_to_le16(0);
args.v3.usSpreadSpectrumStep = cpu_to_le16(0);
break; break;
case ATOM_PPLL_INVALID: case ATOM_PPLL_INVALID:
return; return;
} }
args.v3.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
args.v3.usSpreadSpectrumStep = cpu_to_le16(ss->step);
args.v3.ucEnable = enable; args.v3.ucEnable = enable;
if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev)) if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE61(rdev))
args.v3.ucEnable = ATOM_DISABLE; args.v3.ucEnable = ATOM_DISABLE;
...@@ -482,22 +478,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev, ...@@ -482,22 +478,18 @@ static void atombios_crtc_program_ss(struct radeon_device *rdev,
switch (pll_id) { switch (pll_id) {
case ATOM_PPLL1: case ATOM_PPLL1:
args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL; args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P1PLL;
args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
break; break;
case ATOM_PPLL2: case ATOM_PPLL2:
args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL; args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_P2PLL;
args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
break; break;
case ATOM_DCPLL: case ATOM_DCPLL:
args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL; args.v2.ucSpreadSpectrumType |= ATOM_PPLL_SS_TYPE_V2_DCPLL;
args.v2.usSpreadSpectrumAmount = cpu_to_le16(0);
args.v2.usSpreadSpectrumStep = cpu_to_le16(0);
break; break;
case ATOM_PPLL_INVALID: case ATOM_PPLL_INVALID:
return; return;
} }
args.v2.usSpreadSpectrumAmount = cpu_to_le16(ss->amount);
args.v2.usSpreadSpectrumStep = cpu_to_le16(ss->step);
args.v2.ucEnable = enable; args.v2.ucEnable = enable;
if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev)) if ((ss->percentage == 0) || (ss->type & ATOM_EXTERNAL_SS_MASK) || ASIC_IS_DCE41(rdev))
args.v2.ucEnable = ATOM_DISABLE; args.v2.ucEnable = ATOM_DISABLE;
...@@ -1539,7 +1531,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc) ...@@ -1539,7 +1531,11 @@ static int radeon_atom_pick_pll(struct drm_crtc *crtc)
* crtc virtual pixel clock. * crtc virtual pixel clock.
*/ */
if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) { if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(test_encoder))) {
if (ASIC_IS_DCE5(rdev) || rdev->clock.dp_extclk) if (ASIC_IS_DCE5(rdev))
return ATOM_DCPLL;
else if (ASIC_IS_DCE6(rdev))
return ATOM_PPLL0;
else if (rdev->clock.dp_extclk)
return ATOM_PPLL_INVALID; return ATOM_PPLL_INVALID;
} }
} }
......
...@@ -99,6 +99,14 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev) ...@@ -99,6 +99,14 @@ void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
} }
} }
/**
* dce4_wait_for_vblank - vblank wait asic callback.
*
* @rdev: radeon_device pointer
* @crtc: crtc to wait for vblank on
*
* Wait for vblank on the requested crtc (evergreen+).
*/
void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
{ {
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
...@@ -118,18 +126,49 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc) ...@@ -118,18 +126,49 @@ void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
} }
} }
/**
* radeon_irq_kms_pflip_irq_get - pre-pageflip callback.
*
* @rdev: radeon_device pointer
* @crtc: crtc to prepare for pageflip on
*
* Pre-pageflip callback (evergreen+).
* Enables the pageflip irq (vblank irq).
*/
void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc)
{ {
/* enable the pflip int */ /* enable the pflip int */
radeon_irq_kms_pflip_irq_get(rdev, crtc); radeon_irq_kms_pflip_irq_get(rdev, crtc);
} }
/**
* evergreen_post_page_flip - pos-pageflip callback.
*
* @rdev: radeon_device pointer
* @crtc: crtc to cleanup pageflip on
*
* Post-pageflip callback (evergreen+).
* Disables the pageflip irq (vblank irq).
*/
void evergreen_post_page_flip(struct radeon_device *rdev, int crtc) void evergreen_post_page_flip(struct radeon_device *rdev, int crtc)
{ {
/* disable the pflip int */ /* disable the pflip int */
radeon_irq_kms_pflip_irq_put(rdev, crtc); radeon_irq_kms_pflip_irq_put(rdev, crtc);
} }
/**
* evergreen_page_flip - pageflip callback.
*
* @rdev: radeon_device pointer
* @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address)
*
* Does the actual pageflip (evergreen+).
* During vblank we take the crtc lock and wait for the update_pending
* bit to go high, when it does, we release the lock, and allow the
* double buffered update to take place.
* Returns the current update pending status.
*/
u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) u32 evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
{ {
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
...@@ -214,6 +253,15 @@ int sumo_get_temp(struct radeon_device *rdev) ...@@ -214,6 +253,15 @@ int sumo_get_temp(struct radeon_device *rdev)
return actual_temp * 1000; return actual_temp * 1000;
} }
/**
* sumo_pm_init_profile - Initialize power profiles callback.
*
* @rdev: radeon_device pointer
*
* Initialize the power states used in profile mode
* (sumo, trinity, SI).
* Used for profile mode only.
*/
void sumo_pm_init_profile(struct radeon_device *rdev) void sumo_pm_init_profile(struct radeon_device *rdev)
{ {
int idx; int idx;
...@@ -265,6 +313,14 @@ void sumo_pm_init_profile(struct radeon_device *rdev) ...@@ -265,6 +313,14 @@ void sumo_pm_init_profile(struct radeon_device *rdev)
rdev->pm.power_state[idx].num_clock_modes - 1; rdev->pm.power_state[idx].num_clock_modes - 1;
} }
/**
* evergreen_pm_misc - set additional pm hw parameters callback.
*
* @rdev: radeon_device pointer
*
* Set non-clock parameters associated with a power state
* (voltage, etc.) (evergreen+).
*/
void evergreen_pm_misc(struct radeon_device *rdev) void evergreen_pm_misc(struct radeon_device *rdev)
{ {
int req_ps_idx = rdev->pm.requested_power_state_index; int req_ps_idx = rdev->pm.requested_power_state_index;
...@@ -292,6 +348,13 @@ void evergreen_pm_misc(struct radeon_device *rdev) ...@@ -292,6 +348,13 @@ void evergreen_pm_misc(struct radeon_device *rdev)
} }
} }
/**
* evergreen_pm_prepare - pre-power state change callback.
*
* @rdev: radeon_device pointer
*
* Prepare for a power state change (evergreen+).
*/
void evergreen_pm_prepare(struct radeon_device *rdev) void evergreen_pm_prepare(struct radeon_device *rdev)
{ {
struct drm_device *ddev = rdev->ddev; struct drm_device *ddev = rdev->ddev;
...@@ -310,6 +373,13 @@ void evergreen_pm_prepare(struct radeon_device *rdev) ...@@ -310,6 +373,13 @@ void evergreen_pm_prepare(struct radeon_device *rdev)
} }
} }
/**
* evergreen_pm_finish - post-power state change callback.
*
* @rdev: radeon_device pointer
*
* Clean up after a power state change (evergreen+).
*/
void evergreen_pm_finish(struct radeon_device *rdev) void evergreen_pm_finish(struct radeon_device *rdev)
{ {
struct drm_device *ddev = rdev->ddev; struct drm_device *ddev = rdev->ddev;
...@@ -328,6 +398,15 @@ void evergreen_pm_finish(struct radeon_device *rdev) ...@@ -328,6 +398,15 @@ void evergreen_pm_finish(struct radeon_device *rdev)
} }
} }
/**
* evergreen_hpd_sense - hpd sense callback.
*
* @rdev: radeon_device pointer
* @hpd: hpd (hotplug detect) pin
*
* Checks if a digital monitor is connected (evergreen+).
* Returns true if connected, false if not connected.
*/
bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
{ {
bool connected = false; bool connected = false;
...@@ -364,6 +443,14 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) ...@@ -364,6 +443,14 @@ bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
return connected; return connected;
} }
/**
* evergreen_hpd_set_polarity - hpd set polarity callback.
*
* @rdev: radeon_device pointer
* @hpd: hpd (hotplug detect) pin
*
* Set the polarity of the hpd pin (evergreen+).
*/
void evergreen_hpd_set_polarity(struct radeon_device *rdev, void evergreen_hpd_set_polarity(struct radeon_device *rdev,
enum radeon_hpd_id hpd) enum radeon_hpd_id hpd)
{ {
...@@ -424,6 +511,14 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev, ...@@ -424,6 +511,14 @@ void evergreen_hpd_set_polarity(struct radeon_device *rdev,
} }
} }
/**
* evergreen_hpd_init - hpd setup callback.
*
* @rdev: radeon_device pointer
*
* Setup the hpd pins used by the card (evergreen+).
* Enable the pin, set the polarity, and enable the hpd interrupts.
*/
void evergreen_hpd_init(struct radeon_device *rdev) void evergreen_hpd_init(struct radeon_device *rdev)
{ {
struct drm_device *dev = rdev->ddev; struct drm_device *dev = rdev->ddev;
...@@ -462,6 +557,14 @@ void evergreen_hpd_init(struct radeon_device *rdev) ...@@ -462,6 +557,14 @@ void evergreen_hpd_init(struct radeon_device *rdev)
radeon_irq_kms_enable_hpd(rdev, enabled); radeon_irq_kms_enable_hpd(rdev, enabled);
} }
/**
* evergreen_hpd_fini - hpd tear down callback.
*
* @rdev: radeon_device pointer
*
* Tear down the hpd pins used by the card (evergreen+).
* Disable the hpd interrupts.
*/
void evergreen_hpd_fini(struct radeon_device *rdev) void evergreen_hpd_fini(struct radeon_device *rdev)
{ {
struct drm_device *dev = rdev->ddev; struct drm_device *dev = rdev->ddev;
...@@ -925,6 +1028,14 @@ static void evergreen_program_watermarks(struct radeon_device *rdev, ...@@ -925,6 +1028,14 @@ static void evergreen_program_watermarks(struct radeon_device *rdev,
} }
/**
* evergreen_bandwidth_update - update display watermarks callback.
*
* @rdev: radeon_device pointer
*
* Update the display watermarks based on the requested mode(s)
* (evergreen+).
*/
void evergreen_bandwidth_update(struct radeon_device *rdev) void evergreen_bandwidth_update(struct radeon_device *rdev)
{ {
struct drm_display_mode *mode0 = NULL; struct drm_display_mode *mode0 = NULL;
...@@ -948,6 +1059,15 @@ void evergreen_bandwidth_update(struct radeon_device *rdev) ...@@ -948,6 +1059,15 @@ void evergreen_bandwidth_update(struct radeon_device *rdev)
} }
} }
/**
* evergreen_mc_wait_for_idle - wait for MC idle callback.
*
* @rdev: radeon_device pointer
*
* Wait for the MC (memory controller) to be idle.
* (evergreen+).
* Returns 0 if the MC is idle, -1 if not.
*/
int evergreen_mc_wait_for_idle(struct radeon_device *rdev) int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
{ {
unsigned i; unsigned i;
...@@ -1364,17 +1484,25 @@ void evergreen_mc_program(struct radeon_device *rdev) ...@@ -1364,17 +1484,25 @@ void evergreen_mc_program(struct radeon_device *rdev)
void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) void evergreen_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
{ {
struct radeon_ring *ring = &rdev->ring[ib->ring]; struct radeon_ring *ring = &rdev->ring[ib->ring];
u32 next_rptr;
/* set to DX10/11 mode */ /* set to DX10/11 mode */
radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0)); radeon_ring_write(ring, PACKET3(PACKET3_MODE_CONTROL, 0));
radeon_ring_write(ring, 1); radeon_ring_write(ring, 1);
if (ring->rptr_save_reg) { if (ring->rptr_save_reg) {
uint32_t next_rptr = ring->wptr + 3 + 4; next_rptr = ring->wptr + 3 + 4;
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
radeon_ring_write(ring, ((ring->rptr_save_reg - radeon_ring_write(ring, ((ring->rptr_save_reg -
PACKET3_SET_CONFIG_REG_START) >> 2)); PACKET3_SET_CONFIG_REG_START) >> 2));
radeon_ring_write(ring, next_rptr); radeon_ring_write(ring, next_rptr);
} else if (rdev->wb.enabled) {
next_rptr = ring->wptr + 5 + 4;
radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3));
radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18));
radeon_ring_write(ring, next_rptr);
radeon_ring_write(ring, 0);
} }
radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
......
...@@ -65,6 +65,19 @@ MODULE_FIRMWARE(FIRMWARE_R520); ...@@ -65,6 +65,19 @@ MODULE_FIRMWARE(FIRMWARE_R520);
#include "r100_track.h" #include "r100_track.h"
/* This files gather functions specifics to:
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280
* and others in some cases.
*/
/**
* r100_wait_for_vblank - vblank wait asic callback.
*
* @rdev: radeon_device pointer
* @crtc: crtc to wait for vblank on
*
* Wait for vblank on the requested crtc (r1xx-r4xx).
*/
void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
{ {
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
...@@ -99,22 +112,49 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc) ...@@ -99,22 +112,49 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)
} }
} }
/* This files gather functions specifics to: /**
* r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 * r100_pre_page_flip - pre-pageflip callback.
*
* @rdev: radeon_device pointer
* @crtc: crtc to prepare for pageflip on
*
* Pre-pageflip callback (r1xx-r4xx).
* Enables the pageflip irq (vblank irq).
*/ */
void r100_pre_page_flip(struct radeon_device *rdev, int crtc) void r100_pre_page_flip(struct radeon_device *rdev, int crtc)
{ {
/* enable the pflip int */ /* enable the pflip int */
radeon_irq_kms_pflip_irq_get(rdev, crtc); radeon_irq_kms_pflip_irq_get(rdev, crtc);
} }
/**
* r100_post_page_flip - pos-pageflip callback.
*
* @rdev: radeon_device pointer
* @crtc: crtc to cleanup pageflip on
*
* Post-pageflip callback (r1xx-r4xx).
* Disables the pageflip irq (vblank irq).
*/
void r100_post_page_flip(struct radeon_device *rdev, int crtc) void r100_post_page_flip(struct radeon_device *rdev, int crtc)
{ {
/* disable the pflip int */ /* disable the pflip int */
radeon_irq_kms_pflip_irq_put(rdev, crtc); radeon_irq_kms_pflip_irq_put(rdev, crtc);
} }
/**
* r100_page_flip - pageflip callback.
*
* @rdev: radeon_device pointer
* @crtc_id: crtc to cleanup pageflip on
* @crtc_base: new address of the crtc (GPU MC address)
*
* Does the actual pageflip (r1xx-r4xx).
* During vblank we take the crtc lock and wait for the update_pending
* bit to go high, when it does, we release the lock, and allow the
* double buffered update to take place.
* Returns the current update pending status.
*/
u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
{ {
struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
...@@ -141,6 +181,15 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) ...@@ -141,6 +181,15 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET;
} }
/**
* r100_pm_get_dynpm_state - look up dynpm power state callback.
*
* @rdev: radeon_device pointer
*
* Look up the optimal power state based on the
* current state of the GPU (r1xx-r5xx).
* Used for dynpm only.
*/
void r100_pm_get_dynpm_state(struct radeon_device *rdev) void r100_pm_get_dynpm_state(struct radeon_device *rdev)
{ {
int i; int i;
...@@ -223,6 +272,15 @@ void r100_pm_get_dynpm_state(struct radeon_device *rdev) ...@@ -223,6 +272,15 @@ void r100_pm_get_dynpm_state(struct radeon_device *rdev)
pcie_lanes); pcie_lanes);
} }
/**
* r100_pm_init_profile - Initialize power profiles callback.
*
* @rdev: radeon_device pointer
*
* Initialize the power states used in profile mode
* (r1xx-r3xx).
* Used for profile mode only.
*/
void r100_pm_init_profile(struct radeon_device *rdev) void r100_pm_init_profile(struct radeon_device *rdev)
{ {
/* default */ /* default */
...@@ -262,6 +320,14 @@ void r100_pm_init_profile(struct radeon_device *rdev) ...@@ -262,6 +320,14 @@ void r100_pm_init_profile(struct radeon_device *rdev)
rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0;
} }
/**
* r100_pm_misc - set additional pm hw parameters callback.
*
* @rdev: radeon_device pointer
*
* Set non-clock parameters associated with a power state
* (voltage, pcie lanes, etc.) (r1xx-r4xx).
*/
void r100_pm_misc(struct radeon_device *rdev) void r100_pm_misc(struct radeon_device *rdev)
{ {
int requested_index = rdev->pm.requested_power_state_index; int requested_index = rdev->pm.requested_power_state_index;
...@@ -353,6 +419,13 @@ void r100_pm_misc(struct radeon_device *rdev) ...@@ -353,6 +419,13 @@ void r100_pm_misc(struct radeon_device *rdev)
} }
} }
/**
* r100_pm_prepare - pre-power state change callback.
*
* @rdev: radeon_device pointer
*
* Prepare for a power state change (r1xx-r4xx).
*/
void r100_pm_prepare(struct radeon_device *rdev) void r100_pm_prepare(struct radeon_device *rdev)
{ {
struct drm_device *ddev = rdev->ddev; struct drm_device *ddev = rdev->ddev;
...@@ -377,6 +450,13 @@ void r100_pm_prepare(struct radeon_device *rdev) ...@@ -377,6 +450,13 @@ void r100_pm_prepare(struct radeon_device *rdev)
} }
} }
/**
* r100_pm_finish - post-power state change callback.
*
* @rdev: radeon_device pointer
*
* Clean up after a power state change (r1xx-r4xx).
*/
void r100_pm_finish(struct radeon_device *rdev) void r100_pm_finish(struct radeon_device *rdev)
{ {
struct drm_device *ddev = rdev->ddev; struct drm_device *ddev = rdev->ddev;
...@@ -401,6 +481,14 @@ void r100_pm_finish(struct radeon_device *rdev) ...@@ -401,6 +481,14 @@ void r100_pm_finish(struct radeon_device *rdev)
} }
} }
/**
* r100_gui_idle - gui idle callback.
*
* @rdev: radeon_device pointer
*
* Check of the GUI (2D/3D engines) are idle (r1xx-r5xx).
* Returns true if idle, false if not.
*/
bool r100_gui_idle(struct radeon_device *rdev) bool r100_gui_idle(struct radeon_device *rdev)
{ {
if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE) if (RREG32(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)
...@@ -410,6 +498,15 @@ bool r100_gui_idle(struct radeon_device *rdev) ...@@ -410,6 +498,15 @@ bool r100_gui_idle(struct radeon_device *rdev)
} }
/* hpd for digital panel detect/disconnect */ /* hpd for digital panel detect/disconnect */
/**
* r100_hpd_sense - hpd sense callback.
*
* @rdev: radeon_device pointer
* @hpd: hpd (hotplug detect) pin
*
* Checks if a digital monitor is connected (r1xx-r4xx).
* Returns true if connected, false if not connected.
*/
bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
{ {
bool connected = false; bool connected = false;
...@@ -429,6 +526,14 @@ bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) ...@@ -429,6 +526,14 @@ bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
return connected; return connected;
} }
/**
* r100_hpd_set_polarity - hpd set polarity callback.
*
* @rdev: radeon_device pointer
* @hpd: hpd (hotplug detect) pin
*
* Set the polarity of the hpd pin (r1xx-r4xx).
*/
void r100_hpd_set_polarity(struct radeon_device *rdev, void r100_hpd_set_polarity(struct radeon_device *rdev,
enum radeon_hpd_id hpd) enum radeon_hpd_id hpd)
{ {
...@@ -457,6 +562,14 @@ void r100_hpd_set_polarity(struct radeon_device *rdev, ...@@ -457,6 +562,14 @@ void r100_hpd_set_polarity(struct radeon_device *rdev,
} }
} }
/**
* r100_hpd_init - hpd setup callback.
*
* @rdev: radeon_device pointer
*
* Setup the hpd pins used by the card (r1xx-r4xx).
* Set the polarity, and enable the hpd interrupts.
*/
void r100_hpd_init(struct radeon_device *rdev) void r100_hpd_init(struct radeon_device *rdev)
{ {
struct drm_device *dev = rdev->ddev; struct drm_device *dev = rdev->ddev;
...@@ -471,6 +584,14 @@ void r100_hpd_init(struct radeon_device *rdev) ...@@ -471,6 +584,14 @@ void r100_hpd_init(struct radeon_device *rdev)
radeon_irq_kms_enable_hpd(rdev, enable); radeon_irq_kms_enable_hpd(rdev, enable);
} }
/**
* r100_hpd_fini - hpd tear down callback.
*
* @rdev: radeon_device pointer
*
* Tear down the hpd pins used by the card (r1xx-r4xx).
* Disable the hpd interrupts.
*/
void r100_hpd_fini(struct radeon_device *rdev) void r100_hpd_fini(struct radeon_device *rdev)
{ {
struct drm_device *dev = rdev->ddev; struct drm_device *dev = rdev->ddev;
...@@ -1060,6 +1181,14 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size) ...@@ -1060,6 +1181,14 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
} }
ring->ready = true; ring->ready = true;
radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
if (radeon_ring_supports_scratch_reg(rdev, ring)) {
r = radeon_scratch_get(rdev, &ring->rptr_save_reg);
if (r) {
DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r);
ring->rptr_save_reg = 0;
}
}
return 0; return 0;
} }
...@@ -1070,6 +1199,7 @@ void r100_cp_fini(struct radeon_device *rdev) ...@@ -1070,6 +1199,7 @@ void r100_cp_fini(struct radeon_device *rdev)
} }
/* Disable ring */ /* Disable ring */
r100_cp_disable(rdev); r100_cp_disable(rdev);
radeon_scratch_free(rdev, rdev->ring[RADEON_RING_TYPE_GFX_INDEX].rptr_save_reg);
radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]); radeon_ring_fini(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]);
DRM_INFO("radeon: cp finalized\n"); DRM_INFO("radeon: cp finalized\n");
} }
...@@ -3661,6 +3791,12 @@ void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -3661,6 +3791,12 @@ void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
{ {
struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
if (ring->rptr_save_reg) {
u32 next_rptr = ring->wptr + 2 + 3;
radeon_ring_write(ring, PACKET0(ring->rptr_save_reg, 0));
radeon_ring_write(ring, next_rptr);
}
radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1)); radeon_ring_write(ring, PACKET0(RADEON_CP_IB_BASE, 1));
radeon_ring_write(ring, ib->gpu_addr); radeon_ring_write(ring, ib->gpu_addr);
radeon_ring_write(ring, ib->length_dw); radeon_ring_write(ring, ib->length_dw);
...@@ -3693,7 +3829,7 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -3693,7 +3829,7 @@ int r100_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
ib.ptr[6] = PACKET2(0); ib.ptr[6] = PACKET2(0);
ib.ptr[7] = PACKET2(0); ib.ptr[7] = PACKET2(0);
ib.length_dw = 8; ib.length_dw = 8;
r = radeon_ib_schedule(rdev, &ib); r = radeon_ib_schedule(rdev, &ib, NULL);
if (r) { if (r) {
radeon_scratch_free(rdev, scratch); radeon_scratch_free(rdev, scratch);
radeon_ib_free(rdev, &ib); radeon_ib_free(rdev, &ib);
......
...@@ -2163,10 +2163,12 @@ void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsign ...@@ -2163,10 +2163,12 @@ void r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsign
ring->ring_size = ring_size; ring->ring_size = ring_size;
ring->align_mask = 16 - 1; ring->align_mask = 16 - 1;
r = radeon_scratch_get(rdev, &ring->rptr_save_reg); if (radeon_ring_supports_scratch_reg(rdev, ring)) {
if (r) { r = radeon_scratch_get(rdev, &ring->rptr_save_reg);
DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); if (r) {
ring->rptr_save_reg = 0; DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r);
ring->rptr_save_reg = 0;
}
} }
} }
...@@ -2198,7 +2200,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -2198,7 +2200,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
{ {
uint32_t scratch; uint32_t scratch;
uint32_t tmp = 0; uint32_t tmp = 0;
unsigned i, ridx = radeon_ring_index(rdev, ring); unsigned i;
int r; int r;
r = radeon_scratch_get(rdev, &scratch); r = radeon_scratch_get(rdev, &scratch);
...@@ -2209,7 +2211,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -2209,7 +2211,7 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
WREG32(scratch, 0xCAFEDEAD); WREG32(scratch, 0xCAFEDEAD);
r = radeon_ring_lock(rdev, ring, 3); r = radeon_ring_lock(rdev, ring, 3);
if (r) { if (r) {
DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ridx, r); DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ring->idx, r);
radeon_scratch_free(rdev, scratch); radeon_scratch_free(rdev, scratch);
return r; return r;
} }
...@@ -2224,10 +2226,10 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -2224,10 +2226,10 @@ int r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring)
DRM_UDELAY(1); DRM_UDELAY(1);
} }
if (i < rdev->usec_timeout) { if (i < rdev->usec_timeout) {
DRM_INFO("ring test on %d succeeded in %d usecs\n", ridx, i); DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i);
} else { } else {
DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n",
ridx, scratch, tmp); ring->idx, scratch, tmp);
r = -EINVAL; r = -EINVAL;
} }
radeon_scratch_free(rdev, scratch); radeon_scratch_free(rdev, scratch);
...@@ -2576,13 +2578,21 @@ void r600_fini(struct radeon_device *rdev) ...@@ -2576,13 +2578,21 @@ void r600_fini(struct radeon_device *rdev)
void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
{ {
struct radeon_ring *ring = &rdev->ring[ib->ring]; struct radeon_ring *ring = &rdev->ring[ib->ring];
u32 next_rptr;
if (ring->rptr_save_reg) { if (ring->rptr_save_reg) {
uint32_t next_rptr = ring->wptr + 3 + 4; next_rptr = ring->wptr + 3 + 4;
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
radeon_ring_write(ring, ((ring->rptr_save_reg - radeon_ring_write(ring, ((ring->rptr_save_reg -
PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
radeon_ring_write(ring, next_rptr); radeon_ring_write(ring, next_rptr);
} else if (rdev->wb.enabled) {
next_rptr = ring->wptr + 5 + 4;
radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3));
radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18));
radeon_ring_write(ring, next_rptr);
radeon_ring_write(ring, 0);
} }
radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2));
...@@ -2602,7 +2612,6 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -2602,7 +2612,6 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
uint32_t tmp = 0; uint32_t tmp = 0;
unsigned i; unsigned i;
int r; int r;
int ring_index = radeon_ring_index(rdev, ring);
r = radeon_scratch_get(rdev, &scratch); r = radeon_scratch_get(rdev, &scratch);
if (r) { if (r) {
...@@ -2610,7 +2619,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -2610,7 +2619,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
return r; return r;
} }
WREG32(scratch, 0xCAFEDEAD); WREG32(scratch, 0xCAFEDEAD);
r = radeon_ib_get(rdev, ring_index, &ib, 256); r = radeon_ib_get(rdev, ring->idx, &ib, 256);
if (r) { if (r) {
DRM_ERROR("radeon: failed to get ib (%d).\n", r); DRM_ERROR("radeon: failed to get ib (%d).\n", r);
return r; return r;
...@@ -2619,7 +2628,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) ...@@ -2619,7 +2628,7 @@ int r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring)
ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2);
ib.ptr[2] = 0xDEADBEEF; ib.ptr[2] = 0xDEADBEEF;
ib.length_dw = 3; ib.length_dw = 3;
r = radeon_ib_schedule(rdev, &ib); r = radeon_ib_schedule(rdev, &ib, NULL);
if (r) { if (r) {
radeon_scratch_free(rdev, scratch); radeon_scratch_free(rdev, scratch);
radeon_ib_free(rdev, &ib); radeon_ib_free(rdev, &ib);
......
...@@ -362,7 +362,7 @@ struct radeon_bo_list { ...@@ -362,7 +362,7 @@ struct radeon_bo_list {
* alignment). * alignment).
*/ */
struct radeon_sa_manager { struct radeon_sa_manager {
spinlock_t lock; wait_queue_head_t wq;
struct radeon_bo *bo; struct radeon_bo *bo;
struct list_head *hole; struct list_head *hole;
struct list_head flist[RADEON_NUM_RINGS]; struct list_head flist[RADEON_NUM_RINGS];
...@@ -623,6 +623,8 @@ struct radeon_ring { ...@@ -623,6 +623,8 @@ struct radeon_ring {
unsigned rptr_offs; unsigned rptr_offs;
unsigned rptr_reg; unsigned rptr_reg;
unsigned rptr_save_reg; unsigned rptr_save_reg;
u64 next_rptr_gpu_addr;
volatile u32 *next_rptr_cpu_addr;
unsigned wptr; unsigned wptr;
unsigned wptr_old; unsigned wptr_old;
unsigned wptr_reg; unsigned wptr_reg;
...@@ -638,6 +640,7 @@ struct radeon_ring { ...@@ -638,6 +640,7 @@ struct radeon_ring {
u32 ptr_reg_shift; u32 ptr_reg_shift;
u32 ptr_reg_mask; u32 ptr_reg_mask;
u32 nop; u32 nop;
u32 idx;
}; };
/* /*
...@@ -751,12 +754,14 @@ struct si_rlc { ...@@ -751,12 +754,14 @@ struct si_rlc {
int radeon_ib_get(struct radeon_device *rdev, int ring, int radeon_ib_get(struct radeon_device *rdev, int ring,
struct radeon_ib *ib, unsigned size); struct radeon_ib *ib, unsigned size);
void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib); void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib);
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib); int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
struct radeon_ib *const_ib);
int radeon_ib_pool_init(struct radeon_device *rdev); int radeon_ib_pool_init(struct radeon_device *rdev);
void radeon_ib_pool_fini(struct radeon_device *rdev); void radeon_ib_pool_fini(struct radeon_device *rdev);
int radeon_ib_ring_tests(struct radeon_device *rdev); int radeon_ib_ring_tests(struct radeon_device *rdev);
/* Ring access between begin & end cannot sleep */ /* Ring access between begin & end cannot sleep */
int radeon_ring_index(struct radeon_device *rdev, struct radeon_ring *cp); bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev,
struct radeon_ring *ring);
void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp); void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *cp);
int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw); int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *cp, unsigned ndw);
...@@ -870,6 +875,7 @@ struct radeon_wb { ...@@ -870,6 +875,7 @@ struct radeon_wb {
}; };
#define RADEON_WB_SCRATCH_OFFSET 0 #define RADEON_WB_SCRATCH_OFFSET 0
#define RADEON_WB_RING0_NEXT_RPTR 256
#define RADEON_WB_CP_RPTR_OFFSET 1024 #define RADEON_WB_CP_RPTR_OFFSET 1024
#define RADEON_WB_CP1_RPTR_OFFSET 1280 #define RADEON_WB_CP1_RPTR_OFFSET 1280
#define RADEON_WB_CP2_RPTR_OFFSET 1536 #define RADEON_WB_CP2_RPTR_OFFSET 1536
......
...@@ -40,6 +40,16 @@ ...@@ -40,6 +40,16 @@
/* /*
* Registers accessors functions. * Registers accessors functions.
*/ */
/**
* radeon_invalid_rreg - dummy reg read function
*
* @rdev: radeon device pointer
* @reg: offset of register
*
* Dummy register read function. Used for register blocks
* that certain asics don't have (all asics).
* Returns the value in the register.
*/
static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg)
{ {
DRM_ERROR("Invalid callback to read register 0x%04X\n", reg); DRM_ERROR("Invalid callback to read register 0x%04X\n", reg);
...@@ -47,6 +57,16 @@ static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg) ...@@ -47,6 +57,16 @@ static uint32_t radeon_invalid_rreg(struct radeon_device *rdev, uint32_t reg)
return 0; return 0;
} }
/**
* radeon_invalid_wreg - dummy reg write function
*
* @rdev: radeon device pointer
* @reg: offset of register
* @v: value to write to the register
*
* Dummy register read function. Used for register blocks
* that certain asics don't have (all asics).
*/
static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{ {
DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n", DRM_ERROR("Invalid callback to write register 0x%04X with 0x%08X\n",
...@@ -54,6 +74,14 @@ static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32 ...@@ -54,6 +74,14 @@ static void radeon_invalid_wreg(struct radeon_device *rdev, uint32_t reg, uint32
BUG_ON(1); BUG_ON(1);
} }
/**
* radeon_register_accessor_init - sets up the register accessor callbacks
*
* @rdev: radeon device pointer
*
* Sets up the register accessor callbacks for various register
* apertures. Not all asics have all apertures (all asics).
*/
static void radeon_register_accessor_init(struct radeon_device *rdev) static void radeon_register_accessor_init(struct radeon_device *rdev)
{ {
rdev->mc_rreg = &radeon_invalid_rreg; rdev->mc_rreg = &radeon_invalid_rreg;
...@@ -102,6 +130,14 @@ static void radeon_register_accessor_init(struct radeon_device *rdev) ...@@ -102,6 +130,14 @@ static void radeon_register_accessor_init(struct radeon_device *rdev)
/* helper to disable agp */ /* helper to disable agp */
/**
* radeon_agp_disable - AGP disable helper function
*
* @rdev: radeon device pointer
*
* Removes AGP flags and changes the gart callbacks on AGP
* cards when using the internal gart rather than AGP (all asics).
*/
void radeon_agp_disable(struct radeon_device *rdev) void radeon_agp_disable(struct radeon_device *rdev)
{ {
rdev->flags &= ~RADEON_IS_AGP; rdev->flags &= ~RADEON_IS_AGP;
...@@ -1608,6 +1644,16 @@ static struct radeon_asic si_asic = { ...@@ -1608,6 +1644,16 @@ static struct radeon_asic si_asic = {
}, },
}; };
/**
* radeon_asic_init - register asic specific callbacks
*
* @rdev: radeon device pointer
*
* Registers the appropriate asic specific callbacks for each
* chip family. Also sets other asics specific info like the number
* of crtcs and the register aperture accessors (all asics).
* Returns 0 for success.
*/
int radeon_asic_init(struct radeon_device *rdev) int radeon_asic_init(struct radeon_device *rdev)
{ {
radeon_register_accessor_init(rdev); radeon_register_accessor_init(rdev);
......
...@@ -354,7 +354,7 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev, ...@@ -354,7 +354,7 @@ static int radeon_cs_ib_chunk(struct radeon_device *rdev,
} }
radeon_cs_sync_rings(parser); radeon_cs_sync_rings(parser);
parser->ib.vm_id = 0; parser->ib.vm_id = 0;
r = radeon_ib_schedule(rdev, &parser->ib); r = radeon_ib_schedule(rdev, &parser->ib, NULL);
if (r) { if (r) {
DRM_ERROR("Failed to schedule IB !\n"); DRM_ERROR("Failed to schedule IB !\n");
} }
...@@ -452,25 +452,24 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev, ...@@ -452,25 +452,24 @@ static int radeon_cs_ib_vm_chunk(struct radeon_device *rdev,
} }
radeon_cs_sync_rings(parser); radeon_cs_sync_rings(parser);
parser->ib.vm_id = vm->id;
/* ib pool is bind at 0 in virtual address space,
* so gpu_addr is the offset inside the pool bo
*/
parser->ib.gpu_addr = parser->ib.sa_bo->soffset;
if ((rdev->family >= CHIP_TAHITI) && if ((rdev->family >= CHIP_TAHITI) &&
(parser->chunk_const_ib_idx != -1)) { (parser->chunk_const_ib_idx != -1)) {
parser->const_ib.vm_id = vm->id; parser->const_ib.vm_id = vm->id;
/* ib pool is bind at 0 in virtual address space to gpu_addr is the /* ib pool is bind at 0 in virtual address space,
* offset inside the pool bo * so gpu_addr is the offset inside the pool bo
*/ */
parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset; parser->const_ib.gpu_addr = parser->const_ib.sa_bo->soffset;
r = radeon_ib_schedule(rdev, &parser->const_ib); r = radeon_ib_schedule(rdev, &parser->ib, &parser->const_ib);
if (r) } else {
goto out; r = radeon_ib_schedule(rdev, &parser->ib, NULL);
} }
parser->ib.vm_id = vm->id;
/* ib pool is bind at 0 in virtual address space to gpu_addr is the
* offset inside the pool bo
*/
parser->ib.gpu_addr = parser->ib.sa_bo->soffset;
parser->ib.is_const_ib = false;
r = radeon_ib_schedule(rdev, &parser->ib);
out: out:
if (!r) { if (!r) {
if (vm->fence) { if (vm->fence) {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -34,6 +34,15 @@ ...@@ -34,6 +34,15 @@
#define RADEON_WAIT_IDLE_TIMEOUT 200 #define RADEON_WAIT_IDLE_TIMEOUT 200
/**
* radeon_driver_irq_handler_kms - irq handler for KMS
*
* @DRM_IRQ_ARGS: args
*
* This is the irq handler for the radeon KMS driver (all asics).
* radeon_irq_process is a macro that points to the per-asic
* irq handler callback.
*/
irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
{ {
struct drm_device *dev = (struct drm_device *) arg; struct drm_device *dev = (struct drm_device *) arg;
...@@ -45,6 +54,17 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS) ...@@ -45,6 +54,17 @@ irqreturn_t radeon_driver_irq_handler_kms(DRM_IRQ_ARGS)
/* /*
* Handle hotplug events outside the interrupt handler proper. * Handle hotplug events outside the interrupt handler proper.
*/ */
/**
* radeon_hotplug_work_func - display hotplug work handler
*
* @work: work struct
*
* This is the hot plug event work handler (all asics).
* The work gets scheduled from the irq handler if there
* was a hot plug interrupt. It walks the connector table
* and calls the hotplug handler for each one, then sends
* a drm hotplug event to alert userspace.
*/
static void radeon_hotplug_work_func(struct work_struct *work) static void radeon_hotplug_work_func(struct work_struct *work)
{ {
struct radeon_device *rdev = container_of(work, struct radeon_device, struct radeon_device *rdev = container_of(work, struct radeon_device,
...@@ -61,6 +81,14 @@ static void radeon_hotplug_work_func(struct work_struct *work) ...@@ -61,6 +81,14 @@ static void radeon_hotplug_work_func(struct work_struct *work)
drm_helper_hpd_irq_event(dev); drm_helper_hpd_irq_event(dev);
} }
/**
* radeon_driver_irq_preinstall_kms - drm irq preinstall callback
*
* @dev: drm dev pointer
*
* Gets the hw ready to enable irqs (all asics).
* This function disables all interrupt sources on the GPU.
*/
void radeon_driver_irq_preinstall_kms(struct drm_device *dev) void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -85,12 +113,27 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev) ...@@ -85,12 +113,27 @@ void radeon_driver_irq_preinstall_kms(struct drm_device *dev)
radeon_irq_process(rdev); radeon_irq_process(rdev);
} }
/**
* radeon_driver_irq_postinstall_kms - drm irq preinstall callback
*
* @dev: drm dev pointer
*
* Handles stuff to be done after enabling irqs (all asics).
* Returns 0 on success.
*/
int radeon_driver_irq_postinstall_kms(struct drm_device *dev) int radeon_driver_irq_postinstall_kms(struct drm_device *dev)
{ {
dev->max_vblank_count = 0x001fffff; dev->max_vblank_count = 0x001fffff;
return 0; return 0;
} }
/**
* radeon_driver_irq_uninstall_kms - drm irq uninstall callback
*
* @dev: drm dev pointer
*
* This function disables all interrupt sources on the GPU (all asics).
*/
void radeon_driver_irq_uninstall_kms(struct drm_device *dev) void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -116,6 +159,16 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev) ...@@ -116,6 +159,16 @@ void radeon_driver_irq_uninstall_kms(struct drm_device *dev)
spin_unlock_irqrestore(&rdev->irq.lock, irqflags); spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
} }
/**
* radeon_msi_ok - asic specific msi checks
*
* @rdev: radeon device pointer
*
* Handles asic specific MSI checks to determine if
* MSIs should be enabled on a particular chip (all asics).
* Returns true if MSIs should be enabled, false if MSIs
* should not be enabled.
*/
static bool radeon_msi_ok(struct radeon_device *rdev) static bool radeon_msi_ok(struct radeon_device *rdev)
{ {
/* RV370/RV380 was first asic with MSI support */ /* RV370/RV380 was first asic with MSI support */
...@@ -168,6 +221,14 @@ static bool radeon_msi_ok(struct radeon_device *rdev) ...@@ -168,6 +221,14 @@ static bool radeon_msi_ok(struct radeon_device *rdev)
return true; return true;
} }
/**
* radeon_irq_kms_init - init driver interrupt info
*
* @rdev: radeon device pointer
*
* Sets up the work irq handlers, vblank init, MSIs, etc. (all asics).
* Returns 0 for success, error for failure.
*/
int radeon_irq_kms_init(struct radeon_device *rdev) int radeon_irq_kms_init(struct radeon_device *rdev)
{ {
int r = 0; int r = 0;
...@@ -200,6 +261,13 @@ int radeon_irq_kms_init(struct radeon_device *rdev) ...@@ -200,6 +261,13 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
return 0; return 0;
} }
/**
* radeon_irq_kms_fini - tear down driver interrrupt info
*
* @rdev: radeon device pointer
*
* Tears down the work irq handlers, vblank handlers, MSIs, etc. (all asics).
*/
void radeon_irq_kms_fini(struct radeon_device *rdev) void radeon_irq_kms_fini(struct radeon_device *rdev)
{ {
drm_vblank_cleanup(rdev->ddev); drm_vblank_cleanup(rdev->ddev);
...@@ -212,6 +280,16 @@ void radeon_irq_kms_fini(struct radeon_device *rdev) ...@@ -212,6 +280,16 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
flush_work_sync(&rdev->hotplug_work); flush_work_sync(&rdev->hotplug_work);
} }
/**
* radeon_irq_kms_sw_irq_get - enable software interrupt
*
* @rdev: radeon device pointer
* @ring: ring whose interrupt you want to enable
*
* Enables the software interrupt for a specific ring (all asics).
* The software interrupt is generally used to signal a fence on
* a particular ring.
*/
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -226,6 +304,16 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring) ...@@ -226,6 +304,16 @@ void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev, int ring)
} }
} }
/**
* radeon_irq_kms_sw_irq_put - disable software interrupt
*
* @rdev: radeon device pointer
* @ring: ring whose interrupt you want to disable
*
* Disables the software interrupt for a specific ring (all asics).
* The software interrupt is generally used to signal a fence on
* a particular ring.
*/
void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -240,6 +328,15 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring) ...@@ -240,6 +328,15 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev, int ring)
} }
} }
/**
* radeon_irq_kms_pflip_irq_get - enable pageflip interrupt
*
* @rdev: radeon device pointer
* @crtc: crtc whose interrupt you want to enable
*
* Enables the pageflip interrupt for a specific crtc (all asics).
* For pageflips we use the vblank interrupt source.
*/
void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -257,6 +354,15 @@ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc) ...@@ -257,6 +354,15 @@ void radeon_irq_kms_pflip_irq_get(struct radeon_device *rdev, int crtc)
} }
} }
/**
* radeon_irq_kms_pflip_irq_put - disable pageflip interrupt
*
* @rdev: radeon device pointer
* @crtc: crtc whose interrupt you want to disable
*
* Disables the pageflip interrupt for a specific crtc (all asics).
* For pageflips we use the vblank interrupt source.
*/
void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -274,6 +380,14 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc) ...@@ -274,6 +380,14 @@ void radeon_irq_kms_pflip_irq_put(struct radeon_device *rdev, int crtc)
} }
} }
/**
* radeon_irq_kms_enable_afmt - enable audio format change interrupt
*
* @rdev: radeon device pointer
* @block: afmt block whose interrupt you want to enable
*
* Enables the afmt change interrupt for a specific afmt block (all asics).
*/
void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -285,6 +399,14 @@ void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) ...@@ -285,6 +399,14 @@ void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block)
} }
/**
* radeon_irq_kms_disable_afmt - disable audio format change interrupt
*
* @rdev: radeon device pointer
* @block: afmt block whose interrupt you want to disable
*
* Disables the afmt change interrupt for a specific afmt block (all asics).
*/
void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -295,6 +417,14 @@ void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) ...@@ -295,6 +417,14 @@ void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block)
spin_unlock_irqrestore(&rdev->irq.lock, irqflags); spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
} }
/**
* radeon_irq_kms_enable_hpd - enable hotplug detect interrupt
*
* @rdev: radeon device pointer
* @hpd_mask: mask of hpd pins you want to enable.
*
* Enables the hotplug detect interrupt for a specific hpd pin (all asics).
*/
void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -307,6 +437,14 @@ void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) ...@@ -307,6 +437,14 @@ void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
spin_unlock_irqrestore(&rdev->irq.lock, irqflags); spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
} }
/**
* radeon_irq_kms_disable_hpd - disable hotplug detect interrupt
*
* @rdev: radeon device pointer
* @hpd_mask: mask of hpd pins you want to disable.
*
* Disables the hotplug detect interrupt for a specific hpd pin (all asics).
*/
void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
{ {
unsigned long irqflags; unsigned long irqflags;
...@@ -319,6 +457,18 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) ...@@ -319,6 +457,18 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask)
spin_unlock_irqrestore(&rdev->irq.lock, irqflags); spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
} }
/**
* radeon_irq_kms_wait_gui_idle - waits for drawing engine to be idle
*
* @rdev: radeon device pointer
*
* Enabled the GUI idle interrupt and waits for it to fire (r6xx+).
* This is currently used to make sure the 3D engine is idle for power
* management, but should be replaces with proper fence waits.
* GUI idle interrupts don't work very well on pre-r6xx hw and it also
* does not take into account other aspects of the chip that may be busy.
* DO NOT USE GOING FORWARD.
*/
int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev) int radeon_irq_kms_wait_gui_idle(struct radeon_device *rdev)
{ {
unsigned long irqflags; unsigned long irqflags;
......
...@@ -33,6 +33,17 @@ ...@@ -33,6 +33,17 @@
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
#include <linux/slab.h> #include <linux/slab.h>
/**
* radeon_driver_unload_kms - Main unload function for KMS.
*
* @dev: drm dev pointer
*
* This is the main unload function for KMS (all asics).
* It calls radeon_modeset_fini() to tear down the
* displays, and radeon_device_fini() to tear down
* the rest of the device (CP, writeback, etc.).
* Returns 0 on success.
*/
int radeon_driver_unload_kms(struct drm_device *dev) int radeon_driver_unload_kms(struct drm_device *dev)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -46,6 +57,19 @@ int radeon_driver_unload_kms(struct drm_device *dev) ...@@ -46,6 +57,19 @@ int radeon_driver_unload_kms(struct drm_device *dev)
return 0; return 0;
} }
/**
* radeon_driver_load_kms - Main load function for KMS.
*
* @dev: drm dev pointer
* @flags: device flags
*
* This is the main load function for KMS (all asics).
* It calls radeon_device_init() to set up the non-display
* parts of the chip (asic init, CP, writeback, etc.), and
* radeon_modeset_init() to set up the display parts
* (crtcs, encoders, hotplug detect, etc.).
* Returns 0 on success, error on failure.
*/
int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
{ {
struct radeon_device *rdev; struct radeon_device *rdev;
...@@ -96,6 +120,16 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags) ...@@ -96,6 +120,16 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
return r; return r;
} }
/**
* radeon_set_filp_rights - Set filp right.
*
* @dev: drm dev pointer
* @owner: drm file
* @applier: drm file
* @value: value
*
* Sets the filp rights for the device (all asics).
*/
static void radeon_set_filp_rights(struct drm_device *dev, static void radeon_set_filp_rights(struct drm_device *dev,
struct drm_file **owner, struct drm_file **owner,
struct drm_file *applier, struct drm_file *applier,
...@@ -118,6 +152,18 @@ static void radeon_set_filp_rights(struct drm_device *dev, ...@@ -118,6 +152,18 @@ static void radeon_set_filp_rights(struct drm_device *dev,
/* /*
* Userspace get information ioctl * Userspace get information ioctl
*/ */
/**
* radeon_info_ioctl - answer a device specific request.
*
* @rdev: radeon device pointer
* @data: request object
* @filp: drm filp
*
* This function is used to pass device specific parameters to the userspace
* drivers. Examples include: pci device id, pipeline parms, tiling params,
* etc. (all asics).
* Returns 0 on success, -EINVAL on failure.
*/
int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -301,16 +347,40 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) ...@@ -301,16 +347,40 @@ int radeon_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
/* /*
* Outdated mess for old drm with Xorg being in charge (void function now). * Outdated mess for old drm with Xorg being in charge (void function now).
*/ */
/**
* radeon_driver_firstopen_kms - drm callback for first open
*
* @dev: drm dev pointer
*
* Nothing to be done for KMS (all asics).
* Returns 0 on success.
*/
int radeon_driver_firstopen_kms(struct drm_device *dev) int radeon_driver_firstopen_kms(struct drm_device *dev)
{ {
return 0; return 0;
} }
/**
* radeon_driver_firstopen_kms - drm callback for last close
*
* @dev: drm dev pointer
*
* Switch vga switcheroo state after last close (all asics).
*/
void radeon_driver_lastclose_kms(struct drm_device *dev) void radeon_driver_lastclose_kms(struct drm_device *dev)
{ {
vga_switcheroo_process_delayed_switch(); vga_switcheroo_process_delayed_switch();
} }
/**
* radeon_driver_open_kms - drm callback for open
*
* @dev: drm dev pointer
* @file_priv: drm file
*
* On device open, init vm on cayman+ (all asics).
* Returns 0 on success, error on failure.
*/
int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -339,6 +409,14 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv) ...@@ -339,6 +409,14 @@ int radeon_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
return 0; return 0;
} }
/**
* radeon_driver_postclose_kms - drm callback for post close
*
* @dev: drm dev pointer
* @file_priv: drm file
*
* On device post close, tear down vm on cayman+ (all asics).
*/
void radeon_driver_postclose_kms(struct drm_device *dev, void radeon_driver_postclose_kms(struct drm_device *dev,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
...@@ -354,6 +432,15 @@ void radeon_driver_postclose_kms(struct drm_device *dev, ...@@ -354,6 +432,15 @@ void radeon_driver_postclose_kms(struct drm_device *dev,
} }
} }
/**
* radeon_driver_preclose_kms - drm callback for pre close
*
* @dev: drm dev pointer
* @file_priv: drm file
*
* On device pre close, tear down hyperz and cmask filps on r1xx-r5xx
* (all asics).
*/
void radeon_driver_preclose_kms(struct drm_device *dev, void radeon_driver_preclose_kms(struct drm_device *dev,
struct drm_file *file_priv) struct drm_file *file_priv)
{ {
...@@ -367,6 +454,15 @@ void radeon_driver_preclose_kms(struct drm_device *dev, ...@@ -367,6 +454,15 @@ void radeon_driver_preclose_kms(struct drm_device *dev,
/* /*
* VBlank related functions. * VBlank related functions.
*/ */
/**
* radeon_get_vblank_counter_kms - get frame count
*
* @dev: drm dev pointer
* @crtc: crtc to get the frame count from
*
* Gets the frame count on the requested crtc (all asics).
* Returns frame count on success, -EINVAL on failure.
*/
u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -379,6 +475,15 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) ...@@ -379,6 +475,15 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc)
return radeon_get_vblank_counter(rdev, crtc); return radeon_get_vblank_counter(rdev, crtc);
} }
/**
* radeon_enable_vblank_kms - enable vblank interrupt
*
* @dev: drm dev pointer
* @crtc: crtc to enable vblank interrupt for
*
* Enable the interrupt on the requested crtc (all asics).
* Returns 0 on success, -EINVAL on failure.
*/
int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -397,6 +502,14 @@ int radeon_enable_vblank_kms(struct drm_device *dev, int crtc) ...@@ -397,6 +502,14 @@ int radeon_enable_vblank_kms(struct drm_device *dev, int crtc)
return r; return r;
} }
/**
* radeon_disable_vblank_kms - disable vblank interrupt
*
* @dev: drm dev pointer
* @crtc: crtc to disable vblank interrupt for
*
* Disable the interrupt on the requested crtc (all asics).
*/
void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
{ {
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
...@@ -413,6 +526,19 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc) ...@@ -413,6 +526,19 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
spin_unlock_irqrestore(&rdev->irq.lock, irqflags); spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
} }
/**
* radeon_get_vblank_timestamp_kms - get vblank timestamp
*
* @dev: drm dev pointer
* @crtc: crtc to get the timestamp for
* @max_error: max error
* @vblank_time: time value
* @flags: flags passed to the driver
*
* Gets the timestamp on the requested crtc based on the
* scanout position. (all asics).
* Returns postive status flags on success, negative error on failure.
*/
int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc, int radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
int *max_error, int *max_error,
struct timeval *vblank_time, struct timeval *vblank_time,
......
This diff is collapsed.
...@@ -54,7 +54,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev, ...@@ -54,7 +54,7 @@ int radeon_sa_bo_manager_init(struct radeon_device *rdev,
{ {
int i, r; int i, r;
spin_lock_init(&sa_manager->lock); init_waitqueue_head(&sa_manager->wq);
sa_manager->bo = NULL; sa_manager->bo = NULL;
sa_manager->size = size; sa_manager->size = size;
sa_manager->domain = domain; sa_manager->domain = domain;
...@@ -211,6 +211,39 @@ static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager, ...@@ -211,6 +211,39 @@ static bool radeon_sa_bo_try_alloc(struct radeon_sa_manager *sa_manager,
return false; return false;
} }
/**
* radeon_sa_event - Check if we can stop waiting
*
* @sa_manager: pointer to the sa_manager
* @size: number of bytes we want to allocate
* @align: alignment we need to match
*
* Check if either there is a fence we can wait for or
* enough free memory to satisfy the allocation directly
*/
static bool radeon_sa_event(struct radeon_sa_manager *sa_manager,
unsigned size, unsigned align)
{
unsigned soffset, eoffset, wasted;
int i;
for (i = 0; i < RADEON_NUM_RINGS; ++i) {
if (!list_empty(&sa_manager->flist[i])) {
return true;
}
}
soffset = radeon_sa_bo_hole_soffset(sa_manager);
eoffset = radeon_sa_bo_hole_eoffset(sa_manager);
wasted = (align - (soffset % align)) % align;
if ((eoffset - soffset) >= (size + wasted)) {
return true;
}
return false;
}
static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager, static bool radeon_sa_bo_next_hole(struct radeon_sa_manager *sa_manager,
struct radeon_fence **fences, struct radeon_fence **fences,
unsigned *tries) unsigned *tries)
...@@ -297,8 +330,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev, ...@@ -297,8 +330,8 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
INIT_LIST_HEAD(&(*sa_bo)->olist); INIT_LIST_HEAD(&(*sa_bo)->olist);
INIT_LIST_HEAD(&(*sa_bo)->flist); INIT_LIST_HEAD(&(*sa_bo)->flist);
spin_lock(&sa_manager->lock); spin_lock(&sa_manager->wq.lock);
do { while(1) {
for (i = 0; i < RADEON_NUM_RINGS; ++i) { for (i = 0; i < RADEON_NUM_RINGS; ++i) {
fences[i] = NULL; fences[i] = NULL;
tries[i] = 0; tries[i] = 0;
...@@ -309,30 +342,34 @@ int radeon_sa_bo_new(struct radeon_device *rdev, ...@@ -309,30 +342,34 @@ int radeon_sa_bo_new(struct radeon_device *rdev,
if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo, if (radeon_sa_bo_try_alloc(sa_manager, *sa_bo,
size, align)) { size, align)) {
spin_unlock(&sa_manager->lock); spin_unlock(&sa_manager->wq.lock);
return 0; return 0;
} }
/* see if we can skip over some allocations */ /* see if we can skip over some allocations */
} while (radeon_sa_bo_next_hole(sa_manager, fences, tries)); } while (radeon_sa_bo_next_hole(sa_manager, fences, tries));
if (block) { if (!block) {
spin_unlock(&sa_manager->lock); break;
r = radeon_fence_wait_any(rdev, fences, false); }
spin_lock(&sa_manager->lock);
if (r) { spin_unlock(&sa_manager->wq.lock);
/* if we have nothing to wait for we r = radeon_fence_wait_any(rdev, fences, false);
are practically out of memory */ spin_lock(&sa_manager->wq.lock);
if (r == -ENOENT) { /* if we have nothing to wait for block */
r = -ENOMEM; if (r == -ENOENT) {
} r = wait_event_interruptible_locked(
goto out_err; sa_manager->wq,
} radeon_sa_event(sa_manager, size, align)
);
}
if (r) {
goto out_err;
} }
} while (block); };
out_err: out_err:
spin_unlock(&sa_manager->lock); spin_unlock(&sa_manager->wq.lock);
kfree(*sa_bo); kfree(*sa_bo);
*sa_bo = NULL; *sa_bo = NULL;
return r; return r;
...@@ -348,7 +385,7 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, ...@@ -348,7 +385,7 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo,
} }
sa_manager = (*sa_bo)->manager; sa_manager = (*sa_bo)->manager;
spin_lock(&sa_manager->lock); spin_lock(&sa_manager->wq.lock);
if (fence && !radeon_fence_signaled(fence)) { if (fence && !radeon_fence_signaled(fence)) {
(*sa_bo)->fence = radeon_fence_ref(fence); (*sa_bo)->fence = radeon_fence_ref(fence);
list_add_tail(&(*sa_bo)->flist, list_add_tail(&(*sa_bo)->flist,
...@@ -356,7 +393,8 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo, ...@@ -356,7 +393,8 @@ void radeon_sa_bo_free(struct radeon_device *rdev, struct radeon_sa_bo **sa_bo,
} else { } else {
radeon_sa_bo_remove_locked(*sa_bo); radeon_sa_bo_remove_locked(*sa_bo);
} }
spin_unlock(&sa_manager->lock); wake_up_all_locked(&sa_manager->wq);
spin_unlock(&sa_manager->wq.lock);
*sa_bo = NULL; *sa_bo = NULL;
} }
...@@ -366,7 +404,7 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, ...@@ -366,7 +404,7 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
{ {
struct radeon_sa_bo *i; struct radeon_sa_bo *i;
spin_lock(&sa_manager->lock); spin_lock(&sa_manager->wq.lock);
list_for_each_entry(i, &sa_manager->olist, olist) { list_for_each_entry(i, &sa_manager->olist, olist) {
if (&i->olist == sa_manager->hole) { if (&i->olist == sa_manager->hole) {
seq_printf(m, ">"); seq_printf(m, ">");
...@@ -381,6 +419,6 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager, ...@@ -381,6 +419,6 @@ void radeon_sa_bo_dump_debug_info(struct radeon_sa_manager *sa_manager,
} }
seq_printf(m, "\n"); seq_printf(m, "\n");
} }
spin_unlock(&sa_manager->lock); spin_unlock(&sa_manager->wq.lock);
} }
#endif #endif
...@@ -229,8 +229,6 @@ void radeon_test_ring_sync(struct radeon_device *rdev, ...@@ -229,8 +229,6 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
{ {
struct radeon_fence *fence1 = NULL, *fence2 = NULL; struct radeon_fence *fence1 = NULL, *fence2 = NULL;
struct radeon_semaphore *semaphore = NULL; struct radeon_semaphore *semaphore = NULL;
int ridxA = radeon_ring_index(rdev, ringA);
int ridxB = radeon_ring_index(rdev, ringB);
int r; int r;
r = radeon_semaphore_create(rdev, &semaphore); r = radeon_semaphore_create(rdev, &semaphore);
...@@ -241,18 +239,18 @@ void radeon_test_ring_sync(struct radeon_device *rdev, ...@@ -241,18 +239,18 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
r = radeon_ring_lock(rdev, ringA, 64); r = radeon_ring_lock(rdev, ringA, 64);
if (r) { if (r) {
DRM_ERROR("Failed to lock ring A %d\n", ridxA); DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ridxA, semaphore); radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
r = radeon_fence_emit(rdev, &fence1, ridxA); r = radeon_fence_emit(rdev, &fence1, ringA->idx);
if (r) { if (r) {
DRM_ERROR("Failed to emit fence 1\n"); DRM_ERROR("Failed to emit fence 1\n");
radeon_ring_unlock_undo(rdev, ringA); radeon_ring_unlock_undo(rdev, ringA);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ridxA, semaphore); radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
r = radeon_fence_emit(rdev, &fence2, ridxA); r = radeon_fence_emit(rdev, &fence2, ringA->idx);
if (r) { if (r) {
DRM_ERROR("Failed to emit fence 2\n"); DRM_ERROR("Failed to emit fence 2\n");
radeon_ring_unlock_undo(rdev, ringA); radeon_ring_unlock_undo(rdev, ringA);
...@@ -272,7 +270,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, ...@@ -272,7 +270,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
DRM_ERROR("Failed to lock ring B %p\n", ringB); DRM_ERROR("Failed to lock ring B %p\n", ringB);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_signal(rdev, ridxB, semaphore); radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringB); radeon_ring_unlock_commit(rdev, ringB);
r = radeon_fence_wait(fence1, false); r = radeon_fence_wait(fence1, false);
...@@ -293,7 +291,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev, ...@@ -293,7 +291,7 @@ void radeon_test_ring_sync(struct radeon_device *rdev,
DRM_ERROR("Failed to lock ring B %p\n", ringB); DRM_ERROR("Failed to lock ring B %p\n", ringB);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_signal(rdev, ridxB, semaphore); radeon_semaphore_emit_signal(rdev, ringB->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringB); radeon_ring_unlock_commit(rdev, ringB);
r = radeon_fence_wait(fence2, false); r = radeon_fence_wait(fence2, false);
...@@ -322,9 +320,6 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, ...@@ -322,9 +320,6 @@ void radeon_test_ring_sync2(struct radeon_device *rdev,
{ {
struct radeon_fence *fenceA = NULL, *fenceB = NULL; struct radeon_fence *fenceA = NULL, *fenceB = NULL;
struct radeon_semaphore *semaphore = NULL; struct radeon_semaphore *semaphore = NULL;
int ridxA = radeon_ring_index(rdev, ringA);
int ridxB = radeon_ring_index(rdev, ringB);
int ridxC = radeon_ring_index(rdev, ringC);
bool sigA, sigB; bool sigA, sigB;
int i, r; int i, r;
...@@ -336,11 +331,11 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, ...@@ -336,11 +331,11 @@ void radeon_test_ring_sync2(struct radeon_device *rdev,
r = radeon_ring_lock(rdev, ringA, 64); r = radeon_ring_lock(rdev, ringA, 64);
if (r) { if (r) {
DRM_ERROR("Failed to lock ring A %d\n", ridxA); DRM_ERROR("Failed to lock ring A %d\n", ringA->idx);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ridxA, semaphore); radeon_semaphore_emit_wait(rdev, ringA->idx, semaphore);
r = radeon_fence_emit(rdev, &fenceA, ridxA); r = radeon_fence_emit(rdev, &fenceA, ringA->idx);
if (r) { if (r) {
DRM_ERROR("Failed to emit sync fence 1\n"); DRM_ERROR("Failed to emit sync fence 1\n");
radeon_ring_unlock_undo(rdev, ringA); radeon_ring_unlock_undo(rdev, ringA);
...@@ -350,11 +345,11 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, ...@@ -350,11 +345,11 @@ void radeon_test_ring_sync2(struct radeon_device *rdev,
r = radeon_ring_lock(rdev, ringB, 64); r = radeon_ring_lock(rdev, ringB, 64);
if (r) { if (r) {
DRM_ERROR("Failed to lock ring B %d\n", ridxB); DRM_ERROR("Failed to lock ring B %d\n", ringB->idx);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_wait(rdev, ridxB, semaphore); radeon_semaphore_emit_wait(rdev, ringB->idx, semaphore);
r = radeon_fence_emit(rdev, &fenceB, ridxB); r = radeon_fence_emit(rdev, &fenceB, ringB->idx);
if (r) { if (r) {
DRM_ERROR("Failed to create sync fence 2\n"); DRM_ERROR("Failed to create sync fence 2\n");
radeon_ring_unlock_undo(rdev, ringB); radeon_ring_unlock_undo(rdev, ringB);
...@@ -378,7 +373,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, ...@@ -378,7 +373,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev,
DRM_ERROR("Failed to lock ring B %p\n", ringC); DRM_ERROR("Failed to lock ring B %p\n", ringC);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_signal(rdev, ridxC, semaphore); radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringC); radeon_ring_unlock_commit(rdev, ringC);
for (i = 0; i < 30; ++i) { for (i = 0; i < 30; ++i) {
...@@ -404,7 +399,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev, ...@@ -404,7 +399,7 @@ void radeon_test_ring_sync2(struct radeon_device *rdev,
DRM_ERROR("Failed to lock ring B %p\n", ringC); DRM_ERROR("Failed to lock ring B %p\n", ringC);
goto out_cleanup; goto out_cleanup;
} }
radeon_semaphore_emit_signal(rdev, ridxC, semaphore); radeon_semaphore_emit_signal(rdev, ringC->idx, semaphore);
radeon_ring_unlock_commit(rdev, ringC); radeon_ring_unlock_commit(rdev, ringC);
mdelay(1000); mdelay(1000);
......
...@@ -1765,18 +1765,31 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -1765,18 +1765,31 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
struct radeon_ring *ring = &rdev->ring[ib->ring]; struct radeon_ring *ring = &rdev->ring[ib->ring];
u32 header; u32 header;
if (ring->rptr_save_reg) { if (ib->is_const_ib) {
uint32_t next_rptr = ring->wptr + 3 + 4 + 8; /* set switch buffer packet before const IB */
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); radeon_ring_write(ring, PACKET3(PACKET3_SWITCH_BUFFER, 0));
radeon_ring_write(ring, ((ring->rptr_save_reg - radeon_ring_write(ring, 0);
PACKET3_SET_CONFIG_REG_START) >> 2));
radeon_ring_write(ring, next_rptr);
}
if (ib->is_const_ib)
header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2); header = PACKET3(PACKET3_INDIRECT_BUFFER_CONST, 2);
else } else {
u32 next_rptr;
if (ring->rptr_save_reg) {
next_rptr = ring->wptr + 3 + 4 + 8;
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
radeon_ring_write(ring, ((ring->rptr_save_reg -
PACKET3_SET_CONFIG_REG_START) >> 2));
radeon_ring_write(ring, next_rptr);
} else if (rdev->wb.enabled) {
next_rptr = ring->wptr + 5 + 4 + 8;
radeon_ring_write(ring, PACKET3(PACKET3_WRITE_DATA, 3));
radeon_ring_write(ring, (1 << 8));
radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc);
radeon_ring_write(ring, upper_32_bits(ring->next_rptr_gpu_addr) & 0xffffffff);
radeon_ring_write(ring, next_rptr);
}
header = PACKET3(PACKET3_INDIRECT_BUFFER, 2); header = PACKET3(PACKET3_INDIRECT_BUFFER, 2);
}
radeon_ring_write(ring, header); radeon_ring_write(ring, header);
radeon_ring_write(ring, radeon_ring_write(ring,
...@@ -1787,18 +1800,20 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -1787,18 +1800,20 @@ void si_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib)
radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF); radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFFFF);
radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24)); radeon_ring_write(ring, ib->length_dw | (ib->vm_id << 24));
/* flush read cache over gart for this vmid */ if (!ib->is_const_ib) {
radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); /* flush read cache over gart for this vmid */
radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2); radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1));
radeon_ring_write(ring, ib->vm_id); radeon_ring_write(ring, (CP_COHER_CNTL2 - PACKET3_SET_CONFIG_REG_START) >> 2);
radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); radeon_ring_write(ring, ib->vm_id);
radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA | radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3));
PACKET3_TC_ACTION_ENA | radeon_ring_write(ring, PACKET3_TCL1_ACTION_ENA |
PACKET3_SH_KCACHE_ACTION_ENA | PACKET3_TC_ACTION_ENA |
PACKET3_SH_ICACHE_ACTION_ENA); PACKET3_SH_KCACHE_ACTION_ENA |
radeon_ring_write(ring, 0xFFFFFFFF); PACKET3_SH_ICACHE_ACTION_ENA);
radeon_ring_write(ring, 0); radeon_ring_write(ring, 0xFFFFFFFF);
radeon_ring_write(ring, 10); /* poll interval */ radeon_ring_write(ring, 0);
radeon_ring_write(ring, 10); /* poll interval */
}
} }
/* /*
......
...@@ -901,5 +901,6 @@ ...@@ -901,5 +901,6 @@
#define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88 #define PACKET3_WAIT_ON_DE_COUNTER_DIFF 0x88
#define PACKET3_SET_CE_DE_COUNTERS 0x89 #define PACKET3_SET_CE_DE_COUNTERS 0x89
#define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A #define PACKET3_WAIT_ON_AVAIL_BUFFER 0x8A
#define PACKET3_SWITCH_BUFFER 0x8B
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment