diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 245 |
1 files changed, 197 insertions, 48 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index c9e93eabcf16..824cc6480a06 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -65,6 +65,95 @@ MODULE_FIRMWARE(FIRMWARE_R520); * r100,rv100,rs100,rv200,rs200,r200,rv250,rs300,rv280 */ +/* hpd for digital panel detect/disconnect */ +bool r100_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) +{ + bool connected = false; + + switch (hpd) { + case RADEON_HPD_1: + if (RREG32(RADEON_FP_GEN_CNTL) & RADEON_FP_DETECT_SENSE) + connected = true; + break; + case RADEON_HPD_2: + if (RREG32(RADEON_FP2_GEN_CNTL) & RADEON_FP2_DETECT_SENSE) + connected = true; + break; + default: + break; + } + return connected; +} + +void r100_hpd_set_polarity(struct radeon_device *rdev, + enum radeon_hpd_id hpd) +{ + u32 tmp; + bool connected = r100_hpd_sense(rdev, hpd); + + switch (hpd) { + case RADEON_HPD_1: + tmp = RREG32(RADEON_FP_GEN_CNTL); + if (connected) + tmp &= ~RADEON_FP_DETECT_INT_POL; + else + tmp |= RADEON_FP_DETECT_INT_POL; + WREG32(RADEON_FP_GEN_CNTL, tmp); + break; + case RADEON_HPD_2: + tmp = RREG32(RADEON_FP2_GEN_CNTL); + if (connected) + tmp &= ~RADEON_FP2_DETECT_INT_POL; + else + tmp |= RADEON_FP2_DETECT_INT_POL; + WREG32(RADEON_FP2_GEN_CNTL, tmp); + break; + default: + break; + } +} + +void r100_hpd_init(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + rdev->irq.hpd[0] = true; + break; + case RADEON_HPD_2: + rdev->irq.hpd[1] = true; + break; + default: + break; + } + } + r100_irq_set(rdev); +} + +void r100_hpd_fini(struct radeon_device *rdev) +{ + struct drm_device *dev = rdev->ddev; + struct drm_connector *connector; + + list_for_each_entry(connector, &dev->mode_config.connector_list, head) { + struct radeon_connector *radeon_connector = to_radeon_connector(connector); + switch (radeon_connector->hpd.hpd) { + case RADEON_HPD_1: + rdev->irq.hpd[0] = false; + break; + case RADEON_HPD_2: + rdev->irq.hpd[1] = false; + break; + default: + break; + } + } +} + /* * PCI GART */ @@ -94,6 +183,15 @@ int r100_pci_gart_init(struct radeon_device *rdev) return radeon_gart_table_ram_alloc(rdev); } +/* required on r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ +void r100_enable_bm(struct radeon_device *rdev) +{ + uint32_t tmp; + /* Enable bus mastering */ + tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; + WREG32(RADEON_BUS_CNTL, tmp); +} + int r100_pci_gart_enable(struct radeon_device *rdev) { uint32_t tmp; @@ -105,9 +203,6 @@ int r100_pci_gart_enable(struct radeon_device *rdev) WREG32(RADEON_AIC_LO_ADDR, rdev->mc.gtt_location); tmp = rdev->mc.gtt_location + rdev->mc.gtt_size - 1; WREG32(RADEON_AIC_HI_ADDR, tmp); - /* Enable bus mastering */ - tmp = RREG32(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - WREG32(RADEON_BUS_CNTL, tmp); /* set PCI GART page-table base address */ WREG32(RADEON_AIC_PT_BASE, rdev->gart.table_addr); tmp = RREG32(RADEON_AIC_CNTL) | RADEON_PCIGART_TRANSLATE_EN; @@ -157,6 +252,12 @@ int r100_irq_set(struct radeon_device *rdev) if (rdev->irq.crtc_vblank_int[1]) { tmp |= RADEON_CRTC2_VBLANK_MASK; } + if (rdev->irq.hpd[0]) { + tmp |= RADEON_FP_DETECT_MASK; + } + if (rdev->irq.hpd[1]) { + tmp |= RADEON_FP2_DETECT_MASK; + } WREG32(RADEON_GEN_INT_CNTL, tmp); return 0; } @@ -175,8 +276,9 @@ void r100_irq_disable(struct radeon_device *rdev) static inline uint32_t r100_irq_ack(struct radeon_device *rdev) { uint32_t irqs = RREG32(RADEON_GEN_INT_STATUS); - uint32_t irq_mask = RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT | - RADEON_CRTC2_VBLANK_STAT; + uint32_t irq_mask = RADEON_SW_INT_TEST | + RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT | + RADEON_FP_DETECT_STAT | RADEON_FP2_DETECT_STAT; if (irqs) { WREG32(RADEON_GEN_INT_STATUS, irqs); @@ -187,6 +289,7 @@ static inline uint32_t r100_irq_ack(struct radeon_device *rdev) int r100_irq_process(struct radeon_device *rdev) { uint32_t status, msi_rearm; + bool queue_hotplug = false; status = r100_irq_ack(rdev); if (!status) { @@ -207,8 +310,18 @@ int r100_irq_process(struct radeon_device *rdev) if (status & RADEON_CRTC2_VBLANK_STAT) { drm_handle_vblank(rdev->ddev, 1); } + if (status & RADEON_FP_DETECT_STAT) { + queue_hotplug = true; + DRM_DEBUG("HPD1\n"); + } + if (status & RADEON_FP2_DETECT_STAT) { + queue_hotplug = true; + DRM_DEBUG("HPD2\n"); + } status = r100_irq_ack(rdev); } + if (queue_hotplug) + queue_work(rdev->wq, &rdev->hotplug_work); if (rdev->msi_enabled) { switch (rdev->family) { case CHIP_RS400: @@ -255,24 +368,27 @@ int r100_wb_init(struct radeon_device *rdev) int r; if (rdev->wb.wb_obj == NULL) { - r = radeon_object_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, - true, - RADEON_GEM_DOMAIN_GTT, - false, &rdev->wb.wb_obj); + r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, true, + RADEON_GEM_DOMAIN_GTT, + &rdev->wb.wb_obj); if (r) { - DRM_ERROR("radeon: failed to create WB buffer (%d).\n", r); + dev_err(rdev->dev, "(%d) create WB buffer failed\n", r); return r; } - r = radeon_object_pin(rdev->wb.wb_obj, - RADEON_GEM_DOMAIN_GTT, - &rdev->wb.gpu_addr); + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) + return r; + r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT, + &rdev->wb.gpu_addr); if (r) { - DRM_ERROR("radeon: failed to pin WB buffer (%d).\n", r); + dev_err(rdev->dev, "(%d) pin WB buffer failed\n", r); + radeon_bo_unreserve(rdev->wb.wb_obj); return r; } - r = radeon_object_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); + r = radeon_bo_kmap(rdev->wb.wb_obj, (void **)&rdev->wb.wb); + radeon_bo_unreserve(rdev->wb.wb_obj); if (r) { - DRM_ERROR("radeon: failed to map WB buffer (%d).\n", r); + dev_err(rdev->dev, "(%d) map WB buffer failed\n", r); return r; } } @@ -290,11 +406,19 @@ void r100_wb_disable(struct radeon_device *rdev) void r100_wb_fini(struct radeon_device *rdev) { + int r; + r100_wb_disable(rdev); if (rdev->wb.wb_obj) { - radeon_object_kunmap(rdev->wb.wb_obj); - radeon_object_unpin(rdev->wb.wb_obj); - radeon_object_unref(&rdev->wb.wb_obj); + r = radeon_bo_reserve(rdev->wb.wb_obj, false); + if (unlikely(r != 0)) { + dev_err(rdev->dev, "(%d) can't finish WB\n", r); + return; + } + radeon_bo_kunmap(rdev->wb.wb_obj); + radeon_bo_unpin(rdev->wb.wb_obj); + radeon_bo_unreserve(rdev->wb.wb_obj); + radeon_bo_unref(&rdev->wb.wb_obj); rdev->wb.wb = NULL; rdev->wb.wb_obj = NULL; } @@ -1288,17 +1412,17 @@ static int r100_packet0_check(struct radeon_cs_parser *p, int r100_cs_track_check_pkt3_indx_buffer(struct radeon_cs_parser *p, struct radeon_cs_packet *pkt, - struct radeon_object *robj) + struct radeon_bo *robj) { unsigned idx; u32 value; idx = pkt->idx + 1; value = radeon_get_ib_value(p, idx + 2); - if ((value + 1) > radeon_object_size(robj)) { + if ((value + 1) > radeon_bo_size(robj)) { DRM_ERROR("[drm] Buffer too small for PACKET3 INDX_BUFFER " "(need %u have %lu) !\n", value + 1, - radeon_object_size(robj)); + radeon_bo_size(robj)); return -EINVAL; } return 0; @@ -1583,6 +1707,14 @@ void r100_gpu_init(struct radeon_device *rdev) r100_hdp_reset(rdev); } +void r100_hdp_flush(struct radeon_device *rdev) +{ + u32 tmp; + tmp = RREG32(RADEON_HOST_PATH_CNTL); + tmp |= RADEON_HDP_READ_BUFFER_INVALIDATE; + WREG32(RADEON_HOST_PATH_CNTL, tmp); +} + void r100_hdp_reset(struct radeon_device *rdev) { uint32_t tmp; @@ -1650,6 +1782,17 @@ int r100_gpu_reset(struct radeon_device *rdev) return 0; } +void r100_set_common_regs(struct radeon_device *rdev) +{ + /* set these so they don't interfere with anything */ + WREG32(RADEON_OV0_SCALE_CNTL, 0); + WREG32(RADEON_SUBPIC_CNTL, 0); + WREG32(RADEON_VIPH_CONTROL, 0); + WREG32(RADEON_I2C_CNTL_1, 0); + WREG32(RADEON_DVI_I2C_CNTL_1, 0); + WREG32(RADEON_CAP0_TRIG_CNTL, 0); + WREG32(RADEON_CAP1_TRIG_CNTL, 0); +} /* * VRAM info @@ -2594,7 +2737,7 @@ static int r100_cs_track_cube(struct radeon_device *rdev, struct r100_cs_track *track, unsigned idx) { unsigned face, w, h; - struct radeon_object *cube_robj; + struct radeon_bo *cube_robj; unsigned long size; for (face = 0; face < 5; face++) { @@ -2607,9 +2750,9 @@ static int r100_cs_track_cube(struct radeon_device *rdev, size += track->textures[idx].cube_info[face].offset; - if (size > radeon_object_size(cube_robj)) { + if (size > radeon_bo_size(cube_robj)) { DRM_ERROR("Cube texture offset greater than object size %lu %lu\n", - size, radeon_object_size(cube_robj)); + size, radeon_bo_size(cube_robj)); r100_cs_track_texture_print(&track->textures[idx]); return -1; } @@ -2620,7 +2763,7 @@ static int r100_cs_track_cube(struct radeon_device *rdev, static int r100_cs_track_texture_check(struct radeon_device *rdev, struct r100_cs_track *track) { - struct radeon_object *robj; + struct radeon_bo *robj; unsigned long size; unsigned u, i, w, h; int ret; @@ -2676,9 +2819,9 @@ static int r100_cs_track_texture_check(struct radeon_device *rdev, "%u\n", track->textures[u].tex_coord_type, u); return -EINVAL; } - if (size > radeon_object_size(robj)) { + if (size > radeon_bo_size(robj)) { DRM_ERROR("Texture of unit %u needs %lu bytes but is " - "%lu\n", u, size, radeon_object_size(robj)); + "%lu\n", u, size, radeon_bo_size(robj)); r100_cs_track_texture_print(&track->textures[u]); return -EINVAL; } @@ -2700,10 +2843,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) } size = track->cb[i].pitch * track->cb[i].cpp * track->maxy; size += track->cb[i].offset; - if (size > radeon_object_size(track->cb[i].robj)) { + if (size > radeon_bo_size(track->cb[i].robj)) { DRM_ERROR("[drm] Buffer too small for color buffer %d " "(need %lu have %lu) !\n", i, size, - radeon_object_size(track->cb[i].robj)); + radeon_bo_size(track->cb[i].robj)); DRM_ERROR("[drm] color buffer %d (%u %u %u %u)\n", i, track->cb[i].pitch, track->cb[i].cpp, track->cb[i].offset, track->maxy); @@ -2717,10 +2860,10 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) } size = track->zb.pitch * track->zb.cpp * track->maxy; size += track->zb.offset; - if (size > radeon_object_size(track->zb.robj)) { + if (size > radeon_bo_size(track->zb.robj)) { DRM_ERROR("[drm] Buffer too small for z buffer " "(need %lu have %lu) !\n", size, - radeon_object_size(track->zb.robj)); + radeon_bo_size(track->zb.robj)); DRM_ERROR("[drm] zbuffer (%u %u %u %u)\n", track->zb.pitch, track->zb.cpp, track->zb.offset, track->maxy); @@ -2738,11 +2881,12 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) "bound\n", prim_walk, i); return -EINVAL; } - if (size > radeon_object_size(track->arrays[i].robj)) { - DRM_ERROR("(PW %u) Vertex array %u need %lu dwords " - "have %lu dwords\n", prim_walk, i, - size >> 2, - radeon_object_size(track->arrays[i].robj) >> 2); + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); DRM_ERROR("Max indices %u\n", track->max_indx); return -EINVAL; } @@ -2756,10 +2900,12 @@ int r100_cs_track_check(struct radeon_device *rdev, struct r100_cs_track *track) "bound\n", prim_walk, i); return -EINVAL; } - if (size > radeon_object_size(track->arrays[i].robj)) { - DRM_ERROR("(PW %u) Vertex array %u need %lu dwords " - "have %lu dwords\n", prim_walk, i, size >> 2, - radeon_object_size(track->arrays[i].robj) >> 2); + if (size > radeon_bo_size(track->arrays[i].robj)) { + dev_err(rdev->dev, "(PW %u) Vertex array %u " + "need %lu dwords have %lu dwords\n", + prim_walk, i, size >> 2, + radeon_bo_size(track->arrays[i].robj) + >> 2); return -EINVAL; } } @@ -3101,6 +3247,9 @@ static int r100_startup(struct radeon_device *rdev) { int r; + /* set common regs */ + r100_set_common_regs(rdev); + /* program mc */ r100_mc_program(rdev); /* Resume clock */ r100_clock_startup(rdev); @@ -3108,13 +3257,13 @@ static int r100_startup(struct radeon_device *rdev) r100_gpu_init(rdev); /* Initialize GART (initialize after TTM so we can allocate * memory through TTM but finalize after TTM) */ + r100_enable_bm(rdev); if (rdev->flags & RADEON_IS_PCI) { r = r100_pci_gart_enable(rdev); if (r) return r; } /* Enable IRQ */ - rdev->irq.sw_int = true; r100_irq_set(rdev); /* 1M ring buffer */ r = r100_cp_init(rdev, 1024 * 1024); @@ -3150,6 +3299,8 @@ int r100_resume(struct radeon_device *rdev) radeon_combios_asic_init(rdev->ddev); /* Resume clock after posting */ r100_clock_startup(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); return r100_startup(rdev); } @@ -3174,7 +3325,7 @@ void r100_fini(struct radeon_device *rdev) r100_pci_gart_fini(rdev); radeon_irq_kms_fini(rdev); radeon_fence_driver_fini(rdev); - radeon_object_fini(rdev); + radeon_bo_fini(rdev); radeon_atombios_fini(rdev); kfree(rdev->bios); rdev->bios = NULL; @@ -3242,10 +3393,8 @@ int r100_init(struct radeon_device *rdev) RREG32(R_0007C0_CP_STAT)); } /* check if cards are posted or not */ - if (!radeon_card_posted(rdev) && rdev->bios) { - DRM_INFO("GPU not posted. posting now...\n"); - radeon_combios_asic_init(rdev->ddev); - } + if (radeon_boot_test_post_card(rdev) == false) + return -EINVAL; /* Set asic errata */ r100_errata(rdev); /* Initialize clocks */ @@ -3264,7 +3413,7 @@ int r100_init(struct radeon_device *rdev) if (r) return r; /* Memory manager */ - r = radeon_object_init(rdev); + r = radeon_bo_init(rdev); if (r) return r; if (rdev->flags & RADEON_IS_PCI) { |