Commit f5fc5567 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6

* 'drm-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6:
  drm/radeon/kms/r6xx+: voltage fixes
  drm/nouveau: drop leftover debugging
  drm/radeon: avoid warnings from r600/eg irq handlers on powered off card.
  drm/radeon/kms: add missing param for dce3.2 DP transmitter setup
  drm/radeon/kms/atom: fix duallink on some early DCE3.2 cards
  drm/nouveau: fix assumption that semaphore dmaobj is valid in x-chan sync
  drm/nv50/disp: fix gamma with page flipping overlay turned on
  drm/nouveau/pm: Prevent overflow in nouveau_perf_init()
  drm/nouveau: fix big-endian switch
parents 85d45ade a377e187
...@@ -262,7 +262,6 @@ static bool nouveau_dsm_detect(void) ...@@ -262,7 +262,6 @@ static bool nouveau_dsm_detect(void)
vga_count++; vga_count++;
retval = nouveau_dsm_pci_probe(pdev); retval = nouveau_dsm_pci_probe(pdev);
printk("ret val is %d\n", retval);
if (retval & NOUVEAU_DSM_HAS_MUX) if (retval & NOUVEAU_DSM_HAS_MUX)
has_dsm |= 1; has_dsm |= 1;
if (retval & NOUVEAU_DSM_HAS_OPT) if (retval & NOUVEAU_DSM_HAS_OPT)
......
...@@ -339,11 +339,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) ...@@ -339,11 +339,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
int ret; int ret;
if (dev_priv->chipset < 0x84) { if (dev_priv->chipset < 0x84) {
ret = RING_SPACE(chan, 3); ret = RING_SPACE(chan, 4);
if (ret) if (ret)
return ret; return ret;
BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2); BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 3);
OUT_RING (chan, NvSema);
OUT_RING (chan, sema->mem->start); OUT_RING (chan, sema->mem->start);
OUT_RING (chan, 1); OUT_RING (chan, 1);
} else } else
...@@ -351,10 +352,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema) ...@@ -351,10 +352,12 @@ semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
struct nouveau_vma *vma = &dev_priv->fence.bo->vma; struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
u64 offset = vma->offset + sema->mem->start; u64 offset = vma->offset + sema->mem->start;
ret = RING_SPACE(chan, 5); ret = RING_SPACE(chan, 7);
if (ret) if (ret)
return ret; return ret;
BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
OUT_RING (chan, chan->vram_handle);
BEGIN_RING(chan, NvSubSw, 0x0010, 4); BEGIN_RING(chan, NvSubSw, 0x0010, 4);
OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, upper_32_bits(offset));
OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset));
...@@ -394,11 +397,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) ...@@ -394,11 +397,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
int ret; int ret;
if (dev_priv->chipset < 0x84) { if (dev_priv->chipset < 0x84) {
ret = RING_SPACE(chan, 4); ret = RING_SPACE(chan, 5);
if (ret) if (ret)
return ret; return ret;
BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1); BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 2);
OUT_RING (chan, NvSema);
OUT_RING (chan, sema->mem->start); OUT_RING (chan, sema->mem->start);
BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1); BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
OUT_RING (chan, 1); OUT_RING (chan, 1);
...@@ -407,10 +411,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema) ...@@ -407,10 +411,12 @@ semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
struct nouveau_vma *vma = &dev_priv->fence.bo->vma; struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
u64 offset = vma->offset + sema->mem->start; u64 offset = vma->offset + sema->mem->start;
ret = RING_SPACE(chan, 5); ret = RING_SPACE(chan, 7);
if (ret) if (ret)
return ret; return ret;
BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
OUT_RING (chan, chan->vram_handle);
BEGIN_RING(chan, NvSubSw, 0x0010, 4); BEGIN_RING(chan, NvSubSw, 0x0010, 4);
OUT_RING (chan, upper_32_bits(offset)); OUT_RING (chan, upper_32_bits(offset));
OUT_RING (chan, lower_32_bits(offset)); OUT_RING (chan, lower_32_bits(offset));
...@@ -504,22 +510,22 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) ...@@ -504,22 +510,22 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
struct nouveau_gpuobj *obj = NULL; struct nouveau_gpuobj *obj = NULL;
int ret; int ret;
if (dev_priv->card_type >= NV_C0) if (dev_priv->card_type < NV_C0) {
goto out_initialised;
/* Create an NV_SW object for various sync purposes */ /* Create an NV_SW object for various sync purposes */
ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW); ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW);
if (ret) if (ret)
return ret; return ret;
/* we leave subchannel empty for nvc0 */
ret = RING_SPACE(chan, 2); ret = RING_SPACE(chan, 2);
if (ret) if (ret)
return ret; return ret;
BEGIN_RING(chan, NvSubSw, 0, 1); BEGIN_RING(chan, NvSubSw, 0, 1);
OUT_RING(chan, NvSw); OUT_RING (chan, NvSw);
FIRE_RING (chan);
}
/* Create a DMA object for the shared cross-channel sync area. */ /* Setup area of memory shared between all channels for x-chan sync */
if (USE_SEMA(dev) && dev_priv->chipset < 0x84) { if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {
struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem; struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
...@@ -534,23 +540,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan) ...@@ -534,23 +540,8 @@ nouveau_fence_channel_init(struct nouveau_channel *chan)
nouveau_gpuobj_ref(NULL, &obj); nouveau_gpuobj_ref(NULL, &obj);
if (ret) if (ret)
return ret; return ret;
ret = RING_SPACE(chan, 2);
if (ret)
return ret;
BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
OUT_RING(chan, NvSema);
} else {
ret = RING_SPACE(chan, 2);
if (ret)
return ret;
BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
OUT_RING (chan, chan->vram_handle); /* whole VM */
} }
FIRE_RING(chan);
out_initialised:
INIT_LIST_HEAD(&chan->fence.pending); INIT_LIST_HEAD(&chan->fence.pending);
spin_lock_init(&chan->fence.lock); spin_lock_init(&chan->fence.lock);
atomic_set(&chan->fence.last_sequence_irq, 0); atomic_set(&chan->fence.last_sequence_irq, 0);
......
...@@ -182,6 +182,11 @@ nouveau_perf_init(struct drm_device *dev) ...@@ -182,6 +182,11 @@ nouveau_perf_init(struct drm_device *dev)
entries = perf[2]; entries = perf[2];
} }
if (entries > NOUVEAU_PM_MAX_LEVEL) {
NV_DEBUG(dev, "perf table has too many entries - buggy vbios?\n");
entries = NOUVEAU_PM_MAX_LEVEL;
}
entry = perf + headerlen; entry = perf + headerlen;
for (i = 0; i < entries; i++) { for (i = 0; i < entries; i++) {
struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl]; struct nouveau_pm_level *perflvl = &pm->perflvl[pm->nr_perflvl];
......
...@@ -881,8 +881,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags) ...@@ -881,8 +881,8 @@ int nouveau_load(struct drm_device *dev, unsigned long flags)
#ifdef __BIG_ENDIAN #ifdef __BIG_ENDIAN
/* Put the card in BE mode if it's not */ /* Put the card in BE mode if it's not */
if (nv_rd32(dev, NV03_PMC_BOOT_1)) if (nv_rd32(dev, NV03_PMC_BOOT_1) != 0x01000001)
nv_wr32(dev, NV03_PMC_BOOT_1, 0x00000001); nv_wr32(dev, NV03_PMC_BOOT_1, 0x01000001);
DRM_MEMORYBARRIER(); DRM_MEMORYBARRIER();
#endif #endif
......
...@@ -409,7 +409,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -409,7 +409,7 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
struct nouveau_channel *evo = dispc->sync; struct nouveau_channel *evo = dispc->sync;
int ret; int ret;
ret = RING_SPACE(evo, 24); ret = RING_SPACE(evo, chan ? 25 : 27);
if (unlikely(ret)) if (unlikely(ret))
return ret; return ret;
...@@ -458,8 +458,19 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, ...@@ -458,8 +458,19 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
/* queue the flip on the crtc's "display sync" channel */ /* queue the flip on the crtc's "display sync" channel */
BEGIN_RING(evo, 0, 0x0100, 1); BEGIN_RING(evo, 0, 0x0100, 1);
OUT_RING (evo, 0xfffe0000); OUT_RING (evo, 0xfffe0000);
BEGIN_RING(evo, 0, 0x0084, 5); if (chan) {
OUT_RING (evo, chan ? 0x00000100 : 0x00000010); BEGIN_RING(evo, 0, 0x0084, 1);
OUT_RING (evo, 0x00000100);
} else {
BEGIN_RING(evo, 0, 0x0084, 1);
OUT_RING (evo, 0x00000010);
/* allows gamma somehow, PDISP will bitch at you if
* you don't wait for vblank before changing this..
*/
BEGIN_RING(evo, 0, 0x00e0, 1);
OUT_RING (evo, 0x40000000);
}
BEGIN_RING(evo, 0, 0x0088, 4);
OUT_RING (evo, dispc->sem.offset); OUT_RING (evo, dispc->sem.offset);
OUT_RING (evo, 0xf00d0000 | dispc->sem.value); OUT_RING (evo, 0xf00d0000 | dispc->sem.value);
OUT_RING (evo, 0x74b1e000); OUT_RING (evo, 0x74b1e000);
......
...@@ -140,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev) ...@@ -140,11 +140,17 @@ void evergreen_pm_misc(struct radeon_device *rdev)
struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
if (voltage->type == VOLTAGE_SW) { if (voltage->type == VOLTAGE_SW) {
/* 0xff01 is a flag rather then an actual voltage */
if (voltage->voltage == 0xff01)
return;
if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) { if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {
radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
rdev->pm.current_vddc = voltage->voltage; rdev->pm.current_vddc = voltage->voltage;
DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage); DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
} }
/* 0xff01 is a flag rather then an actual voltage */
if (voltage->vddci == 0xff01)
return;
if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) { if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {
radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI); radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);
rdev->pm.current_vddci = voltage->vddci; rdev->pm.current_vddci = voltage->vddci;
...@@ -2695,28 +2701,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev) ...@@ -2695,28 +2701,25 @@ static inline u32 evergreen_get_ih_wptr(struct radeon_device *rdev)
int evergreen_irq_process(struct radeon_device *rdev) int evergreen_irq_process(struct radeon_device *rdev)
{ {
u32 wptr = evergreen_get_ih_wptr(rdev); u32 wptr;
u32 rptr = rdev->ih.rptr; u32 rptr;
u32 src_id, src_data; u32 src_id, src_data;
u32 ring_index; u32 ring_index;
unsigned long flags; unsigned long flags;
bool queue_hotplug = false; bool queue_hotplug = false;
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); if (!rdev->ih.enabled || rdev->shutdown)
if (!rdev->ih.enabled)
return IRQ_NONE; return IRQ_NONE;
spin_lock_irqsave(&rdev->ih.lock, flags); wptr = evergreen_get_ih_wptr(rdev);
rptr = rdev->ih.rptr;
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
spin_lock_irqsave(&rdev->ih.lock, flags);
if (rptr == wptr) { if (rptr == wptr) {
spin_unlock_irqrestore(&rdev->ih.lock, flags); spin_unlock_irqrestore(&rdev->ih.lock, flags);
return IRQ_NONE; return IRQ_NONE;
} }
if (rdev->shutdown) {
spin_unlock_irqrestore(&rdev->ih.lock, flags);
return IRQ_NONE;
}
restart_ih: restart_ih:
/* display interrupts */ /* display interrupts */
evergreen_irq_ack(rdev); evergreen_irq_ack(rdev);
......
...@@ -590,6 +590,9 @@ void r600_pm_misc(struct radeon_device *rdev) ...@@ -590,6 +590,9 @@ void r600_pm_misc(struct radeon_device *rdev)
struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
/* 0xff01 is a flag rather then an actual voltage */
if (voltage->voltage == 0xff01)
return;
if (voltage->voltage != rdev->pm.current_vddc) { if (voltage->voltage != rdev->pm.current_vddc) {
radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
rdev->pm.current_vddc = voltage->voltage; rdev->pm.current_vddc = voltage->voltage;
...@@ -3294,27 +3297,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) ...@@ -3294,27 +3297,26 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
int r600_irq_process(struct radeon_device *rdev) int r600_irq_process(struct radeon_device *rdev)
{ {
u32 wptr = r600_get_ih_wptr(rdev); u32 wptr;
u32 rptr = rdev->ih.rptr; u32 rptr;
u32 src_id, src_data; u32 src_id, src_data;
u32 ring_index; u32 ring_index;
unsigned long flags; unsigned long flags;
bool queue_hotplug = false; bool queue_hotplug = false;
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); if (!rdev->ih.enabled || rdev->shutdown)
if (!rdev->ih.enabled)
return IRQ_NONE; return IRQ_NONE;
wptr = r600_get_ih_wptr(rdev);
rptr = rdev->ih.rptr;
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
spin_lock_irqsave(&rdev->ih.lock, flags); spin_lock_irqsave(&rdev->ih.lock, flags);
if (rptr == wptr) { if (rptr == wptr) {
spin_unlock_irqrestore(&rdev->ih.lock, flags); spin_unlock_irqrestore(&rdev->ih.lock, flags);
return IRQ_NONE; return IRQ_NONE;
} }
if (rdev->shutdown) {
spin_unlock_irqrestore(&rdev->ih.lock, flags);
return IRQ_NONE;
}
restart_ih: restart_ih:
/* display interrupts */ /* display interrupts */
......
...@@ -2607,6 +2607,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v ...@@ -2607,6 +2607,10 @@ void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 v
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
return; return;
/* 0xff01 is a flag rather then an actual voltage */
if (voltage_level == 0xff01)
return;
switch (crev) { switch (crev) {
case 1: case 1:
args.v1.ucVoltageType = voltage_type; args.v1.ucVoltageType = voltage_type;
......
...@@ -1090,9 +1090,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t ...@@ -1090,9 +1090,10 @@ atombios_dig_transmitter_setup(struct drm_encoder *encoder, int action, uint8_t
break; break;
} }
if (is_dp) if (is_dp) {
args.v2.acConfig.fCoherentMode = 1; args.v2.acConfig.fCoherentMode = 1;
else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { args.v2.acConfig.fDPConnector = 1;
} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
if (dig->coherent_mode) if (dig->coherent_mode)
args.v2.acConfig.fCoherentMode = 1; args.v2.acConfig.fCoherentMode = 1;
if (radeon_encoder->pixel_clock > 165000) if (radeon_encoder->pixel_clock > 165000)
...@@ -1431,6 +1432,10 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode) ...@@ -1431,6 +1432,10 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
if (is_dig) { if (is_dig) {
switch (mode) { switch (mode) {
case DRM_MODE_DPMS_ON: case DRM_MODE_DPMS_ON:
/* some early dce3.2 boards have a bug in their transmitter control table */
if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730))
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
else
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0); atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) { if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_DP) {
struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
......
...@@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev) ...@@ -105,6 +105,9 @@ void rv770_pm_misc(struct radeon_device *rdev)
struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
/* 0xff01 is a flag rather then an actual voltage */
if (voltage->voltage == 0xff01)
return;
if (voltage->voltage != rdev->pm.current_vddc) { if (voltage->voltage != rdev->pm.current_vddc) {
radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
rdev->pm.current_vddc = voltage->voltage; rdev->pm.current_vddc = voltage->voltage;
......
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