Commit 3f838fc5 authored by Dave Airlie's avatar Dave Airlie

Merge remote branch 'korg/drm-radeon-next' into drm-linus

This merges all the radeon changes that weren't reliant on core-next.
parents 3ff99164 22dd5013
......@@ -241,6 +241,7 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
switch (mode) {
case DRM_MODE_DPMS_ON:
......@@ -248,20 +249,19 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
if (ASIC_IS_DCE3(rdev))
atombios_enable_crtc_memreq(crtc, 1);
atombios_blank_crtc(crtc, 0);
drm_vblank_post_modeset(dev, radeon_crtc->crtc_id);
radeon_crtc_load_lut(crtc);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
atombios_blank_crtc(crtc, 1);
if (ASIC_IS_DCE3(rdev))
atombios_enable_crtc_memreq(crtc, 0);
atombios_enable_crtc(crtc, 0);
break;
}
if (mode != DRM_MODE_DPMS_OFF) {
radeon_crtc_load_lut(crtc);
}
}
static void
......@@ -457,9 +457,8 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
if (encoder->encoder_type !=
DRM_MODE_ENCODER_DAC)
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
if (!ASIC_IS_AVIVO(rdev)
&& (encoder->encoder_type ==
DRM_MODE_ENCODER_LVDS))
if (encoder->encoder_type ==
DRM_MODE_ENCODER_LVDS)
pll_flags |= RADEON_PLL_USE_REF_DIV;
}
radeon_encoder = to_radeon_encoder(encoder);
......@@ -574,21 +573,34 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
struct radeon_device *rdev = dev->dev_private;
struct radeon_framebuffer *radeon_fb;
struct drm_gem_object *obj;
struct drm_radeon_gem_object *obj_priv;
struct radeon_bo *rbo;
uint64_t fb_location;
uint32_t fb_format, fb_pitch_pixels, tiling_flags;
int r;
if (!crtc->fb)
return -EINVAL;
/* no fb bound */
if (!crtc->fb) {
DRM_DEBUG("No FB bound\n");
return 0;
}
radeon_fb = to_radeon_framebuffer(crtc->fb);
/* Pin framebuffer & get tilling informations */
obj = radeon_fb->obj;
obj_priv = obj->driver_private;
if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &fb_location)) {
rbo = obj->driver_private;
r = radeon_bo_reserve(rbo, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_location);
if (unlikely(r != 0)) {
radeon_bo_unreserve(rbo);
return -EINVAL;
}
radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
radeon_bo_unreserve(rbo);
if (tiling_flags & RADEON_TILING_MACRO)
fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
switch (crtc->fb->bits_per_pixel) {
case 8:
......@@ -618,11 +630,6 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
return -EINVAL;
}
radeon_object_get_tiling_flags(obj->driver_private,
&tiling_flags, NULL);
if (tiling_flags & RADEON_TILING_MACRO)
fb_format |= AVIVO_D1GRPH_MACRO_ADDRESS_MODE;
if (tiling_flags & RADEON_TILING_MICRO)
fb_format |= AVIVO_D1GRPH_TILED;
......@@ -674,7 +681,12 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y,
if (old_fb && old_fb != crtc->fb) {
radeon_fb = to_radeon_framebuffer(old_fb);
radeon_gem_object_unpin(radeon_fb->obj);
rbo = radeon_fb->obj->driver_private;
r = radeon_bo_reserve(rbo, false);
if (unlikely(r != 0))
return r;
radeon_bo_unpin(rbo);
radeon_bo_unreserve(rbo);
}
/* Bytes per pixel may have changed */
......
......@@ -94,6 +94,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 +114,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;
......@@ -255,24 +261,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 +299,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 +1305,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 +1600,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 +1675,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 +2630,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 +2643,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 +2656,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 +2712,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 +2736,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 +2753,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 +2774,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 +2793,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 +3140,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 +3150,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);
......@@ -3174,7 +3216,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 +3284,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 +3304,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) {
......
......@@ -10,26 +10,26 @@
* CS functions
*/
struct r100_cs_track_cb {
struct radeon_object *robj;
struct radeon_bo *robj;
unsigned pitch;
unsigned cpp;
unsigned offset;
};
struct r100_cs_track_array {
struct radeon_object *robj;
struct radeon_bo *robj;
unsigned esize;
};
struct r100_cs_cube_info {
struct radeon_object *robj;
unsigned offset;
struct radeon_bo *robj;
unsigned offset;
unsigned width;
unsigned height;
};
struct r100_cs_track_texture {
struct radeon_object *robj;
struct radeon_bo *robj;
struct r100_cs_cube_info cube_info[5]; /* info for 5 non-primary faces */
unsigned pitch;
unsigned width;
......
......@@ -137,14 +137,19 @@ int rv370_pcie_gart_enable(struct radeon_device *rdev)
void rv370_pcie_gart_disable(struct radeon_device *rdev)
{
uint32_t tmp;
u32 tmp;
int r;
tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
if (rdev->gart.table.vram.robj) {
radeon_object_kunmap(rdev->gart.table.vram.robj);
radeon_object_unpin(rdev->gart.table.vram.robj);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
}
......@@ -1181,6 +1186,9 @@ static int r300_startup(struct radeon_device *rdev)
{
int r;
/* set common regs */
r100_set_common_regs(rdev);
/* program mc */
r300_mc_program(rdev);
/* Resume clock */
r300_clock_startup(rdev);
......@@ -1193,13 +1201,18 @@ static int r300_startup(struct radeon_device *rdev)
if (r)
return r;
}
if (rdev->family == CHIP_R300 ||
rdev->family == CHIP_R350 ||
rdev->family == CHIP_RV350)
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);
......@@ -1265,7 +1278,7 @@ void r300_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;
......@@ -1303,10 +1316,8 @@ int r300_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 */
r300_errata(rdev);
/* Initialize clocks */
......@@ -1325,7 +1336,7 @@ int r300_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_PCIE) {
......
......@@ -169,6 +169,9 @@ static int r420_startup(struct radeon_device *rdev)
{
int r;
/* set common regs */
r100_set_common_regs(rdev);
/* program mc */
r300_mc_program(rdev);
/* Resume clock */
r420_clock_resume(rdev);
......@@ -186,7 +189,6 @@ static int r420_startup(struct radeon_device *rdev)
}
r420_pipes_init(rdev);
/* Enable IRQ */
rdev->irq.sw_int = true;
r100_irq_set(rdev);
/* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024);
......@@ -258,7 +260,7 @@ void r420_fini(struct radeon_device *rdev)
radeon_agp_fini(rdev);
radeon_irq_kms_fini(rdev);
radeon_fence_driver_fini(rdev);
radeon_object_fini(rdev);
radeon_bo_fini(rdev);
if (rdev->is_atom_bios) {
radeon_atombios_fini(rdev);
} else {
......@@ -301,14 +303,9 @@ int r420_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");
if (rdev->is_atom_bios) {
atom_asic_init(rdev->mode_info.atom_context);
} else {
radeon_combios_asic_init(rdev->ddev);
}
}
if (radeon_boot_test_post_card(rdev) == false)
return -EINVAL;
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
......@@ -331,10 +328,13 @@ int r420_init(struct radeon_device *rdev)
return r;
}
/* Memory manager */
r = radeon_object_init(rdev);
r = radeon_bo_init(rdev);
if (r) {
return r;
}
if (rdev->family == CHIP_R420)
r100_enable_bm(rdev);
if (rdev->flags & RADEON_IS_PCIE) {
r = rv370_pcie_gart_init(rdev);
if (r)
......
......@@ -185,7 +185,6 @@ static int r520_startup(struct radeon_device *rdev)
return r;
}
/* Enable IRQ */
rdev->irq.sw_int = true;
rs600_irq_set(rdev);
/* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024);
......@@ -254,6 +253,9 @@ int r520_init(struct radeon_device *rdev)
RREG32(R_0007C0_CP_STAT));
}
/* check if cards are posted or not */
if (radeon_boot_test_post_card(rdev) == false)
return -EINVAL;
if (!radeon_card_posted(rdev) && rdev->bios) {
DRM_INFO("GPU not posted. posting now...\n");
atom_asic_init(rdev->mode_info.atom_context);
......@@ -277,7 +279,7 @@ int r520_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;
r = rv370_pcie_gart_init(rdev);
......
......@@ -38,8 +38,10 @@
#define PFP_UCODE_SIZE 576
#define PM4_UCODE_SIZE 1792
#define RLC_UCODE_SIZE 768
#define R700_PFP_UCODE_SIZE 848
#define R700_PM4_UCODE_SIZE 1360
#define R700_RLC_UCODE_SIZE 1024
/* Firmware Names */
MODULE_FIRMWARE("radeon/R600_pfp.bin");
......@@ -62,6 +64,8 @@ MODULE_FIRMWARE("radeon/RV730_pfp.bin");
MODULE_FIRMWARE("radeon/RV730_me.bin");
MODULE_FIRMWARE("radeon/RV710_pfp.bin");
MODULE_FIRMWARE("radeon/RV710_me.bin");
MODULE_FIRMWARE("radeon/R600_rlc.bin");
MODULE_FIRMWARE("radeon/R700_rlc.bin");
int r600_debugfs_mc_info_init(struct radeon_device *rdev);
......@@ -180,7 +184,7 @@ int r600_pcie_gart_enable(struct radeon_device *rdev)
void r600_pcie_gart_disable(struct radeon_device *rdev)
{
u32 tmp;
int i;
int i, r;
/* Disable all tables */
for (i = 0; i < 7; i++)
......@@ -208,8 +212,12 @@ void r600_pcie_gart_disable(struct radeon_device *rdev)
WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp);
WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp);
if (rdev->gart.table.vram.robj) {
radeon_object_kunmap(rdev->gart.table.vram.robj);
radeon_object_unpin(rdev->gart.table.vram.robj);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
}
......@@ -1101,6 +1109,10 @@ void r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v)
(void)RREG32(PCIE_PORT_DATA);
}
void r600_hdp_flush(struct radeon_device *rdev)
{
WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
}
/*
* CP & Ring
......@@ -1110,11 +1122,12 @@ void r600_cp_stop(struct radeon_device *rdev)
WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1));
}
int r600_cp_init_microcode(struct radeon_device *rdev)
int r600_init_microcode(struct radeon_device *rdev)
{
struct platform_device *pdev;
const char *chip_name;
size_t pfp_req_size, me_req_size;
const char *rlc_chip_name;
size_t pfp_req_size, me_req_size, rlc_req_size;
char fw_name[30];
int err;
......@@ -1128,30 +1141,62 @@ int r600_cp_init_microcode(struct radeon_device *rdev)
}
switch (rdev->family) {
case CHIP_R600: chip_name = "R600"; break;
case CHIP_RV610: chip_name = "RV610"; break;
case CHIP_RV630: chip_name = "RV630"; break;
case CHIP_RV620: chip_name = "RV620"; break;
case CHIP_RV635: chip_name = "RV635"; break;
case CHIP_RV670: chip_name = "RV670"; break;
case CHIP_R600:
chip_name = "R600";
rlc_chip_name = "R600";
break;
case CHIP_RV610:
chip_name = "RV610";
rlc_chip_name = "R600";
break;
case CHIP_RV630:
chip_name = "RV630";
rlc_chip_name = "R600";
break;
case CHIP_RV620:
chip_name = "RV620";
rlc_chip_name = "R600";
break;
case CHIP_RV635:
chip_name = "RV635";
rlc_chip_name = "R600";
break;
case CHIP_RV670:
chip_name = "RV670";
rlc_chip_name = "R600";
break;
case CHIP_RS780:
case CHIP_RS880: chip_name = "RS780"; break;
case CHIP_RV770: chip_name = "RV770"; break;
case CHIP_RS880:
chip_name = "RS780";
rlc_chip_name = "R600";
break;
case CHIP_RV770:
chip_name = "RV770";
rlc_chip_name = "R700";
break;
case CHIP_RV730:
case CHIP_RV740: chip_name = "RV730"; break;
case CHIP_RV710: chip_name = "RV710"; break;
case CHIP_RV740:
chip_name = "RV730";
rlc_chip_name = "R700";
break;
case CHIP_RV710:
chip_name = "RV710";
rlc_chip_name = "R700";
break;
default: BUG();
}
if (rdev->family >= CHIP_RV770) {
pfp_req_size = R700_PFP_UCODE_SIZE * 4;
me_req_size = R700_PM4_UCODE_SIZE * 4;
rlc_req_size = R700_RLC_UCODE_SIZE * 4;
} else {
pfp_req_size = PFP_UCODE_SIZE * 4;
me_req_size = PM4_UCODE_SIZE * 12;
rlc_req_size = RLC_UCODE_SIZE * 4;
}
DRM_INFO("Loading %s CP Microcode\n", chip_name);
DRM_INFO("Loading %s Microcode\n", chip_name);
snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev);
......@@ -1175,6 +1220,18 @@ int r600_cp_init_microcode(struct radeon_device *rdev)
rdev->me_fw->size, fw_name);
err = -EINVAL;
}
snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name);
err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev);
if (err)
goto out;
if (rdev->rlc_fw->size != rlc_req_size) {
printk(KERN_ERR
"r600_rlc: Bogus length %zu in firmware \"%s\"\n",
rdev->rlc_fw->size, fw_name);
err = -EINVAL;
}
out:
platform_device_unregister(pdev);
......@@ -1187,6 +1244,8 @@ int r600_cp_init_microcode(struct radeon_device *rdev)
rdev->pfp_fw = NULL;
release_firmware(rdev->me_fw);
rdev->me_fw = NULL;
release_firmware(rdev->rlc_fw);
rdev->rlc_fw = NULL;
}
return err;
}
......@@ -1381,10 +1440,16 @@ int r600_ring_test(struct radeon_device *rdev)
void r600_wb_disable(struct radeon_device *rdev)
{
int r;
WREG32(SCRATCH_UMSK, 0);
if (rdev->wb.wb_obj) {
radeon_object_kunmap(rdev->wb.wb_obj);
radeon_object_unpin(rdev->wb.wb_obj);
r = radeon_bo_reserve(rdev->wb.wb_obj, false);
if (unlikely(r != 0))
return;
radeon_bo_kunmap(rdev->wb.wb_obj);
radeon_bo_unpin(rdev->wb.wb_obj);
radeon_bo_unreserve(rdev->wb.wb_obj);
}
}
......@@ -1392,7 +1457,7 @@ void r600_wb_fini(struct radeon_device *rdev)
{
r600_wb_disable(rdev);
if (rdev->wb.wb_obj) {
radeon_object_unref(&rdev->wb.wb_obj);
radeon_bo_unref(&rdev->wb.wb_obj);
rdev->wb.wb = NULL;
rdev->wb.wb_obj = NULL;
}
......@@ -1403,22 +1468,29 @@ int r600_wb_enable(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) {
dev_warn(rdev->dev, "failed to create WB buffer (%d).\n", r);
dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
return r;
}
r = radeon_bo_reserve(rdev->wb.wb_obj, false);
if (unlikely(r != 0)) {
r600_wb_fini(rdev);
return r;
}
r = radeon_object_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
r = radeon_bo_pin(rdev->wb.wb_obj, RADEON_GEM_DOMAIN_GTT,
&rdev->wb.gpu_addr);
if (r) {
dev_warn(rdev->dev, "failed to pin WB buffer (%d).\n", r);
radeon_bo_unreserve(rdev->wb.wb_obj);
dev_warn(rdev->dev, "(%d) pin WB bo failed\n", r);
r600_wb_fini(rdev);
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) {
dev_warn(rdev->dev, "failed to map WB buffer (%d).\n", r);
dev_warn(rdev->dev, "(%d) map WB bo failed\n", r);
r600_wb_fini(rdev);
return r;
}
......@@ -1433,10 +1505,14 @@ int r600_wb_enable(struct radeon_device *rdev)
void r600_fence_ring_emit(struct radeon_device *rdev,
struct radeon_fence *fence)
{
/* Also consider EVENT_WRITE_EOP. it handles the interrupts + timestamps + events */
/* Emit fence sequence & fire IRQ */
radeon_ring_write(rdev, PACKET3(PACKET3_SET_CONFIG_REG, 1));
radeon_ring_write(rdev, ((rdev->fence_drv.scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2));
radeon_ring_write(rdev, fence->seq);
/* CP_INTERRUPT packet 3 no longer exists, use packet 0 */
radeon_ring_write(rdev, PACKET0(CP_INT_STATUS, 0));
radeon_ring_write(rdev, RB_INT_STAT);
}
int r600_copy_dma(struct radeon_device *rdev,
......@@ -1459,18 +1535,6 @@ int r600_copy_blit(struct radeon_device *rdev,
return 0;
}
int r600_irq_process(struct radeon_device *rdev)
{
/* FIXME: implement */
return 0;
}
int r600_irq_set(struct radeon_device *rdev)
{
/* FIXME: implement */
return 0;
}
int r600_set_surface_reg(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size)
......@@ -1516,12 +1580,25 @@ int r600_startup(struct radeon_device *rdev)
}
r600_gpu_init(rdev);
r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->r600_blit.shader_gpu_addr);
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->r600_blit.shader_gpu_addr);
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
if (r) {
dev_err(rdev->dev, "(%d) pin blit object failed\n", r);
return r;
}
/* Enable IRQ */
r = r600_irq_init(rdev);
if (r) {
DRM_ERROR("failed to pin blit object %d\n", r);
DRM_ERROR("radeon: IH init failed (%d).\n", r);
radeon_irq_kms_fini(rdev);
return r;
}
r600_irq_set(rdev);
r = radeon_ring_init(rdev, rdev->cp.ring_size);
if (r)
......@@ -1583,13 +1660,19 @@ int r600_resume(struct radeon_device *rdev)
int r600_suspend(struct radeon_device *rdev)
{
int r;
/* FIXME: we should wait for ring to be empty */
r600_cp_stop(rdev);
rdev->cp.ready = false;
r600_wb_disable(rdev);
r600_pcie_gart_disable(rdev);
/* unpin shaders bo */
radeon_object_unpin(rdev->r600_blit.shader_obj);
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
if (unlikely(r != 0))
return r;
radeon_bo_unpin(rdev->r600_blit.shader_obj);
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
return 0;
}
......@@ -1627,7 +1710,11 @@ int r600_init(struct radeon_device *rdev)
if (r)
return r;
/* Post card if necessary */
if (!r600_card_posted(rdev) && rdev->bios) {
if (!r600_card_posted(rdev)) {
if (!rdev->bios) {
dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
return -EINVAL;
}
DRM_INFO("GPU not posted. posting now...\n");
atom_asic_init(rdev->mode_info.atom_context);
}
......@@ -1650,14 +1737,22 @@ int r600_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;
r = radeon_irq_kms_init(rdev);
if (r)
return r;
rdev->cp.ring_obj = NULL;
r600_ring_init(rdev, 1024 * 1024);
if (!rdev->me_fw || !rdev->pfp_fw) {
r = r600_cp_init_microcode(rdev);
rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024);
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
r = r600_init_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load firmware!\n");
return r;
......@@ -1704,6 +1799,8 @@ void r600_fini(struct radeon_device *rdev)
r600_suspend(rdev);
r600_blit_fini(rdev);
r600_irq_fini(rdev);
radeon_irq_kms_fini(rdev);
radeon_ring_fini(rdev);
r600_wb_fini(rdev);
r600_pcie_gart_fini(rdev);
......@@ -1712,7 +1809,7 @@ void r600_fini(struct radeon_device *rdev)
radeon_clocks_fini(rdev);
if (rdev->flags & RADEON_IS_AGP)
radeon_agp_fini(rdev);
radeon_object_fini(rdev);
radeon_bo_fini(rdev);
radeon_atombios_fini(rdev);
kfree(rdev->bios);
rdev->bios = NULL;
......@@ -1798,8 +1895,461 @@ int r600_ib_test(struct radeon_device *rdev)
return r;
}
/*
* Interrupts
*
* Interrupts use a ring buffer on r6xx/r7xx hardware. It works pretty
* the same as the CP ring buffer, but in reverse. Rather than the CPU
* writing to the ring and the GPU consuming, the GPU writes to the ring
* and host consumes. As the host irq handler processes interrupts, it
* increments the rptr. When the rptr catches up with the wptr, all the
* current interrupts have been processed.
*/
void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size)
{
u32 rb_bufsz;
/* Align ring size */
rb_bufsz = drm_order(ring_size / 4);
ring_size = (1 << rb_bufsz) * 4;
rdev->ih.ring_size = ring_size;
rdev->ih.align_mask = 4 - 1;
}
static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size)
{
int r;
rdev->ih.ring_size = ring_size;
/* Allocate ring buffer */
if (rdev->ih.ring_obj == NULL) {
r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
true,
RADEON_GEM_DOMAIN_GTT,
&rdev->ih.ring_obj);
if (r) {
DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r);
return r;
}
r = radeon_bo_reserve(rdev->ih.ring_obj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rdev->ih.ring_obj,
RADEON_GEM_DOMAIN_GTT,
&rdev->ih.gpu_addr);
if (r) {
radeon_bo_unreserve(rdev->ih.ring_obj);
DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r);
return r;
}
r = radeon_bo_kmap(rdev->ih.ring_obj,
(void **)&rdev->ih.ring);
radeon_bo_unreserve(rdev->ih.ring_obj);
if (r) {
DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r);
return r;
}
}
rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1;
rdev->ih.rptr = 0;
return 0;
}
static void r600_ih_ring_fini(struct radeon_device *rdev)
{
int r;
if (rdev->ih.ring_obj) {
r = radeon_bo_reserve(rdev->ih.ring_obj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->ih.ring_obj);
radeon_bo_unpin(rdev->ih.ring_obj);
radeon_bo_unreserve(rdev->ih.ring_obj);
}
radeon_bo_unref(&rdev->ih.ring_obj);
rdev->ih.ring = NULL;
rdev->ih.ring_obj = NULL;
}
}
static void r600_rlc_stop(struct radeon_device *rdev)
{
if (rdev->family >= CHIP_RV770) {
/* r7xx asics need to soft reset RLC before halting */
WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC);
RREG32(SRBM_SOFT_RESET);
udelay(15000);
WREG32(SRBM_SOFT_RESET, 0);
RREG32(SRBM_SOFT_RESET);
}
WREG32(RLC_CNTL, 0);
}
static void r600_rlc_start(struct radeon_device *rdev)
{
WREG32(RLC_CNTL, RLC_ENABLE);
}
static int r600_rlc_init(struct radeon_device *rdev)
{
u32 i;
const __be32 *fw_data;
if (!rdev->rlc_fw)
return -EINVAL;
r600_rlc_stop(rdev);
WREG32(RLC_HB_BASE, 0);
WREG32(RLC_HB_CNTL, 0);
WREG32(RLC_HB_RPTR, 0);
WREG32(RLC_HB_WPTR, 0);
WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
WREG32(RLC_MC_CNTL, 0);
WREG32(RLC_UCODE_CNTL, 0);
fw_data = (const __be32 *)rdev->rlc_fw->data;
if (rdev->family >= CHIP_RV770) {
for (i = 0; i < R700_RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
} else {
for (i = 0; i < RLC_UCODE_SIZE; i++) {
WREG32(RLC_UCODE_ADDR, i);
WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
}
}
WREG32(RLC_UCODE_ADDR, 0);
r600_rlc_start(rdev);
return 0;
}
static void r600_enable_interrupts(struct radeon_device *rdev)
{
u32 ih_cntl = RREG32(IH_CNTL);
u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
ih_cntl |= ENABLE_INTR;
ih_rb_cntl |= IH_RB_ENABLE;
WREG32(IH_CNTL, ih_cntl);
WREG32(IH_RB_CNTL, ih_rb_cntl);
rdev->ih.enabled = true;
}
static void r600_disable_interrupts(struct radeon_device *rdev)
{
u32 ih_rb_cntl = RREG32(IH_RB_CNTL);
u32 ih_cntl = RREG32(IH_CNTL);
ih_rb_cntl &= ~IH_RB_ENABLE;
ih_cntl &= ~ENABLE_INTR;
WREG32(IH_RB_CNTL, ih_rb_cntl);
WREG32(IH_CNTL, ih_cntl);
/* set rptr, wptr to 0 */
WREG32(IH_RB_RPTR, 0);
WREG32(IH_RB_WPTR, 0);
rdev->ih.enabled = false;
rdev->ih.wptr = 0;
rdev->ih.rptr = 0;
}
int r600_irq_init(struct radeon_device *rdev)
{
int ret = 0;
int rb_bufsz;
u32 interrupt_cntl, ih_cntl, ih_rb_cntl;
/* allocate ring */
ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size);
if (ret)
return ret;
/* disable irqs */
r600_disable_interrupts(rdev);
/* init rlc */
ret = r600_rlc_init(rdev);
if (ret) {
r600_ih_ring_fini(rdev);
return ret;
}
/* setup interrupt control */
/* set dummy read address to ring address */
WREG32(INTERRUPT_CNTL2, rdev->ih.gpu_addr >> 8);
interrupt_cntl = RREG32(INTERRUPT_CNTL);
/* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi
* IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN
*/
interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE;
/* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */
interrupt_cntl &= ~IH_REQ_NONSNOOP_EN;
WREG32(INTERRUPT_CNTL, interrupt_cntl);
WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8);
rb_bufsz = drm_order(rdev->ih.ring_size / 4);
ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE |
IH_WPTR_OVERFLOW_CLEAR |
(rb_bufsz << 1));
/* WPTR writeback, not yet */
/*ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE;*/
WREG32(IH_RB_WPTR_ADDR_LO, 0);
WREG32(IH_RB_WPTR_ADDR_HI, 0);
WREG32(IH_RB_CNTL, ih_rb_cntl);
/* set rptr, wptr to 0 */
WREG32(IH_RB_RPTR, 0);
WREG32(IH_RB_WPTR, 0);
/* Default settings for IH_CNTL (disabled at first) */
ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10);
/* RPTR_REARM only works if msi's are enabled */
if (rdev->msi_enabled)
ih_cntl |= RPTR_REARM;
#ifdef __BIG_ENDIAN
ih_cntl |= IH_MC_SWAP(IH_MC_SWAP_32BIT);
#endif
WREG32(IH_CNTL, ih_cntl);
/* force the active interrupt state to all disabled */
WREG32(CP_INT_CNTL, 0);
WREG32(GRBM_INT_CNTL, 0);
WREG32(DxMODE_INT_MASK, 0);
/* enable irqs */
r600_enable_interrupts(rdev);
return ret;
}
void r600_irq_fini(struct radeon_device *rdev)
{
r600_disable_interrupts(rdev);
r600_rlc_stop(rdev);
r600_ih_ring_fini(rdev);
}
int r600_irq_set(struct radeon_device *rdev)
{
uint32_t cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE;
uint32_t mode_int = 0;
/* don't enable anything if the ih is disabled */
if (!rdev->ih.enabled)
return 0;
if (rdev->irq.sw_int) {
DRM_DEBUG("r600_irq_set: sw int\n");
cp_int_cntl |= RB_INT_ENABLE;
}
if (rdev->irq.crtc_vblank_int[0]) {
DRM_DEBUG("r600_irq_set: vblank 0\n");
mode_int |= D1MODE_VBLANK_INT_MASK;
}
if (rdev->irq.crtc_vblank_int[1]) {
DRM_DEBUG("r600_irq_set: vblank 1\n");
mode_int |= D2MODE_VBLANK_INT_MASK;
}
WREG32(CP_INT_CNTL, cp_int_cntl);
WREG32(DxMODE_INT_MASK, mode_int);
return 0;
}
static inline void r600_irq_ack(struct radeon_device *rdev, u32 disp_int)
{
if (disp_int & LB_D1_VBLANK_INTERRUPT)
WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
if (disp_int & LB_D1_VLINE_INTERRUPT)
WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
if (disp_int & LB_D2_VBLANK_INTERRUPT)
WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK);
if (disp_int & LB_D2_VLINE_INTERRUPT)
WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK);
}
void r600_irq_disable(struct radeon_device *rdev)
{
u32 disp_int;
r600_disable_interrupts(rdev);
/* Wait and acknowledge irq */
mdelay(1);
if (ASIC_IS_DCE3(rdev))
disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
else
disp_int = RREG32(DISP_INTERRUPT_STATUS);
r600_irq_ack(rdev, disp_int);
}
static inline u32 r600_get_ih_wptr(struct radeon_device *rdev)
{
u32 wptr, tmp;
/* XXX use writeback */
wptr = RREG32(IH_RB_WPTR);
if (wptr & RB_OVERFLOW) {
WARN_ON(1);
/* XXX deal with overflow */
DRM_ERROR("IH RB overflow\n");
tmp = RREG32(IH_RB_CNTL);
tmp |= IH_WPTR_OVERFLOW_CLEAR;
WREG32(IH_RB_CNTL, tmp);
}
wptr = wptr & WPTR_OFFSET_MASK;
return wptr;
}
/* r600 IV Ring
* Each IV ring entry is 128 bits:
* [7:0] - interrupt source id
* [31:8] - reserved
* [59:32] - interrupt source data
* [127:60] - reserved
*
* The basic interrupt vector entries
* are decoded as follows:
* src_id src_data description
* 1 0 D1 Vblank
* 1 1 D1 Vline
* 5 0 D2 Vblank
* 5 1 D2 Vline
* 19 0 FP Hot plug detection A
* 19 1 FP Hot plug detection B
* 19 2 DAC A auto-detection
* 19 3 DAC B auto-detection
* 176 - CP_INT RB
* 177 - CP_INT IB1
* 178 - CP_INT IB2
* 181 - EOP Interrupt
* 233 - GUI Idle
*
* Note, these are based on r600 and may need to be
* adjusted or added to on newer asics
*/
int r600_irq_process(struct radeon_device *rdev)
{
u32 wptr = r600_get_ih_wptr(rdev);
u32 rptr = rdev->ih.rptr;
u32 src_id, src_data;
u32 last_entry = rdev->ih.ring_size - 16;
u32 ring_index, disp_int;
unsigned long flags;
DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr);
spin_lock_irqsave(&rdev->ih.lock, flags);
if (rptr == wptr) {
spin_unlock_irqrestore(&rdev->ih.lock, flags);
return IRQ_NONE;
}
if (rdev->shutdown) {
spin_unlock_irqrestore(&rdev->ih.lock, flags);
return IRQ_NONE;
}
restart_ih:
/* display interrupts */
if (ASIC_IS_DCE3(rdev))
disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS);
else
disp_int = RREG32(DISP_INTERRUPT_STATUS);
r600_irq_ack(rdev, disp_int);
rdev->ih.wptr = wptr;
while (rptr != wptr) {
/* wptr/rptr are in bytes! */
ring_index = rptr / 4;
src_id = rdev->ih.ring[ring_index] & 0xff;
src_data = rdev->ih.ring[ring_index + 1] & 0xfffffff;
switch (src_id) {
case 1: /* D1 vblank/vline */
switch (src_data) {
case 0: /* D1 vblank */
if (disp_int & LB_D1_VBLANK_INTERRUPT) {
drm_handle_vblank(rdev->ddev, 0);
disp_int &= ~LB_D1_VBLANK_INTERRUPT;
DRM_DEBUG("IH: D1 vblank\n");
}
break;
case 1: /* D1 vline */
if (disp_int & LB_D1_VLINE_INTERRUPT) {
disp_int &= ~LB_D1_VLINE_INTERRUPT;
DRM_DEBUG("IH: D1 vline\n");
}
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
break;
}
break;
case 5: /* D2 vblank/vline */
switch (src_data) {
case 0: /* D2 vblank */
if (disp_int & LB_D2_VBLANK_INTERRUPT) {
drm_handle_vblank(rdev->ddev, 1);
disp_int &= ~LB_D2_VBLANK_INTERRUPT;
DRM_DEBUG("IH: D2 vblank\n");
}
break;
case 1: /* D1 vline */
if (disp_int & LB_D2_VLINE_INTERRUPT) {
disp_int &= ~LB_D2_VLINE_INTERRUPT;
DRM_DEBUG("IH: D2 vline\n");
}
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
break;
}
break;
case 176: /* CP_INT in ring buffer */
case 177: /* CP_INT in IB1 */
case 178: /* CP_INT in IB2 */
DRM_DEBUG("IH: CP int: 0x%08x\n", src_data);
radeon_fence_process(rdev);
break;
case 181: /* CP EOP event */
DRM_DEBUG("IH: CP EOP\n");
break;
default:
DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data);
break;
}
/* wptr/rptr are in bytes! */
if (rptr == last_entry)
rptr = 0;
else
rptr += 16;
}
/* make sure wptr hasn't changed while processing */
wptr = r600_get_ih_wptr(rdev);
if (wptr != rdev->ih.wptr)
goto restart_ih;
rdev->ih.rptr = rptr;
WREG32(IH_RB_RPTR, rdev->ih.rptr);
spin_unlock_irqrestore(&rdev->ih.lock, flags);
return IRQ_HANDLED;
}
/*
* Debugfs info
......@@ -1811,21 +2361,21 @@ static int r600_debugfs_cp_ring_info(struct seq_file *m, void *data)
struct drm_info_node *node = (struct drm_info_node *) m->private;
struct drm_device *dev = node->minor->dev;
struct radeon_device *rdev = dev->dev_private;
uint32_t rdp, wdp;
unsigned count, i, j;
radeon_ring_free_size(rdev);
rdp = RREG32(CP_RB_RPTR);
wdp = RREG32(CP_RB_WPTR);
count = (rdp + rdev->cp.ring_size - wdp) & rdev->cp.ptr_mask;
count = (rdev->cp.ring_size / 4) - rdev->cp.ring_free_dw;
seq_printf(m, "CP_STAT 0x%08x\n", RREG32(CP_STAT));
seq_printf(m, "CP_RB_WPTR 0x%08x\n", wdp);
seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp);
seq_printf(m, "CP_RB_WPTR 0x%08x\n", RREG32(CP_RB_WPTR));
seq_printf(m, "CP_RB_RPTR 0x%08x\n", RREG32(CP_RB_RPTR));
seq_printf(m, "driver's copy of the CP_RB_WPTR 0x%08x\n", rdev->cp.wptr);
seq_printf(m, "driver's copy of the CP_RB_RPTR 0x%08x\n", rdev->cp.rptr);
seq_printf(m, "%u free dwords in ring\n", rdev->cp.ring_free_dw);
seq_printf(m, "%u dwords in ring\n", count);
i = rdev->cp.rptr;
for (j = 0; j <= count; j++) {
i = (rdp + j) & rdev->cp.ptr_mask;
seq_printf(m, "r[%04d]=0x%08x\n", i, rdev->cp.ring[i]);
i = (i + 1) & rdev->cp.ptr_mask;
}
return 0;
}
......
......@@ -473,9 +473,8 @@ int r600_blit_init(struct radeon_device *rdev)
obj_size += r6xx_ps_size * 4;
obj_size = ALIGN(obj_size, 256);
r = radeon_object_create(rdev, NULL, obj_size,
true, RADEON_GEM_DOMAIN_VRAM,
false, &rdev->r600_blit.shader_obj);
r = radeon_bo_create(rdev, NULL, obj_size, true, RADEON_GEM_DOMAIN_VRAM,
&rdev->r600_blit.shader_obj);
if (r) {
DRM_ERROR("r600 failed to allocate shader\n");
return r;
......@@ -485,12 +484,14 @@ int r600_blit_init(struct radeon_device *rdev)
obj_size,
rdev->r600_blit.vs_offset, rdev->r600_blit.ps_offset);
r = radeon_object_kmap(rdev->r600_blit.shader_obj, &ptr);
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_kmap(rdev->r600_blit.shader_obj, &ptr);
if (r) {
DRM_ERROR("failed to map blit object %d\n", r);
return r;
}
if (rdev->family >= CHIP_RV770)
memcpy_toio(ptr + rdev->r600_blit.state_offset,
r7xx_default_state, rdev->r600_blit.state_len * 4);
......@@ -500,19 +501,26 @@ int r600_blit_init(struct radeon_device *rdev)
if (num_packet2s)
memcpy_toio(ptr + rdev->r600_blit.state_offset + (rdev->r600_blit.state_len * 4),
packet2s, num_packet2s * 4);
memcpy(ptr + rdev->r600_blit.vs_offset, r6xx_vs, r6xx_vs_size * 4);
memcpy(ptr + rdev->r600_blit.ps_offset, r6xx_ps, r6xx_ps_size * 4);
radeon_object_kunmap(rdev->r600_blit.shader_obj);
radeon_bo_kunmap(rdev->r600_blit.shader_obj);
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
return 0;
}
void r600_blit_fini(struct radeon_device *rdev)
{
radeon_object_unpin(rdev->r600_blit.shader_obj);
radeon_object_unref(&rdev->r600_blit.shader_obj);
int r;
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
if (unlikely(r != 0)) {
dev_err(rdev->dev, "(%d) can't finish r600 blit\n", r);
goto out_unref;
}
radeon_bo_unpin(rdev->r600_blit.shader_obj);
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
out_unref:
radeon_bo_unref(&rdev->r600_blit.shader_obj);
}
int r600_vb_ib_get(struct radeon_device *rdev)
......@@ -569,9 +577,9 @@ int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes)
ring_size = num_loops * dwords_per_loop;
/* set default + shaders */
ring_size += 40; /* shaders + def state */
ring_size += 3; /* fence emit for VB IB */
ring_size += 5; /* fence emit for VB IB */
ring_size += 5; /* done copy */
ring_size += 3; /* fence emit for done copy */
ring_size += 5; /* fence emit for done copy */
r = radeon_ring_lock(rdev, ring_size);
WARN_ON(r);
......
......@@ -456,7 +456,163 @@
#define WAIT_2D_IDLECLEAN_bit (1 << 16)
#define WAIT_3D_IDLECLEAN_bit (1 << 17)
#define IH_RB_CNTL 0x3e00
# define IH_RB_ENABLE (1 << 0)
# define IH_IB_SIZE(x) ((x) << 1) /* log2 */
# define IH_RB_FULL_DRAIN_ENABLE (1 << 6)
# define IH_WPTR_WRITEBACK_ENABLE (1 << 8)
# define IH_WPTR_WRITEBACK_TIMER(x) ((x) << 9) /* log2 */
# define IH_WPTR_OVERFLOW_ENABLE (1 << 16)
# define IH_WPTR_OVERFLOW_CLEAR (1 << 31)
#define IH_RB_BASE 0x3e04
#define IH_RB_RPTR 0x3e08
#define IH_RB_WPTR 0x3e0c
# define RB_OVERFLOW (1 << 0)
# define WPTR_OFFSET_MASK 0x3fffc
#define IH_RB_WPTR_ADDR_HI 0x3e10
#define IH_RB_WPTR_ADDR_LO 0x3e14
#define IH_CNTL 0x3e18
# define ENABLE_INTR (1 << 0)
# define IH_MC_SWAP(x) ((x) << 2)
# define IH_MC_SWAP_NONE 0
# define IH_MC_SWAP_16BIT 1
# define IH_MC_SWAP_32BIT 2
# define IH_MC_SWAP_64BIT 3
# define RPTR_REARM (1 << 4)
# define MC_WRREQ_CREDIT(x) ((x) << 15)
# define MC_WR_CLEAN_CNT(x) ((x) << 20)
#define RLC_CNTL 0x3f00
# define RLC_ENABLE (1 << 0)
#define RLC_HB_BASE 0x3f10
#define RLC_HB_CNTL 0x3f0c
#define RLC_HB_RPTR 0x3f20
#define RLC_HB_WPTR 0x3f1c
#define RLC_HB_WPTR_LSB_ADDR 0x3f14
#define RLC_HB_WPTR_MSB_ADDR 0x3f18
#define RLC_MC_CNTL 0x3f44
#define RLC_UCODE_CNTL 0x3f48
#define RLC_UCODE_ADDR 0x3f2c
#define RLC_UCODE_DATA 0x3f30
#define SRBM_SOFT_RESET 0xe60
# define SOFT_RESET_RLC (1 << 13)
#define CP_INT_CNTL 0xc124
# define CNTX_BUSY_INT_ENABLE (1 << 19)
# define CNTX_EMPTY_INT_ENABLE (1 << 20)
# define SCRATCH_INT_ENABLE (1 << 25)
# define TIME_STAMP_INT_ENABLE (1 << 26)
# define IB2_INT_ENABLE (1 << 29)
# define IB1_INT_ENABLE (1 << 30)
# define RB_INT_ENABLE (1 << 31)
#define CP_INT_STATUS 0xc128
# define SCRATCH_INT_STAT (1 << 25)
# define TIME_STAMP_INT_STAT (1 << 26)
# define IB2_INT_STAT (1 << 29)
# define IB1_INT_STAT (1 << 30)
# define RB_INT_STAT (1 << 31)
#define GRBM_INT_CNTL 0x8060
# define RDERR_INT_ENABLE (1 << 0)
# define WAIT_COUNT_TIMEOUT_INT_ENABLE (1 << 1)
# define GUI_IDLE_INT_ENABLE (1 << 19)
#define INTERRUPT_CNTL 0x5468
# define IH_DUMMY_RD_OVERRIDE (1 << 0)
# define IH_DUMMY_RD_EN (1 << 1)
# define IH_REQ_NONSNOOP_EN (1 << 3)
# define GEN_IH_INT_EN (1 << 8)
#define INTERRUPT_CNTL2 0x546c
#define D1MODE_VBLANK_STATUS 0x6534
#define D2MODE_VBLANK_STATUS 0x6d34
# define DxMODE_VBLANK_OCCURRED (1 << 0)
# define DxMODE_VBLANK_ACK (1 << 4)
# define DxMODE_VBLANK_STAT (1 << 12)
# define DxMODE_VBLANK_INTERRUPT (1 << 16)
# define DxMODE_VBLANK_INTERRUPT_TYPE (1 << 17)
#define D1MODE_VLINE_STATUS 0x653c
#define D2MODE_VLINE_STATUS 0x6d3c
# define DxMODE_VLINE_OCCURRED (1 << 0)
# define DxMODE_VLINE_ACK (1 << 4)
# define DxMODE_VLINE_STAT (1 << 12)
# define DxMODE_VLINE_INTERRUPT (1 << 16)
# define DxMODE_VLINE_INTERRUPT_TYPE (1 << 17)
#define DxMODE_INT_MASK 0x6540
# define D1MODE_VBLANK_INT_MASK (1 << 0)
# define D1MODE_VLINE_INT_MASK (1 << 4)
# define D2MODE_VBLANK_INT_MASK (1 << 8)
# define D2MODE_VLINE_INT_MASK (1 << 12)
#define DCE3_DISP_INTERRUPT_STATUS 0x7ddc
# define DC_HPD1_INTERRUPT (1 << 18)
# define DC_HPD2_INTERRUPT (1 << 19)
#define DISP_INTERRUPT_STATUS 0x7edc
# define LB_D1_VLINE_INTERRUPT (1 << 2)
# define LB_D2_VLINE_INTERRUPT (1 << 3)
# define LB_D1_VBLANK_INTERRUPT (1 << 4)
# define LB_D2_VBLANK_INTERRUPT (1 << 5)
# define DACA_AUTODETECT_INTERRUPT (1 << 16)
# define DACB_AUTODETECT_INTERRUPT (1 << 17)
# define DC_HOT_PLUG_DETECT1_INTERRUPT (1 << 18)
# define DC_HOT_PLUG_DETECT2_INTERRUPT (1 << 19)
# define DC_I2C_SW_DONE_INTERRUPT (1 << 20)
# define DC_I2C_HW_DONE_INTERRUPT (1 << 21)
#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE 0x7de8
# define DC_HPD4_INTERRUPT (1 << 14)
# define DC_HPD4_RX_INTERRUPT (1 << 15)
# define DC_HPD3_INTERRUPT (1 << 28)
# define DC_HPD1_RX_INTERRUPT (1 << 29)
# define DC_HPD2_RX_INTERRUPT (1 << 30)
#define DCE3_DISP_INTERRUPT_STATUS_CONTINUE2 0x7dec
# define DC_HPD3_RX_INTERRUPT (1 << 0)
# define DIGA_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 1)
# define DIGA_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 2)
# define DIGB_DP_VID_STREAM_DISABLE_INTERRUPT (1 << 3)
# define DIGB_DP_STEER_FIFO_OVERFLOW_INTERRUPT (1 << 4)
# define AUX1_SW_DONE_INTERRUPT (1 << 5)
# define AUX1_LS_DONE_INTERRUPT (1 << 6)
# define AUX2_SW_DONE_INTERRUPT (1 << 7)
# define AUX2_LS_DONE_INTERRUPT (1 << 8)
# define AUX3_SW_DONE_INTERRUPT (1 << 9)
# define AUX3_LS_DONE_INTERRUPT (1 << 10)
# define AUX4_SW_DONE_INTERRUPT (1 << 11)
# define AUX4_LS_DONE_INTERRUPT (1 << 12)
# define DIGA_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 13)
# define DIGB_DP_FAST_TRAINING_COMPLETE_INTERRUPT (1 << 14)
/* DCE 3.2 */
# define AUX5_SW_DONE_INTERRUPT (1 << 15)
# define AUX5_LS_DONE_INTERRUPT (1 << 16)
# define AUX6_SW_DONE_INTERRUPT (1 << 17)
# define AUX6_LS_DONE_INTERRUPT (1 << 18)
# define DC_HPD5_INTERRUPT (1 << 19)
# define DC_HPD5_RX_INTERRUPT (1 << 20)
# define DC_HPD6_INTERRUPT (1 << 21)
# define DC_HPD6_RX_INTERRUPT (1 << 22)
#define DCE3_DACA_AUTODETECT_INT_CONTROL 0x7038
#define DCE3_DACB_AUTODETECT_INT_CONTROL 0x7138
#define DACA_AUTODETECT_INT_CONTROL 0x7838
#define DACB_AUTODETECT_INT_CONTROL 0x7a38
# define DACx_AUTODETECT_ACK (1 << 0)
# define DACx_AUTODETECT_INT_ENABLE (1 << 16)
#define DC_HOT_PLUG_DETECT1_INT_CONTROL 0x7d08
#define DC_HOT_PLUG_DETECT2_INT_CONTROL 0x7d18
#define DC_HOT_PLUG_DETECT3_INT_CONTROL 0x7d2c
# define DC_HOT_PLUG_DETECTx_INT_ACK (1 << 0)
# define DC_HOT_PLUG_DETECTx_INT_POLARITY (1 << 8)
# define DC_HOT_PLUG_DETECTx_INT_EN (1 << 16)
/* DCE 3.2 */
#define DC_HPD1_INT_CONTROL 0x7d04
#define DC_HPD2_INT_CONTROL 0x7d10
#define DC_HPD3_INT_CONTROL 0x7d1c
#define DC_HPD4_INT_CONTROL 0x7d28
# define DC_HPDx_INT_ACK (1 << 0)
# define DC_HPDx_INT_POLARITY (1 << 8)
# define DC_HPDx_INT_EN (1 << 16)
# define DC_HPDx_RX_INT_ACK (1 << 20)
# define DC_HPDx_RX_INT_EN (1 << 24)
/*
* PM4
......@@ -500,7 +656,6 @@
#define PACKET3_WAIT_REG_MEM 0x3C
#define PACKET3_MEM_WRITE 0x3D
#define PACKET3_INDIRECT_BUFFER 0x32
#define PACKET3_CP_INTERRUPT 0x40
#define PACKET3_SURFACE_SYNC 0x43
# define PACKET3_CB0_DEST_BASE_ENA (1 << 6)
# define PACKET3_TC_ACTION_ENA (1 << 23)
......@@ -674,4 +829,5 @@
#define S_000E60_SOFT_RESET_TSC(x) (((x) & 1) << 16)
#define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17)
#define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480
#endif
......@@ -28,8 +28,6 @@
#ifndef __RADEON_H__
#define __RADEON_H__
#include "radeon_object.h"
/* TODO: Here are things that needs to be done :
* - surface allocator & initializer : (bit like scratch reg) should
* initialize HDP_ stuff on RS600, R600, R700 hw, well anythings
......@@ -67,6 +65,11 @@
#include <linux/list.h>
#include <linux/kref.h>
#include <ttm/ttm_bo_api.h>
#include <ttm/ttm_bo_driver.h>
#include <ttm/ttm_placement.h>
#include <ttm/ttm_module.h>
#include "radeon_family.h"
#include "radeon_mode.h"
#include "radeon_reg.h"
......@@ -186,76 +189,60 @@ void radeon_fence_unref(struct radeon_fence **fence);
* Tiling registers
*/
struct radeon_surface_reg {
struct radeon_object *robj;
struct radeon_bo *bo;
};
#define RADEON_GEM_MAX_SURFACES 8
/*
* Radeon buffer.
* TTM.
*/
struct radeon_object;
struct radeon_mman {
struct ttm_bo_global_ref bo_global_ref;
struct ttm_global_reference mem_global_ref;
bool mem_global_referenced;
struct ttm_bo_device bdev;
};
struct radeon_bo {
/* Protected by gem.mutex */
struct list_head list;
/* Protected by tbo.reserved */
struct ttm_buffer_object tbo;
struct ttm_bo_kmap_obj kmap;
unsigned pin_count;
void *kptr;
u32 tiling_flags;
u32 pitch;
int surface_reg;
/* Constant after initialization */
struct radeon_device *rdev;
struct drm_gem_object *gobj;
};
struct radeon_object_list {
struct radeon_bo_list {
struct list_head list;
struct radeon_object *robj;
struct radeon_bo *bo;
uint64_t gpu_offset;
unsigned rdomain;
unsigned wdomain;
uint32_t tiling_flags;
u32 tiling_flags;
};
int radeon_object_init(struct radeon_device *rdev);
void radeon_object_fini(struct radeon_device *rdev);
int radeon_object_create(struct radeon_device *rdev,
struct drm_gem_object *gobj,
unsigned long size,
bool kernel,
uint32_t domain,
bool interruptible,
struct radeon_object **robj_ptr);
int radeon_object_kmap(struct radeon_object *robj, void **ptr);
void radeon_object_kunmap(struct radeon_object *robj);
void radeon_object_unref(struct radeon_object **robj);
int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
uint64_t *gpu_addr);
void radeon_object_unpin(struct radeon_object *robj);
int radeon_object_wait(struct radeon_object *robj);
int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement);
int radeon_object_evict_vram(struct radeon_device *rdev);
int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset);
void radeon_object_force_delete(struct radeon_device *rdev);
void radeon_object_list_add_object(struct radeon_object_list *lobj,
struct list_head *head);
int radeon_object_list_validate(struct list_head *head, void *fence);
void radeon_object_list_unvalidate(struct list_head *head);
void radeon_object_list_clean(struct list_head *head);
int radeon_object_fbdev_mmap(struct radeon_object *robj,
struct vm_area_struct *vma);
unsigned long radeon_object_size(struct radeon_object *robj);
void radeon_object_clear_surface_reg(struct radeon_object *robj);
int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
bool force_drop);
void radeon_object_set_tiling_flags(struct radeon_object *robj,
uint32_t tiling_flags, uint32_t pitch);
void radeon_object_get_tiling_flags(struct radeon_object *robj, uint32_t *tiling_flags, uint32_t *pitch);
void radeon_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem);
void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
/*
* GEM objects.
*/
struct radeon_gem {
struct mutex mutex;
struct list_head objects;
};
int radeon_gem_init(struct radeon_device *rdev);
void radeon_gem_fini(struct radeon_device *rdev);
int radeon_gem_object_create(struct radeon_device *rdev, int size,
int alignment, int initial_domain,
bool discardable, bool kernel,
bool interruptible,
struct drm_gem_object **obj);
int alignment, int initial_domain,
bool discardable, bool kernel,
struct drm_gem_object **obj);
int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
uint64_t *gpu_addr);
void radeon_gem_object_unpin(struct drm_gem_object *obj);
......@@ -271,7 +258,7 @@ struct radeon_gart_table_ram {
};
struct radeon_gart_table_vram {
struct radeon_object *robj;
struct radeon_bo *robj;
volatile uint32_t *ptr;
};
......@@ -352,11 +339,14 @@ struct radeon_irq {
bool sw_int;
/* FIXME: use a define max crtc rather than hardcode it */
bool crtc_vblank_int[2];
spinlock_t sw_lock;
int sw_refcount;
};
int radeon_irq_kms_init(struct radeon_device *rdev);
void radeon_irq_kms_fini(struct radeon_device *rdev);
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev);
void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev);
/*
* CP & ring.
......@@ -376,7 +366,7 @@ struct radeon_ib {
*/
struct radeon_ib_pool {
struct mutex mutex;
struct radeon_object *robj;
struct radeon_bo *robj;
struct list_head scheduled_ibs;
struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
bool ready;
......@@ -384,7 +374,7 @@ struct radeon_ib_pool {
};
struct radeon_cp {
struct radeon_object *ring_obj;
struct radeon_bo *ring_obj;
volatile uint32_t *ring;
unsigned rptr;
unsigned wptr;
......@@ -399,8 +389,25 @@ struct radeon_cp {
bool ready;
};
/*
* R6xx+ IH ring
*/
struct r600_ih {
struct radeon_bo *ring_obj;
volatile uint32_t *ring;
unsigned rptr;
unsigned wptr;
unsigned wptr_old;
unsigned ring_size;
uint64_t gpu_addr;
uint32_t align_mask;
uint32_t ptr_mask;
spinlock_t lock;
bool enabled;
};
struct r600_blit {
struct radeon_object *shader_obj;
struct radeon_bo *shader_obj;
u64 shader_gpu_addr;
u32 vs_offset, ps_offset;
u32 state_offset;
......@@ -430,8 +437,8 @@ void radeon_ring_fini(struct radeon_device *rdev);
*/
struct radeon_cs_reloc {
struct drm_gem_object *gobj;
struct radeon_object *robj;
struct radeon_object_list lobj;
struct radeon_bo *robj;
struct radeon_bo_list lobj;
uint32_t handle;
uint32_t flags;
};
......@@ -527,7 +534,7 @@ void radeon_agp_fini(struct radeon_device *rdev);
* Writeback
*/
struct radeon_wb {
struct radeon_object *wb_obj;
struct radeon_bo *wb_obj;
volatile uint32_t *wb;
uint64_t gpu_addr;
};
......@@ -639,6 +646,7 @@ struct radeon_asic {
uint32_t offset, uint32_t obj_size);
int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
void (*bandwidth_update)(struct radeon_device *rdev);
void (*hdp_flush)(struct radeon_device *rdev);
};
/*
......@@ -751,9 +759,9 @@ struct radeon_device {
uint8_t *bios;
bool is_atom_bios;
uint16_t bios_header_start;
struct radeon_object *stollen_vga_memory;
struct radeon_bo *stollen_vga_memory;
struct fb_info *fbdev_info;
struct radeon_object *fbdev_robj;
struct radeon_bo *fbdev_rbo;
struct radeon_framebuffer *fbdev_rfb;
/* Register mmio */
resource_size_t rmmio_base;
......@@ -791,8 +799,10 @@ struct radeon_device {
struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
const struct firmware *me_fw; /* all family ME firmware */
const struct firmware *pfp_fw; /* r6/700 PFP firmware */
const struct firmware *rlc_fw; /* r6/700 RLC firmware */
struct r600_blit r600_blit;
int msi_enabled; /* msi enabled */
struct r600_ih ih; /* r6/700 interrupt ring */
};
int radeon_device_init(struct radeon_device *rdev,
......@@ -829,6 +839,10 @@ static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32
}
}
/*
* Cast helper
*/
#define to_radeon_fence(p) ((struct radeon_fence *)(p))
/*
* Registers read & write functions.
......@@ -965,18 +979,20 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
#define radeon_get_engine_clock(rdev) (rdev)->asic->get_engine_clock((rdev))
#define radeon_set_engine_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
#define radeon_get_memory_clock(rdev) (rdev)->asic->get_memory_clock((rdev))
#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_memory_clock((rdev), (e))
#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l))
#define radeon_set_clock_gating(rdev, e) (rdev)->asic->set_clock_gating((rdev), (e))
#define radeon_set_surface_reg(rdev, r, f, p, o, s) ((rdev)->asic->set_surface_reg((rdev), (r), (f), (p), (o), (s)))
#define radeon_clear_surface_reg(rdev, r) ((rdev)->asic->clear_surface_reg((rdev), (r)))
#define radeon_bandwidth_update(rdev) (rdev)->asic->bandwidth_update((rdev))
#define radeon_hdp_flush(rdev) (rdev)->asic->hdp_flush((rdev))
/* Common functions */
extern int radeon_gart_table_vram_pin(struct radeon_device *rdev);
extern int radeon_modeset_init(struct radeon_device *rdev);
extern void radeon_modeset_fini(struct radeon_device *rdev);
extern bool radeon_card_posted(struct radeon_device *rdev);
extern bool radeon_boot_test_post_card(struct radeon_device *rdev);
extern int radeon_clocks_init(struct radeon_device *rdev);
extern void radeon_clocks_fini(struct radeon_device *rdev);
extern void radeon_scratch_init(struct radeon_device *rdev);
......@@ -1021,7 +1037,7 @@ extern int r100_cp_reset(struct radeon_device *rdev);
extern void r100_vga_render_disable(struct radeon_device *rdev);
extern 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);
extern int r100_cs_parse_packet0(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
const unsigned *auth, unsigned n,
......@@ -1029,6 +1045,8 @@ extern int r100_cs_parse_packet0(struct radeon_cs_parser *p,
extern int r100_cs_packet_parse(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt,
unsigned idx);
extern void r100_enable_bm(struct radeon_device *rdev);
extern void r100_set_common_regs(struct radeon_device *rdev);
/* rv200,rv250,rv280 */
extern void r200_set_safe_registers(struct radeon_device *rdev);
......@@ -1104,7 +1122,14 @@ extern void r600_wb_disable(struct radeon_device *rdev);
extern void r600_scratch_init(struct radeon_device *rdev);
extern int r600_blit_init(struct radeon_device *rdev);
extern void r600_blit_fini(struct radeon_device *rdev);
extern int r600_cp_init_microcode(struct radeon_device *rdev);
extern int r600_init_microcode(struct radeon_device *rdev);
extern int r600_gpu_reset(struct radeon_device *rdev);
/* r600 irq */
extern int r600_irq_init(struct radeon_device *rdev);
extern void r600_irq_fini(struct radeon_device *rdev);
extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
extern int r600_irq_set(struct radeon_device *rdev);
#include "radeon_object.h"
#endif
......@@ -76,6 +76,7 @@ int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
void r100_bandwidth_update(struct radeon_device *rdev);
void r100_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
int r100_ring_test(struct radeon_device *rdev);
void r100_hdp_flush(struct radeon_device *rdev);
static struct radeon_asic r100_asic = {
.init = &r100_init,
......@@ -107,6 +108,7 @@ static struct radeon_asic r100_asic = {
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
......@@ -162,6 +164,7 @@ static struct radeon_asic r300_asic = {
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
/*
......@@ -201,6 +204,7 @@ static struct radeon_asic r420_asic = {
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
......@@ -245,6 +249,7 @@ static struct radeon_asic rs400_asic = {
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
......@@ -291,6 +296,7 @@ static struct radeon_asic rs600_asic = {
.set_pcie_lanes = NULL,
.set_clock_gating = &radeon_atom_set_clock_gating,
.bandwidth_update = &rs600_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
......@@ -334,6 +340,7 @@ static struct radeon_asic rs690_asic = {
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rs690_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
......@@ -381,6 +388,7 @@ static struct radeon_asic rv515_asic = {
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rv515_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
......@@ -419,6 +427,7 @@ static struct radeon_asic r520_asic = {
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rv515_bandwidth_update,
.hdp_flush = &r100_hdp_flush,
};
/*
......@@ -455,6 +464,7 @@ int r600_ring_test(struct radeon_device *rdev);
int r600_copy_blit(struct radeon_device *rdev,
uint64_t src_offset, uint64_t dst_offset,
unsigned num_pages, struct radeon_fence *fence);
void r600_hdp_flush(struct radeon_device *rdev);
static struct radeon_asic r600_asic = {
.init = &r600_init,
......@@ -470,6 +480,7 @@ static struct radeon_asic r600_asic = {
.ring_ib_execute = &r600_ring_ib_execute,
.irq_set = &r600_irq_set,
.irq_process = &r600_irq_process,
.get_vblank_counter = &rs600_get_vblank_counter,
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &r600_cs_parse,
.copy_blit = &r600_copy_blit,
......@@ -484,6 +495,7 @@ static struct radeon_asic r600_asic = {
.set_surface_reg = r600_set_surface_reg,
.clear_surface_reg = r600_clear_surface_reg,
.bandwidth_update = &rv515_bandwidth_update,
.hdp_flush = &r600_hdp_flush,
};
/*
......@@ -509,6 +521,7 @@ static struct radeon_asic rv770_asic = {
.ring_ib_execute = &r600_ring_ib_execute,
.irq_set = &r600_irq_set,
.irq_process = &r600_irq_process,
.get_vblank_counter = &rs600_get_vblank_counter,
.fence_ring_emit = &r600_fence_ring_emit,
.cs_parse = &r600_cs_parse,
.copy_blit = &r600_copy_blit,
......@@ -523,6 +536,7 @@ static struct radeon_asic rv770_asic = {
.set_surface_reg = r600_set_surface_reg,
.clear_surface_reg = r600_clear_surface_reg,
.bandwidth_update = &rv515_bandwidth_update,
.hdp_flush = &r600_hdp_flush,
};
#endif
......@@ -82,18 +82,18 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
i2c.mask_clk_reg = le16_to_cpu(gpio.usClkMaskRegisterIndex) * 4;
i2c.mask_data_reg = le16_to_cpu(gpio.usDataMaskRegisterIndex) * 4;
i2c.put_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
i2c.put_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
i2c.get_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
i2c.get_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
i2c.en_clk_reg = le16_to_cpu(gpio.usClkEnRegisterIndex) * 4;
i2c.en_data_reg = le16_to_cpu(gpio.usDataEnRegisterIndex) * 4;
i2c.y_clk_reg = le16_to_cpu(gpio.usClkY_RegisterIndex) * 4;
i2c.y_data_reg = le16_to_cpu(gpio.usDataY_RegisterIndex) * 4;
i2c.a_clk_reg = le16_to_cpu(gpio.usClkA_RegisterIndex) * 4;
i2c.a_data_reg = le16_to_cpu(gpio.usDataA_RegisterIndex) * 4;
i2c.mask_clk_mask = (1 << gpio.ucClkMaskShift);
i2c.mask_data_mask = (1 << gpio.ucDataMaskShift);
i2c.put_clk_mask = (1 << gpio.ucClkEnShift);
i2c.put_data_mask = (1 << gpio.ucDataEnShift);
i2c.get_clk_mask = (1 << gpio.ucClkY_Shift);
i2c.get_data_mask = (1 << gpio.ucDataY_Shift);
i2c.en_clk_mask = (1 << gpio.ucClkEnShift);
i2c.en_data_mask = (1 << gpio.ucDataEnShift);
i2c.y_clk_mask = (1 << gpio.ucClkY_Shift);
i2c.y_data_mask = (1 << gpio.ucDataY_Shift);
i2c.a_clk_mask = (1 << gpio.ucClkA_Shift);
i2c.a_data_mask = (1 << gpio.ucDataA_Shift);
i2c.valid = true;
......@@ -135,6 +135,23 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
}
}
/* HIS X1300 is DVI+VGA, not DVI+DVI */
if ((dev->pdev->device == 0x7146) &&
(dev->pdev->subsystem_vendor == 0x17af) &&
(dev->pdev->subsystem_device == 0x2058)) {
if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
return false;
}
/* Gigabyte X1300 is DVI+VGA, not DVI+DVI */
if ((dev->pdev->device == 0x7142) &&
(dev->pdev->subsystem_vendor == 0x1458) &&
(dev->pdev->subsystem_device == 0x2134)) {
if (supported_device == ATOM_DEVICE_DFP1_SUPPORT)
return false;
}
/* Funky macbooks */
if ((dev->pdev->device == 0x71C5) &&
(dev->pdev->subsystem_vendor == 0x106b) &&
......@@ -172,6 +189,15 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
}
}
/* Acer laptop reports DVI-D as DVI-I */
if ((dev->pdev->device == 0x95c4) &&
(dev->pdev->subsystem_vendor == 0x1025) &&
(dev->pdev->subsystem_device == 0x013c)) {
if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
(supported_device == ATOM_DEVICE_DFP1_SUPPORT))
*connector_type = DRM_MODE_CONNECTOR_DVID;
}
return true;
}
......@@ -901,7 +927,7 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
struct radeon_device *rdev = dev->dev_private;
struct radeon_mode_info *mode_info = &rdev->mode_info;
int index = GetIndexIntoMasterTable(DATA, LVDS_Info);
uint16_t data_offset;
uint16_t data_offset, misc;
union lvds_info *lvds_info;
uint8_t frev, crev;
struct radeon_encoder_atom_dig *lvds = NULL;
......@@ -940,6 +966,19 @@ struct radeon_encoder_atom_dig *radeon_atombios_get_lvds_info(struct
lvds->panel_pwr_delay =
le16_to_cpu(lvds_info->info.usOffDelayInMs);
lvds->lvds_misc = lvds_info->info.ucLVDS_Misc;
misc = le16_to_cpu(lvds_info->info.sLCDTiming.susModeMiscInfo.usAccess);
if (misc & ATOM_VSYNC_POLARITY)
lvds->native_mode.flags |= DRM_MODE_FLAG_NVSYNC;
if (misc & ATOM_HSYNC_POLARITY)
lvds->native_mode.flags |= DRM_MODE_FLAG_NHSYNC;
if (misc & ATOM_COMPOSITESYNC)
lvds->native_mode.flags |= DRM_MODE_FLAG_CSYNC;
if (misc & ATOM_INTERLACE)
lvds->native_mode.flags |= DRM_MODE_FLAG_INTERLACE;
if (misc & ATOM_DOUBLE_CLOCK_MODE)
lvds->native_mode.flags |= DRM_MODE_FLAG_DBLSCAN;
/* set crtc values */
drm_mode_set_crtcinfo(&lvds->native_mode, CRTC_INTERLACE_HALVE_V);
......
......@@ -29,8 +29,8 @@
void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
unsigned sdomain, unsigned ddomain)
{
struct radeon_object *dobj = NULL;
struct radeon_object *sobj = NULL;
struct radeon_bo *dobj = NULL;
struct radeon_bo *sobj = NULL;
struct radeon_fence *fence = NULL;
uint64_t saddr, daddr;
unsigned long start_jiffies;
......@@ -41,19 +41,27 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
size = bsize;
n = 1024;
r = radeon_object_create(rdev, NULL, size, true, sdomain, false, &sobj);
r = radeon_bo_create(rdev, NULL, size, true, sdomain, &sobj);
if (r) {
goto out_cleanup;
}
r = radeon_object_pin(sobj, sdomain, &saddr);
r = radeon_bo_reserve(sobj, false);
if (unlikely(r != 0))
goto out_cleanup;
r = radeon_bo_pin(sobj, sdomain, &saddr);
radeon_bo_unreserve(sobj);
if (r) {
goto out_cleanup;
}
r = radeon_object_create(rdev, NULL, size, true, ddomain, false, &dobj);
r = radeon_bo_create(rdev, NULL, size, true, ddomain, &dobj);
if (r) {
goto out_cleanup;
}
r = radeon_object_pin(dobj, ddomain, &daddr);
r = radeon_bo_reserve(dobj, false);
if (unlikely(r != 0))
goto out_cleanup;
r = radeon_bo_pin(dobj, ddomain, &daddr);
radeon_bo_unreserve(dobj);
if (r) {
goto out_cleanup;
}
......@@ -109,12 +117,20 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
}
out_cleanup:
if (sobj) {
radeon_object_unpin(sobj);
radeon_object_unref(&sobj);
r = radeon_bo_reserve(sobj, false);
if (likely(r == 0)) {
radeon_bo_unpin(sobj);
radeon_bo_unreserve(sobj);
}
radeon_bo_unref(&sobj);
}
if (dobj) {
radeon_object_unpin(dobj);
radeon_object_unref(&dobj);
r = radeon_bo_reserve(dobj, false);
if (likely(r == 0)) {
radeon_bo_unpin(dobj);
radeon_bo_unreserve(dobj);
}
radeon_bo_unref(&dobj);
}
if (fence) {
radeon_fence_unref(&fence);
......
......@@ -44,6 +44,10 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev)
ref_div =
RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
if (ref_div == 0)
return 0;
sclk = fb_div / ref_div;
post_div = RREG32_PLL(RADEON_SCLK_CNTL) & RADEON_SCLK_SRC_SEL_MASK;
......@@ -70,6 +74,10 @@ static uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev)
ref_div =
RREG32_PLL(RADEON_M_SPLL_REF_FB_DIV) & RADEON_M_SPLL_REF_DIV_MASK;
if (ref_div == 0)
return 0;
mclk = fb_div / ref_div;
post_div = RREG32_PLL(RADEON_MCLK_CNTL) & 0x7;
......@@ -98,8 +106,19 @@ void radeon_get_clock_info(struct drm_device *dev)
ret = radeon_combios_get_clock_info(dev);
if (ret) {
if (p1pll->reference_div < 2)
p1pll->reference_div = 12;
if (p1pll->reference_div < 2) {
if (!ASIC_IS_AVIVO(rdev)) {
u32 tmp = RREG32_PLL(RADEON_PPLL_REF_DIV);
if (ASIC_IS_R300(rdev))
p1pll->reference_div =
(tmp & R300_PPLL_REF_DIV_ACC_MASK) >> R300_PPLL_REF_DIV_ACC_SHIFT;
else
p1pll->reference_div = tmp & RADEON_PPLL_REF_DIV_MASK;
if (p1pll->reference_div < 2)
p1pll->reference_div = 12;
} else
p1pll->reference_div = 12;
}
if (p2pll->reference_div < 2)
p2pll->reference_div = 12;
if (rdev->family < CHIP_RS600) {
......
......@@ -450,29 +450,29 @@ struct radeon_i2c_bus_rec combios_setup_i2c_bus(int ddc_line)
i2c.mask_data_mask = RADEON_GPIO_EN_0;
i2c.a_clk_mask = RADEON_GPIO_A_1;
i2c.a_data_mask = RADEON_GPIO_A_0;
i2c.put_clk_mask = RADEON_GPIO_EN_1;
i2c.put_data_mask = RADEON_GPIO_EN_0;
i2c.get_clk_mask = RADEON_GPIO_Y_1;
i2c.get_data_mask = RADEON_GPIO_Y_0;
i2c.en_clk_mask = RADEON_GPIO_EN_1;
i2c.en_data_mask = RADEON_GPIO_EN_0;
i2c.y_clk_mask = RADEON_GPIO_Y_1;
i2c.y_data_mask = RADEON_GPIO_Y_0;
if ((ddc_line == RADEON_LCD_GPIO_MASK) ||
(ddc_line == RADEON_MDGPIO_EN_REG)) {
i2c.mask_clk_reg = ddc_line;
i2c.mask_data_reg = ddc_line;
i2c.a_clk_reg = ddc_line;
i2c.a_data_reg = ddc_line;
i2c.put_clk_reg = ddc_line;
i2c.put_data_reg = ddc_line;
i2c.get_clk_reg = ddc_line + 4;
i2c.get_data_reg = ddc_line + 4;
i2c.en_clk_reg = ddc_line;
i2c.en_data_reg = ddc_line;
i2c.y_clk_reg = ddc_line + 4;
i2c.y_data_reg = ddc_line + 4;
} else {
i2c.mask_clk_reg = ddc_line;
i2c.mask_data_reg = ddc_line;
i2c.a_clk_reg = ddc_line;
i2c.a_data_reg = ddc_line;
i2c.put_clk_reg = ddc_line;
i2c.put_data_reg = ddc_line;
i2c.get_clk_reg = ddc_line;
i2c.get_data_reg = ddc_line;
i2c.en_clk_reg = ddc_line;
i2c.en_data_reg = ddc_line;
i2c.y_clk_reg = ddc_line;
i2c.y_data_reg = ddc_line;
}
if (ddc_line)
......@@ -495,7 +495,7 @@ bool radeon_combios_get_clock_info(struct drm_device *dev)
uint16_t sclk, mclk;
if (rdev->bios == NULL)
return NULL;
return false;
pll_info = combios_get_table_offset(dev, COMBIOS_PLL_INFO_TABLE);
if (pll_info) {
......@@ -993,8 +993,8 @@ static const struct radeon_tmds_pll default_tmds_pll[CHIP_LAST][4] = {
{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R420 */
{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_R423 */
{{0xffffffff, 0xb01cb}, {0, 0}, {0, 0}, {0, 0}}, /* CHIP_RV410 */
{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS400 */
{{15000, 0xb0155}, {0xffffffff, 0xb01cb}, {0, 0}, {0, 0}}, /* CHIP_RS480 */
{ {0, 0}, {0, 0}, {0, 0}, {0, 0} }, /* CHIP_RS400 */
{ {0, 0}, {0, 0}, {0, 0}, {0, 0} }, /* CHIP_RS480 */
};
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
......@@ -1028,7 +1028,6 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
tmds_info = combios_get_table_offset(dev, COMBIOS_DFP_INFO_TABLE);
if (tmds_info) {
ver = RBIOS8(tmds_info);
DRM_INFO("DFP table revision: %d\n", ver);
if (ver == 3) {
......@@ -1063,45 +1062,132 @@ bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
tmds->tmds_pll[i].value);
}
}
} else
} else {
DRM_INFO("No TMDS info found in BIOS\n");
return false;
}
return true;
}
struct radeon_encoder_int_tmds *radeon_combios_get_tmds_info(struct radeon_encoder *encoder)
bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_ext_tmds *tmds)
{
struct radeon_encoder_int_tmds *tmds = NULL;
bool ret;
tmds = kzalloc(sizeof(struct radeon_encoder_int_tmds), GFP_KERNEL);
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_i2c_bus_rec i2c_bus;
if (!tmds)
return NULL;
/* default for macs */
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
ret = radeon_legacy_get_tmds_info_from_combios(encoder, tmds);
if (ret == false)
radeon_legacy_get_tmds_info_from_table(encoder, tmds);
/* XXX some macs have duallink chips */
switch (rdev->mode_info.connector_table) {
case CT_POWERBOOK_EXTERNAL:
case CT_MINI_EXTERNAL:
default:
tmds->dvo_chip = DVO_SIL164;
tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
break;
}
return tmds;
return true;
}
void radeon_combios_get_ext_tmds_info(struct radeon_encoder *encoder)
bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_ext_tmds *tmds)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
uint16_t ext_tmds_info;
uint8_t ver;
uint16_t offset;
uint8_t ver, id, blocks, clk, data;
int i;
enum radeon_combios_ddc gpio;
struct radeon_i2c_bus_rec i2c_bus;
if (rdev->bios == NULL)
return;
return false;
ext_tmds_info =
combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
if (ext_tmds_info) {
ver = RBIOS8(ext_tmds_info);
DRM_INFO("External TMDS Table revision: %d\n", ver);
// TODO
tmds->i2c_bus = NULL;
if (rdev->flags & RADEON_IS_IGP) {
offset = combios_get_table_offset(dev, COMBIOS_I2C_INFO_TABLE);
if (offset) {
ver = RBIOS8(offset);
DRM_INFO("GPIO Table revision: %d\n", ver);
blocks = RBIOS8(offset + 2);
for (i = 0; i < blocks; i++) {
id = RBIOS8(offset + 3 + (i * 5) + 0);
if (id == 136) {
clk = RBIOS8(offset + 3 + (i * 5) + 3);
data = RBIOS8(offset + 3 + (i * 5) + 4);
i2c_bus.valid = true;
i2c_bus.mask_clk_mask = (1 << clk);
i2c_bus.mask_data_mask = (1 << data);
i2c_bus.a_clk_mask = (1 << clk);
i2c_bus.a_data_mask = (1 << data);
i2c_bus.en_clk_mask = (1 << clk);
i2c_bus.en_data_mask = (1 << data);
i2c_bus.y_clk_mask = (1 << clk);
i2c_bus.y_data_mask = (1 << data);
i2c_bus.mask_clk_reg = RADEON_GPIOPAD_MASK;
i2c_bus.mask_data_reg = RADEON_GPIOPAD_MASK;
i2c_bus.a_clk_reg = RADEON_GPIOPAD_A;
i2c_bus.a_data_reg = RADEON_GPIOPAD_A;
i2c_bus.en_clk_reg = RADEON_GPIOPAD_EN;
i2c_bus.en_data_reg = RADEON_GPIOPAD_EN;
i2c_bus.y_clk_reg = RADEON_GPIOPAD_Y;
i2c_bus.y_data_reg = RADEON_GPIOPAD_Y;
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
tmds->dvo_chip = DVO_SIL164;
tmds->slave_addr = 0x70 >> 1; /* 7 bit addressing */
break;
}
}
}
} else {
offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
if (offset) {
ver = RBIOS8(offset);
DRM_INFO("External TMDS Table revision: %d\n", ver);
tmds->slave_addr = RBIOS8(offset + 4 + 2);
tmds->slave_addr >>= 1; /* 7 bit addressing */
gpio = RBIOS8(offset + 4 + 3);
switch (gpio) {
case DDC_MONID:
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
break;
case DDC_DVI:
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
break;
case DDC_VGA:
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_VGA_DDC);
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
break;
case DDC_CRT2:
/* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */
if (rdev->family >= CHIP_R300)
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_MONID);
else
i2c_bus = combios_setup_i2c_bus(RADEON_GPIO_CRT2_DDC);
tmds->i2c_bus = radeon_i2c_create(dev, &i2c_bus, "DVO");
break;
case DDC_LCD: /* MM i2c */
DRM_ERROR("MM i2c requires hw i2c engine\n");
break;
default:
DRM_ERROR("Unsupported gpio %d\n", gpio);
break;
}
}
}
if (!tmds->i2c_bus) {
DRM_INFO("No valid Ext TMDS info found in BIOS\n");
return false;
}
return true;
}
bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev)
......@@ -1567,20 +1653,25 @@ static bool radeon_apply_legacy_quirks(struct drm_device *dev,
ddc_i2c->mask_data_mask = 0x80;
ddc_i2c->a_clk_mask = (0x20 << 8);
ddc_i2c->a_data_mask = 0x80;
ddc_i2c->put_clk_mask = (0x20 << 8);
ddc_i2c->put_data_mask = 0x80;
ddc_i2c->get_clk_mask = (0x20 << 8);
ddc_i2c->get_data_mask = 0x80;
ddc_i2c->en_clk_mask = (0x20 << 8);
ddc_i2c->en_data_mask = 0x80;
ddc_i2c->y_clk_mask = (0x20 << 8);
ddc_i2c->y_data_mask = 0x80;
ddc_i2c->mask_clk_reg = RADEON_GPIOPAD_MASK;
ddc_i2c->mask_data_reg = RADEON_GPIOPAD_MASK;
ddc_i2c->a_clk_reg = RADEON_GPIOPAD_A;
ddc_i2c->a_data_reg = RADEON_GPIOPAD_A;
ddc_i2c->put_clk_reg = RADEON_GPIOPAD_EN;
ddc_i2c->put_data_reg = RADEON_GPIOPAD_EN;
ddc_i2c->get_clk_reg = RADEON_LCD_GPIO_Y_REG;
ddc_i2c->get_data_reg = RADEON_LCD_GPIO_Y_REG;
ddc_i2c->en_clk_reg = RADEON_GPIOPAD_EN;
ddc_i2c->en_data_reg = RADEON_GPIOPAD_EN;
ddc_i2c->y_clk_reg = RADEON_GPIOPAD_Y;
ddc_i2c->y_data_reg = RADEON_GPIOPAD_Y;
}
/* R3xx+ chips don't have GPIO_CRT2_DDC gpio pad */
if ((rdev->family >= CHIP_R300) &&
ddc_i2c->mask_clk_reg == RADEON_GPIO_CRT2_DDC)
*ddc_i2c = combios_setup_i2c_bus(RADEON_GPIO_DVI_DDC);
/* Certain IBM chipset RN50s have a BIOS reporting two VGAs,
one with VGA DDC and one with CRT2 DDC. - kill the CRT2 DDC one */
if (dev->pdev->device == 0x515e &&
......@@ -1624,6 +1715,12 @@ static bool radeon_apply_legacy_tv_quirks(struct drm_device *dev)
dev->pdev->subsystem_device == 0x280a)
return false;
/* MSI S270 has non-existent TV port */
if (dev->pdev->device == 0x5955 &&
dev->pdev->subsystem_vendor == 0x1462 &&
dev->pdev->subsystem_device == 0x0131)
return false;
return true;
}
......@@ -1939,13 +2036,13 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
RBIOS32(lcd_ddc_info + 3);
ddc_i2c.a_data_mask =
RBIOS32(lcd_ddc_info + 7);
ddc_i2c.put_clk_mask =
ddc_i2c.en_clk_mask =
RBIOS32(lcd_ddc_info + 3);
ddc_i2c.put_data_mask =
ddc_i2c.en_data_mask =
RBIOS32(lcd_ddc_info + 7);
ddc_i2c.get_clk_mask =
ddc_i2c.y_clk_mask =
RBIOS32(lcd_ddc_info + 3);
ddc_i2c.get_data_mask =
ddc_i2c.y_data_mask =
RBIOS32(lcd_ddc_info + 7);
break;
case DDC_GPIO:
......@@ -1960,13 +2057,13 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
RBIOS32(lcd_ddc_info + 3);
ddc_i2c.a_data_mask =
RBIOS32(lcd_ddc_info + 7);
ddc_i2c.put_clk_mask =
ddc_i2c.en_clk_mask =
RBIOS32(lcd_ddc_info + 3);
ddc_i2c.put_data_mask =
ddc_i2c.en_data_mask =
RBIOS32(lcd_ddc_info + 7);
ddc_i2c.get_clk_mask =
ddc_i2c.y_clk_mask =
RBIOS32(lcd_ddc_info + 3);
ddc_i2c.get_data_mask =
ddc_i2c.y_data_mask =
RBIOS32(lcd_ddc_info + 7);
break;
default:
......@@ -2014,6 +2111,193 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev)
return true;
}
void radeon_external_tmds_setup(struct drm_encoder *encoder)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
if (!tmds)
return;
switch (tmds->dvo_chip) {
case DVO_SIL164:
/* sil 164 */
radeon_i2c_do_lock(tmds->i2c_bus, 1);
radeon_i2c_sw_put_byte(tmds->i2c_bus,
tmds->slave_addr,
0x08, 0x30);
radeon_i2c_sw_put_byte(tmds->i2c_bus,
tmds->slave_addr,
0x09, 0x00);
radeon_i2c_sw_put_byte(tmds->i2c_bus,
tmds->slave_addr,
0x0a, 0x90);
radeon_i2c_sw_put_byte(tmds->i2c_bus,
tmds->slave_addr,
0x0c, 0x89);
radeon_i2c_sw_put_byte(tmds->i2c_bus,
tmds->slave_addr,
0x08, 0x3b);
radeon_i2c_do_lock(tmds->i2c_bus, 0);
break;
case DVO_SIL1178:
/* sil 1178 - untested */
/*
* 0x0f, 0x44
* 0x0f, 0x4c
* 0x0e, 0x01
* 0x0a, 0x80
* 0x09, 0x30
* 0x0c, 0xc9
* 0x0d, 0x70
* 0x08, 0x32
* 0x08, 0x33
*/
break;
default:
break;
}
}
bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
uint16_t offset;
uint8_t blocks, slave_addr, rev;
uint32_t index, id;
uint32_t reg, val, and_mask, or_mask;
struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
if (rdev->bios == NULL)
return false;
if (!tmds)
return false;
if (rdev->flags & RADEON_IS_IGP) {
offset = combios_get_table_offset(dev, COMBIOS_TMDS_POWER_ON_TABLE);
rev = RBIOS8(offset);
if (offset) {
rev = RBIOS8(offset);
if (rev > 1) {
blocks = RBIOS8(offset + 3);
index = offset + 4;
while (blocks > 0) {
id = RBIOS16(index);
index += 2;
switch (id >> 13) {
case 0:
reg = (id & 0x1fff) * 4;
val = RBIOS32(index);
index += 4;
WREG32(reg, val);
break;
case 2:
reg = (id & 0x1fff) * 4;
and_mask = RBIOS32(index);
index += 4;
or_mask = RBIOS32(index);
index += 4;
val = RREG32(reg);
val = (val & and_mask) | or_mask;
WREG32(reg, val);
break;
case 3:
val = RBIOS16(index);
index += 2;
udelay(val);
break;
case 4:
val = RBIOS16(index);
index += 2;
udelay(val * 1000);
break;
case 6:
slave_addr = id & 0xff;
slave_addr >>= 1; /* 7 bit addressing */
index++;
reg = RBIOS8(index);
index++;
val = RBIOS8(index);
index++;
radeon_i2c_do_lock(tmds->i2c_bus, 1);
radeon_i2c_sw_put_byte(tmds->i2c_bus,
slave_addr,
reg, val);
radeon_i2c_do_lock(tmds->i2c_bus, 0);
break;
default:
DRM_ERROR("Unknown id %d\n", id >> 13);
break;
}
blocks--;
}
return true;
}
}
} else {
offset = combios_get_table_offset(dev, COMBIOS_EXT_TMDS_INFO_TABLE);
if (offset) {
index = offset + 10;
id = RBIOS16(index);
while (id != 0xffff) {
index += 2;
switch (id >> 13) {
case 0:
reg = (id & 0x1fff) * 4;
val = RBIOS32(index);
WREG32(reg, val);
break;
case 2:
reg = (id & 0x1fff) * 4;
and_mask = RBIOS32(index);
index += 4;
or_mask = RBIOS32(index);
index += 4;
val = RREG32(reg);
val = (val & and_mask) | or_mask;
WREG32(reg, val);
break;
case 4:
val = RBIOS16(index);
index += 2;
udelay(val);
break;
case 5:
reg = id & 0x1fff;
and_mask = RBIOS32(index);
index += 4;
or_mask = RBIOS32(index);
index += 4;
val = RREG32_PLL(reg);
val = (val & and_mask) | or_mask;
WREG32_PLL(reg, val);
break;
case 6:
reg = id & 0x1fff;
val = RBIOS8(index);
index += 1;
radeon_i2c_do_lock(tmds->i2c_bus, 1);
radeon_i2c_sw_put_byte(tmds->i2c_bus,
tmds->slave_addr,
reg, val);
radeon_i2c_do_lock(tmds->i2c_bus, 0);
break;
default:
DRM_ERROR("Unknown id %d\n", id >> 13);
break;
}
id = RBIOS16(index);
}
return true;
}
}
return false;
}
static void combios_parse_mmio_table(struct drm_device *dev, uint16_t offset)
{
struct radeon_device *rdev = dev->dev_private;
......
......@@ -445,10 +445,10 @@ static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connec
ret = connector_status_connected;
else {
if (radeon_connector->ddc_bus) {
radeon_i2c_do_lock(radeon_connector, 1);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
radeon_connector->edid = drm_get_edid(&radeon_connector->base,
&radeon_connector->ddc_bus->adapter);
radeon_i2c_do_lock(radeon_connector, 0);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
if (radeon_connector->edid)
ret = connector_status_connected;
}
......@@ -553,17 +553,17 @@ static enum drm_connector_status radeon_vga_detect(struct drm_connector *connect
if (!encoder)
ret = connector_status_disconnected;
radeon_i2c_do_lock(radeon_connector, 1);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
dret = radeon_ddc_probe(radeon_connector);
radeon_i2c_do_lock(radeon_connector, 0);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
if (dret) {
if (radeon_connector->edid) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
}
radeon_i2c_do_lock(radeon_connector, 1);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
radeon_i2c_do_lock(radeon_connector, 0);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
if (!radeon_connector->edid) {
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
......@@ -708,17 +708,17 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
enum drm_connector_status ret = connector_status_disconnected;
bool dret;
radeon_i2c_do_lock(radeon_connector, 1);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
dret = radeon_ddc_probe(radeon_connector);
radeon_i2c_do_lock(radeon_connector, 0);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
if (dret) {
if (radeon_connector->edid) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
}
radeon_i2c_do_lock(radeon_connector, 1);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
radeon_i2c_do_lock(radeon_connector, 0);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
if (!radeon_connector->edid) {
DRM_ERROR("%s: probed a monitor but no|invalid EDID\n",
......@@ -735,6 +735,39 @@ static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connect
ret = connector_status_disconnected;
} else
ret = connector_status_connected;
/* multiple connectors on the same encoder with the same ddc line
* This tends to be HDMI and DVI on the same encoder with the
* same ddc line. If the edid says HDMI, consider the HDMI port
* connected and the DVI port disconnected. If the edid doesn't
* say HDMI, vice versa.
*/
if (radeon_connector->shared_ddc && connector_status_connected) {
struct drm_device *dev = connector->dev;
struct drm_connector *list_connector;
struct radeon_connector *list_radeon_connector;
list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
if (connector == list_connector)
continue;
list_radeon_connector = to_radeon_connector(list_connector);
if (radeon_connector->devices == list_radeon_connector->devices) {
if (drm_detect_hdmi_monitor(radeon_connector->edid)) {
if (connector->connector_type == DRM_MODE_CONNECTOR_DVID) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
ret = connector_status_disconnected;
}
} else {
if ((connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) ||
(connector->connector_type == DRM_MODE_CONNECTOR_HDMIB)) {
kfree(radeon_connector->edid);
radeon_connector->edid = NULL;
ret = connector_status_disconnected;
}
}
}
}
}
}
}
......@@ -1020,6 +1053,9 @@ radeon_add_atom_connector(struct drm_device *dev,
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.tv_std_property,
1);
}
break;
case DRM_MODE_CONNECTOR_LVDS:
......@@ -1160,6 +1196,9 @@ radeon_add_legacy_connector(struct drm_device *dev,
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.load_detect_property,
1);
drm_connector_attach_property(&radeon_connector->base,
rdev->mode_info.tv_std_property,
1);
}
break;
case DRM_MODE_CONNECTOR_LVDS:
......
......@@ -76,17 +76,17 @@ int radeon_cs_parser_relocs(struct radeon_cs_parser *p)
}
p->relocs_ptr[i] = &p->relocs[i];
p->relocs[i].robj = p->relocs[i].gobj->driver_private;
p->relocs[i].lobj.robj = p->relocs[i].robj;
p->relocs[i].lobj.bo = p->relocs[i].robj;
p->relocs[i].lobj.rdomain = r->read_domains;
p->relocs[i].lobj.wdomain = r->write_domain;
p->relocs[i].handle = r->handle;
p->relocs[i].flags = r->flags;
INIT_LIST_HEAD(&p->relocs[i].lobj.list);
radeon_object_list_add_object(&p->relocs[i].lobj,
&p->validated);
radeon_bo_list_add_object(&p->relocs[i].lobj,
&p->validated);
}
}
return radeon_object_list_validate(&p->validated, p->ib->fence);
return radeon_bo_list_validate(&p->validated, p->ib->fence);
}
int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
......@@ -190,9 +190,10 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error)
unsigned i;
if (error) {
radeon_object_list_unvalidate(&parser->validated);
radeon_bo_list_unvalidate(&parser->validated,
parser->ib->fence);
} else {
radeon_object_list_clean(&parser->validated);
radeon_bo_list_unreserve(&parser->validated);
}
for (i = 0; i < parser->nrelocs; i++) {
if (parser->relocs[i].gobj) {
......
......@@ -208,6 +208,24 @@ bool radeon_card_posted(struct radeon_device *rdev)
}
bool radeon_boot_test_post_card(struct radeon_device *rdev)
{
if (radeon_card_posted(rdev))
return true;
if (rdev->bios) {
DRM_INFO("GPU not posted. posting now...\n");
if (rdev->is_atom_bios)
atom_asic_init(rdev->mode_info.atom_context);
else
radeon_combios_asic_init(rdev->ddev);
return true;
} else {
dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
return false;
}
}
int radeon_dummy_page_init(struct radeon_device *rdev)
{
rdev->dummy_page.page = alloc_page(GFP_DMA32 | GFP_KERNEL | __GFP_ZERO);
......@@ -544,6 +562,9 @@ int radeon_device_init(struct radeon_device *rdev,
mutex_init(&rdev->cs_mutex);
mutex_init(&rdev->ib_pool.mutex);
mutex_init(&rdev->cp.mutex);
if (rdev->family >= CHIP_R600)
spin_lock_init(&rdev->ih.lock);
mutex_init(&rdev->gem.mutex);
rwlock_init(&rdev->fence_drv.lock);
INIT_LIST_HEAD(&rdev->gem.objects);
......@@ -553,7 +574,7 @@ int radeon_device_init(struct radeon_device *rdev,
return r;
}
if (radeon_agpmode == -1) {
if (rdev->flags & RADEON_IS_AGP && radeon_agpmode == -1) {
radeon_agp_disable(rdev);
}
......@@ -633,6 +654,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
{
struct radeon_device *rdev = dev->dev_private;
struct drm_crtc *crtc;
int r;
if (dev == NULL || rdev == NULL) {
return -ENODEV;
......@@ -643,18 +665,22 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
/* unpin the front buffers */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct radeon_framebuffer *rfb = to_radeon_framebuffer(crtc->fb);
struct radeon_object *robj;
struct radeon_bo *robj;
if (rfb == NULL || rfb->obj == NULL) {
continue;
}
robj = rfb->obj->driver_private;
if (robj != rdev->fbdev_robj) {
radeon_object_unpin(robj);
if (robj != rdev->fbdev_rbo) {
r = radeon_bo_reserve(robj, false);
if (unlikely(r == 0)) {
radeon_bo_unpin(robj);
radeon_bo_unreserve(robj);
}
}
}
/* evict vram memory */
radeon_object_evict_vram(rdev);
radeon_bo_evict_vram(rdev);
/* wait for gpu to finish processing current batch */
radeon_fence_wait_last(rdev);
......@@ -662,7 +688,7 @@ int radeon_suspend_kms(struct drm_device *dev, pm_message_t state)
radeon_suspend(rdev);
/* evict remaining vram memory */
radeon_object_evict_vram(rdev);
radeon_bo_evict_vram(rdev);
pci_save_state(dev->pdev);
if (state.event == PM_EVENT_SUSPEND) {
......
......@@ -270,10 +270,10 @@ static void radeon_print_display_setup(struct drm_device *dev)
radeon_connector->ddc_bus->rec.mask_data_reg,
radeon_connector->ddc_bus->rec.a_clk_reg,
radeon_connector->ddc_bus->rec.a_data_reg,
radeon_connector->ddc_bus->rec.put_clk_reg,
radeon_connector->ddc_bus->rec.put_data_reg,
radeon_connector->ddc_bus->rec.get_clk_reg,
radeon_connector->ddc_bus->rec.get_data_reg);
radeon_connector->ddc_bus->rec.en_clk_reg,
radeon_connector->ddc_bus->rec.en_data_reg,
radeon_connector->ddc_bus->rec.y_clk_reg,
radeon_connector->ddc_bus->rec.y_data_reg);
DRM_INFO(" Encoders:\n");
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
radeon_encoder = to_radeon_encoder(encoder);
......@@ -324,6 +324,7 @@ static bool radeon_setup_enc_conn(struct drm_device *dev)
ret = radeon_get_legacy_connector_info_from_table(dev);
}
if (ret) {
radeon_setup_encoder_clones(dev);
radeon_print_display_setup(dev);
list_for_each_entry(drm_connector, &dev->mode_config.connector_list, head)
radeon_ddc_dump(drm_connector);
......@@ -339,9 +340,9 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector)
if (!radeon_connector->ddc_bus)
return -1;
if (!radeon_connector->edid) {
radeon_i2c_do_lock(radeon_connector, 1);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
radeon_connector->edid = drm_get_edid(&radeon_connector->base, &radeon_connector->ddc_bus->adapter);
radeon_i2c_do_lock(radeon_connector, 0);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
}
if (radeon_connector->edid) {
......@@ -361,9 +362,9 @@ static int radeon_ddc_dump(struct drm_connector *connector)
if (!radeon_connector->ddc_bus)
return -1;
radeon_i2c_do_lock(radeon_connector, 1);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 1);
edid = drm_get_edid(connector, &radeon_connector->ddc_bus->adapter);
radeon_i2c_do_lock(radeon_connector, 0);
radeon_i2c_do_lock(radeon_connector->ddc_bus, 0);
if (edid) {
kfree(edid);
}
......@@ -750,9 +751,17 @@ bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
if (encoder->crtc != crtc)
continue;
if (first) {
radeon_crtc->rmx_type = radeon_encoder->rmx_type;
/* set scaling */
if (radeon_encoder->rmx_type == RMX_OFF)
radeon_crtc->rmx_type = RMX_OFF;
else if (mode->hdisplay < radeon_encoder->native_mode.hdisplay ||
mode->vdisplay < radeon_encoder->native_mode.vdisplay)
radeon_crtc->rmx_type = radeon_encoder->rmx_type;
else
radeon_crtc->rmx_type = RMX_OFF;
/* copy native mode */
memcpy(&radeon_crtc->native_mode,
&radeon_encoder->native_mode,
&radeon_encoder->native_mode,
sizeof(struct drm_display_mode));
first = false;
} else {
......
......@@ -1104,7 +1104,6 @@ extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index);
# define R600_IT_WAIT_REG_MEM 0x00003C00
# define R600_IT_MEM_WRITE 0x00003D00
# define R600_IT_INDIRECT_BUFFER 0x00003200
# define R600_IT_CP_INTERRUPT 0x00004000
# define R600_IT_SURFACE_SYNC 0x00004300
# define R600_CB0_DEST_BASE_ENA (1 << 6)
# define R600_TC_ACTION_ENA (1 << 23)
......
......@@ -35,6 +35,51 @@ extern int atom_debug;
bool radeon_atom_get_tv_timings(struct radeon_device *rdev, int index,
struct drm_display_mode *mode);
static uint32_t radeon_encoder_clones(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_encoder *clone_encoder;
uint32_t index_mask = 0;
int count;
/* DIG routing gets problematic */
if (rdev->family >= CHIP_R600)
return index_mask;
/* LVDS/TV are too wacky */
if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
return index_mask;
/* DVO requires 2x ppll clocks depending on tmds chip */
if (radeon_encoder->devices & ATOM_DEVICE_DFP2_SUPPORT)
return index_mask;
count = -1;
list_for_each_entry(clone_encoder, &dev->mode_config.encoder_list, head) {
struct radeon_encoder *radeon_clone = to_radeon_encoder(clone_encoder);
count++;
if (clone_encoder == encoder)
continue;
if (radeon_clone->devices & (ATOM_DEVICE_LCD_SUPPORT))
continue;
if (radeon_clone->devices & ATOM_DEVICE_DFP2_SUPPORT)
continue;
else
index_mask |= (1 << count);
}
return index_mask;
}
void radeon_setup_encoder_clones(struct drm_device *dev)
{
struct drm_encoder *encoder;
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
encoder->possible_clones = radeon_encoder_clones(encoder);
}
}
uint32_t
radeon_get_encoder_id(struct drm_device *dev, uint32_t supported_device, uint8_t dac)
{
......@@ -163,29 +208,6 @@ radeon_get_connector_for_encoder(struct drm_encoder *encoder)
return NULL;
}
/* used for both atom and legacy */
void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
if (mode->hdisplay < native_mode->hdisplay ||
mode->vdisplay < native_mode->vdisplay) {
int mode_id = adjusted_mode->base.id;
*adjusted_mode = *native_mode;
if (!ASIC_IS_AVIVO(rdev)) {
adjusted_mode->hdisplay = mode->hdisplay;
adjusted_mode->vdisplay = mode->vdisplay;
}
adjusted_mode->base.id = mode_id;
}
}
static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
......@@ -198,14 +220,24 @@ static bool radeon_atom_mode_fixup(struct drm_encoder *encoder,
radeon_encoder_set_active_device(encoder);
drm_mode_set_crtcinfo(adjusted_mode, 0);
if (radeon_encoder->rmx_type != RMX_OFF)
radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
/* hw bug */
if ((mode->flags & DRM_MODE_FLAG_INTERLACE)
&& (mode->crtc_vsync_start < (mode->crtc_vdisplay + 2)))
adjusted_mode->crtc_vsync_start = adjusted_mode->crtc_vdisplay + 2;
/* get the native mode for LVDS */
if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
int mode_id = adjusted_mode->base.id;
*adjusted_mode = *native_mode;
if (!ASIC_IS_AVIVO(rdev)) {
adjusted_mode->hdisplay = mode->hdisplay;
adjusted_mode->vdisplay = mode->vdisplay;
}
adjusted_mode->base.id = mode_id;
}
/* get the native mode for TV */
if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT)) {
struct radeon_encoder_atom_dac *tv_dac = radeon_encoder->enc_priv;
if (tv_dac) {
......@@ -392,7 +424,7 @@ union lvds_encoder_control {
LVDS_ENCODER_CONTROL_PS_ALLOCATION_V2 v2;
};
static void
void
atombios_digital_setup(struct drm_encoder *encoder, int action)
{
struct drm_device *dev = encoder->dev;
......@@ -918,12 +950,12 @@ radeon_atom_encoder_dpms(struct drm_encoder *encoder, int mode)
if (is_dig) {
switch (mode) {
case DRM_MODE_DPMS_ON:
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT);
break;
case DRM_MODE_DPMS_STANDBY:
case DRM_MODE_DPMS_SUSPEND:
case DRM_MODE_DPMS_OFF:
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE);
atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT);
break;
}
} else {
......@@ -1354,7 +1386,6 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
encoder->possible_crtcs = 0x1;
else
encoder->possible_crtcs = 0x3;
encoder->possible_clones = 0;
radeon_encoder->enc_priv = NULL;
......
......@@ -140,7 +140,7 @@ int radeonfb_create(struct drm_device *dev,
struct radeon_framebuffer *rfb;
struct drm_mode_fb_cmd mode_cmd;
struct drm_gem_object *gobj = NULL;
struct radeon_object *robj = NULL;
struct radeon_bo *rbo = NULL;
struct device *device = &rdev->pdev->dev;
int size, aligned_size, ret;
u64 fb_gpuaddr;
......@@ -168,14 +168,14 @@ int radeonfb_create(struct drm_device *dev,
ret = radeon_gem_object_create(rdev, aligned_size, 0,
RADEON_GEM_DOMAIN_VRAM,
false, ttm_bo_type_kernel,
false, &gobj);
&gobj);
if (ret) {
printk(KERN_ERR "failed to allocate framebuffer (%d %d)\n",
surface_width, surface_height);
ret = -ENOMEM;
goto out;
}
robj = gobj->driver_private;
rbo = gobj->driver_private;
if (fb_tiled)
tiling_flags = RADEON_TILING_MACRO;
......@@ -192,8 +192,13 @@ int radeonfb_create(struct drm_device *dev,
}
#endif
if (tiling_flags)
radeon_object_set_tiling_flags(robj, tiling_flags | RADEON_TILING_SURFACE, mode_cmd.pitch);
if (tiling_flags) {
ret = radeon_bo_set_tiling_flags(rbo,
tiling_flags | RADEON_TILING_SURFACE,
mode_cmd.pitch);
if (ret)
dev_err(rdev->dev, "FB failed to set tiling flags\n");
}
mutex_lock(&rdev->ddev->struct_mutex);
fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
if (fb == NULL) {
......@@ -201,10 +206,19 @@ int radeonfb_create(struct drm_device *dev,
ret = -ENOMEM;
goto out_unref;
}
ret = radeon_object_pin(robj, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
ret = radeon_bo_reserve(rbo, false);
if (unlikely(ret != 0))
goto out_unref;
ret = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &fb_gpuaddr);
if (ret) {
radeon_bo_unreserve(rbo);
goto out_unref;
}
if (fb_tiled)
radeon_bo_check_tiling(rbo, 0, 0);
ret = radeon_bo_kmap(rbo, &fbptr);
radeon_bo_unreserve(rbo);
if (ret) {
printk(KERN_ERR "failed to pin framebuffer\n");
ret = -ENOMEM;
goto out_unref;
}
......@@ -213,7 +227,7 @@ int radeonfb_create(struct drm_device *dev,
*fb_p = fb;
rfb = to_radeon_framebuffer(fb);
rdev->fbdev_rfb = rfb;
rdev->fbdev_robj = robj;
rdev->fbdev_rbo = rbo;
info = framebuffer_alloc(sizeof(struct radeon_fb_device), device);
if (info == NULL) {
......@@ -234,15 +248,7 @@ int radeonfb_create(struct drm_device *dev,
if (ret)
goto out_unref;
if (fb_tiled)
radeon_object_check_tiling(robj, 0, 0);
ret = radeon_object_kmap(robj, &fbptr);
if (ret) {
goto out_unref;
}
memset_io(fbptr, 0, aligned_size);
memset_io(fbptr, 0xff, aligned_size);
strcpy(info->fix.id, "radeondrmfb");
......@@ -288,8 +294,12 @@ int radeonfb_create(struct drm_device *dev,
return 0;
out_unref:
if (robj) {
radeon_object_kunmap(robj);
if (rbo) {
ret = radeon_bo_reserve(rbo, false);
if (likely(ret == 0)) {
radeon_bo_kunmap(rbo);
radeon_bo_unreserve(rbo);
}
}
if (fb && ret) {
list_del(&fb->filp_head);
......@@ -321,14 +331,22 @@ int radeon_parse_options(char *options)
int radeonfb_probe(struct drm_device *dev)
{
return drm_fb_helper_single_fb_probe(dev, 32, &radeonfb_create);
struct radeon_device *rdev = dev->dev_private;
int bpp_sel = 32;
/* select 8 bpp console on RN50 or 16MB cards */
if (ASIC_IS_RN50(rdev) || rdev->mc.real_vram_size <= (32*1024*1024))
bpp_sel = 8;
return drm_fb_helper_single_fb_probe(dev, bpp_sel, &radeonfb_create);
}
int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
{
struct fb_info *info;
struct radeon_framebuffer *rfb = to_radeon_framebuffer(fb);
struct radeon_object *robj;
struct radeon_bo *rbo;
int r;
if (!fb) {
return -EINVAL;
......@@ -336,10 +354,14 @@ int radeonfb_remove(struct drm_device *dev, struct drm_framebuffer *fb)
info = fb->fbdev;
if (info) {
struct radeon_fb_device *rfbdev = info->par;
robj = rfb->obj->driver_private;
rbo = rfb->obj->driver_private;
unregister_framebuffer(info);
radeon_object_kunmap(robj);
radeon_object_unpin(robj);
r = radeon_bo_reserve(rbo, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rbo);
radeon_bo_unpin(rbo);
radeon_bo_unreserve(rbo);
}
drm_fb_helper_free(&rfbdev->helper);
framebuffer_release(info);
}
......
......@@ -168,37 +168,6 @@ bool radeon_fence_signaled(struct radeon_fence *fence)
return signaled;
}
int r600_fence_wait(struct radeon_fence *fence, bool intr, bool lazy)
{
struct radeon_device *rdev;
int ret = 0;
rdev = fence->rdev;
__set_current_state(intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE);
while (1) {
if (radeon_fence_signaled(fence))
break;
if (time_after_eq(jiffies, fence->timeout)) {
ret = -EBUSY;
break;
}
if (lazy)
schedule_timeout(1);
if (intr && signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
}
__set_current_state(TASK_RUNNING);
return ret;
}
int radeon_fence_wait(struct radeon_fence *fence, bool intr)
{
struct radeon_device *rdev;
......@@ -216,13 +185,6 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
return 0;
}
if (rdev->family >= CHIP_R600) {
r = r600_fence_wait(fence, intr, 0);
if (r == -ERESTARTSYS)
return -EBUSY;
return r;
}
retry:
cur_jiffies = jiffies;
timeout = HZ / 100;
......@@ -231,14 +193,18 @@ int radeon_fence_wait(struct radeon_fence *fence, bool intr)
}
if (intr) {
radeon_irq_kms_sw_irq_get(rdev);
r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
radeon_fence_signaled(fence), timeout);
radeon_irq_kms_sw_irq_put(rdev);
if (unlikely(r == -ERESTARTSYS)) {
return -EBUSY;
}
} else {
radeon_irq_kms_sw_irq_get(rdev);
r = wait_event_timeout(rdev->fence_drv.queue,
radeon_fence_signaled(fence), timeout);
radeon_irq_kms_sw_irq_put(rdev);
}
if (unlikely(!radeon_fence_signaled(fence))) {
if (unlikely(r == 0)) {
......
......@@ -78,11 +78,9 @@ int radeon_gart_table_vram_alloc(struct radeon_device *rdev)
int r;
if (rdev->gart.table.vram.robj == NULL) {
r = radeon_object_create(rdev, NULL,
rdev->gart.table_size,
true,
RADEON_GEM_DOMAIN_VRAM,
false, &rdev->gart.table.vram.robj);
r = radeon_bo_create(rdev, NULL, rdev->gart.table_size,
true, RADEON_GEM_DOMAIN_VRAM,
&rdev->gart.table.vram.robj);
if (r) {
return r;
}
......@@ -95,32 +93,38 @@ int radeon_gart_table_vram_pin(struct radeon_device *rdev)
uint64_t gpu_addr;
int r;
r = radeon_object_pin(rdev->gart.table.vram.robj,
RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
if (r) {
radeon_object_unref(&rdev->gart.table.vram.robj);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (unlikely(r != 0))
return r;
}
r = radeon_object_kmap(rdev->gart.table.vram.robj,
(void **)&rdev->gart.table.vram.ptr);
r = radeon_bo_pin(rdev->gart.table.vram.robj,
RADEON_GEM_DOMAIN_VRAM, &gpu_addr);
if (r) {
radeon_object_unpin(rdev->gart.table.vram.robj);
radeon_object_unref(&rdev->gart.table.vram.robj);
DRM_ERROR("radeon: failed to map gart vram table.\n");
radeon_bo_unreserve(rdev->gart.table.vram.robj);
return r;
}
r = radeon_bo_kmap(rdev->gart.table.vram.robj,
(void **)&rdev->gart.table.vram.ptr);
if (r)
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
rdev->gart.table_addr = gpu_addr;
return 0;
return r;
}
void radeon_gart_table_vram_free(struct radeon_device *rdev)
{
int r;
if (rdev->gart.table.vram.robj == NULL) {
return;
}
radeon_object_kunmap(rdev->gart.table.vram.robj);
radeon_object_unpin(rdev->gart.table.vram.robj);
radeon_object_unref(&rdev->gart.table.vram.robj);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
radeon_bo_unref(&rdev->gart.table.vram.robj);
}
......
......@@ -38,22 +38,21 @@ int radeon_gem_object_init(struct drm_gem_object *obj)
void radeon_gem_object_free(struct drm_gem_object *gobj)
{
struct radeon_object *robj = gobj->driver_private;
struct radeon_bo *robj = gobj->driver_private;
gobj->driver_private = NULL;
if (robj) {
radeon_object_unref(&robj);
radeon_bo_unref(&robj);
}
}
int radeon_gem_object_create(struct radeon_device *rdev, int size,
int alignment, int initial_domain,
bool discardable, bool kernel,
bool interruptible,
struct drm_gem_object **obj)
int alignment, int initial_domain,
bool discardable, bool kernel,
struct drm_gem_object **obj)
{
struct drm_gem_object *gobj;
struct radeon_object *robj;
struct radeon_bo *robj;
int r;
*obj = NULL;
......@@ -65,8 +64,7 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
if (alignment < PAGE_SIZE) {
alignment = PAGE_SIZE;
}
r = radeon_object_create(rdev, gobj, size, kernel, initial_domain,
interruptible, &robj);
r = radeon_bo_create(rdev, gobj, size, kernel, initial_domain, &robj);
if (r) {
DRM_ERROR("Failed to allocate GEM object (%d, %d, %u)\n",
size, initial_domain, alignment);
......@@ -83,33 +81,33 @@ int radeon_gem_object_create(struct radeon_device *rdev, int size,
int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
uint64_t *gpu_addr)
{
struct radeon_object *robj = obj->driver_private;
uint32_t flags;
struct radeon_bo *robj = obj->driver_private;
int r;
switch (pin_domain) {
case RADEON_GEM_DOMAIN_VRAM:
flags = TTM_PL_FLAG_VRAM;
break;
case RADEON_GEM_DOMAIN_GTT:
flags = TTM_PL_FLAG_TT;
break;
default:
flags = TTM_PL_FLAG_SYSTEM;
break;
}
return radeon_object_pin(robj, flags, gpu_addr);
r = radeon_bo_reserve(robj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(robj, pin_domain, gpu_addr);
radeon_bo_unreserve(robj);
return r;
}
void radeon_gem_object_unpin(struct drm_gem_object *obj)
{
struct radeon_object *robj = obj->driver_private;
radeon_object_unpin(robj);
struct radeon_bo *robj = obj->driver_private;
int r;
r = radeon_bo_reserve(robj, false);
if (likely(r == 0)) {
radeon_bo_unpin(robj);
radeon_bo_unreserve(robj);
}
}
int radeon_gem_set_domain(struct drm_gem_object *gobj,
uint32_t rdomain, uint32_t wdomain)
{
struct radeon_object *robj;
struct radeon_bo *robj;
uint32_t domain;
int r;
......@@ -127,11 +125,12 @@ int radeon_gem_set_domain(struct drm_gem_object *gobj,
}
if (domain == RADEON_GEM_DOMAIN_CPU) {
/* Asking for cpu access wait for object idle */
r = radeon_object_wait(robj);
r = radeon_bo_wait(robj, NULL, false);
if (r) {
printk(KERN_ERR "Failed to wait for object !\n");
return r;
}
radeon_hdp_flush(robj->rdev);
}
return 0;
}
......@@ -144,7 +143,7 @@ int radeon_gem_init(struct radeon_device *rdev)
void radeon_gem_fini(struct radeon_device *rdev)
{
radeon_object_force_delete(rdev);
radeon_bo_force_delete(rdev);
}
......@@ -158,9 +157,13 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
struct drm_radeon_gem_info *args = data;
args->vram_size = rdev->mc.real_vram_size;
/* FIXME: report somethings that makes sense */
args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024);
args->gart_size = rdev->mc.gtt_size;
args->vram_visible = rdev->mc.real_vram_size;
if (rdev->stollen_vga_memory)
args->vram_visible -= radeon_bo_size(rdev->stollen_vga_memory);
if (rdev->fbdev_rbo)
args->vram_visible -= radeon_bo_size(rdev->fbdev_rbo);
args->gart_size = rdev->mc.gtt_size - rdev->cp.ring_size - 4096 -
RADEON_IB_POOL_SIZE*64*1024;
return 0;
}
......@@ -192,8 +195,8 @@ int radeon_gem_create_ioctl(struct drm_device *dev, void *data,
/* create a gem object to contain this object in */
args->size = roundup(args->size, PAGE_SIZE);
r = radeon_gem_object_create(rdev, args->size, args->alignment,
args->initial_domain, false,
false, true, &gobj);
args->initial_domain, false,
false, &gobj);
if (r) {
return r;
}
......@@ -218,7 +221,7 @@ int radeon_gem_set_domain_ioctl(struct drm_device *dev, void *data,
* just validate the BO into a certain domain */
struct drm_radeon_gem_set_domain *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
struct radeon_bo *robj;
int r;
/* for now if someone requests domain CPU -
......@@ -244,19 +247,18 @@ int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
{
struct drm_radeon_gem_mmap *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
int r;
struct radeon_bo *robj;
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL) {
return -EINVAL;
}
robj = gobj->driver_private;
r = radeon_object_mmap(robj, &args->addr_ptr);
args->addr_ptr = radeon_bo_mmap_offset(robj);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
return r;
return 0;
}
int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
......@@ -264,7 +266,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
{
struct drm_radeon_gem_busy *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
struct radeon_bo *robj;
int r;
uint32_t cur_placement;
......@@ -273,7 +275,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
robj = gobj->driver_private;
r = radeon_object_busy_domain(robj, &cur_placement);
r = radeon_bo_wait(robj, &cur_placement, true);
switch (cur_placement) {
case TTM_PL_VRAM:
args->domain = RADEON_GEM_DOMAIN_VRAM;
......@@ -297,7 +299,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
{
struct drm_radeon_gem_wait_idle *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
struct radeon_bo *robj;
int r;
gobj = drm_gem_object_lookup(dev, filp, args->handle);
......@@ -305,10 +307,11 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
robj = gobj->driver_private;
r = radeon_object_wait(robj);
r = radeon_bo_wait(robj, NULL, false);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
radeon_hdp_flush(robj->rdev);
return r;
}
......@@ -317,7 +320,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
{
struct drm_radeon_gem_set_tiling *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
struct radeon_bo *robj;
int r = 0;
DRM_DEBUG("%d \n", args->handle);
......@@ -325,7 +328,7 @@ int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
if (gobj == NULL)
return -EINVAL;
robj = gobj->driver_private;
radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch);
r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
......@@ -337,16 +340,19 @@ int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
{
struct drm_radeon_gem_get_tiling *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
struct radeon_bo *rbo;
int r = 0;
DRM_DEBUG("\n");
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL)
return -EINVAL;
robj = gobj->driver_private;
radeon_object_get_tiling_flags(robj, &args->tiling_flags,
&args->pitch);
rbo = gobj->driver_private;
r = radeon_bo_reserve(rbo, false);
if (unlikely(r != 0))
return r;
radeon_bo_get_tiling_flags(rbo, &args->tiling_flags, &args->pitch);
radeon_bo_unreserve(rbo);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
......
......@@ -59,11 +59,11 @@ bool radeon_ddc_probe(struct radeon_connector *radeon_connector)
}
void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state)
void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state)
{
struct radeon_device *rdev = radeon_connector->base.dev->dev_private;
struct radeon_device *rdev = i2c->dev->dev_private;
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t temp;
struct radeon_i2c_bus_rec *rec = &radeon_connector->ddc_bus->rec;
/* RV410 appears to have a bug where the hw i2c in reset
* holds the i2c port in a bad state - switch hw i2c away before
......@@ -78,16 +78,16 @@ void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_stat
R200_DVI_I2C_PIN_SEL(R200_SEL_DDC3)));
}
}
if (lock_state) {
temp = RREG32(rec->a_clk_reg);
temp &= ~(rec->a_clk_mask);
WREG32(rec->a_clk_reg, temp);
temp = RREG32(rec->a_data_reg);
temp &= ~(rec->a_data_mask);
WREG32(rec->a_data_reg, temp);
}
/* clear the output pin values */
temp = RREG32(rec->a_clk_reg) & ~rec->a_clk_mask;
WREG32(rec->a_clk_reg, temp);
temp = RREG32(rec->a_data_reg) & ~rec->a_data_mask;
WREG32(rec->a_data_reg, temp);
/* mask the gpio pins for software use */
temp = RREG32(rec->mask_clk_reg);
if (lock_state)
temp |= rec->mask_clk_mask;
......@@ -112,8 +112,9 @@ static int get_clock(void *i2c_priv)
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RREG32(rec->get_clk_reg);
val &= rec->get_clk_mask;
/* read the value off the pin */
val = RREG32(rec->y_clk_reg);
val &= rec->y_clk_mask;
return (val != 0);
}
......@@ -126,8 +127,10 @@ static int get_data(void *i2c_priv)
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RREG32(rec->get_data_reg);
val &= rec->get_data_mask;
/* read the value off the pin */
val = RREG32(rec->y_data_reg);
val &= rec->y_data_mask;
return (val != 0);
}
......@@ -138,9 +141,10 @@ static void set_clock(void *i2c_priv, int clock)
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RREG32(rec->put_clk_reg) & (uint32_t)~(rec->put_clk_mask);
val |= clock ? 0 : rec->put_clk_mask;
WREG32(rec->put_clk_reg, val);
/* set pin direction */
val = RREG32(rec->en_clk_reg) & ~rec->en_clk_mask;
val |= clock ? 0 : rec->en_clk_mask;
WREG32(rec->en_clk_reg, val);
}
static void set_data(void *i2c_priv, int data)
......@@ -150,14 +154,15 @@ static void set_data(void *i2c_priv, int data)
struct radeon_i2c_bus_rec *rec = &i2c->rec;
uint32_t val;
val = RREG32(rec->put_data_reg) & (uint32_t)~(rec->put_data_mask);
val |= data ? 0 : rec->put_data_mask;
WREG32(rec->put_data_reg, val);
/* set pin direction */
val = RREG32(rec->en_data_reg) & ~rec->en_data_mask;
val |= data ? 0 : rec->en_data_mask;
WREG32(rec->en_data_reg, val);
}
struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name)
struct radeon_i2c_bus_rec *rec,
const char *name)
{
struct radeon_i2c_chan *i2c;
int ret;
......@@ -207,3 +212,59 @@ struct drm_encoder *radeon_best_encoder(struct drm_connector *connector)
{
return NULL;
}
void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
u8 slave_addr,
u8 addr,
u8 *val)
{
u8 out_buf[2];
u8 in_buf[2];
struct i2c_msg msgs[] = {
{
.addr = slave_addr,
.flags = 0,
.len = 1,
.buf = out_buf,
},
{
.addr = slave_addr,
.flags = I2C_M_RD,
.len = 1,
.buf = in_buf,
}
};
out_buf[0] = addr;
out_buf[1] = 0;
if (i2c_transfer(&i2c_bus->adapter, msgs, 2) == 2) {
*val = in_buf[0];
DRM_DEBUG("val = 0x%02x\n", *val);
} else {
DRM_ERROR("i2c 0x%02x 0x%02x read failed\n",
addr, *val);
}
}
void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c_bus,
u8 slave_addr,
u8 addr,
u8 val)
{
uint8_t out_buf[2];
struct i2c_msg msg = {
.addr = slave_addr,
.flags = 0,
.len = 2,
.buf = out_buf,
};
out_buf[0] = addr;
out_buf[1] = val;
if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1)
DRM_ERROR("i2c 0x%02x 0x%02x write failed\n",
addr, val);
}
......@@ -87,17 +87,25 @@ int radeon_irq_kms_init(struct radeon_device *rdev)
if (rdev->flags & RADEON_SINGLE_CRTC)
num_crtc = 1;
spin_lock_init(&rdev->irq.sw_lock);
r = drm_vblank_init(rdev->ddev, num_crtc);
if (r) {
return r;
}
/* enable msi */
rdev->msi_enabled = 0;
if (rdev->family >= CHIP_RV380) {
/* MSIs don't seem to work on my rs780;
* not sure about rs880 or other rs780s.
* Needs more investigation.
*/
if ((rdev->family >= CHIP_RV380) &&
(rdev->family != CHIP_RS780) &&
(rdev->family != CHIP_RS880)) {
int ret = pci_enable_msi(rdev->pdev);
if (!ret)
if (!ret) {
rdev->msi_enabled = 1;
DRM_INFO("radeon: using MSI.\n");
}
}
drm_irq_install(rdev->ddev);
rdev->irq.installed = true;
......@@ -114,3 +122,29 @@ void radeon_irq_kms_fini(struct radeon_device *rdev)
pci_disable_msi(rdev->pdev);
}
}
void radeon_irq_kms_sw_irq_get(struct radeon_device *rdev)
{
unsigned long irqflags;
spin_lock_irqsave(&rdev->irq.sw_lock, irqflags);
if (rdev->ddev->irq_enabled && (++rdev->irq.sw_refcount == 1)) {
rdev->irq.sw_int = true;
radeon_irq_set(rdev);
}
spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags);
}
void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev)
{
unsigned long irqflags;
spin_lock_irqsave(&rdev->irq.sw_lock, irqflags);
BUG_ON(rdev->ddev->irq_enabled && rdev->irq.sw_refcount <= 0);
if (rdev->ddev->irq_enabled && (--rdev->irq.sw_refcount == 0)) {
rdev->irq.sw_int = false;
radeon_irq_set(rdev);
}
spin_unlock_irqrestore(&rdev->irq.sw_lock, irqflags);
}
......@@ -30,6 +30,18 @@
#include "radeon.h"
#include "atom.h"
static void radeon_overscan_setup(struct drm_crtc *crtc,
struct drm_display_mode *mode)
{
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
WREG32(RADEON_OVR_CLR + radeon_crtc->crtc_offset, 0);
WREG32(RADEON_OVR_WID_LEFT_RIGHT + radeon_crtc->crtc_offset, 0);
WREG32(RADEON_OVR_WID_TOP_BOTTOM + radeon_crtc->crtc_offset, 0);
}
static void radeon_legacy_rmx_mode_set(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
......@@ -292,8 +304,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
uint32_t mask;
if (radeon_crtc->crtc_id)
mask = (RADEON_CRTC2_EN |
RADEON_CRTC2_DISP_DIS |
mask = (RADEON_CRTC2_DISP_DIS |
RADEON_CRTC2_VSYNC_DIS |
RADEON_CRTC2_HSYNC_DIS |
RADEON_CRTC2_DISP_REQ_EN_B);
......@@ -305,7 +316,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
switch (mode) {
case DRM_MODE_DPMS_ON:
if (radeon_crtc->crtc_id)
WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~mask);
WREG32_P(RADEON_CRTC2_GEN_CNTL, RADEON_CRTC2_EN, ~(RADEON_CRTC2_EN | mask));
else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_EN, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B));
......@@ -319,7 +330,7 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode)
case DRM_MODE_DPMS_OFF:
drm_vblank_pre_modeset(dev, radeon_crtc->crtc_id);
if (radeon_crtc->crtc_id)
WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~mask);
WREG32_P(RADEON_CRTC2_GEN_CNTL, mask, ~(RADEON_CRTC2_EN | mask));
else {
WREG32_P(RADEON_CRTC_GEN_CNTL, RADEON_CRTC_DISP_REQ_EN_B, ~(RADEON_CRTC_EN |
RADEON_CRTC_DISP_REQ_EN_B));
......@@ -400,14 +411,21 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct radeon_framebuffer *radeon_fb;
struct drm_gem_object *obj;
struct radeon_bo *rbo;
uint64_t base;
uint32_t crtc_offset, crtc_offset_cntl, crtc_tile_x0_y0 = 0;
uint32_t crtc_pitch, pitch_pixels;
uint32_t tiling_flags;
int format;
uint32_t gen_cntl_reg, gen_cntl_val;
int r;
DRM_DEBUG("\n");
/* no fb bound */
if (!crtc->fb) {
DRM_DEBUG("No FB bound\n");
return 0;
}
radeon_fb = to_radeon_framebuffer(crtc->fb);
......@@ -431,10 +449,22 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
return false;
}
/* Pin framebuffer & get tilling informations */
obj = radeon_fb->obj;
if (radeon_gem_object_pin(obj, RADEON_GEM_DOMAIN_VRAM, &base)) {
rbo = obj->driver_private;
r = radeon_bo_reserve(rbo, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rbo, RADEON_GEM_DOMAIN_VRAM, &base);
if (unlikely(r != 0)) {
radeon_bo_unreserve(rbo);
return -EINVAL;
}
radeon_bo_get_tiling_flags(rbo, &tiling_flags, NULL);
radeon_bo_unreserve(rbo);
if (tiling_flags & RADEON_TILING_MICRO)
DRM_ERROR("trying to scanout microtiled buffer\n");
/* if scanout was in GTT this really wouldn't work */
/* crtc offset is from display base addr not FB location */
radeon_crtc->legacy_display_base_addr = rdev->mc.vram_location;
......@@ -449,10 +479,6 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
(crtc->fb->bits_per_pixel * 8));
crtc_pitch |= crtc_pitch << 16;
radeon_object_get_tiling_flags(obj->driver_private,
&tiling_flags, NULL);
if (tiling_flags & RADEON_TILING_MICRO)
DRM_ERROR("trying to scanout microtiled buffer\n");
if (tiling_flags & RADEON_TILING_MACRO) {
if (ASIC_IS_R300(rdev))
......@@ -530,7 +556,12 @@ int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y,
if (old_fb && old_fb != crtc->fb) {
radeon_fb = to_radeon_framebuffer(old_fb);
radeon_gem_object_unpin(radeon_fb->obj);
rbo = radeon_fb->obj->driver_private;
r = radeon_bo_reserve(rbo, false);
if (unlikely(r != 0))
return r;
radeon_bo_unpin(rbo);
radeon_bo_unreserve(rbo);
}
/* Bytes per pixel may have changed */
......@@ -642,12 +673,8 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
uint32_t crtc2_gen_cntl;
uint32_t disp2_merge_cntl;
/* check to see if TV DAC is enabled for another crtc and keep it enabled */
if (RREG32(RADEON_CRTC2_GEN_CNTL) & RADEON_CRTC2_CRT2_ON)
crtc2_gen_cntl = RADEON_CRTC2_CRT2_ON;
else
crtc2_gen_cntl = 0;
/* if TV DAC is enabled for another crtc and keep it enabled */
crtc2_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0x00718080;
crtc2_gen_cntl |= ((format << 8)
| RADEON_CRTC2_VSYNC_DIS
| RADEON_CRTC2_HSYNC_DIS
......@@ -676,7 +703,8 @@ static bool radeon_set_crtc_timing(struct drm_crtc *crtc, struct drm_display_mod
uint32_t crtc_ext_cntl;
uint32_t disp_merge_cntl;
crtc_gen_cntl = (RADEON_CRTC_EXT_DISP_EN
crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0x00718000;
crtc_gen_cntl |= (RADEON_CRTC_EXT_DISP_EN
| (format << 8)
| RADEON_CRTC_DISP_REQ_EN_B
| ((mode->flags & DRM_MODE_FLAG_DBLSCAN)
......@@ -779,15 +807,17 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
pll_flags |= RADEON_PLL_NO_ODD_POST_DIV;
if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
if (lvds) {
if (lvds->use_bios_dividers) {
pll_ref_div = lvds->panel_ref_divider;
pll_fb_post_div = (lvds->panel_fb_divider |
(lvds->panel_post_divider << 16));
htotal_cntl = 0;
use_bios_divs = true;
if (!rdev->is_atom_bios) {
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
if (lvds) {
if (lvds->use_bios_dividers) {
pll_ref_div = lvds->panel_ref_divider;
pll_fb_post_div = (lvds->panel_fb_divider |
(lvds->panel_post_divider << 16));
htotal_cntl = 0;
use_bios_divs = true;
}
}
}
pll_flags |= RADEON_PLL_USE_REF_DIV;
......@@ -1027,6 +1057,7 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
radeon_crtc_set_base(crtc, x, y, old_fb);
radeon_set_crtc_timing(crtc, adjusted_mode);
radeon_set_pll(crtc, adjusted_mode);
radeon_overscan_setup(crtc, adjusted_mode);
if (radeon_crtc->crtc_id == 0) {
radeon_legacy_rmx_mode_set(crtc, mode, adjusted_mode);
} else {
......@@ -1042,12 +1073,29 @@ static int radeon_crtc_mode_set(struct drm_crtc *crtc,
static void radeon_crtc_prepare(struct drm_crtc *crtc)
{
radeon_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
struct drm_device *dev = crtc->dev;
struct drm_crtc *crtci;
/*
* The hardware wedges sometimes if you reconfigure one CRTC
* whilst another is running (see fdo bug #24611).
*/
list_for_each_entry(crtci, &dev->mode_config.crtc_list, head)
radeon_crtc_dpms(crtci, DRM_MODE_DPMS_OFF);
}
static void radeon_crtc_commit(struct drm_crtc *crtc)
{
radeon_crtc_dpms(crtc, DRM_MODE_DPMS_ON);
struct drm_device *dev = crtc->dev;
struct drm_crtc *crtci;
/*
* Reenable the CRTCs that should be running.
*/
list_for_each_entry(crtci, &dev->mode_config.crtc_list, head) {
if (crtci->enabled)
radeon_crtc_dpms(crtci, DRM_MODE_DPMS_ON);
}
}
static const struct drm_crtc_helper_funcs legacy_helper_funcs = {
......
......@@ -136,7 +136,14 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
lvds_ss_gen_cntl = RREG32(RADEON_LVDS_SS_GEN_CNTL);
if ((!rdev->is_atom_bios)) {
if (rdev->is_atom_bios) {
/* LVDS_GEN_CNTL parameters are computed in LVDSEncoderControl
* need to call that on resume to set up the reg properly.
*/
radeon_encoder->pixel_clock = adjusted_mode->clock;
atombios_digital_setup(encoder, PANEL_ENCODER_ACTION_ENABLE);
lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
} else {
struct radeon_encoder_lvds *lvds = (struct radeon_encoder_lvds *)radeon_encoder->enc_priv;
if (lvds) {
DRM_DEBUG("bios LVDS_GEN_CNTL: 0x%x\n", lvds->lvds_gen_cntl);
......@@ -147,8 +154,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
(lvds->panel_blon_delay << RADEON_LVDS_PWRSEQ_DELAY2_SHIFT));
} else
lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
} else
lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
}
lvds_gen_cntl |= RADEON_LVDS_DISPLAY_DIS;
lvds_gen_cntl &= ~(RADEON_LVDS_ON |
RADEON_LVDS_BLON |
......@@ -184,9 +190,9 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
}
static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
static bool radeon_legacy_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
......@@ -194,15 +200,22 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
radeon_encoder_set_active_device(encoder);
drm_mode_set_crtcinfo(adjusted_mode, 0);
if (radeon_encoder->rmx_type != RMX_OFF)
radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
/* get the native mode for LVDS */
if (radeon_encoder->active_device & (ATOM_DEVICE_LCD_SUPPORT)) {
struct drm_display_mode *native_mode = &radeon_encoder->native_mode;
int mode_id = adjusted_mode->base.id;
*adjusted_mode = *native_mode;
adjusted_mode->hdisplay = mode->hdisplay;
adjusted_mode->vdisplay = mode->vdisplay;
adjusted_mode->base.id = mode_id;
}
return true;
}
static const struct drm_encoder_helper_funcs radeon_legacy_lvds_helper_funcs = {
.dpms = radeon_legacy_lvds_dpms,
.mode_fixup = radeon_legacy_lvds_mode_fixup,
.mode_fixup = radeon_legacy_mode_fixup,
.prepare = radeon_legacy_lvds_prepare,
.mode_set = radeon_legacy_lvds_mode_set,
.commit = radeon_legacy_lvds_commit,
......@@ -214,17 +227,6 @@ static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
.destroy = radeon_enc_destroy,
};
static bool radeon_legacy_primary_dac_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
/* set the active encoder to connector routing */
radeon_encoder_set_active_device(encoder);
drm_mode_set_crtcinfo(adjusted_mode, 0);
return true;
}
static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
......@@ -410,7 +412,7 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc
static const struct drm_encoder_helper_funcs radeon_legacy_primary_dac_helper_funcs = {
.dpms = radeon_legacy_primary_dac_dpms,
.mode_fixup = radeon_legacy_primary_dac_mode_fixup,
.mode_fixup = radeon_legacy_mode_fixup,
.prepare = radeon_legacy_primary_dac_prepare,
.mode_set = radeon_legacy_primary_dac_mode_set,
.commit = radeon_legacy_primary_dac_commit,
......@@ -423,16 +425,6 @@ static const struct drm_encoder_funcs radeon_legacy_primary_dac_enc_funcs = {
.destroy = radeon_enc_destroy,
};
static bool radeon_legacy_tmds_int_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
drm_mode_set_crtcinfo(adjusted_mode, 0);
return true;
}
static void radeon_legacy_tmds_int_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
......@@ -584,7 +576,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
static const struct drm_encoder_helper_funcs radeon_legacy_tmds_int_helper_funcs = {
.dpms = radeon_legacy_tmds_int_dpms,
.mode_fixup = radeon_legacy_tmds_int_mode_fixup,
.mode_fixup = radeon_legacy_mode_fixup,
.prepare = radeon_legacy_tmds_int_prepare,
.mode_set = radeon_legacy_tmds_int_mode_set,
.commit = radeon_legacy_tmds_int_commit,
......@@ -596,17 +588,6 @@ static const struct drm_encoder_funcs radeon_legacy_tmds_int_enc_funcs = {
.destroy = radeon_enc_destroy,
};
static bool radeon_legacy_tmds_ext_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
/* set the active encoder to connector routing */
radeon_encoder_set_active_device(encoder);
drm_mode_set_crtcinfo(adjusted_mode, 0);
return true;
}
static void radeon_legacy_tmds_ext_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
......@@ -697,6 +678,8 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
/*if (mode->clock > 165000)
fp2_gen_cntl |= R300_FP2_DVO_DUAL_CHANNEL_EN;*/
}
if (!radeon_combios_external_tmds_setup(encoder))
radeon_external_tmds_setup(encoder);
}
if (radeon_crtc->crtc_id == 0) {
......@@ -724,9 +707,22 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
radeon_combios_encoder_crtc_scratch_regs(encoder, radeon_crtc->crtc_id);
}
static void radeon_ext_tmds_enc_destroy(struct drm_encoder *encoder)
{
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_ext_tmds *tmds = radeon_encoder->enc_priv;
if (tmds) {
if (tmds->i2c_bus)
radeon_i2c_destroy(tmds->i2c_bus);
}
kfree(radeon_encoder->enc_priv);
drm_encoder_cleanup(encoder);
kfree(radeon_encoder);
}
static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs = {
.dpms = radeon_legacy_tmds_ext_dpms,
.mode_fixup = radeon_legacy_tmds_ext_mode_fixup,
.mode_fixup = radeon_legacy_mode_fixup,
.prepare = radeon_legacy_tmds_ext_prepare,
.mode_set = radeon_legacy_tmds_ext_mode_set,
.commit = radeon_legacy_tmds_ext_commit,
......@@ -735,20 +731,9 @@ static const struct drm_encoder_helper_funcs radeon_legacy_tmds_ext_helper_funcs
static const struct drm_encoder_funcs radeon_legacy_tmds_ext_enc_funcs = {
.destroy = radeon_enc_destroy,
.destroy = radeon_ext_tmds_enc_destroy,
};
static bool radeon_legacy_tv_dac_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
/* set the active encoder to connector routing */
radeon_encoder_set_active_device(encoder);
drm_mode_set_crtcinfo(adjusted_mode, 0);
return true;
}
static void radeon_legacy_tv_dac_dpms(struct drm_encoder *encoder, int mode)
{
struct drm_device *dev = encoder->dev;
......@@ -1265,7 +1250,7 @@ static enum drm_connector_status radeon_legacy_tv_dac_detect(struct drm_encoder
static const struct drm_encoder_helper_funcs radeon_legacy_tv_dac_helper_funcs = {
.dpms = radeon_legacy_tv_dac_dpms,
.mode_fixup = radeon_legacy_tv_dac_mode_fixup,
.mode_fixup = radeon_legacy_mode_fixup,
.prepare = radeon_legacy_tv_dac_prepare,
.mode_set = radeon_legacy_tv_dac_mode_set,
.commit = radeon_legacy_tv_dac_commit,
......@@ -1302,6 +1287,29 @@ static struct radeon_encoder_int_tmds *radeon_legacy_get_tmds_info(struct radeon
return tmds;
}
static struct radeon_encoder_ext_tmds *radeon_legacy_get_ext_tmds_info(struct radeon_encoder *encoder)
{
struct drm_device *dev = encoder->base.dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder_ext_tmds *tmds = NULL;
bool ret;
if (rdev->is_atom_bios)
return NULL;
tmds = kzalloc(sizeof(struct radeon_encoder_ext_tmds), GFP_KERNEL);
if (!tmds)
return NULL;
ret = radeon_legacy_get_ext_tmds_info_from_combios(encoder, tmds);
if (ret == false)
radeon_legacy_get_ext_tmds_info_from_table(encoder, tmds);
return tmds;
}
void
radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t supported_device)
{
......@@ -1329,7 +1337,6 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
encoder->possible_crtcs = 0x1;
else
encoder->possible_crtcs = 0x3;
encoder->possible_clones = 0;
radeon_encoder->enc_priv = NULL;
......@@ -1373,7 +1380,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
drm_encoder_init(dev, encoder, &radeon_legacy_tmds_ext_enc_funcs, DRM_MODE_ENCODER_TMDS);
drm_encoder_helper_add(encoder, &radeon_legacy_tmds_ext_helper_funcs);
if (!rdev->is_atom_bios)
radeon_combios_get_ext_tmds_info(radeon_encoder);
radeon_encoder->enc_priv = radeon_legacy_get_ext_tmds_info(radeon_encoder);
break;
}
}
......@@ -89,24 +89,38 @@ enum radeon_tv_std {
TV_STD_PAL_CN,
};
/* radeon gpio-based i2c
* 1. "mask" reg and bits
* grabs the gpio pins for software use
* 0=not held 1=held
* 2. "a" reg and bits
* output pin value
* 0=low 1=high
* 3. "en" reg and bits
* sets the pin direction
* 0=input 1=output
* 4. "y" reg and bits
* input pin value
* 0=low 1=high
*/
struct radeon_i2c_bus_rec {
bool valid;
uint32_t mask_clk_reg;
uint32_t mask_data_reg;
uint32_t a_clk_reg;
uint32_t a_data_reg;
uint32_t put_clk_reg;
uint32_t put_data_reg;
uint32_t get_clk_reg;
uint32_t get_data_reg;
uint32_t en_clk_reg;
uint32_t en_data_reg;
uint32_t y_clk_reg;
uint32_t y_data_reg;
uint32_t mask_clk_mask;
uint32_t mask_data_mask;
uint32_t put_clk_mask;
uint32_t put_data_mask;
uint32_t get_clk_mask;
uint32_t get_data_mask;
uint32_t a_clk_mask;
uint32_t a_data_mask;
uint32_t en_clk_mask;
uint32_t en_data_mask;
uint32_t y_clk_mask;
uint32_t y_data_mask;
};
struct radeon_tmds_pll {
......@@ -170,6 +184,11 @@ enum radeon_connector_table {
CT_EMAC,
};
enum radeon_dvo_chip {
DVO_SIL164,
DVO_SIL1178,
};
struct radeon_mode_info {
struct atom_context *atom_context;
struct card_info *atom_card_info;
......@@ -261,6 +280,13 @@ struct radeon_encoder_int_tmds {
struct radeon_tmds_pll tmds_pll[4];
};
struct radeon_encoder_ext_tmds {
/* tmds over dvo */
struct radeon_i2c_chan *i2c_bus;
uint8_t slave_addr;
enum radeon_dvo_chip dvo_chip;
};
/* spread spectrum */
struct radeon_atom_ss {
uint16_t percentage;
......@@ -329,6 +355,14 @@ extern struct radeon_i2c_chan *radeon_i2c_create(struct drm_device *dev,
struct radeon_i2c_bus_rec *rec,
const char *name);
extern void radeon_i2c_destroy(struct radeon_i2c_chan *i2c);
extern void radeon_i2c_sw_get_byte(struct radeon_i2c_chan *i2c_bus,
u8 slave_addr,
u8 addr,
u8 *val);
extern void radeon_i2c_sw_put_byte(struct radeon_i2c_chan *i2c,
u8 slave_addr,
u8 addr,
u8 val);
extern bool radeon_ddc_probe(struct radeon_connector *radeon_connector);
extern int radeon_ddc_get_modes(struct radeon_connector *radeon_connector);
......@@ -343,12 +377,15 @@ extern void radeon_compute_pll(struct radeon_pll *pll,
uint32_t *post_div_p,
int flags);
extern void radeon_setup_encoder_clones(struct drm_device *dev);
struct drm_encoder *radeon_encoder_legacy_lvds_add(struct drm_device *dev, int bios_index);
struct drm_encoder *radeon_encoder_legacy_primary_dac_add(struct drm_device *dev, int bios_index, int with_tv);
struct drm_encoder *radeon_encoder_legacy_tv_dac_add(struct drm_device *dev, int bios_index, int with_tv);
struct drm_encoder *radeon_encoder_legacy_tmds_int_add(struct drm_device *dev, int bios_index);
struct drm_encoder *radeon_encoder_legacy_tmds_ext_add(struct drm_device *dev, int bios_index);
extern void atombios_external_tmds_setup(struct drm_encoder *encoder, int action);
extern void atombios_digital_setup(struct drm_encoder *encoder, int action);
extern int atombios_get_encoder_mode(struct drm_encoder *encoder);
extern void radeon_encoder_set_active_device(struct drm_encoder *encoder);
......@@ -378,12 +415,16 @@ extern bool radeon_atom_get_clock_info(struct drm_device *dev);
extern bool radeon_combios_get_clock_info(struct drm_device *dev);
extern struct radeon_encoder_atom_dig *
radeon_atombios_get_lvds_info(struct radeon_encoder *encoder);
bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_atombios_get_tmds_info(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_legacy_get_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_legacy_get_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_int_tmds *tmds);
extern bool radeon_legacy_get_ext_tmds_info_from_combios(struct radeon_encoder *encoder,
struct radeon_encoder_ext_tmds *tmds);
extern bool radeon_legacy_get_ext_tmds_info_from_table(struct radeon_encoder *encoder,
struct radeon_encoder_ext_tmds *tmds);
extern struct radeon_encoder_primary_dac *
radeon_atombios_get_primary_dac_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_tv_dac *
......@@ -395,6 +436,8 @@ extern struct radeon_encoder_tv_dac *
radeon_combios_get_tv_dac_info(struct radeon_encoder *encoder);
extern struct radeon_encoder_primary_dac *
radeon_combios_get_primary_dac_info(struct radeon_encoder *encoder);
extern bool radeon_combios_external_tmds_setup(struct drm_encoder *encoder);
extern void radeon_external_tmds_setup(struct drm_encoder *encoder);
extern void radeon_combios_output_lock(struct drm_encoder *encoder, bool lock);
extern void radeon_combios_initialize_bios_scratch_regs(struct drm_device *dev);
extern void radeon_atom_output_lock(struct drm_encoder *encoder, bool lock);
......@@ -426,16 +469,13 @@ void radeon_atombios_init_crtc(struct drm_device *dev,
struct radeon_crtc *radeon_crtc);
void radeon_legacy_init_crtc(struct drm_device *dev,
struct radeon_crtc *radeon_crtc);
void radeon_i2c_do_lock(struct radeon_connector *radeon_connector, int lock_state);
extern void radeon_i2c_do_lock(struct radeon_i2c_chan *i2c, int lock_state);
void radeon_get_clock_info(struct drm_device *dev);
extern bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev);
extern bool radeon_get_atom_connector_info_from_supported_devices_table(struct drm_device *dev);
void radeon_rmx_mode_fixup(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode);
void radeon_enc_destroy(struct drm_encoder *encoder);
void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
void radeon_combios_asic_init(struct drm_device *dev);
......
......@@ -34,74 +34,32 @@
#include "radeon_drm.h"
#include "radeon.h"
struct radeon_object {
struct ttm_buffer_object tobj;
struct list_head list;
struct radeon_device *rdev;
struct drm_gem_object *gobj;
struct ttm_bo_kmap_obj kmap;
unsigned pin_count;
uint64_t gpu_addr;
void *kptr;
bool is_iomem;
uint32_t tiling_flags;
uint32_t pitch;
int surface_reg;
};
int radeon_ttm_init(struct radeon_device *rdev);
void radeon_ttm_fini(struct radeon_device *rdev);
static void radeon_bo_clear_surface_reg(struct radeon_bo *bo);
/*
* To exclude mutual BO access we rely on bo_reserve exclusion, as all
* function are calling it.
*/
static int radeon_object_reserve(struct radeon_object *robj, bool interruptible)
static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo)
{
return ttm_bo_reserve(&robj->tobj, interruptible, false, false, 0);
}
struct radeon_bo *bo;
static void radeon_object_unreserve(struct radeon_object *robj)
{
ttm_bo_unreserve(&robj->tobj);
bo = container_of(tbo, struct radeon_bo, tbo);
mutex_lock(&bo->rdev->gem.mutex);
list_del_init(&bo->list);
mutex_unlock(&bo->rdev->gem.mutex);
radeon_bo_clear_surface_reg(bo);
kfree(bo);
}
static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj)
static inline u32 radeon_ttm_flags_from_domain(u32 domain)
{
struct radeon_object *robj;
robj = container_of(tobj, struct radeon_object, tobj);
list_del_init(&robj->list);
radeon_object_clear_surface_reg(robj);
kfree(robj);
}
static inline void radeon_object_gpu_addr(struct radeon_object *robj)
{
/* Default gpu address */
robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL;
if (robj->tobj.mem.mm_node == NULL) {
return;
}
robj->gpu_addr = ((u64)robj->tobj.mem.mm_node->start) << PAGE_SHIFT;
switch (robj->tobj.mem.mem_type) {
case TTM_PL_VRAM:
robj->gpu_addr += (u64)robj->rdev->mc.vram_location;
break;
case TTM_PL_TT:
robj->gpu_addr += (u64)robj->rdev->mc.gtt_location;
break;
default:
DRM_ERROR("Unknown placement %d\n", robj->tobj.mem.mem_type);
robj->gpu_addr = 0xFFFFFFFFFFFFFFFFULL;
return;
}
}
u32 flags = 0;
static inline uint32_t radeon_object_flags_from_domain(uint32_t domain)
{
uint32_t flags = 0;
if (domain & RADEON_GEM_DOMAIN_VRAM) {
flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
}
......@@ -117,17 +75,13 @@ static inline uint32_t radeon_object_flags_from_domain(uint32_t domain)
return flags;
}
int radeon_object_create(struct radeon_device *rdev,
struct drm_gem_object *gobj,
unsigned long size,
bool kernel,
uint32_t domain,
bool interruptible,
struct radeon_object **robj_ptr)
int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
unsigned long size, bool kernel, u32 domain,
struct radeon_bo **bo_ptr)
{
struct radeon_object *robj;
struct radeon_bo *bo;
enum ttm_bo_type type;
uint32_t flags;
u32 flags;
int r;
if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
......@@ -138,206 +92,140 @@ int radeon_object_create(struct radeon_device *rdev,
} else {
type = ttm_bo_type_device;
}
*robj_ptr = NULL;
robj = kzalloc(sizeof(struct radeon_object), GFP_KERNEL);
if (robj == NULL) {
*bo_ptr = NULL;
bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
if (bo == NULL)
return -ENOMEM;
}
robj->rdev = rdev;
robj->gobj = gobj;
robj->surface_reg = -1;
INIT_LIST_HEAD(&robj->list);
flags = radeon_object_flags_from_domain(domain);
r = ttm_buffer_object_init(&rdev->mman.bdev, &robj->tobj, size, type, flags,
0, 0, false, NULL, size,
&radeon_ttm_object_object_destroy);
bo->rdev = rdev;
bo->gobj = gobj;
bo->surface_reg = -1;
INIT_LIST_HEAD(&bo->list);
flags = radeon_ttm_flags_from_domain(domain);
retry:
r = ttm_buffer_object_init(&rdev->mman.bdev, &bo->tbo, size, type,
flags, 0, 0, true, NULL, size,
&radeon_ttm_bo_destroy);
if (unlikely(r != 0)) {
if (r == -ERESTART)
goto retry;
/* ttm call radeon_ttm_object_object_destroy if error happen */
DRM_ERROR("Failed to allocate TTM object (%ld, 0x%08X, %u)\n",
size, flags, 0);
dev_err(rdev->dev, "object_init failed for (%ld, 0x%08X)\n",
size, flags);
return r;
}
*robj_ptr = robj;
*bo_ptr = bo;
if (gobj) {
list_add_tail(&robj->list, &rdev->gem.objects);
mutex_lock(&bo->rdev->gem.mutex);
list_add_tail(&bo->list, &rdev->gem.objects);
mutex_unlock(&bo->rdev->gem.mutex);
}
return 0;
}
int radeon_object_kmap(struct radeon_object *robj, void **ptr)
int radeon_bo_kmap(struct radeon_bo *bo, void **ptr)
{
bool is_iomem;
int r;
spin_lock(&robj->tobj.lock);
if (robj->kptr) {
if (bo->kptr) {
if (ptr) {
*ptr = robj->kptr;
*ptr = bo->kptr;
}
spin_unlock(&robj->tobj.lock);
return 0;
}
spin_unlock(&robj->tobj.lock);
r = ttm_bo_kmap(&robj->tobj, 0, robj->tobj.num_pages, &robj->kmap);
r = ttm_bo_kmap(&bo->tbo, 0, bo->tbo.num_pages, &bo->kmap);
if (r) {
return r;
}
spin_lock(&robj->tobj.lock);
robj->kptr = ttm_kmap_obj_virtual(&robj->kmap, &robj->is_iomem);
spin_unlock(&robj->tobj.lock);
bo->kptr = ttm_kmap_obj_virtual(&bo->kmap, &is_iomem);
if (ptr) {
*ptr = robj->kptr;
*ptr = bo->kptr;
}
radeon_object_check_tiling(robj, 0, 0);
radeon_bo_check_tiling(bo, 0, 0);
return 0;
}
void radeon_object_kunmap(struct radeon_object *robj)
void radeon_bo_kunmap(struct radeon_bo *bo)
{
spin_lock(&robj->tobj.lock);
if (robj->kptr == NULL) {
spin_unlock(&robj->tobj.lock);
if (bo->kptr == NULL)
return;
}
robj->kptr = NULL;
spin_unlock(&robj->tobj.lock);
radeon_object_check_tiling(robj, 0, 0);
ttm_bo_kunmap(&robj->kmap);
bo->kptr = NULL;
radeon_bo_check_tiling(bo, 0, 0);
ttm_bo_kunmap(&bo->kmap);
}
void radeon_object_unref(struct radeon_object **robj)
void radeon_bo_unref(struct radeon_bo **bo)
{
struct ttm_buffer_object *tobj;
struct ttm_buffer_object *tbo;
if ((*robj) == NULL) {
if ((*bo) == NULL)
return;
}
tobj = &((*robj)->tobj);
ttm_bo_unref(&tobj);
if (tobj == NULL) {
*robj = NULL;
}
}
int radeon_object_mmap(struct radeon_object *robj, uint64_t *offset)
{
*offset = robj->tobj.addr_space_offset;
return 0;
tbo = &((*bo)->tbo);
ttm_bo_unref(&tbo);
if (tbo == NULL)
*bo = NULL;
}
int radeon_object_pin(struct radeon_object *robj, uint32_t domain,
uint64_t *gpu_addr)
int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr)
{
uint32_t flags;
uint32_t tmp;
u32 flags;
u32 tmp;
int r;
flags = radeon_object_flags_from_domain(domain);
spin_lock(&robj->tobj.lock);
if (robj->pin_count) {
robj->pin_count++;
if (gpu_addr != NULL) {
*gpu_addr = robj->gpu_addr;
}
spin_unlock(&robj->tobj.lock);
flags = radeon_ttm_flags_from_domain(domain);
if (bo->pin_count) {
bo->pin_count++;
if (gpu_addr)
*gpu_addr = radeon_bo_gpu_offset(bo);
return 0;
}
spin_unlock(&robj->tobj.lock);
r = radeon_object_reserve(robj, false);
if (unlikely(r != 0)) {
DRM_ERROR("radeon: failed to reserve object for pinning it.\n");
return r;
}
tmp = robj->tobj.mem.placement;
tmp = bo->tbo.mem.placement;
ttm_flag_masked(&tmp, flags, TTM_PL_MASK_MEM);
robj->tobj.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT | TTM_PL_MASK_CACHING;
r = ttm_buffer_object_validate(&robj->tobj,
robj->tobj.proposed_placement,
false, false);
radeon_object_gpu_addr(robj);
if (gpu_addr != NULL) {
*gpu_addr = robj->gpu_addr;
bo->tbo.proposed_placement = tmp | TTM_PL_FLAG_NO_EVICT |
TTM_PL_MASK_CACHING;
retry:
r = ttm_buffer_object_validate(&bo->tbo, bo->tbo.proposed_placement,
true, false);
if (likely(r == 0)) {
bo->pin_count = 1;
if (gpu_addr != NULL)
*gpu_addr = radeon_bo_gpu_offset(bo);
}
robj->pin_count = 1;
if (unlikely(r != 0)) {
DRM_ERROR("radeon: failed to pin object.\n");
if (r == -ERESTART)
goto retry;
dev_err(bo->rdev->dev, "%p pin failed\n", bo);
}
radeon_object_unreserve(robj);
return r;
}
void radeon_object_unpin(struct radeon_object *robj)
int radeon_bo_unpin(struct radeon_bo *bo)
{
uint32_t flags;
int r;
spin_lock(&robj->tobj.lock);
if (!robj->pin_count) {
spin_unlock(&robj->tobj.lock);
printk(KERN_WARNING "Unpin not necessary for %p !\n", robj);
return;
}
robj->pin_count--;
if (robj->pin_count) {
spin_unlock(&robj->tobj.lock);
return;
}
spin_unlock(&robj->tobj.lock);
r = radeon_object_reserve(robj, false);
if (unlikely(r != 0)) {
DRM_ERROR("radeon: failed to reserve object for unpinning it.\n");
return;
}
flags = robj->tobj.mem.placement;
robj->tobj.proposed_placement = flags & ~TTM_PL_FLAG_NO_EVICT;
r = ttm_buffer_object_validate(&robj->tobj,
robj->tobj.proposed_placement,
false, false);
if (unlikely(r != 0)) {
DRM_ERROR("radeon: failed to unpin buffer.\n");
}
radeon_object_unreserve(robj);
}
int radeon_object_wait(struct radeon_object *robj)
{
int r = 0;
/* FIXME: should use block reservation instead */
r = radeon_object_reserve(robj, true);
if (unlikely(r != 0)) {
DRM_ERROR("radeon: failed to reserve object for waiting.\n");
return r;
}
spin_lock(&robj->tobj.lock);
if (robj->tobj.sync_obj) {
r = ttm_bo_wait(&robj->tobj, true, true, false);
if (!bo->pin_count) {
dev_warn(bo->rdev->dev, "%p unpin not necessary\n", bo);
return 0;
}
spin_unlock(&robj->tobj.lock);
radeon_object_unreserve(robj);
return r;
}
int radeon_object_busy_domain(struct radeon_object *robj, uint32_t *cur_placement)
{
int r = 0;
r = radeon_object_reserve(robj, true);
bo->pin_count--;
if (bo->pin_count)
return 0;
bo->tbo.proposed_placement = bo->tbo.mem.placement &
~TTM_PL_FLAG_NO_EVICT;
retry:
r = ttm_buffer_object_validate(&bo->tbo, bo->tbo.proposed_placement,
true, false);
if (unlikely(r != 0)) {
DRM_ERROR("radeon: failed to reserve object for waiting.\n");
if (r == -ERESTART)
goto retry;
dev_err(bo->rdev->dev, "%p validate failed for unpin\n", bo);
return r;
}
spin_lock(&robj->tobj.lock);
*cur_placement = robj->tobj.mem.mem_type;
if (robj->tobj.sync_obj) {
r = ttm_bo_wait(&robj->tobj, true, true, true);
}
spin_unlock(&robj->tobj.lock);
radeon_object_unreserve(robj);
return r;
return 0;
}
int radeon_object_evict_vram(struct radeon_device *rdev)
int radeon_bo_evict_vram(struct radeon_device *rdev)
{
if (rdev->flags & RADEON_IS_IGP) {
/* Useless to evict on IGP chips */
......@@ -346,30 +234,32 @@ int radeon_object_evict_vram(struct radeon_device *rdev)
return ttm_bo_evict_mm(&rdev->mman.bdev, TTM_PL_VRAM);
}
void radeon_object_force_delete(struct radeon_device *rdev)
void radeon_bo_force_delete(struct radeon_device *rdev)
{
struct radeon_object *robj, *n;
struct radeon_bo *bo, *n;
struct drm_gem_object *gobj;
if (list_empty(&rdev->gem.objects)) {
return;
}
DRM_ERROR("Userspace still has active objects !\n");
list_for_each_entry_safe(robj, n, &rdev->gem.objects, list) {
dev_err(rdev->dev, "Userspace still has active objects !\n");
list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
mutex_lock(&rdev->ddev->struct_mutex);
gobj = robj->gobj;
DRM_ERROR("Force free for (%p,%p,%lu,%lu)\n",
gobj, robj, (unsigned long)gobj->size,
*((unsigned long *)&gobj->refcount));
list_del_init(&robj->list);
radeon_object_unref(&robj);
gobj = bo->gobj;
dev_err(rdev->dev, "%p %p %lu %lu force free\n",
gobj, bo, (unsigned long)gobj->size,
*((unsigned long *)&gobj->refcount));
mutex_lock(&bo->rdev->gem.mutex);
list_del_init(&bo->list);
mutex_unlock(&bo->rdev->gem.mutex);
radeon_bo_unref(&bo);
gobj->driver_private = NULL;
drm_gem_object_unreference(gobj);
mutex_unlock(&rdev->ddev->struct_mutex);
}
}
int radeon_object_init(struct radeon_device *rdev)
int radeon_bo_init(struct radeon_device *rdev)
{
/* Add an MTRR for the VRAM */
rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
......@@ -382,13 +272,13 @@ int radeon_object_init(struct radeon_device *rdev)
return radeon_ttm_init(rdev);
}
void radeon_object_fini(struct radeon_device *rdev)
void radeon_bo_fini(struct radeon_device *rdev)
{
radeon_ttm_fini(rdev);
}
void radeon_object_list_add_object(struct radeon_object_list *lobj,
struct list_head *head)
void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
struct list_head *head)
{
if (lobj->wdomain) {
list_add(&lobj->list, head);
......@@ -397,72 +287,67 @@ void radeon_object_list_add_object(struct radeon_object_list *lobj,
}
}
int radeon_object_list_reserve(struct list_head *head)
int radeon_bo_list_reserve(struct list_head *head)
{
struct radeon_object_list *lobj;
struct radeon_bo_list *lobj;
int r;
list_for_each_entry(lobj, head, list){
if (!lobj->robj->pin_count) {
r = radeon_object_reserve(lobj->robj, true);
if (unlikely(r != 0)) {
DRM_ERROR("radeon: failed to reserve object.\n");
return r;
}
} else {
}
r = radeon_bo_reserve(lobj->bo, false);
if (unlikely(r != 0))
return r;
}
return 0;
}
void radeon_object_list_unreserve(struct list_head *head)
void radeon_bo_list_unreserve(struct list_head *head)
{
struct radeon_object_list *lobj;
struct radeon_bo_list *lobj;
list_for_each_entry(lobj, head, list) {
if (!lobj->robj->pin_count) {
radeon_object_unreserve(lobj->robj);
}
/* only unreserve object we successfully reserved */
if (radeon_bo_is_reserved(lobj->bo))
radeon_bo_unreserve(lobj->bo);
}
}
int radeon_object_list_validate(struct list_head *head, void *fence)
int radeon_bo_list_validate(struct list_head *head, void *fence)
{
struct radeon_object_list *lobj;
struct radeon_object *robj;
struct radeon_bo_list *lobj;
struct radeon_bo *bo;
struct radeon_fence *old_fence = NULL;
int r;
r = radeon_object_list_reserve(head);
r = radeon_bo_list_reserve(head);
if (unlikely(r != 0)) {
radeon_object_list_unreserve(head);
return r;
}
list_for_each_entry(lobj, head, list) {
robj = lobj->robj;
if (!robj->pin_count) {
bo = lobj->bo;
if (!bo->pin_count) {
if (lobj->wdomain) {
robj->tobj.proposed_placement =
radeon_object_flags_from_domain(lobj->wdomain);
bo->tbo.proposed_placement =
radeon_ttm_flags_from_domain(lobj->wdomain);
} else {
robj->tobj.proposed_placement =
radeon_object_flags_from_domain(lobj->rdomain);
bo->tbo.proposed_placement =
radeon_ttm_flags_from_domain(lobj->rdomain);
}
r = ttm_buffer_object_validate(&robj->tobj,
robj->tobj.proposed_placement,
true, false);
retry:
r = ttm_buffer_object_validate(&bo->tbo,
bo->tbo.proposed_placement,
true, false);
if (unlikely(r)) {
DRM_ERROR("radeon: failed to validate.\n");
if (r == -ERESTART)
goto retry;
return r;
}
radeon_object_gpu_addr(robj);
}
lobj->gpu_offset = robj->gpu_addr;
lobj->tiling_flags = robj->tiling_flags;
lobj->gpu_offset = radeon_bo_gpu_offset(bo);
lobj->tiling_flags = bo->tiling_flags;
if (fence) {
old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
robj->tobj.sync_obj = radeon_fence_ref(fence);
robj->tobj.sync_obj_arg = NULL;
old_fence = (struct radeon_fence *)bo->tbo.sync_obj;
bo->tbo.sync_obj = radeon_fence_ref(fence);
bo->tbo.sync_obj_arg = NULL;
}
if (old_fence) {
radeon_fence_unref(&old_fence);
......@@ -471,51 +356,44 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
return 0;
}
void radeon_object_list_unvalidate(struct list_head *head)
void radeon_bo_list_unvalidate(struct list_head *head, void *fence)
{
struct radeon_object_list *lobj;
struct radeon_fence *old_fence = NULL;
struct radeon_bo_list *lobj;
struct radeon_fence *old_fence;
list_for_each_entry(lobj, head, list) {
old_fence = (struct radeon_fence *)lobj->robj->tobj.sync_obj;
lobj->robj->tobj.sync_obj = NULL;
if (old_fence) {
radeon_fence_unref(&old_fence);
if (fence)
list_for_each_entry(lobj, head, list) {
old_fence = to_radeon_fence(lobj->bo->tbo.sync_obj);
if (old_fence == fence) {
lobj->bo->tbo.sync_obj = NULL;
radeon_fence_unref(&old_fence);
}
}
}
radeon_object_list_unreserve(head);
}
void radeon_object_list_clean(struct list_head *head)
{
radeon_object_list_unreserve(head);
radeon_bo_list_unreserve(head);
}
int radeon_object_fbdev_mmap(struct radeon_object *robj,
int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
struct vm_area_struct *vma)
{
return ttm_fbdev_mmap(vma, &robj->tobj);
return ttm_fbdev_mmap(vma, &bo->tbo);
}
unsigned long radeon_object_size(struct radeon_object *robj)
static int radeon_bo_get_surface_reg(struct radeon_bo *bo)
{
return robj->tobj.num_pages << PAGE_SHIFT;
}
int radeon_object_get_surface_reg(struct radeon_object *robj)
{
struct radeon_device *rdev = robj->rdev;
struct radeon_device *rdev = bo->rdev;
struct radeon_surface_reg *reg;
struct radeon_object *old_object;
struct radeon_bo *old_object;
int steal;
int i;
if (!robj->tiling_flags)
BUG_ON(!atomic_read(&bo->tbo.reserved));
if (!bo->tiling_flags)
return 0;
if (robj->surface_reg >= 0) {
reg = &rdev->surface_regs[robj->surface_reg];
i = robj->surface_reg;
if (bo->surface_reg >= 0) {
reg = &rdev->surface_regs[bo->surface_reg];
i = bo->surface_reg;
goto out;
}
......@@ -523,10 +401,10 @@ int radeon_object_get_surface_reg(struct radeon_object *robj)
for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
reg = &rdev->surface_regs[i];
if (!reg->robj)
if (!reg->bo)
break;
old_object = reg->robj;
old_object = reg->bo;
if (old_object->pin_count == 0)
steal = i;
}
......@@ -537,91 +415,101 @@ int radeon_object_get_surface_reg(struct radeon_object *robj)
return -ENOMEM;
/* find someone with a surface reg and nuke their BO */
reg = &rdev->surface_regs[steal];
old_object = reg->robj;
old_object = reg->bo;
/* blow away the mapping */
DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
ttm_bo_unmap_virtual(&old_object->tobj);
ttm_bo_unmap_virtual(&old_object->tbo);
old_object->surface_reg = -1;
i = steal;
}
robj->surface_reg = i;
reg->robj = robj;
bo->surface_reg = i;
reg->bo = bo;
out:
radeon_set_surface_reg(rdev, i, robj->tiling_flags, robj->pitch,
robj->tobj.mem.mm_node->start << PAGE_SHIFT,
robj->tobj.num_pages << PAGE_SHIFT);
radeon_set_surface_reg(rdev, i, bo->tiling_flags, bo->pitch,
bo->tbo.mem.mm_node->start << PAGE_SHIFT,
bo->tbo.num_pages << PAGE_SHIFT);
return 0;
}
void radeon_object_clear_surface_reg(struct radeon_object *robj)
static void radeon_bo_clear_surface_reg(struct radeon_bo *bo)
{
struct radeon_device *rdev = robj->rdev;
struct radeon_device *rdev = bo->rdev;
struct radeon_surface_reg *reg;
if (robj->surface_reg == -1)
if (bo->surface_reg == -1)
return;
reg = &rdev->surface_regs[robj->surface_reg];
radeon_clear_surface_reg(rdev, robj->surface_reg);
reg = &rdev->surface_regs[bo->surface_reg];
radeon_clear_surface_reg(rdev, bo->surface_reg);
reg->robj = NULL;
robj->surface_reg = -1;
reg->bo = NULL;
bo->surface_reg = -1;
}
void radeon_object_set_tiling_flags(struct radeon_object *robj,
uint32_t tiling_flags, uint32_t pitch)
int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
uint32_t tiling_flags, uint32_t pitch)
{
robj->tiling_flags = tiling_flags;
robj->pitch = pitch;
int r;
r = radeon_bo_reserve(bo, false);
if (unlikely(r != 0))
return r;
bo->tiling_flags = tiling_flags;
bo->pitch = pitch;
radeon_bo_unreserve(bo);
return 0;
}
void radeon_object_get_tiling_flags(struct radeon_object *robj,
uint32_t *tiling_flags,
uint32_t *pitch)
void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
uint32_t *tiling_flags,
uint32_t *pitch)
{
BUG_ON(!atomic_read(&bo->tbo.reserved));
if (tiling_flags)
*tiling_flags = robj->tiling_flags;
*tiling_flags = bo->tiling_flags;
if (pitch)
*pitch = robj->pitch;
*pitch = bo->pitch;
}
int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
bool force_drop)
int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
bool force_drop)
{
if (!(robj->tiling_flags & RADEON_TILING_SURFACE))
BUG_ON(!atomic_read(&bo->tbo.reserved));
if (!(bo->tiling_flags & RADEON_TILING_SURFACE))
return 0;
if (force_drop) {
radeon_object_clear_surface_reg(robj);
radeon_bo_clear_surface_reg(bo);
return 0;
}
if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
if (bo->tbo.mem.mem_type != TTM_PL_VRAM) {
if (!has_moved)
return 0;
if (robj->surface_reg >= 0)
radeon_object_clear_surface_reg(robj);
if (bo->surface_reg >= 0)
radeon_bo_clear_surface_reg(bo);
return 0;
}
if ((robj->surface_reg >= 0) && !has_moved)
if ((bo->surface_reg >= 0) && !has_moved)
return 0;
return radeon_object_get_surface_reg(robj);
return radeon_bo_get_surface_reg(bo);
}
void radeon_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem)
struct ttm_mem_reg *mem)
{
struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
radeon_object_check_tiling(robj, 0, 1);
struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo);
radeon_bo_check_tiling(rbo, 0, 1);
}
void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo)
{
struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
radeon_object_check_tiling(robj, 0, 0);
struct radeon_bo *rbo = container_of(bo, struct radeon_bo, tbo);
radeon_bo_check_tiling(rbo, 0, 0);
}
......@@ -28,19 +28,152 @@
#ifndef __RADEON_OBJECT_H__
#define __RADEON_OBJECT_H__
#include <ttm/ttm_bo_api.h>
#include <ttm/ttm_bo_driver.h>
#include <ttm/ttm_placement.h>
#include <ttm/ttm_module.h>
#include <drm/radeon_drm.h>
#include "radeon.h"
/*
* TTM.
/**
* radeon_mem_type_to_domain - return domain corresponding to mem_type
* @mem_type: ttm memory type
*
* Returns corresponding domain of the ttm mem_type
*/
static inline unsigned radeon_mem_type_to_domain(u32 mem_type)
{
switch (mem_type) {
case TTM_PL_VRAM:
return RADEON_GEM_DOMAIN_VRAM;
case TTM_PL_TT:
return RADEON_GEM_DOMAIN_GTT;
case TTM_PL_SYSTEM:
return RADEON_GEM_DOMAIN_CPU;
default:
break;
}
return 0;
}
/**
* radeon_bo_reserve - reserve bo
* @bo: bo structure
* @no_wait: don't sleep while trying to reserve (return -EBUSY)
*
* Returns:
* -EBUSY: buffer is busy and @no_wait is true
* -ERESTART: A wait for the buffer to become unreserved was interrupted by
* a signal. Release all buffer reservations and return to user-space.
*/
static inline int radeon_bo_reserve(struct radeon_bo *bo, bool no_wait)
{
int r;
retry:
r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
if (unlikely(r != 0)) {
if (r == -ERESTART)
goto retry;
dev_err(bo->rdev->dev, "%p reserve failed\n", bo);
return r;
}
return 0;
}
static inline void radeon_bo_unreserve(struct radeon_bo *bo)
{
ttm_bo_unreserve(&bo->tbo);
}
/**
* radeon_bo_gpu_offset - return GPU offset of bo
* @bo: radeon object for which we query the offset
*
* Returns current GPU offset of the object.
*
* Note: object should either be pinned or reserved when calling this
* function, it might be usefull to add check for this for debugging.
*/
static inline u64 radeon_bo_gpu_offset(struct radeon_bo *bo)
{
return bo->tbo.offset;
}
static inline unsigned long radeon_bo_size(struct radeon_bo *bo)
{
return bo->tbo.num_pages << PAGE_SHIFT;
}
static inline bool radeon_bo_is_reserved(struct radeon_bo *bo)
{
return !!atomic_read(&bo->tbo.reserved);
}
/**
* radeon_bo_mmap_offset - return mmap offset of bo
* @bo: radeon object for which we query the offset
*
* Returns mmap offset of the object.
*
* Note: addr_space_offset is constant after ttm bo init thus isn't protected
* by any lock.
*/
struct radeon_mman {
struct ttm_bo_global_ref bo_global_ref;
struct ttm_global_reference mem_global_ref;
bool mem_global_referenced;
struct ttm_bo_device bdev;
};
static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo)
{
return bo->tbo.addr_space_offset;
}
static inline int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type,
bool no_wait)
{
int r;
retry:
r = ttm_bo_reserve(&bo->tbo, true, no_wait, false, 0);
if (unlikely(r != 0)) {
if (r == -ERESTART)
goto retry;
dev_err(bo->rdev->dev, "%p reserve failed for wait\n", bo);
return r;
}
spin_lock(&bo->tbo.lock);
if (mem_type)
*mem_type = bo->tbo.mem.mem_type;
if (bo->tbo.sync_obj)
r = ttm_bo_wait(&bo->tbo, true, true, no_wait);
spin_unlock(&bo->tbo.lock);
ttm_bo_unreserve(&bo->tbo);
if (unlikely(r == -ERESTART))
goto retry;
return r;
}
extern int radeon_bo_create(struct radeon_device *rdev,
struct drm_gem_object *gobj, unsigned long size,
bool kernel, u32 domain,
struct radeon_bo **bo_ptr);
extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
extern void radeon_bo_kunmap(struct radeon_bo *bo);
extern void radeon_bo_unref(struct radeon_bo **bo);
extern int radeon_bo_pin(struct radeon_bo *bo, u32 domain, u64 *gpu_addr);
extern int radeon_bo_unpin(struct radeon_bo *bo);
extern int radeon_bo_evict_vram(struct radeon_device *rdev);
extern void radeon_bo_force_delete(struct radeon_device *rdev);
extern int radeon_bo_init(struct radeon_device *rdev);
extern void radeon_bo_fini(struct radeon_device *rdev);
extern void radeon_bo_list_add_object(struct radeon_bo_list *lobj,
struct list_head *head);
extern int radeon_bo_list_reserve(struct list_head *head);
extern void radeon_bo_list_unreserve(struct list_head *head);
extern int radeon_bo_list_validate(struct list_head *head, void *fence);
extern void radeon_bo_list_unvalidate(struct list_head *head, void *fence);
extern int radeon_bo_fbdev_mmap(struct radeon_bo *bo,
struct vm_area_struct *vma);
extern int radeon_bo_set_tiling_flags(struct radeon_bo *bo,
u32 tiling_flags, u32 pitch);
extern void radeon_bo_get_tiling_flags(struct radeon_bo *bo,
u32 *tiling_flags, u32 *pitch);
extern int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved,
bool force_drop);
extern void radeon_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem);
extern void radeon_bo_fault_reserve_notify(struct ttm_buffer_object *bo);
#endif
......@@ -27,7 +27,7 @@ int radeon_debugfs_pm_init(struct radeon_device *rdev);
int radeon_pm_init(struct radeon_device *rdev)
{
if (radeon_debugfs_pm_init(rdev)) {
DRM_ERROR("Failed to register debugfs file for CP !\n");
DRM_ERROR("Failed to register debugfs file for PM!\n");
}
return 0;
......@@ -44,8 +44,8 @@ static int radeon_debugfs_pm_info(struct seq_file *m, void *data)
struct drm_device *dev = node->minor->dev;
struct radeon_device *rdev = dev->dev_private;
seq_printf(m, "engine clock: %u0 Hz\n", radeon_get_engine_clock(rdev));
seq_printf(m, "memory clock: %u0 Hz\n", radeon_get_memory_clock(rdev));
seq_printf(m, "engine clock: %u0 kHz\n", radeon_get_engine_clock(rdev));
seq_printf(m, "memory clock: %u0 kHz\n", radeon_get_memory_clock(rdev));
return 0;
}
......
......@@ -1051,20 +1051,25 @@
/* Multimedia I2C bus */
#define RADEON_I2C_CNTL_0 0x0090
#define RADEON_I2C_DONE (1<<0)
#define RADEON_I2C_NACK (1<<1)
#define RADEON_I2C_HALT (1<<2)
#define RADEON_I2C_SOFT_RST (1<<5)
#define RADEON_I2C_DRIVE_EN (1<<6)
#define RADEON_I2C_DRIVE_SEL (1<<7)
#define RADEON_I2C_START (1<<8)
#define RADEON_I2C_STOP (1<<9)
#define RADEON_I2C_RECEIVE (1<<10)
#define RADEON_I2C_ABORT (1<<11)
#define RADEON_I2C_GO (1<<12)
#define RADEON_I2C_DONE (1 << 0)
#define RADEON_I2C_NACK (1 << 1)
#define RADEON_I2C_HALT (1 << 2)
#define RADEON_I2C_SOFT_RST (1 << 5)
#define RADEON_I2C_DRIVE_EN (1 << 6)
#define RADEON_I2C_DRIVE_SEL (1 << 7)
#define RADEON_I2C_START (1 << 8)
#define RADEON_I2C_STOP (1 << 9)
#define RADEON_I2C_RECEIVE (1 << 10)
#define RADEON_I2C_ABORT (1 << 11)
#define RADEON_I2C_GO (1 << 12)
#define RADEON_I2C_PRESCALE_SHIFT 16
#define RADEON_I2C_CNTL_1 0x0094
#define RADEON_I2C_SEL (1<<16)
#define RADEON_I2C_EN (1<<17)
#define RADEON_I2C_DATA_COUNT_SHIFT 0
#define RADEON_I2C_ADDR_COUNT_SHIFT 4
#define RADEON_I2C_INTRA_BYTE_DELAY_SHIFT 8
#define RADEON_I2C_SEL (1 << 16)
#define RADEON_I2C_EN (1 << 17)
#define RADEON_I2C_TIME_LIMIT_SHIFT 24
#define RADEON_I2C_DATA 0x0098
#define RADEON_DVI_I2C_CNTL_0 0x02e0
......@@ -1072,7 +1077,7 @@
# define R200_SEL_DDC1 0 /* 0x60 - VGA_DDC */
# define R200_SEL_DDC2 1 /* 0x64 - DVI_DDC */
# define R200_SEL_DDC3 2 /* 0x68 - MONID_DDC */
#define RADEON_DVI_I2C_CNTL_1 0x02e4 /* ? */
#define RADEON_DVI_I2C_CNTL_1 0x02e4
#define RADEON_DVI_I2C_DATA 0x02e8
#define RADEON_INTERRUPT_LINE 0x0f3c /* PCI */
......@@ -1143,14 +1148,15 @@
# define RADEON_IO_MCLK_MAX_DYN_STOP_LAT (1 << 13)
# define RADEON_MC_MCLK_DYN_ENABLE (1 << 14)
# define RADEON_IO_MCLK_DYN_ENABLE (1 << 15)
#define RADEON_LCD_GPIO_MASK 0x01a0
#define RADEON_GPIOPAD_MASK 0x0198
#define RADEON_GPIOPAD_A 0x019c
#define RADEON_GPIOPAD_EN 0x01a0
#define RADEON_GPIOPAD_Y 0x01a4
#define RADEON_LCD_GPIO_MASK 0x01a0
#define RADEON_LCD_GPIO_Y_REG 0x01a4
#define RADEON_MDGPIO_A_REG 0x01ac
#define RADEON_MDGPIO_EN_REG 0x01b0
#define RADEON_MDGPIO_MASK 0x0198
#define RADEON_GPIOPAD_MASK 0x0198
#define RADEON_GPIOPAD_A 0x019c
#define RADEON_MDGPIO_Y_REG 0x01b4
#define RADEON_MEM_ADDR_CONFIG 0x0148
#define RADEON_MEM_BASE 0x0f10 /* PCI */
......@@ -1360,6 +1366,9 @@
#define RADEON_OVR_CLR 0x0230
#define RADEON_OVR_WID_LEFT_RIGHT 0x0234
#define RADEON_OVR_WID_TOP_BOTTOM 0x0238
#define RADEON_OVR2_CLR 0x0330
#define RADEON_OVR2_WID_LEFT_RIGHT 0x0334
#define RADEON_OVR2_WID_TOP_BOTTOM 0x0338
/* first capture unit */
......
......@@ -165,19 +165,24 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
return 0;
/* Allocate 1M object buffer */
INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
r = radeon_object_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
true, RADEON_GEM_DOMAIN_GTT,
false, &rdev->ib_pool.robj);
r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
true, RADEON_GEM_DOMAIN_GTT,
&rdev->ib_pool.robj);
if (r) {
DRM_ERROR("radeon: failed to ib pool (%d).\n", r);
return r;
}
r = radeon_object_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
r = radeon_bo_reserve(rdev->ib_pool.robj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rdev->ib_pool.robj, RADEON_GEM_DOMAIN_GTT, &gpu_addr);
if (r) {
radeon_bo_unreserve(rdev->ib_pool.robj);
DRM_ERROR("radeon: failed to pin ib pool (%d).\n", r);
return r;
}
r = radeon_object_kmap(rdev->ib_pool.robj, &ptr);
r = radeon_bo_kmap(rdev->ib_pool.robj, &ptr);
radeon_bo_unreserve(rdev->ib_pool.robj);
if (r) {
DRM_ERROR("radeon: failed to map ib poll (%d).\n", r);
return r;
......@@ -203,14 +208,21 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
void radeon_ib_pool_fini(struct radeon_device *rdev)
{
int r;
if (!rdev->ib_pool.ready) {
return;
}
mutex_lock(&rdev->ib_pool.mutex);
bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
if (rdev->ib_pool.robj) {
radeon_object_kunmap(rdev->ib_pool.robj);
radeon_object_unref(&rdev->ib_pool.robj);
r = radeon_bo_reserve(rdev->ib_pool.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->ib_pool.robj);
radeon_bo_unpin(rdev->ib_pool.robj);
radeon_bo_unreserve(rdev->ib_pool.robj);
}
radeon_bo_unref(&rdev->ib_pool.robj);
rdev->ib_pool.robj = NULL;
}
mutex_unlock(&rdev->ib_pool.mutex);
......@@ -288,29 +300,28 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
rdev->cp.ring_size = ring_size;
/* Allocate ring buffer */
if (rdev->cp.ring_obj == NULL) {
r = radeon_object_create(rdev, NULL, rdev->cp.ring_size,
true,
RADEON_GEM_DOMAIN_GTT,
false,
&rdev->cp.ring_obj);
r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, true,
RADEON_GEM_DOMAIN_GTT,
&rdev->cp.ring_obj);
if (r) {
DRM_ERROR("radeon: failed to create ring buffer (%d).\n", r);
mutex_unlock(&rdev->cp.mutex);
dev_err(rdev->dev, "(%d) ring create failed\n", r);
return r;
}
r = radeon_object_pin(rdev->cp.ring_obj,
RADEON_GEM_DOMAIN_GTT,
&rdev->cp.gpu_addr);
r = radeon_bo_reserve(rdev->cp.ring_obj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rdev->cp.ring_obj, RADEON_GEM_DOMAIN_GTT,
&rdev->cp.gpu_addr);
if (r) {
DRM_ERROR("radeon: failed to pin ring buffer (%d).\n", r);
mutex_unlock(&rdev->cp.mutex);
radeon_bo_unreserve(rdev->cp.ring_obj);
dev_err(rdev->dev, "(%d) ring pin failed\n", r);
return r;
}
r = radeon_object_kmap(rdev->cp.ring_obj,
r = radeon_bo_kmap(rdev->cp.ring_obj,
(void **)&rdev->cp.ring);
radeon_bo_unreserve(rdev->cp.ring_obj);
if (r) {
DRM_ERROR("radeon: failed to map ring buffer (%d).\n", r);
mutex_unlock(&rdev->cp.mutex);
dev_err(rdev->dev, "(%d) ring map failed\n", r);
return r;
}
}
......@@ -321,11 +332,17 @@ int radeon_ring_init(struct radeon_device *rdev, unsigned ring_size)
void radeon_ring_fini(struct radeon_device *rdev)
{
int r;
mutex_lock(&rdev->cp.mutex);
if (rdev->cp.ring_obj) {
radeon_object_kunmap(rdev->cp.ring_obj);
radeon_object_unpin(rdev->cp.ring_obj);
radeon_object_unref(&rdev->cp.ring_obj);
r = radeon_bo_reserve(rdev->cp.ring_obj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->cp.ring_obj);
radeon_bo_unpin(rdev->cp.ring_obj);
radeon_bo_unreserve(rdev->cp.ring_obj);
}
radeon_bo_unref(&rdev->cp.ring_obj);
rdev->cp.ring = NULL;
rdev->cp.ring_obj = NULL;
}
......
......@@ -30,8 +30,8 @@
/* Test BO GTT->VRAM and VRAM->GTT GPU copies across the whole GTT aperture */
void radeon_test_moves(struct radeon_device *rdev)
{
struct radeon_object *vram_obj = NULL;
struct radeon_object **gtt_obj = NULL;
struct radeon_bo *vram_obj = NULL;
struct radeon_bo **gtt_obj = NULL;
struct radeon_fence *fence = NULL;
uint64_t gtt_addr, vram_addr;
unsigned i, n, size;
......@@ -52,38 +52,42 @@ void radeon_test_moves(struct radeon_device *rdev)
goto out_cleanup;
}
r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
false, &vram_obj);
r = radeon_bo_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
&vram_obj);
if (r) {
DRM_ERROR("Failed to create VRAM object\n");
goto out_cleanup;
}
r = radeon_object_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
r = radeon_bo_reserve(vram_obj, false);
if (unlikely(r != 0))
goto out_cleanup;
r = radeon_bo_pin(vram_obj, RADEON_GEM_DOMAIN_VRAM, &vram_addr);
if (r) {
DRM_ERROR("Failed to pin VRAM object\n");
goto out_cleanup;
}
for (i = 0; i < n; i++) {
void *gtt_map, *vram_map;
void **gtt_start, **gtt_end;
void **vram_start, **vram_end;
r = radeon_object_create(rdev, NULL, size, true,
RADEON_GEM_DOMAIN_GTT, false, gtt_obj + i);
r = radeon_bo_create(rdev, NULL, size, true,
RADEON_GEM_DOMAIN_GTT, gtt_obj + i);
if (r) {
DRM_ERROR("Failed to create GTT object %d\n", i);
goto out_cleanup;
}
r = radeon_object_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
r = radeon_bo_reserve(gtt_obj[i], false);
if (unlikely(r != 0))
goto out_cleanup;
r = radeon_bo_pin(gtt_obj[i], RADEON_GEM_DOMAIN_GTT, &gtt_addr);
if (r) {
DRM_ERROR("Failed to pin GTT object %d\n", i);
goto out_cleanup;
}
r = radeon_object_kmap(gtt_obj[i], &gtt_map);
r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
if (r) {
DRM_ERROR("Failed to map GTT object %d\n", i);
goto out_cleanup;
......@@ -94,7 +98,7 @@ void radeon_test_moves(struct radeon_device *rdev)
gtt_start++)
*gtt_start = gtt_start;
radeon_object_kunmap(gtt_obj[i]);
radeon_bo_kunmap(gtt_obj[i]);
r = radeon_fence_create(rdev, &fence);
if (r) {
......@@ -116,7 +120,7 @@ void radeon_test_moves(struct radeon_device *rdev)
radeon_fence_unref(&fence);
r = radeon_object_kmap(vram_obj, &vram_map);
r = radeon_bo_kmap(vram_obj, &vram_map);
if (r) {
DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
goto out_cleanup;
......@@ -131,13 +135,13 @@ void radeon_test_moves(struct radeon_device *rdev)
"expected 0x%p (GTT map 0x%p-0x%p)\n",
i, *vram_start, gtt_start, gtt_map,
gtt_end);
radeon_object_kunmap(vram_obj);
radeon_bo_kunmap(vram_obj);
goto out_cleanup;
}
*vram_start = vram_start;
}
radeon_object_kunmap(vram_obj);
radeon_bo_kunmap(vram_obj);
r = radeon_fence_create(rdev, &fence);
if (r) {
......@@ -159,7 +163,7 @@ void radeon_test_moves(struct radeon_device *rdev)
radeon_fence_unref(&fence);
r = radeon_object_kmap(gtt_obj[i], &gtt_map);
r = radeon_bo_kmap(gtt_obj[i], &gtt_map);
if (r) {
DRM_ERROR("Failed to map GTT object after copy %d\n", i);
goto out_cleanup;
......@@ -174,12 +178,12 @@ void radeon_test_moves(struct radeon_device *rdev)
"expected 0x%p (VRAM map 0x%p-0x%p)\n",
i, *gtt_start, vram_start, vram_map,
vram_end);
radeon_object_kunmap(gtt_obj[i]);
radeon_bo_kunmap(gtt_obj[i]);
goto out_cleanup;
}
}
radeon_object_kunmap(gtt_obj[i]);
radeon_bo_kunmap(gtt_obj[i]);
DRM_INFO("Tested GTT->VRAM and VRAM->GTT copy for GTT offset 0x%llx\n",
gtt_addr - rdev->mc.gtt_location);
......@@ -187,14 +191,20 @@ void radeon_test_moves(struct radeon_device *rdev)
out_cleanup:
if (vram_obj) {
radeon_object_unpin(vram_obj);
radeon_object_unref(&vram_obj);
if (radeon_bo_is_reserved(vram_obj)) {
radeon_bo_unpin(vram_obj);
radeon_bo_unreserve(vram_obj);
}
radeon_bo_unref(&vram_obj);
}
if (gtt_obj) {
for (i = 0; i < n; i++) {
if (gtt_obj[i]) {
radeon_object_unpin(gtt_obj[i]);
radeon_object_unref(&gtt_obj[i]);
if (radeon_bo_is_reserved(gtt_obj[i])) {
radeon_bo_unpin(gtt_obj[i]);
radeon_bo_unreserve(gtt_obj[i]);
}
radeon_bo_unref(&gtt_obj[i]);
}
}
kfree(gtt_obj);
......@@ -206,4 +216,3 @@ void radeon_test_moves(struct radeon_device *rdev)
printk(KERN_WARNING "Error while testing BO move.\n");
}
}
......@@ -150,7 +150,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
man->default_caching = TTM_PL_FLAG_CACHED;
break;
case TTM_PL_TT:
man->gpu_offset = 0;
man->gpu_offset = rdev->mc.gtt_location;
man->available_caching = TTM_PL_MASK_CACHING;
man->default_caching = TTM_PL_FLAG_CACHED;
man->flags = TTM_MEMTYPE_FLAG_MAPPABLE | TTM_MEMTYPE_FLAG_CMA;
......@@ -180,7 +180,7 @@ static int radeon_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
break;
case TTM_PL_VRAM:
/* "On-card" video ram */
man->gpu_offset = 0;
man->gpu_offset = rdev->mc.vram_location;
man->flags = TTM_MEMTYPE_FLAG_FIXED |
TTM_MEMTYPE_FLAG_NEEDS_IOREMAP |
TTM_MEMTYPE_FLAG_MAPPABLE;
......@@ -482,27 +482,31 @@ int radeon_ttm_init(struct radeon_device *rdev)
DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
return r;
}
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0,
((rdev->mc.real_vram_size) >> PAGE_SHIFT));
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM,
0, rdev->mc.real_vram_size >> PAGE_SHIFT);
if (r) {
DRM_ERROR("Failed initializing VRAM heap.\n");
return r;
}
r = radeon_object_create(rdev, NULL, 256 * 1024, true,
RADEON_GEM_DOMAIN_VRAM, false,
&rdev->stollen_vga_memory);
r = radeon_bo_create(rdev, NULL, 256 * 1024, true,
RADEON_GEM_DOMAIN_VRAM,
&rdev->stollen_vga_memory);
if (r) {
return r;
}
r = radeon_object_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL);
r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
if (r)
return r;
r = radeon_bo_pin(rdev->stollen_vga_memory, RADEON_GEM_DOMAIN_VRAM, NULL);
radeon_bo_unreserve(rdev->stollen_vga_memory);
if (r) {
radeon_object_unref(&rdev->stollen_vga_memory);
radeon_bo_unref(&rdev->stollen_vga_memory);
return r;
}
DRM_INFO("radeon: %uM of VRAM memory ready\n",
(unsigned)rdev->mc.real_vram_size / (1024 * 1024));
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0,
((rdev->mc.gtt_size) >> PAGE_SHIFT));
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT,
0, rdev->mc.gtt_size >> PAGE_SHIFT);
if (r) {
DRM_ERROR("Failed initializing GTT heap.\n");
return r;
......@@ -523,9 +527,15 @@ int radeon_ttm_init(struct radeon_device *rdev)
void radeon_ttm_fini(struct radeon_device *rdev)
{
int r;
if (rdev->stollen_vga_memory) {
radeon_object_unpin(rdev->stollen_vga_memory);
radeon_object_unref(&rdev->stollen_vga_memory);
r = radeon_bo_reserve(rdev->stollen_vga_memory, false);
if (r == 0) {
radeon_bo_unpin(rdev->stollen_vga_memory);
radeon_bo_unreserve(rdev->stollen_vga_memory);
}
radeon_bo_unref(&rdev->stollen_vga_memory);
}
ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_VRAM);
ttm_bo_clean_mm(&rdev->mman.bdev, TTM_PL_TT);
......
......@@ -352,7 +352,7 @@ static int rs400_mc_init(struct radeon_device *rdev)
u32 tmp;
/* Setup GPU memory space */
tmp = G_00015C_MC_FB_START(RREG32(R_00015C_NB_TOM));
tmp = RREG32(R_00015C_NB_TOM);
rdev->mc.vram_location = G_00015C_MC_FB_START(tmp) << 16;
rdev->mc.gtt_location = 0xFFFFFFFFUL;
r = radeon_mc_setup(rdev);
......@@ -387,13 +387,13 @@ static int rs400_startup(struct radeon_device *rdev)
r300_clock_startup(rdev);
/* Initialize GPU configuration (# pipes, ...) */
rs400_gpu_init(rdev);
r100_enable_bm(rdev);
/* Initialize GART (initialize after TTM so we can allocate
* memory through TTM but finalize after TTM) */
r = rs400_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);
......@@ -452,7 +452,7 @@ void rs400_fini(struct radeon_device *rdev)
rs400_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;
......@@ -490,10 +490,9 @@ int rs400_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;
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Get vram informations */
......@@ -510,7 +509,7 @@ int rs400_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;
r = rs400_gart_init(rdev);
......
......@@ -45,6 +45,21 @@
void rs600_gpu_init(struct radeon_device *rdev);
int rs600_mc_wait_for_idle(struct radeon_device *rdev);
int rs600_mc_init(struct radeon_device *rdev)
{
/* read back the MC value from the hw */
int r;
u32 tmp;
/* Setup GPU memory space */
tmp = RREG32_MC(R_000004_MC_FB_LOCATION);
rdev->mc.vram_location = G_000004_MC_FB_START(tmp) << 16;
rdev->mc.gtt_location = 0xffffffffUL;
r = radeon_mc_setup(rdev);
if (r)
return r;
return 0;
}
/*
* GART.
*/
......@@ -100,40 +115,40 @@ int rs600_gart_enable(struct radeon_device *rdev)
WREG32(R_00004C_BUS_CNTL, tmp);
/* FIXME: setup default page */
WREG32_MC(R_000100_MC_PT0_CNTL,
(S_000100_EFFECTIVE_L2_CACHE_SIZE(6) |
S_000100_EFFECTIVE_L2_QUEUE_SIZE(6)));
(S_000100_EFFECTIVE_L2_CACHE_SIZE(6) |
S_000100_EFFECTIVE_L2_QUEUE_SIZE(6)));
for (i = 0; i < 19; i++) {
WREG32_MC(R_00016C_MC_PT0_CLIENT0_CNTL + i,
S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) |
S_00016C_SYSTEM_ACCESS_MODE_MASK(
V_00016C_SYSTEM_ACCESS_MODE_IN_SYS) |
S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(
V_00016C_SYSTEM_APERTURE_UNMAPPED_DEFAULT_PAGE) |
S_00016C_EFFECTIVE_L1_CACHE_SIZE(1) |
S_00016C_ENABLE_FRAGMENT_PROCESSING(1) |
S_00016C_EFFECTIVE_L1_QUEUE_SIZE(1));
S_00016C_ENABLE_TRANSLATION_MODE_OVERRIDE(1) |
S_00016C_SYSTEM_ACCESS_MODE_MASK(
V_00016C_SYSTEM_ACCESS_MODE_NOT_IN_SYS) |
S_00016C_SYSTEM_APERTURE_UNMAPPED_ACCESS(
V_00016C_SYSTEM_APERTURE_UNMAPPED_PASSTHROUGH) |
S_00016C_EFFECTIVE_L1_CACHE_SIZE(3) |
S_00016C_ENABLE_FRAGMENT_PROCESSING(1) |
S_00016C_EFFECTIVE_L1_QUEUE_SIZE(3));
}
/* System context map to GART space */
WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.gtt_start);
WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.gtt_end);
/* enable first context */
WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start);
WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end);
WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL,
S_000102_ENABLE_PAGE_TABLE(1) |
S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT));
S_000102_ENABLE_PAGE_TABLE(1) |
S_000102_PAGE_TABLE_DEPTH(V_000102_PAGE_TABLE_FLAT));
/* disable all other contexts */
for (i = 1; i < 8; i++) {
for (i = 1; i < 8; i++)
WREG32_MC(R_000102_MC_PT0_CONTEXT0_CNTL + i, 0);
}
/* setup the page table */
WREG32_MC(R_00012C_MC_PT0_CONTEXT0_FLAT_BASE_ADDR,
rdev->gart.table_addr);
rdev->gart.table_addr);
WREG32_MC(R_00013C_MC_PT0_CONTEXT0_FLAT_START_ADDR, rdev->mc.gtt_start);
WREG32_MC(R_00014C_MC_PT0_CONTEXT0_FLAT_END_ADDR, rdev->mc.gtt_end);
WREG32_MC(R_00011C_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0);
/* System context maps to VRAM space */
WREG32_MC(R_000112_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start);
WREG32_MC(R_000114_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end);
/* enable page tables */
tmp = RREG32_MC(R_000100_MC_PT0_CNTL);
WREG32_MC(R_000100_MC_PT0_CNTL, (tmp | S_000100_ENABLE_PT(1)));
......@@ -146,15 +161,20 @@ int rs600_gart_enable(struct radeon_device *rdev)
void rs600_gart_disable(struct radeon_device *rdev)
{
uint32_t tmp;
u32 tmp;
int r;
/* FIXME: disable out of gart access */
WREG32_MC(R_000100_MC_PT0_CNTL, 0);
tmp = RREG32_MC(R_000009_MC_CNTL1);
WREG32_MC(R_000009_MC_CNTL1, tmp & C_000009_ENABLE_PAGE_TABLES);
if (rdev->gart.table.vram.robj) {
radeon_object_kunmap(rdev->gart.table.vram.robj);
radeon_object_unpin(rdev->gart.table.vram.robj);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (r == 0) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
}
......@@ -301,9 +321,7 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev)
void rs600_gpu_init(struct radeon_device *rdev)
{
/* FIXME: HDP same place on rs600 ? */
r100_hdp_reset(rdev);
/* FIXME: is this correct ? */
r420_pipes_init(rdev);
/* Wait for mc idle */
if (rs600_mc_wait_for_idle(rdev))
......@@ -312,9 +330,20 @@ void rs600_gpu_init(struct radeon_device *rdev)
void rs600_vram_info(struct radeon_device *rdev)
{
/* FIXME: to do or is these values sane ? */
rdev->mc.vram_is_ddr = true;
rdev->mc.vram_width = 128;
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
rdev->mc.mc_vram_size = rdev->mc.aper_size;
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
rdev->mc.real_vram_size = rdev->mc.aper_size;
}
void rs600_bandwidth_update(struct radeon_device *rdev)
......@@ -388,7 +417,6 @@ static int rs600_startup(struct radeon_device *rdev)
if (r)
return r;
/* Enable IRQ */
rdev->irq.sw_int = true;
rs600_irq_set(rdev);
/* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024);
......@@ -445,7 +473,7 @@ void rs600_fini(struct radeon_device *rdev)
rs600_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;
......@@ -482,10 +510,9 @@ int rs600_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");
atom_asic_init(rdev->mode_info.atom_context);
}
if (radeon_boot_test_post_card(rdev) == false)
return -EINVAL;
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
......@@ -493,7 +520,7 @@ int rs600_init(struct radeon_device *rdev)
/* Get vram informations */
rs600_vram_info(rdev);
/* Initialize memory controller (also test AGP) */
r = r420_mc_init(rdev);
r = rs600_mc_init(rdev);
if (r)
return r;
rs600_debugfs(rdev);
......@@ -505,7 +532,7 @@ int rs600_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;
r = rs600_gart_init(rdev);
......
......@@ -131,24 +131,25 @@ void rs690_pm_info(struct radeon_device *rdev)
void rs690_vram_info(struct radeon_device *rdev)
{
uint32_t tmp;
fixed20_12 a;
rs400_gart_adjust_size(rdev);
/* DDR for all card after R300 & IGP */
rdev->mc.vram_is_ddr = true;
/* FIXME: is this correct for RS690/RS740 ? */
tmp = RREG32(RADEON_MEM_CNTL);
if (tmp & R300_MEM_NUM_CHANNELS_MASK) {
rdev->mc.vram_width = 128;
} else {
rdev->mc.vram_width = 64;
}
rdev->mc.vram_width = 128;
rdev->mc.real_vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
if (rdev->mc.mc_vram_size > rdev->mc.aper_size)
rdev->mc.mc_vram_size = rdev->mc.aper_size;
if (rdev->mc.real_vram_size > rdev->mc.aper_size)
rdev->mc.real_vram_size = rdev->mc.aper_size;
rs690_pm_info(rdev);
/* FIXME: we should enforce default clock in case GPU is not in
* default setup
......@@ -161,6 +162,21 @@ void rs690_vram_info(struct radeon_device *rdev)
rdev->pm.core_bandwidth.full = rfixed_div(rdev->pm.sclk, a);
}
static int rs690_mc_init(struct radeon_device *rdev)
{
int r;
u32 tmp;
/* Setup GPU memory space */
tmp = RREG32_MC(R_000100_MCCFG_FB_LOCATION);
rdev->mc.vram_location = G_000100_MC_FB_START(tmp) << 16;
rdev->mc.gtt_location = 0xFFFFFFFFUL;
r = radeon_mc_setup(rdev);
if (r)
return r;
return 0;
}
void rs690_line_buffer_adjust(struct radeon_device *rdev,
struct drm_display_mode *mode1,
struct drm_display_mode *mode2)
......@@ -605,7 +621,6 @@ static int rs690_startup(struct radeon_device *rdev)
if (r)
return r;
/* Enable IRQ */
rdev->irq.sw_int = true;
rs600_irq_set(rdev);
/* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024);
......@@ -662,7 +677,7 @@ void rs690_fini(struct radeon_device *rdev)
rs400_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;
......@@ -700,10 +715,9 @@ int rs690_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");
atom_asic_init(rdev->mode_info.atom_context);
}
if (radeon_boot_test_post_card(rdev) == false)
return -EINVAL;
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
......@@ -711,7 +725,7 @@ int rs690_init(struct radeon_device *rdev)
/* Get vram informations */
rs690_vram_info(rdev);
/* Initialize memory controller (also test AGP) */
r = r420_mc_init(rdev);
r = rs690_mc_init(rdev);
if (r)
return r;
rv515_debugfs(rdev);
......@@ -723,7 +737,7 @@ int rs690_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;
r = rs400_gart_init(rdev);
......
......@@ -478,7 +478,6 @@ static int rv515_startup(struct radeon_device *rdev)
return r;
}
/* Enable IRQ */
rdev->irq.sw_int = true;
rs600_irq_set(rdev);
/* 1M ring buffer */
r = r100_cp_init(rdev, 1024 * 1024);
......@@ -540,11 +539,11 @@ void rv515_fini(struct radeon_device *rdev)
r100_wb_fini(rdev);
r100_ib_fini(rdev);
radeon_gem_fini(rdev);
rv370_pcie_gart_fini(rdev);
rv370_pcie_gart_fini(rdev);
radeon_agp_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;
......@@ -580,10 +579,8 @@ int rv515_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");
atom_asic_init(rdev->mode_info.atom_context);
}
if (radeon_boot_test_post_card(rdev) == false)
return -EINVAL;
/* Initialize clocks */
radeon_get_clock_info(rdev->ddev);
/* Initialize power management */
......@@ -603,7 +600,7 @@ int rv515_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;
r = rv370_pcie_gart_init(rdev);
......
......@@ -92,7 +92,7 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)
void rv770_pcie_gart_disable(struct radeon_device *rdev)
{
u32 tmp;
int i;
int i, r;
/* Disable all tables */
for (i = 0; i < 7; i++)
......@@ -113,8 +113,12 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev)
WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
if (rdev->gart.table.vram.robj) {
radeon_object_kunmap(rdev->gart.table.vram.robj);
radeon_object_unpin(rdev->gart.table.vram.robj);
r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
if (likely(r == 0)) {
radeon_bo_kunmap(rdev->gart.table.vram.robj);
radeon_bo_unpin(rdev->gart.table.vram.robj);
radeon_bo_unreserve(rdev->gart.table.vram.robj);
}
}
}
......@@ -880,13 +884,26 @@ static int rv770_startup(struct radeon_device *rdev)
}
rv770_gpu_init(rdev);
r = radeon_object_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->r600_blit.shader_gpu_addr);
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
if (unlikely(r != 0))
return r;
r = radeon_bo_pin(rdev->r600_blit.shader_obj, RADEON_GEM_DOMAIN_VRAM,
&rdev->r600_blit.shader_gpu_addr);
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
if (r) {
DRM_ERROR("failed to pin blit object %d\n", r);
return r;
}
/* Enable IRQ */
r = r600_irq_init(rdev);
if (r) {
DRM_ERROR("radeon: IH init failed (%d).\n", r);
radeon_irq_kms_fini(rdev);
return r;
}
r600_irq_set(rdev);
r = radeon_ring_init(rdev, rdev->cp.ring_size);
if (r)
return r;
......@@ -934,13 +951,19 @@ int rv770_resume(struct radeon_device *rdev)
int rv770_suspend(struct radeon_device *rdev)
{
int r;
/* FIXME: we should wait for ring to be empty */
r700_cp_stop(rdev);
rdev->cp.ready = false;
r600_wb_disable(rdev);
rv770_pcie_gart_disable(rdev);
/* unpin shaders bo */
radeon_object_unpin(rdev->r600_blit.shader_obj);
r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
if (likely(r == 0)) {
radeon_bo_unpin(rdev->r600_blit.shader_obj);
radeon_bo_unreserve(rdev->r600_blit.shader_obj);
}
return 0;
}
......@@ -975,7 +998,11 @@ int rv770_init(struct radeon_device *rdev)
if (r)
return r;
/* Post card if necessary */
if (!r600_card_posted(rdev) && rdev->bios) {
if (!r600_card_posted(rdev)) {
if (!rdev->bios) {
dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
return -EINVAL;
}
DRM_INFO("GPU not posted. posting now...\n");
atom_asic_init(rdev->mode_info.atom_context);
}
......@@ -998,14 +1025,22 @@ int rv770_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;
r = radeon_irq_kms_init(rdev);
if (r)
return r;
rdev->cp.ring_obj = NULL;
r600_ring_init(rdev, 1024 * 1024);
if (!rdev->me_fw || !rdev->pfp_fw) {
r = r600_cp_init_microcode(rdev);
rdev->ih.ring_obj = NULL;
r600_ih_ring_init(rdev, 64 * 1024);
if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
r = r600_init_microcode(rdev);
if (r) {
DRM_ERROR("Failed to load firmware!\n");
return r;
......@@ -1051,6 +1086,8 @@ void rv770_fini(struct radeon_device *rdev)
rv770_suspend(rdev);
r600_blit_fini(rdev);
r600_irq_fini(rdev);
radeon_irq_kms_fini(rdev);
radeon_ring_fini(rdev);
r600_wb_fini(rdev);
rv770_pcie_gart_fini(rdev);
......@@ -1059,7 +1096,7 @@ void rv770_fini(struct radeon_device *rdev)
radeon_clocks_fini(rdev);
if (rdev->flags & RADEON_IS_AGP)
radeon_agp_fini(rdev);
radeon_object_fini(rdev);
radeon_bo_fini(rdev);
radeon_atombios_fini(rdev);
kfree(rdev->bios);
rdev->bios = NULL;
......
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