Commit 84210aeb authored by Linus Torvalds's avatar Linus Torvalds

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

* 'drm-radeon-kms' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (35 commits)
  drm/radeon: set fb aperture sizes for framebuffer handoff.
  drm/ttm: fix highuser vs dma32 confusion.
  drm/radeon: Fix size used for benchmarking BO copies.
  drm/radeon: Add radeon.test parameter for running BO GPU copy tests.
  drm/radeon/kms: allow interruptible waits for objects.
  drm/ttm: powerpc: Fix Highmem cache flushing.
  x86: Export kmap_atomic_prot() needed for TTM.
  drm/ttm: Fix ttm in-kernel copying of pages with non-standard caching attributes.
  drm/ttm: Fix an oops and sync object leak.
  drm/radeon/kms: vram sizing on certain r100 chips needs workaround.
  drm/radeon: Pay more attention to object placement requested by userspace.
  drm/radeon: Fall back to evicting BOs with memcpy if necessary.
  drm/radeon: Don't unreserve twice on failure to validate.
  drm/radeon/kms: fix bandwidth computation on avivo hardware
  drm/radeon/kms: add initial colortiling support.
  drm/radeon/kms: fix hotspot handling on pre-avivo chips
  drm/radeon/kms: enable frac fb divs on rs600/rs690/rs740
  drm/radeon/kms: add PLL flag to prefer frequencies <= the target freq
  drm/radeon/kms: block RN50 from using 3D engine.
  drm/radeon/kms: fix VRAM sizing like DDX does it.
  ...
parents 7d4dd028 ed8f0d9e
...@@ -103,6 +103,7 @@ EXPORT_SYMBOL(kmap); ...@@ -103,6 +103,7 @@ EXPORT_SYMBOL(kmap);
EXPORT_SYMBOL(kunmap); EXPORT_SYMBOL(kunmap);
EXPORT_SYMBOL(kmap_atomic); EXPORT_SYMBOL(kmap_atomic);
EXPORT_SYMBOL(kunmap_atomic); EXPORT_SYMBOL(kunmap_atomic);
EXPORT_SYMBOL(kmap_atomic_prot);
void __init set_highmem_pages_init(void) void __init set_highmem_pages_init(void)
{ {
......
...@@ -13,7 +13,8 @@ radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \ ...@@ -13,7 +13,8 @@ radeon-$(CONFIG_DRM_RADEON_KMS) += radeon_device.o radeon_kms.o \
radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \ radeon_encoders.o radeon_display.o radeon_cursor.o radeon_i2c.o \
radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \ radeon_clocks.o radeon_fb.o radeon_gem.o radeon_ring.o radeon_irq_kms.o \
radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \ radeon_cs.o radeon_bios.o radeon_benchmark.o r100.o r300.o r420.o \
rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o rs400.o rs600.o rs690.o rv515.o r520.o r600.o rs780.o rv770.o \
radeon_test.o
radeon-$(CONFIG_COMPAT) += radeon_ioc32.o radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
......
This diff is collapsed.
This diff is collapsed.
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "drm.h" #include "drm.h"
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "radeon_drm.h"
#include "radeon_share.h"
/* r300,r350,rv350,rv370,rv380 depends on : */ /* r300,r350,rv350,rv370,rv380 depends on : */
void r100_hdp_reset(struct radeon_device *rdev); void r100_hdp_reset(struct radeon_device *rdev);
...@@ -44,6 +46,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev); ...@@ -44,6 +46,7 @@ int r100_gui_wait_for_idle(struct radeon_device *rdev);
int r100_cs_packet_parse(struct radeon_cs_parser *p, int r100_cs_packet_parse(struct radeon_cs_parser *p,
struct radeon_cs_packet *pkt, struct radeon_cs_packet *pkt,
unsigned idx); unsigned idx);
int r100_cs_packet_parse_vline(struct radeon_cs_parser *p);
int r100_cs_packet_next_reloc(struct radeon_cs_parser *p, int r100_cs_packet_next_reloc(struct radeon_cs_parser *p,
struct radeon_cs_reloc **cs_reloc); struct radeon_cs_reloc **cs_reloc);
int r100_cs_parse_packet0(struct radeon_cs_parser *p, int r100_cs_parse_packet0(struct radeon_cs_parser *p,
...@@ -150,8 +153,13 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) ...@@ -150,8 +153,13 @@ int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
} }
addr = (((u32)addr) >> 8) | ((upper_32_bits(addr) & 0xff) << 4) | 0xC; addr = (lower_32_bits(addr) >> 8) |
writel(cpu_to_le32(addr), ((void __iomem *)ptr) + (i * 4)); ((upper_32_bits(addr) & 0xff) << 24) |
0xc;
/* on x86 we want this to be CPU endian, on powerpc
* on powerpc without HW swappers, it'll get swapped on way
* into VRAM - so no need for cpu_to_le32 on VRAM tables */
writel(addr, ((void __iomem *)ptr) + (i * 4));
return 0; return 0;
} }
...@@ -579,10 +587,8 @@ void r300_vram_info(struct radeon_device *rdev) ...@@ -579,10 +587,8 @@ void r300_vram_info(struct radeon_device *rdev)
} else { } else {
rdev->mc.vram_width = 64; rdev->mc.vram_width = 64;
} }
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); r100_vram_init_sizes(rdev);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
} }
...@@ -970,7 +976,7 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track) ...@@ -970,7 +976,7 @@ static inline void r300_cs_track_clear(struct r300_cs_track *track)
static const unsigned r300_reg_safe_bm[159] = { static const unsigned r300_reg_safe_bm[159] = {
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFBF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
...@@ -1019,7 +1025,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1019,7 +1025,7 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
struct radeon_cs_reloc *reloc; struct radeon_cs_reloc *reloc;
struct r300_cs_track *track; struct r300_cs_track *track;
volatile uint32_t *ib; volatile uint32_t *ib;
uint32_t tmp; uint32_t tmp, tile_flags = 0;
unsigned i; unsigned i;
int r; int r;
...@@ -1027,6 +1033,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1027,6 +1033,16 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
ib_chunk = &p->chunks[p->chunk_ib_idx]; ib_chunk = &p->chunks[p->chunk_ib_idx];
track = (struct r300_cs_track*)p->track; track = (struct r300_cs_track*)p->track;
switch(reg) { switch(reg) {
case AVIVO_D1MODE_VLINE_START_END:
case RADEON_CRTC_GUI_TRIG_VLINE:
r = r100_cs_packet_parse_vline(p);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
break;
case RADEON_DST_PITCH_OFFSET: case RADEON_DST_PITCH_OFFSET:
case RADEON_SRC_PITCH_OFFSET: case RADEON_SRC_PITCH_OFFSET:
r = r100_cs_packet_next_reloc(p, &reloc); r = r100_cs_packet_next_reloc(p, &reloc);
...@@ -1038,7 +1054,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1038,7 +1054,19 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
} }
tmp = ib_chunk->kdata[idx] & 0x003fffff; tmp = ib_chunk->kdata[idx] & 0x003fffff;
tmp += (((u32)reloc->lobj.gpu_offset) >> 10); tmp += (((u32)reloc->lobj.gpu_offset) >> 10);
ib[idx] = (ib_chunk->kdata[idx] & 0xffc00000) | tmp;
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= RADEON_DST_TILE_MACRO;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) {
if (reg == RADEON_SRC_PITCH_OFFSET) {
DRM_ERROR("Cannot src blit from microtiled surface\n");
r100_cs_dump_packet(p, pkt);
return -EINVAL;
}
tile_flags |= RADEON_DST_TILE_MICRO;
}
tmp |= tile_flags;
ib[idx] = (ib_chunk->kdata[idx] & 0x3fc00000) | tmp;
break; break;
case R300_RB3D_COLOROFFSET0: case R300_RB3D_COLOROFFSET0:
case R300_RB3D_COLOROFFSET1: case R300_RB3D_COLOROFFSET1:
...@@ -1127,6 +1155,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1127,6 +1155,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
/* RB3D_COLORPITCH1 */ /* RB3D_COLORPITCH1 */
/* RB3D_COLORPITCH2 */ /* RB3D_COLORPITCH2 */
/* RB3D_COLORPITCH3 */ /* RB3D_COLORPITCH3 */
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= R300_COLOR_TILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_COLOR_MICROTILE_ENABLE;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
i = (reg - 0x4E38) >> 2; i = (reg - 0x4E38) >> 2;
track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE; track->cb[i].pitch = ib_chunk->kdata[idx] & 0x3FFE;
switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) { switch (((ib_chunk->kdata[idx] >> 21) & 0xF)) {
...@@ -1182,6 +1227,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p, ...@@ -1182,6 +1227,23 @@ static int r300_packet0_check(struct radeon_cs_parser *p,
break; break;
case 0x4F24: case 0x4F24:
/* ZB_DEPTHPITCH */ /* ZB_DEPTHPITCH */
r = r100_cs_packet_next_reloc(p, &reloc);
if (r) {
DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
idx, reg);
r100_cs_dump_packet(p, pkt);
return r;
}
if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
tile_flags |= R300_DEPTHMACROTILE_ENABLE;
if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
tile_flags |= R300_DEPTHMICROTILE_TILED;;
tmp = ib_chunk->kdata[idx] & ~(0x7 << 16);
tmp |= tile_flags;
ib[idx] = tmp;
track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC; track->zb.pitch = ib_chunk->kdata[idx] & 0x3FFC;
break; break;
case 0x4104: case 0x4104:
......
...@@ -27,7 +27,9 @@ ...@@ -27,7 +27,9 @@
#ifndef _R300_REG_H_ #ifndef _R300_REG_H_
#define _R300_REG_H_ #define _R300_REG_H_
#define R300_SURF_TILE_MACRO (1<<16)
#define R300_SURF_TILE_MICRO (2<<16)
#define R300_SURF_TILE_BOTH (3<<16)
#define R300_MC_INIT_MISC_LAT_TIMER 0x180 #define R300_MC_INIT_MISC_LAT_TIMER 0x180
......
...@@ -445,6 +445,7 @@ ...@@ -445,6 +445,7 @@
#define AVIVO_D1MODE_DATA_FORMAT 0x6528 #define AVIVO_D1MODE_DATA_FORMAT 0x6528
# define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0) # define AVIVO_D1MODE_INTERLEAVE_EN (1 << 0)
#define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C #define AVIVO_D1MODE_DESKTOP_HEIGHT 0x652C
#define AVIVO_D1MODE_VLINE_START_END 0x6538
#define AVIVO_D1MODE_VIEWPORT_START 0x6580 #define AVIVO_D1MODE_VIEWPORT_START 0x6580
#define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584 #define AVIVO_D1MODE_VIEWPORT_SIZE 0x6584
#define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588 #define AVIVO_D1MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6588
...@@ -496,6 +497,7 @@ ...@@ -496,6 +497,7 @@
#define AVIVO_D2CUR_SIZE 0x6c10 #define AVIVO_D2CUR_SIZE 0x6c10
#define AVIVO_D2CUR_POSITION 0x6c14 #define AVIVO_D2CUR_POSITION 0x6c14
#define AVIVO_D2MODE_VLINE_START_END 0x6d38
#define AVIVO_D2MODE_VIEWPORT_START 0x6d80 #define AVIVO_D2MODE_VIEWPORT_START 0x6d80
#define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84 #define AVIVO_D2MODE_VIEWPORT_SIZE 0x6d84
#define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88 #define AVIVO_D2MODE_EXT_OVERSCAN_LEFT_RIGHT 0x6d88
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "drmP.h" #include "drmP.h"
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "radeon_share.h"
/* r520,rv530,rv560,rv570,r580 depends on : */ /* r520,rv530,rv560,rv570,r580 depends on : */
void r100_hdp_reset(struct radeon_device *rdev); void r100_hdp_reset(struct radeon_device *rdev);
...@@ -94,8 +95,8 @@ int r520_mc_init(struct radeon_device *rdev) ...@@ -94,8 +95,8 @@ int r520_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
/* Write VRAM size in case we are limiting it */ /* Write VRAM size in case we are limiting it */
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size); WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.real_vram_size);
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16); tmp = REG_SET(R520_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16); tmp |= REG_SET(R520_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(R520_MC_FB_LOCATION, tmp); WREG32_MC(R520_MC_FB_LOCATION, tmp);
...@@ -226,9 +227,20 @@ static void r520_vram_get_type(struct radeon_device *rdev) ...@@ -226,9 +227,20 @@ static void r520_vram_get_type(struct radeon_device *rdev)
void r520_vram_info(struct radeon_device *rdev) void r520_vram_info(struct radeon_device *rdev)
{ {
fixed20_12 a;
r520_vram_get_type(rdev); r520_vram_get_type(rdev);
rdev->mc.vram_size = RREG32(RADEON_CONFIG_MEMSIZE);
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); r100_vram_init_sizes(rdev);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0); /* FIXME: we should enforce default clock in case GPU is not in
* default setup
*/
a.full = rfixed_const(100);
rdev->pm.sclk.full = rfixed_const(rdev->clock.default_sclk);
rdev->pm.sclk.full = rfixed_div(rdev->pm.sclk, a);
}
void r520_bandwidth_update(struct radeon_device *rdev)
{
rv515_bandwidth_avivo_update(rdev);
} }
...@@ -67,7 +67,7 @@ int r600_mc_init(struct radeon_device *rdev) ...@@ -67,7 +67,7 @@ int r600_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24); tmp = REG_SET(R600_MC_FB_TOP, tmp >> 24);
tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24); tmp |= REG_SET(R600_MC_FB_BASE, rdev->mc.vram_location >> 24);
WREG32(R600_MC_VM_FB_LOCATION, tmp); WREG32(R600_MC_VM_FB_LOCATION, tmp);
...@@ -140,7 +140,8 @@ void r600_vram_get_type(struct radeon_device *rdev) ...@@ -140,7 +140,8 @@ void r600_vram_get_type(struct radeon_device *rdev)
void r600_vram_info(struct radeon_device *rdev) void r600_vram_info(struct radeon_device *rdev)
{ {
r600_vram_get_type(rdev); r600_vram_get_type(rdev);
rdev->mc.vram_size = RREG32(R600_CONFIG_MEMSIZE); rdev->mc.real_vram_size = RREG32(R600_CONFIG_MEMSIZE);
rdev->mc.mc_vram_size = rdev->mc.real_vram_size;
/* Could aper size report 0 ? */ /* Could aper size report 0 ? */
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0); rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
......
...@@ -64,6 +64,7 @@ extern int radeon_agpmode; ...@@ -64,6 +64,7 @@ extern int radeon_agpmode;
extern int radeon_vram_limit; extern int radeon_vram_limit;
extern int radeon_gart_size; extern int radeon_gart_size;
extern int radeon_benchmarking; extern int radeon_benchmarking;
extern int radeon_testing;
extern int radeon_connector_table; extern int radeon_connector_table;
/* /*
...@@ -113,6 +114,7 @@ enum radeon_family { ...@@ -113,6 +114,7 @@ enum radeon_family {
CHIP_RV770, CHIP_RV770,
CHIP_RV730, CHIP_RV730,
CHIP_RV710, CHIP_RV710,
CHIP_RS880,
CHIP_LAST, CHIP_LAST,
}; };
...@@ -201,6 +203,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev); ...@@ -201,6 +203,14 @@ int radeon_fence_wait_last(struct radeon_device *rdev);
struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence); struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence);
void radeon_fence_unref(struct radeon_fence **fence); void radeon_fence_unref(struct radeon_fence **fence);
/*
* Tiling registers
*/
struct radeon_surface_reg {
struct radeon_object *robj;
};
#define RADEON_GEM_MAX_SURFACES 8
/* /*
* Radeon buffer. * Radeon buffer.
...@@ -213,6 +223,7 @@ struct radeon_object_list { ...@@ -213,6 +223,7 @@ struct radeon_object_list {
uint64_t gpu_offset; uint64_t gpu_offset;
unsigned rdomain; unsigned rdomain;
unsigned wdomain; unsigned wdomain;
uint32_t tiling_flags;
}; };
int radeon_object_init(struct radeon_device *rdev); int radeon_object_init(struct radeon_device *rdev);
...@@ -242,8 +253,15 @@ void radeon_object_list_clean(struct list_head *head); ...@@ -242,8 +253,15 @@ void radeon_object_list_clean(struct list_head *head);
int radeon_object_fbdev_mmap(struct radeon_object *robj, int radeon_object_fbdev_mmap(struct radeon_object *robj,
struct vm_area_struct *vma); struct vm_area_struct *vma);
unsigned long radeon_object_size(struct radeon_object *robj); 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. * GEM objects.
*/ */
...@@ -315,8 +333,11 @@ struct radeon_mc { ...@@ -315,8 +333,11 @@ struct radeon_mc {
unsigned gtt_location; unsigned gtt_location;
unsigned gtt_size; unsigned gtt_size;
unsigned vram_location; unsigned vram_location;
unsigned vram_size; /* for some chips with <= 32MB we need to lie
* about vram size near mc fb location */
unsigned mc_vram_size;
unsigned vram_width; unsigned vram_width;
unsigned real_vram_size;
int vram_mtrr; int vram_mtrr;
bool vram_is_ddr; bool vram_is_ddr;
}; };
...@@ -474,6 +495,39 @@ struct radeon_wb { ...@@ -474,6 +495,39 @@ struct radeon_wb {
uint64_t gpu_addr; uint64_t gpu_addr;
}; };
/**
* struct radeon_pm - power management datas
* @max_bandwidth: maximum bandwidth the gpu has (MByte/s)
* @igp_sideport_mclk: sideport memory clock Mhz (rs690,rs740,rs780,rs880)
* @igp_system_mclk: system clock Mhz (rs690,rs740,rs780,rs880)
* @igp_ht_link_clk: ht link clock Mhz (rs690,rs740,rs780,rs880)
* @igp_ht_link_width: ht link width in bits (rs690,rs740,rs780,rs880)
* @k8_bandwidth: k8 bandwidth the gpu has (MByte/s) (IGP)
* @sideport_bandwidth: sideport bandwidth the gpu has (MByte/s) (IGP)
* @ht_bandwidth: ht bandwidth the gpu has (MByte/s) (IGP)
* @core_bandwidth: core GPU bandwidth the gpu has (MByte/s) (IGP)
* @sclk: GPU clock Mhz (core bandwith depends of this clock)
* @needed_bandwidth: current bandwidth needs
*
* It keeps track of various data needed to take powermanagement decision.
* Bandwith need is used to determine minimun clock of the GPU and memory.
* Equation between gpu/memory clock and available bandwidth is hw dependent
* (type of memory, bus size, efficiency, ...)
*/
struct radeon_pm {
fixed20_12 max_bandwidth;
fixed20_12 igp_sideport_mclk;
fixed20_12 igp_system_mclk;
fixed20_12 igp_ht_link_clk;
fixed20_12 igp_ht_link_width;
fixed20_12 k8_bandwidth;
fixed20_12 sideport_bandwidth;
fixed20_12 ht_bandwidth;
fixed20_12 core_bandwidth;
fixed20_12 sclk;
fixed20_12 needed_bandwidth;
};
/* /*
* Benchmarking * Benchmarking
...@@ -481,6 +535,12 @@ struct radeon_wb { ...@@ -481,6 +535,12 @@ struct radeon_wb {
void radeon_benchmark(struct radeon_device *rdev); void radeon_benchmark(struct radeon_device *rdev);
/*
* Testing
*/
void radeon_test_moves(struct radeon_device *rdev);
/* /*
* Debugfs * Debugfs
*/ */
...@@ -535,6 +595,11 @@ struct radeon_asic { ...@@ -535,6 +595,11 @@ struct radeon_asic {
void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock); void (*set_memory_clock)(struct radeon_device *rdev, uint32_t mem_clock);
void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes); void (*set_pcie_lanes)(struct radeon_device *rdev, int lanes);
void (*set_clock_gating)(struct radeon_device *rdev, int enable); void (*set_clock_gating)(struct radeon_device *rdev, int enable);
int (*set_surface_reg)(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size);
int (*clear_surface_reg)(struct radeon_device *rdev, int reg);
void (*bandwidth_update)(struct radeon_device *rdev);
}; };
union radeon_asic_config { union radeon_asic_config {
...@@ -566,6 +631,10 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, ...@@ -566,6 +631,10 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp); struct drm_file *filp);
int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp); int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp);
int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp);
/* /*
...@@ -594,8 +663,8 @@ struct radeon_device { ...@@ -594,8 +663,8 @@ struct radeon_device {
struct radeon_object *fbdev_robj; struct radeon_object *fbdev_robj;
struct radeon_framebuffer *fbdev_rfb; struct radeon_framebuffer *fbdev_rfb;
/* Register mmio */ /* Register mmio */
unsigned long rmmio_base; resource_size_t rmmio_base;
unsigned long rmmio_size; resource_size_t rmmio_size;
void *rmmio; void *rmmio;
radeon_rreg_t mm_rreg; radeon_rreg_t mm_rreg;
radeon_wreg_t mm_wreg; radeon_wreg_t mm_wreg;
...@@ -619,11 +688,14 @@ struct radeon_device { ...@@ -619,11 +688,14 @@ struct radeon_device {
struct radeon_irq irq; struct radeon_irq irq;
struct radeon_asic *asic; struct radeon_asic *asic;
struct radeon_gem gem; struct radeon_gem gem;
struct radeon_pm pm;
struct mutex cs_mutex; struct mutex cs_mutex;
struct radeon_wb wb; struct radeon_wb wb;
bool gpu_lockup; bool gpu_lockup;
bool shutdown; bool shutdown;
bool suspend; bool suspend;
bool need_dma32;
struct radeon_surface_reg surface_regs[RADEON_GEM_MAX_SURFACES];
}; };
int radeon_device_init(struct radeon_device *rdev, int radeon_device_init(struct radeon_device *rdev,
...@@ -670,6 +742,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev); ...@@ -670,6 +742,8 @@ void r100_pll_errata_after_index(struct radeon_device *rdev);
/* /*
* ASICs helpers. * ASICs helpers.
*/ */
#define ASIC_IS_RN50(rdev) ((rdev->pdev->device == 0x515e) || \
(rdev->pdev->device == 0x5969))
#define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \ #define ASIC_IS_RV100(rdev) ((rdev->family == CHIP_RV100) || \
(rdev->family == CHIP_RV200) || \ (rdev->family == CHIP_RV200) || \
(rdev->family == CHIP_RS100) || \ (rdev->family == CHIP_RS100) || \
...@@ -796,5 +870,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) ...@@ -796,5 +870,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v)
#define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e)) #define radeon_set_memory_clock(rdev, e) (rdev)->asic->set_engine_clock((rdev), (e))
#define radeon_set_pcie_lanes(rdev, l) (rdev)->asic->set_pcie_lanes((rdev), (l)) #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_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))
#endif #endif
...@@ -71,6 +71,11 @@ int r100_copy_blit(struct radeon_device *rdev, ...@@ -71,6 +71,11 @@ int r100_copy_blit(struct radeon_device *rdev,
uint64_t dst_offset, uint64_t dst_offset,
unsigned num_pages, unsigned num_pages,
struct radeon_fence *fence); struct radeon_fence *fence);
int r100_set_surface_reg(struct radeon_device *rdev, int reg,
uint32_t tiling_flags, uint32_t pitch,
uint32_t offset, uint32_t obj_size);
int r100_clear_surface_reg(struct radeon_device *rdev, int reg);
void r100_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic r100_asic = { static struct radeon_asic r100_asic = {
.init = &r100_init, .init = &r100_init,
...@@ -100,6 +105,9 @@ static struct radeon_asic r100_asic = { ...@@ -100,6 +105,9 @@ static struct radeon_asic r100_asic = {
.set_memory_clock = NULL, .set_memory_clock = NULL,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_legacy_set_clock_gating, .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
...@@ -128,6 +136,7 @@ int r300_copy_dma(struct radeon_device *rdev, ...@@ -128,6 +136,7 @@ int r300_copy_dma(struct radeon_device *rdev,
uint64_t dst_offset, uint64_t dst_offset,
unsigned num_pages, unsigned num_pages,
struct radeon_fence *fence); struct radeon_fence *fence);
static struct radeon_asic r300_asic = { static struct radeon_asic r300_asic = {
.init = &r300_init, .init = &r300_init,
.errata = &r300_errata, .errata = &r300_errata,
...@@ -156,6 +165,9 @@ static struct radeon_asic r300_asic = { ...@@ -156,6 +165,9 @@ static struct radeon_asic r300_asic = {
.set_memory_clock = NULL, .set_memory_clock = NULL,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_legacy_set_clock_gating, .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
/* /*
...@@ -193,6 +205,9 @@ static struct radeon_asic r420_asic = { ...@@ -193,6 +205,9 @@ static struct radeon_asic r420_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
...@@ -237,6 +252,9 @@ static struct radeon_asic rs400_asic = { ...@@ -237,6 +252,9 @@ static struct radeon_asic rs400_asic = {
.set_memory_clock = NULL, .set_memory_clock = NULL,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_legacy_set_clock_gating, .set_clock_gating = &radeon_legacy_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r100_bandwidth_update,
}; };
...@@ -254,6 +272,7 @@ void rs600_gart_tlb_flush(struct radeon_device *rdev); ...@@ -254,6 +272,7 @@ void rs600_gart_tlb_flush(struct radeon_device *rdev);
int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr); int rs600_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg); uint32_t rs600_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs600_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rs600_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rs600_asic = { static struct radeon_asic rs600_asic = {
.init = &r300_init, .init = &r300_init,
.errata = &rs600_errata, .errata = &rs600_errata,
...@@ -282,6 +301,7 @@ static struct radeon_asic rs600_asic = { ...@@ -282,6 +301,7 @@ static struct radeon_asic rs600_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.bandwidth_update = &rs600_bandwidth_update,
}; };
...@@ -294,6 +314,7 @@ int rs690_mc_init(struct radeon_device *rdev); ...@@ -294,6 +314,7 @@ int rs690_mc_init(struct radeon_device *rdev);
void rs690_mc_fini(struct radeon_device *rdev); void rs690_mc_fini(struct radeon_device *rdev);
uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg); uint32_t rs690_mc_rreg(struct radeon_device *rdev, uint32_t reg);
void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rs690_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rs690_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rs690_asic = { static struct radeon_asic rs690_asic = {
.init = &r300_init, .init = &r300_init,
.errata = &rs690_errata, .errata = &rs690_errata,
...@@ -322,6 +343,9 @@ static struct radeon_asic rs690_asic = { ...@@ -322,6 +343,9 @@ static struct radeon_asic rs690_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = NULL, .set_pcie_lanes = NULL,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rs690_bandwidth_update,
}; };
...@@ -339,6 +363,7 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); ...@@ -339,6 +363,7 @@ void rv515_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_ring_start(struct radeon_device *rdev); void rv515_ring_start(struct radeon_device *rdev);
uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg); uint32_t rv515_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v); void rv515_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
void rv515_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic rv515_asic = { static struct radeon_asic rv515_asic = {
.init = &rv515_init, .init = &rv515_init,
.errata = &rv515_errata, .errata = &rv515_errata,
...@@ -367,6 +392,9 @@ static struct radeon_asic rv515_asic = { ...@@ -367,6 +392,9 @@ static struct radeon_asic rv515_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &rv515_bandwidth_update,
}; };
...@@ -377,6 +405,7 @@ void r520_errata(struct radeon_device *rdev); ...@@ -377,6 +405,7 @@ void r520_errata(struct radeon_device *rdev);
void r520_vram_info(struct radeon_device *rdev); void r520_vram_info(struct radeon_device *rdev);
int r520_mc_init(struct radeon_device *rdev); int r520_mc_init(struct radeon_device *rdev);
void r520_mc_fini(struct radeon_device *rdev); void r520_mc_fini(struct radeon_device *rdev);
void r520_bandwidth_update(struct radeon_device *rdev);
static struct radeon_asic r520_asic = { static struct radeon_asic r520_asic = {
.init = &rv515_init, .init = &rv515_init,
.errata = &r520_errata, .errata = &r520_errata,
...@@ -405,6 +434,9 @@ static struct radeon_asic r520_asic = { ...@@ -405,6 +434,9 @@ static struct radeon_asic r520_asic = {
.set_memory_clock = &radeon_atom_set_memory_clock, .set_memory_clock = &radeon_atom_set_memory_clock,
.set_pcie_lanes = &rv370_set_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes,
.set_clock_gating = &radeon_atom_set_clock_gating, .set_clock_gating = &radeon_atom_set_clock_gating,
.set_surface_reg = r100_set_surface_reg,
.clear_surface_reg = r100_clear_surface_reg,
.bandwidth_update = &r520_bandwidth_update,
}; };
/* /*
......
...@@ -103,7 +103,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device ...@@ -103,7 +103,8 @@ static inline struct radeon_i2c_bus_rec radeon_lookup_gpio(struct drm_device
static bool radeon_atom_apply_quirks(struct drm_device *dev, static bool radeon_atom_apply_quirks(struct drm_device *dev,
uint32_t supported_device, uint32_t supported_device,
int *connector_type, int *connector_type,
struct radeon_i2c_bus_rec *i2c_bus) struct radeon_i2c_bus_rec *i2c_bus,
uint8_t *line_mux)
{ {
/* Asus M2A-VM HDMI board lists the DVI port as HDMI */ /* Asus M2A-VM HDMI board lists the DVI port as HDMI */
...@@ -127,8 +128,10 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, ...@@ -127,8 +128,10 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev,
if ((dev->pdev->device == 0x5653) && if ((dev->pdev->device == 0x5653) &&
(dev->pdev->subsystem_vendor == 0x1462) && (dev->pdev->subsystem_vendor == 0x1462) &&
(dev->pdev->subsystem_device == 0x0291)) { (dev->pdev->subsystem_device == 0x0291)) {
if (*connector_type == DRM_MODE_CONNECTOR_LVDS) if (*connector_type == DRM_MODE_CONNECTOR_LVDS) {
i2c_bus->valid = false; i2c_bus->valid = false;
*line_mux = 53;
}
} }
/* Funky macbooks */ /* Funky macbooks */
...@@ -526,7 +529,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct ...@@ -526,7 +529,7 @@ bool radeon_get_atom_connector_info_from_supported_devices_table(struct
if (!radeon_atom_apply_quirks if (!radeon_atom_apply_quirks
(dev, (1 << i), &bios_connectors[i].connector_type, (dev, (1 << i), &bios_connectors[i].connector_type,
&bios_connectors[i].ddc_bus)) &bios_connectors[i].ddc_bus, &bios_connectors[i].line_mux))
continue; continue;
bios_connectors[i].valid = true; bios_connectors[i].valid = true;
......
...@@ -63,7 +63,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, ...@@ -63,7 +63,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
r = radeon_copy_dma(rdev, saddr, daddr, size >> 14, fence); r = radeon_copy_dma(rdev, saddr, daddr, size / 4096, fence);
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
...@@ -88,7 +88,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize, ...@@ -88,7 +88,7 @@ void radeon_benchmark_move(struct radeon_device *rdev, unsigned bsize,
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
r = radeon_copy_blit(rdev, saddr, daddr, size >> 14, fence); r = radeon_copy_blit(rdev, saddr, daddr, size / 4096, fence);
if (r) { if (r) {
goto out_cleanup; goto out_cleanup;
} }
......
...@@ -127,17 +127,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) ...@@ -127,17 +127,23 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data)
sizeof(struct drm_radeon_cs_chunk))) { sizeof(struct drm_radeon_cs_chunk))) {
return -EFAULT; return -EFAULT;
} }
p->chunks[i].length_dw = user_chunk.length_dw;
p->chunks[i].kdata = NULL;
p->chunks[i].chunk_id = user_chunk.chunk_id; p->chunks[i].chunk_id = user_chunk.chunk_id;
if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) { if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_RELOCS) {
p->chunk_relocs_idx = i; p->chunk_relocs_idx = i;
} }
if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) { if (p->chunks[i].chunk_id == RADEON_CHUNK_ID_IB) {
p->chunk_ib_idx = i; p->chunk_ib_idx = i;
/* zero length IB isn't useful */
if (p->chunks[i].length_dw == 0)
return -EINVAL;
} }
p->chunks[i].length_dw = user_chunk.length_dw; p->chunks[i].length_dw = user_chunk.length_dw;
cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data; cdata = (uint32_t *)(unsigned long)user_chunk.chunk_data;
p->chunks[i].kdata = NULL;
size = p->chunks[i].length_dw * sizeof(uint32_t); size = p->chunks[i].length_dw * sizeof(uint32_t);
p->chunks[i].kdata = kzalloc(size, GFP_KERNEL); p->chunks[i].kdata = kzalloc(size, GFP_KERNEL);
if (p->chunks[i].kdata == NULL) { if (p->chunks[i].kdata == NULL) {
......
...@@ -111,9 +111,11 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj, ...@@ -111,9 +111,11 @@ static void radeon_set_cursor(struct drm_crtc *crtc, struct drm_gem_object *obj,
if (ASIC_IS_AVIVO(rdev)) if (ASIC_IS_AVIVO(rdev))
WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr); WREG32(AVIVO_D1CUR_SURFACE_ADDRESS + radeon_crtc->crtc_offset, gpu_addr);
else else {
radeon_crtc->legacy_cursor_offset = gpu_addr - radeon_crtc->legacy_display_base_addr;
/* offset is from DISP(2)_BASE_ADDRESS */ /* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, gpu_addr); WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, radeon_crtc->legacy_cursor_offset);
}
} }
int radeon_crtc_cursor_set(struct drm_crtc *crtc, int radeon_crtc_cursor_set(struct drm_crtc *crtc,
...@@ -245,6 +247,9 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, ...@@ -245,6 +247,9 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc,
(RADEON_CUR_LOCK (RADEON_CUR_LOCK
| ((xorigin ? 0 : x) << 16) | ((xorigin ? 0 : x) << 16)
| (yorigin ? 0 : y))); | (yorigin ? 0 : y)));
/* offset is from DISP(2)_BASE_ADDRESS */
WREG32(RADEON_CUR_OFFSET + radeon_crtc->crtc_offset, (radeon_crtc->legacy_cursor_offset +
(yorigin * 256)));
} }
radeon_lock_cursor(crtc, false); radeon_lock_cursor(crtc, false);
......
...@@ -48,6 +48,8 @@ static void radeon_surface_init(struct radeon_device *rdev) ...@@ -48,6 +48,8 @@ static void radeon_surface_init(struct radeon_device *rdev)
i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO), i * (RADEON_SURFACE1_INFO - RADEON_SURFACE0_INFO),
0); 0);
} }
/* enable surfaces */
WREG32(RADEON_SURFACE_CNTL, 0);
} }
} }
...@@ -119,7 +121,7 @@ int radeon_mc_setup(struct radeon_device *rdev) ...@@ -119,7 +121,7 @@ int radeon_mc_setup(struct radeon_device *rdev)
if (rdev->mc.vram_location != 0xFFFFFFFFUL) { if (rdev->mc.vram_location != 0xFFFFFFFFUL) {
/* vram location was already setup try to put gtt after /* vram location was already setup try to put gtt after
* if it fits */ * if it fits */
tmp = rdev->mc.vram_location + rdev->mc.vram_size; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size;
tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1); tmp = (tmp + rdev->mc.gtt_size - 1) & ~(rdev->mc.gtt_size - 1);
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) { if ((0xFFFFFFFFUL - tmp) >= rdev->mc.gtt_size) {
rdev->mc.gtt_location = tmp; rdev->mc.gtt_location = tmp;
...@@ -134,13 +136,13 @@ int radeon_mc_setup(struct radeon_device *rdev) ...@@ -134,13 +136,13 @@ int radeon_mc_setup(struct radeon_device *rdev)
} else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) { } else if (rdev->mc.gtt_location != 0xFFFFFFFFUL) {
/* gtt location was already setup try to put vram before /* gtt location was already setup try to put vram before
* if it fits */ * if it fits */
if (rdev->mc.vram_size < rdev->mc.gtt_location) { if (rdev->mc.mc_vram_size < rdev->mc.gtt_location) {
rdev->mc.vram_location = 0; rdev->mc.vram_location = 0;
} else { } else {
tmp = rdev->mc.gtt_location + rdev->mc.gtt_size; tmp = rdev->mc.gtt_location + rdev->mc.gtt_size;
tmp += (rdev->mc.vram_size - 1); tmp += (rdev->mc.mc_vram_size - 1);
tmp &= ~(rdev->mc.vram_size - 1); tmp &= ~(rdev->mc.mc_vram_size - 1);
if ((0xFFFFFFFFUL - tmp) >= rdev->mc.vram_size) { if ((0xFFFFFFFFUL - tmp) >= rdev->mc.mc_vram_size) {
rdev->mc.vram_location = tmp; rdev->mc.vram_location = tmp;
} else { } else {
printk(KERN_ERR "[drm] vram too big to fit " printk(KERN_ERR "[drm] vram too big to fit "
...@@ -150,12 +152,14 @@ int radeon_mc_setup(struct radeon_device *rdev) ...@@ -150,12 +152,14 @@ int radeon_mc_setup(struct radeon_device *rdev)
} }
} else { } else {
rdev->mc.vram_location = 0; rdev->mc.vram_location = 0;
rdev->mc.gtt_location = rdev->mc.vram_size; rdev->mc.gtt_location = rdev->mc.mc_vram_size;
} }
DRM_INFO("radeon: VRAM %uM\n", rdev->mc.vram_size >> 20); DRM_INFO("radeon: VRAM %uM\n", rdev->mc.real_vram_size >> 20);
DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n", DRM_INFO("radeon: VRAM from 0x%08X to 0x%08X\n",
rdev->mc.vram_location, rdev->mc.vram_location,
rdev->mc.vram_location + rdev->mc.vram_size - 1); rdev->mc.vram_location + rdev->mc.mc_vram_size - 1);
if (rdev->mc.real_vram_size != rdev->mc.mc_vram_size)
DRM_INFO("radeon: VRAM less than aperture workaround enabled\n");
DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20); DRM_INFO("radeon: GTT %uM\n", rdev->mc.gtt_size >> 20);
DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n", DRM_INFO("radeon: GTT from 0x%08X to 0x%08X\n",
rdev->mc.gtt_location, rdev->mc.gtt_location,
...@@ -450,6 +454,7 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -450,6 +454,7 @@ int radeon_device_init(struct radeon_device *rdev,
uint32_t flags) uint32_t flags)
{ {
int r, ret; int r, ret;
int dma_bits;
DRM_INFO("radeon: Initializing kernel modesetting.\n"); DRM_INFO("radeon: Initializing kernel modesetting.\n");
rdev->shutdown = false; rdev->shutdown = false;
...@@ -492,8 +497,20 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -492,8 +497,20 @@ int radeon_device_init(struct radeon_device *rdev,
return r; return r;
} }
/* Report DMA addressing limitation */ /* set DMA mask + need_dma32 flags.
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(32)); * PCIE - can handle 40-bits.
* IGP - can handle 40-bits (in theory)
* AGP - generally dma32 is safest
* PCI - only dma32
*/
rdev->need_dma32 = false;
if (rdev->flags & RADEON_IS_AGP)
rdev->need_dma32 = true;
if (rdev->flags & RADEON_IS_PCI)
rdev->need_dma32 = true;
dma_bits = rdev->need_dma32 ? 32 : 40;
r = pci_set_dma_mask(rdev->pdev, DMA_BIT_MASK(dma_bits));
if (r) { if (r) {
printk(KERN_WARNING "radeon: No suitable DMA available.\n"); printk(KERN_WARNING "radeon: No suitable DMA available.\n");
} }
...@@ -546,27 +563,22 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -546,27 +563,22 @@ int radeon_device_init(struct radeon_device *rdev,
radeon_combios_asic_init(rdev->ddev); radeon_combios_asic_init(rdev->ddev);
} }
} }
/* Initialize clocks */
r = radeon_clocks_init(rdev);
if (r) {
return r;
}
/* Get vram informations */ /* Get vram informations */
radeon_vram_info(rdev); radeon_vram_info(rdev);
/* Device is severly broken if aper size > vram size.
* for RN50/M6/M7 - Novell bug 204882 ?
*/
if (rdev->mc.vram_size < rdev->mc.aper_size) {
rdev->mc.aper_size = rdev->mc.vram_size;
}
/* Add an MTRR for the VRAM */ /* Add an MTRR for the VRAM */
rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size, rdev->mc.vram_mtrr = mtrr_add(rdev->mc.aper_base, rdev->mc.aper_size,
MTRR_TYPE_WRCOMB, 1); MTRR_TYPE_WRCOMB, 1);
DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n", DRM_INFO("Detected VRAM RAM=%uM, BAR=%uM\n",
rdev->mc.vram_size >> 20, rdev->mc.real_vram_size >> 20,
(unsigned)rdev->mc.aper_size >> 20); (unsigned)rdev->mc.aper_size >> 20);
DRM_INFO("RAM width %dbits %cDR\n", DRM_INFO("RAM width %dbits %cDR\n",
rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S'); rdev->mc.vram_width, rdev->mc.vram_is_ddr ? 'D' : 'S');
/* Initialize clocks */
r = radeon_clocks_init(rdev);
if (r) {
return r;
}
/* Initialize memory controller (also test AGP) */ /* Initialize memory controller (also test AGP) */
r = radeon_mc_init(rdev); r = radeon_mc_init(rdev);
if (r) { if (r) {
...@@ -626,6 +638,9 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -626,6 +638,9 @@ int radeon_device_init(struct radeon_device *rdev,
if (!ret) { if (!ret) {
DRM_INFO("radeon: kernel modesetting successfully initialized.\n"); DRM_INFO("radeon: kernel modesetting successfully initialized.\n");
} }
if (radeon_testing) {
radeon_test_moves(rdev);
}
if (radeon_benchmarking) { if (radeon_benchmarking) {
radeon_benchmark(rdev); radeon_benchmark(rdev);
} }
......
...@@ -187,6 +187,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index) ...@@ -187,6 +187,7 @@ static void radeon_crtc_init(struct drm_device *dev, int index)
drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256); drm_mode_crtc_set_gamma_size(&radeon_crtc->base, 256);
radeon_crtc->crtc_id = index; radeon_crtc->crtc_id = index;
rdev->mode_info.crtcs[index] = radeon_crtc;
radeon_crtc->mode_set.crtc = &radeon_crtc->base; radeon_crtc->mode_set.crtc = &radeon_crtc->base;
radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1); radeon_crtc->mode_set.connectors = (struct drm_connector **)(radeon_crtc + 1);
...@@ -491,7 +492,11 @@ void radeon_compute_pll(struct radeon_pll *pll, ...@@ -491,7 +492,11 @@ void radeon_compute_pll(struct radeon_pll *pll,
tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div;
current_freq = radeon_div(tmp, ref_div * post_div); current_freq = radeon_div(tmp, ref_div * post_div);
error = abs(current_freq - freq); if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) {
error = freq - current_freq;
error = error < 0 ? 0xffffffff : error;
} else
error = abs(current_freq - freq);
vco_diff = abs(vco - best_vco); vco_diff = abs(vco - best_vco);
if ((best_vco == 0 && error < best_error) || if ((best_vco == 0 && error < best_error) ||
...@@ -657,36 +662,51 @@ void radeon_modeset_fini(struct radeon_device *rdev) ...@@ -657,36 +662,51 @@ void radeon_modeset_fini(struct radeon_device *rdev)
} }
} }
void radeon_init_disp_bandwidth(struct drm_device *dev) bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{ {
struct radeon_device *rdev = dev->dev_private; struct drm_device *dev = crtc->dev;
struct drm_display_mode *modes[2]; struct drm_encoder *encoder;
int pixel_bytes[2]; struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_crtc *crtc; struct radeon_encoder *radeon_encoder;
bool first = true;
pixel_bytes[0] = pixel_bytes[1] = 0;
modes[0] = modes[1] = NULL;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
if (crtc->enabled && crtc->fb) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
modes[radeon_crtc->crtc_id] = &crtc->mode; radeon_encoder = to_radeon_encoder(encoder);
pixel_bytes[radeon_crtc->crtc_id] = crtc->fb->bits_per_pixel / 8; if (encoder->crtc != crtc)
continue;
if (first) {
radeon_crtc->rmx_type = radeon_encoder->rmx_type;
radeon_crtc->devices = radeon_encoder->devices;
memcpy(&radeon_crtc->native_mode,
&radeon_encoder->native_mode,
sizeof(struct radeon_native_mode));
first = false;
} else {
if (radeon_crtc->rmx_type != radeon_encoder->rmx_type) {
/* WARNING: Right now this can't happen but
* in the future we need to check that scaling
* are consistent accross different encoder
* (ie all encoder can work with the same
* scaling).
*/
DRM_ERROR("Scaling not consistent accross encoder.\n");
return false;
}
} }
} }
if (radeon_crtc->rmx_type != RMX_OFF) {
if (ASIC_IS_AVIVO(rdev)) { fixed20_12 a, b;
radeon_init_disp_bw_avivo(dev, a.full = rfixed_const(crtc->mode.vdisplay);
modes[0], b.full = rfixed_const(radeon_crtc->native_mode.panel_xres);
pixel_bytes[0], radeon_crtc->vsc.full = rfixed_div(a, b);
modes[1], a.full = rfixed_const(crtc->mode.hdisplay);
pixel_bytes[1]); b.full = rfixed_const(radeon_crtc->native_mode.panel_yres);
radeon_crtc->hsc.full = rfixed_div(a, b);
} else { } else {
radeon_init_disp_bw_legacy(dev, radeon_crtc->vsc.full = rfixed_const(1);
modes[0], radeon_crtc->hsc.full = rfixed_const(1);
pixel_bytes[0],
modes[1],
pixel_bytes[1]);
} }
return true;
} }
...@@ -89,6 +89,7 @@ int radeon_agpmode = 0; ...@@ -89,6 +89,7 @@ int radeon_agpmode = 0;
int radeon_vram_limit = 0; int radeon_vram_limit = 0;
int radeon_gart_size = 512; /* default gart size */ int radeon_gart_size = 512; /* default gart size */
int radeon_benchmarking = 0; int radeon_benchmarking = 0;
int radeon_testing = 0;
int radeon_connector_table = 0; int radeon_connector_table = 0;
#endif #endif
...@@ -117,6 +118,9 @@ module_param_named(gartsize, radeon_gart_size, int, 0600); ...@@ -117,6 +118,9 @@ module_param_named(gartsize, radeon_gart_size, int, 0600);
MODULE_PARM_DESC(benchmark, "Run benchmark"); MODULE_PARM_DESC(benchmark, "Run benchmark");
module_param_named(benchmark, radeon_benchmarking, int, 0444); module_param_named(benchmark, radeon_benchmarking, int, 0444);
MODULE_PARM_DESC(test, "Run tests");
module_param_named(test, radeon_testing, int, 0444);
MODULE_PARM_DESC(connector_table, "Force connector table"); MODULE_PARM_DESC(connector_table, "Force connector table");
module_param_named(connector_table, radeon_connector_table, int, 0444); module_param_named(connector_table, radeon_connector_table, int, 0444);
#endif #endif
......
This diff is collapsed.
...@@ -101,9 +101,10 @@ static int radeonfb_setcolreg(unsigned regno, ...@@ -101,9 +101,10 @@ static int radeonfb_setcolreg(unsigned regno,
break; break;
case 24: case 24:
case 32: case 32:
fb->pseudo_palette[regno] = ((red & 0xff00) << 8) | fb->pseudo_palette[regno] =
(green & 0xff00) | (((red >> 8) & 0xff) << info->var.red.offset) |
((blue & 0xff00) >> 8); (((green >> 8) & 0xff) << info->var.green.offset) |
(((blue >> 8) & 0xff) << info->var.blue.offset);
break; break;
} }
} }
...@@ -154,6 +155,7 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var, ...@@ -154,6 +155,7 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,
var->transp.length = 0; var->transp.length = 0;
var->transp.offset = 0; var->transp.offset = 0;
break; break;
#ifdef __LITTLE_ENDIAN
case 15: case 15:
var->red.offset = 10; var->red.offset = 10;
var->green.offset = 5; var->green.offset = 5;
...@@ -194,6 +196,28 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var, ...@@ -194,6 +196,28 @@ static int radeonfb_check_var(struct fb_var_screeninfo *var,
var->transp.length = 8; var->transp.length = 8;
var->transp.offset = 24; var->transp.offset = 24;
break; break;
#else
case 24:
var->red.offset = 8;
var->green.offset = 16;
var->blue.offset = 24;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 0;
var->transp.offset = 0;
break;
case 32:
var->red.offset = 8;
var->green.offset = 16;
var->blue.offset = 24;
var->red.length = 8;
var->green.length = 8;
var->blue.length = 8;
var->transp.length = 8;
var->transp.offset = 0;
break;
#endif
default: default:
return -EINVAL; return -EINVAL;
} }
...@@ -447,10 +471,10 @@ static struct notifier_block paniced = { ...@@ -447,10 +471,10 @@ static struct notifier_block paniced = {
.notifier_call = radeonfb_panic, .notifier_call = radeonfb_panic,
}; };
static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp) static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
{ {
int aligned = width; int aligned = width;
int align_large = (ASIC_IS_AVIVO(rdev)); int align_large = (ASIC_IS_AVIVO(rdev)) || tiled;
int pitch_mask = 0; int pitch_mask = 0;
switch (bpp / 8) { switch (bpp / 8) {
...@@ -488,12 +512,13 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -488,12 +512,13 @@ int radeonfb_create(struct radeon_device *rdev,
u64 fb_gpuaddr; u64 fb_gpuaddr;
void *fbptr = NULL; void *fbptr = NULL;
unsigned long tmp; unsigned long tmp;
bool fb_tiled = false; /* useful for testing */
mode_cmd.width = surface_width; mode_cmd.width = surface_width;
mode_cmd.height = surface_height; mode_cmd.height = surface_height;
mode_cmd.bpp = 32; mode_cmd.bpp = 32;
/* need to align pitch with crtc limits */ /* need to align pitch with crtc limits */
mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp) * ((mode_cmd.bpp + 1) / 8); mode_cmd.pitch = radeon_align_pitch(rdev, mode_cmd.width, mode_cmd.bpp, fb_tiled) * ((mode_cmd.bpp + 1) / 8);
mode_cmd.depth = 24; mode_cmd.depth = 24;
size = mode_cmd.pitch * mode_cmd.height; size = mode_cmd.pitch * mode_cmd.height;
...@@ -511,6 +536,8 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -511,6 +536,8 @@ int radeonfb_create(struct radeon_device *rdev,
} }
robj = gobj->driver_private; robj = gobj->driver_private;
if (fb_tiled)
radeon_object_set_tiling_flags(robj, RADEON_TILING_MACRO|RADEON_TILING_SURFACE, mode_cmd.pitch);
mutex_lock(&rdev->ddev->struct_mutex); mutex_lock(&rdev->ddev->struct_mutex);
fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj); fb = radeon_framebuffer_create(rdev->ddev, &mode_cmd, gobj);
if (fb == NULL) { if (fb == NULL) {
...@@ -539,6 +566,9 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -539,6 +566,9 @@ int radeonfb_create(struct radeon_device *rdev,
} }
rfbdev = info->par; rfbdev = info->par;
if (fb_tiled)
radeon_object_check_tiling(robj, 0, 0);
ret = radeon_object_kmap(robj, &fbptr); ret = radeon_object_kmap(robj, &fbptr);
if (ret) { if (ret) {
goto out_unref; goto out_unref;
...@@ -572,6 +602,11 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -572,6 +602,11 @@ int radeonfb_create(struct radeon_device *rdev,
info->var.width = -1; info->var.width = -1;
info->var.xres = fb_width; info->var.xres = fb_width;
info->var.yres = fb_height; info->var.yres = fb_height;
/* setup aperture base/size for vesafb takeover */
info->aperture_base = rdev->ddev->mode_config.fb_base;
info->aperture_size = rdev->mc.real_vram_size;
info->fix.mmio_start = 0; info->fix.mmio_start = 0;
info->fix.mmio_len = 0; info->fix.mmio_len = 0;
info->pixmap.size = 64*1024; info->pixmap.size = 64*1024;
...@@ -600,6 +635,7 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -600,6 +635,7 @@ int radeonfb_create(struct radeon_device *rdev,
info->var.transp.offset = 0; info->var.transp.offset = 0;
info->var.transp.length = 0; info->var.transp.length = 0;
break; break;
#ifdef __LITTLE_ENDIAN
case 15: case 15:
info->var.red.offset = 10; info->var.red.offset = 10;
info->var.green.offset = 5; info->var.green.offset = 5;
...@@ -639,7 +675,29 @@ int radeonfb_create(struct radeon_device *rdev, ...@@ -639,7 +675,29 @@ int radeonfb_create(struct radeon_device *rdev,
info->var.transp.offset = 24; info->var.transp.offset = 24;
info->var.transp.length = 8; info->var.transp.length = 8;
break; break;
#else
case 24:
info->var.red.offset = 8;
info->var.green.offset = 16;
info->var.blue.offset = 24;
info->var.red.length = 8;
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 0;
info->var.transp.length = 0;
break;
case 32:
info->var.red.offset = 8;
info->var.green.offset = 16;
info->var.blue.offset = 24;
info->var.red.length = 8;
info->var.green.length = 8;
info->var.blue.length = 8;
info->var.transp.offset = 0;
info->var.transp.length = 8;
break;
default: default:
#endif
break; break;
} }
......
...@@ -195,7 +195,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool interruptible) ...@@ -195,7 +195,7 @@ int radeon_fence_wait(struct radeon_fence *fence, bool interruptible)
r = wait_event_interruptible_timeout(rdev->fence_drv.queue, r = wait_event_interruptible_timeout(rdev->fence_drv.queue,
radeon_fence_signaled(fence), timeout); radeon_fence_signaled(fence), timeout);
if (unlikely(r == -ERESTARTSYS)) { if (unlikely(r == -ERESTARTSYS)) {
return -ERESTART; return -EBUSY;
} }
} else { } else {
r = wait_event_timeout(rdev->fence_drv.queue, r = wait_event_timeout(rdev->fence_drv.queue,
......
...@@ -177,7 +177,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset, ...@@ -177,7 +177,7 @@ int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
return -ENOMEM; return -ENOMEM;
} }
rdev->gart.pages[p] = pagelist[i]; rdev->gart.pages[p] = pagelist[i];
page_base = (uint32_t)rdev->gart.pages_addr[p]; page_base = rdev->gart.pages_addr[p];
for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) { for (j = 0; j < (PAGE_SIZE / 4096); j++, t++) {
radeon_gart_set_page(rdev, t, page_base); radeon_gart_set_page(rdev, t, page_base);
page_base += 4096; page_base += 4096;
......
...@@ -157,9 +157,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data, ...@@ -157,9 +157,9 @@ int radeon_gem_info_ioctl(struct drm_device *dev, void *data,
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct drm_radeon_gem_info *args = data; struct drm_radeon_gem_info *args = data;
args->vram_size = rdev->mc.vram_size; args->vram_size = rdev->mc.real_vram_size;
/* FIXME: report somethings that makes sense */ /* FIXME: report somethings that makes sense */
args->vram_visible = rdev->mc.vram_size - (4 * 1024 * 1024); args->vram_visible = rdev->mc.real_vram_size - (4 * 1024 * 1024);
args->gart_size = rdev->mc.gtt_size; args->gart_size = rdev->mc.gtt_size;
return 0; return 0;
} }
...@@ -285,3 +285,44 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, ...@@ -285,3 +285,44 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data,
mutex_unlock(&dev->struct_mutex); mutex_unlock(&dev->struct_mutex);
return r; return r;
} }
int radeon_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
struct drm_radeon_gem_set_tiling *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
int r = 0;
DRM_DEBUG("%d \n", args->handle);
gobj = drm_gem_object_lookup(dev, filp, args->handle);
if (gobj == NULL)
return -EINVAL;
robj = gobj->driver_private;
radeon_object_set_tiling_flags(robj, args->tiling_flags, args->pitch);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
return r;
}
int radeon_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
struct drm_file *filp)
{
struct drm_radeon_gem_get_tiling *args = data;
struct drm_gem_object *gobj;
struct radeon_object *robj;
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);
mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(gobj);
mutex_unlock(&dev->struct_mutex);
return r;
}
...@@ -291,5 +291,7 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = { ...@@ -291,5 +291,7 @@ struct drm_ioctl_desc radeon_ioctls_kms[] = {
DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_GEM_WAIT_IDLE, radeon_gem_wait_idle_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_CS, radeon_cs_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH), DRM_IOCTL_DEF(DRM_RADEON_INFO, radeon_info_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_SET_TILING, radeon_gem_set_tiling_ioctl, DRM_AUTH),
DRM_IOCTL_DEF(DRM_RADEON_GEM_GET_TILING, radeon_gem_get_tiling_ioctl, DRM_AUTH),
}; };
int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms); int radeon_max_kms_ioctl = DRM_ARRAY_SIZE(radeon_ioctls_kms);
This diff is collapsed.
...@@ -30,170 +30,6 @@ ...@@ -30,170 +30,6 @@
#include "atom.h" #include "atom.h"
static void radeon_legacy_rmx_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
int xres = mode->hdisplay;
int yres = mode->vdisplay;
bool hscale = true, vscale = true;
int hsync_wid;
int vsync_wid;
int hsync_start;
uint32_t scale, inc;
uint32_t fp_horz_stretch, fp_vert_stretch, crtc_more_cntl, fp_horz_vert_active;
uint32_t fp_h_sync_strt_wid, fp_v_sync_strt_wid, fp_crtc_h_total_disp, fp_crtc_v_total_disp;
struct radeon_native_mode *native_mode = &radeon_encoder->native_mode;
DRM_DEBUG("\n");
fp_vert_stretch = RREG32(RADEON_FP_VERT_STRETCH) &
(RADEON_VERT_STRETCH_RESERVED |
RADEON_VERT_AUTO_RATIO_INC);
fp_horz_stretch = RREG32(RADEON_FP_HORZ_STRETCH) &
(RADEON_HORZ_FP_LOOP_STRETCH |
RADEON_HORZ_AUTO_RATIO_INC);
crtc_more_cntl = 0;
if ((rdev->family == CHIP_RS100) ||
(rdev->family == CHIP_RS200)) {
/* This is to workaround the asic bug for RMX, some versions
of BIOS dosen't have this register initialized correctly. */
crtc_more_cntl |= RADEON_CRTC_H_CUTOFF_ACTIVE_EN;
}
fp_crtc_h_total_disp = ((((mode->crtc_htotal / 8) - 1) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
hsync_start = mode->crtc_hsync_start - 8;
fp_h_sync_strt_wid = ((hsync_start & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
fp_crtc_v_total_disp = (((mode->crtc_vtotal - 1) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
fp_v_sync_strt_wid = (((mode->crtc_vsync_start - 1) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0));
fp_horz_vert_active = 0;
if (native_mode->panel_xres == 0 ||
native_mode->panel_yres == 0) {
hscale = false;
vscale = false;
} else {
if (xres > native_mode->panel_xres)
xres = native_mode->panel_xres;
if (yres > native_mode->panel_yres)
yres = native_mode->panel_yres;
if (xres == native_mode->panel_xres)
hscale = false;
if (yres == native_mode->panel_yres)
vscale = false;
}
if (radeon_encoder->flags & RADEON_USE_RMX) {
if (radeon_encoder->rmx_type != RMX_CENTER) {
if (!hscale)
fp_horz_stretch |= ((xres/8-1) << 16);
else {
inc = (fp_horz_stretch & RADEON_HORZ_AUTO_RATIO_INC) ? 1 : 0;
scale = ((xres + inc) * RADEON_HORZ_STRETCH_RATIO_MAX)
/ native_mode->panel_xres + 1;
fp_horz_stretch |= (((scale) & RADEON_HORZ_STRETCH_RATIO_MASK) |
RADEON_HORZ_STRETCH_BLEND |
RADEON_HORZ_STRETCH_ENABLE |
((native_mode->panel_xres/8-1) << 16));
}
if (!vscale)
fp_vert_stretch |= ((yres-1) << 12);
else {
inc = (fp_vert_stretch & RADEON_VERT_AUTO_RATIO_INC) ? 1 : 0;
scale = ((yres + inc) * RADEON_VERT_STRETCH_RATIO_MAX)
/ native_mode->panel_yres + 1;
fp_vert_stretch |= (((scale) & RADEON_VERT_STRETCH_RATIO_MASK) |
RADEON_VERT_STRETCH_ENABLE |
RADEON_VERT_STRETCH_BLEND |
((native_mode->panel_yres-1) << 12));
}
} else if (radeon_encoder->rmx_type == RMX_CENTER) {
int blank_width;
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
crtc_more_cntl |= (RADEON_CRTC_AUTO_HORZ_CENTER_EN |
RADEON_CRTC_AUTO_VERT_CENTER_EN);
blank_width = (mode->crtc_hblank_end - mode->crtc_hblank_start) / 8;
if (blank_width > 110)
blank_width = 110;
fp_crtc_h_total_disp = (((blank_width) & 0x3ff)
| ((((mode->crtc_hdisplay / 8) - 1) & 0x1ff) << 16));
hsync_wid = (mode->crtc_hsync_end - mode->crtc_hsync_start) / 8;
if (!hsync_wid)
hsync_wid = 1;
fp_h_sync_strt_wid = ((((mode->crtc_hsync_start - mode->crtc_hblank_start) / 8) & 0x1fff)
| ((hsync_wid & 0x3f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NHSYNC)
? RADEON_CRTC_H_SYNC_POL
: 0));
fp_crtc_v_total_disp = (((mode->crtc_vblank_end - mode->crtc_vblank_start) & 0xffff)
| ((mode->crtc_vdisplay - 1) << 16));
vsync_wid = mode->crtc_vsync_end - mode->crtc_vsync_start;
if (!vsync_wid)
vsync_wid = 1;
fp_v_sync_strt_wid = ((((mode->crtc_vsync_start - mode->crtc_vblank_start) & 0xfff)
| ((vsync_wid & 0x1f) << 16)
| ((mode->flags & DRM_MODE_FLAG_NVSYNC)
? RADEON_CRTC_V_SYNC_POL
: 0)));
fp_horz_vert_active = (((native_mode->panel_yres) & 0xfff) |
(((native_mode->panel_xres / 8) & 0x1ff) << 16));
}
} else {
fp_horz_stretch |= ((xres/8-1) << 16);
fp_vert_stretch |= ((yres-1) << 12);
}
WREG32(RADEON_FP_HORZ_STRETCH, fp_horz_stretch);
WREG32(RADEON_FP_VERT_STRETCH, fp_vert_stretch);
WREG32(RADEON_CRTC_MORE_CNTL, crtc_more_cntl);
WREG32(RADEON_FP_HORZ_VERT_ACTIVE, fp_horz_vert_active);
WREG32(RADEON_FP_H_SYNC_STRT_WID, fp_h_sync_strt_wid);
WREG32(RADEON_FP_V_SYNC_STRT_WID, fp_v_sync_strt_wid);
WREG32(RADEON_FP_CRTC_H_TOTAL_DISP, fp_crtc_h_total_disp);
WREG32(RADEON_FP_CRTC_V_TOTAL_DISP, fp_crtc_v_total_disp);
}
static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode) static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
{ {
struct drm_device *dev = encoder->dev; struct drm_device *dev = encoder->dev;
...@@ -287,9 +123,6 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, ...@@ -287,9 +123,6 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL); lvds_pll_cntl = RREG32(RADEON_LVDS_PLL_CNTL);
lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN; lvds_pll_cntl &= ~RADEON_LVDS_PLL_EN;
...@@ -318,7 +151,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder, ...@@ -318,7 +151,7 @@ static void radeon_legacy_lvds_mode_set(struct drm_encoder *encoder,
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if (ASIC_IS_R300(rdev)) { if (ASIC_IS_R300(rdev)) {
if (radeon_encoder->flags & RADEON_USE_RMX) if (radeon_encoder->rmx_type != RMX_OFF)
lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX; lvds_pll_cntl |= R300_LVDS_SRC_SEL_RMX;
} else } else
lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2; lvds_gen_cntl &= ~RADEON_LVDS_SEL_CRTC2;
...@@ -350,8 +183,6 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder, ...@@ -350,8 +183,6 @@ static bool radeon_legacy_lvds_mode_fixup(struct drm_encoder *encoder,
drm_mode_set_crtcinfo(adjusted_mode, 0); drm_mode_set_crtcinfo(adjusted_mode, 0);
radeon_encoder->flags &= ~RADEON_USE_RMX;
if (radeon_encoder->rmx_type != RMX_OFF) if (radeon_encoder->rmx_type != RMX_OFF)
radeon_rmx_mode_fixup(encoder, mode, adjusted_mode); radeon_rmx_mode_fixup(encoder, mode, adjusted_mode);
...@@ -455,9 +286,6 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder, ...@@ -455,9 +286,6 @@ static void radeon_legacy_primary_dac_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) { if (rdev->family == CHIP_R200 || ASIC_IS_R300(rdev)) {
disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) & disp_output_cntl = RREG32(RADEON_DISP_OUTPUT_CNTL) &
...@@ -653,9 +481,6 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, ...@@ -653,9 +481,6 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL); tmp = tmds_pll_cntl = RREG32(RADEON_TMDS_PLL_CNTL);
tmp &= 0xfffff; tmp &= 0xfffff;
if (rdev->family == CHIP_RV280) { if (rdev->family == CHIP_RV280) {
...@@ -711,7 +536,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder, ...@@ -711,7 +536,7 @@ static void radeon_legacy_tmds_int_mode_set(struct drm_encoder *encoder,
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) { if (ASIC_IS_R300(rdev) || rdev->family == CHIP_R200) {
fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK; fp_gen_cntl &= ~R200_FP_SOURCE_SEL_MASK;
if (radeon_encoder->flags & RADEON_USE_RMX) if (radeon_encoder->rmx_type != RMX_OFF)
fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX; fp_gen_cntl |= R200_FP_SOURCE_SEL_RMX;
else else
fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1; fp_gen_cntl |= R200_FP_SOURCE_SEL_CRTC1;
...@@ -820,9 +645,6 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, ...@@ -820,9 +645,6 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
if (rdev->is_atom_bios) { if (rdev->is_atom_bios) {
radeon_encoder->pixel_clock = adjusted_mode->clock; radeon_encoder->pixel_clock = adjusted_mode->clock;
atombios_external_tmds_setup(encoder, ATOM_ENABLE); atombios_external_tmds_setup(encoder, ATOM_ENABLE);
...@@ -856,7 +678,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder, ...@@ -856,7 +678,7 @@ static void radeon_legacy_tmds_ext_mode_set(struct drm_encoder *encoder,
if (radeon_crtc->crtc_id == 0) { if (radeon_crtc->crtc_id == 0) {
if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) { if ((rdev->family == CHIP_R200) || ASIC_IS_R300(rdev)) {
fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK; fp2_gen_cntl &= ~R200_FP2_SOURCE_SEL_MASK;
if (radeon_encoder->flags & RADEON_USE_RMX) if (radeon_encoder->rmx_type != RMX_OFF)
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX; fp2_gen_cntl |= R200_FP2_SOURCE_SEL_RMX;
else else
fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1; fp2_gen_cntl |= R200_FP2_SOURCE_SEL_CRTC1;
...@@ -1014,9 +836,6 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder, ...@@ -1014,9 +836,6 @@ static void radeon_legacy_tv_dac_mode_set(struct drm_encoder *encoder,
DRM_DEBUG("\n"); DRM_DEBUG("\n");
if (radeon_crtc->crtc_id == 0)
radeon_legacy_rmx_mode_set(encoder, mode, adjusted_mode);
if (rdev->family != CHIP_R200) { if (rdev->family != CHIP_R200) {
tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL); tv_dac_cntl = RREG32(RADEON_TV_DAC_CNTL);
if (rdev->family == CHIP_R420 || if (rdev->family == CHIP_R420 ||
...@@ -1243,6 +1062,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t ...@@ -1243,6 +1062,7 @@ radeon_add_legacy_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t
radeon_encoder->encoder_id = encoder_id; radeon_encoder->encoder_id = encoder_id;
radeon_encoder->devices = supported_device; radeon_encoder->devices = supported_device;
radeon_encoder->rmx_type = RMX_OFF;
switch (radeon_encoder->encoder_id) { switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_LVDS: case ENCODER_OBJECT_ID_INTERNAL_LVDS:
......
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-id.h> #include <linux/i2c-id.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include "radeon_fixed.h"
struct radeon_device;
#define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base) #define to_radeon_crtc(x) container_of(x, struct radeon_crtc, base)
#define to_radeon_connector(x) container_of(x, struct radeon_connector, base) #define to_radeon_connector(x) container_of(x, struct radeon_connector, base)
...@@ -124,6 +127,7 @@ struct radeon_tmds_pll { ...@@ -124,6 +127,7 @@ struct radeon_tmds_pll {
#define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8) #define RADEON_PLL_PREFER_LOW_POST_DIV (1 << 8)
#define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9)
#define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10)
#define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11)
struct radeon_pll { struct radeon_pll {
uint16_t reference_freq; uint16_t reference_freq;
...@@ -170,6 +174,18 @@ struct radeon_mode_info { ...@@ -170,6 +174,18 @@ struct radeon_mode_info {
struct atom_context *atom_context; struct atom_context *atom_context;
enum radeon_connector_table connector_table; enum radeon_connector_table connector_table;
bool mode_config_initialized; bool mode_config_initialized;
struct radeon_crtc *crtcs[2];
};
struct radeon_native_mode {
/* preferred mode */
uint32_t panel_xres, panel_yres;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
uint32_t dotclock;
uint32_t flags;
}; };
struct radeon_crtc { struct radeon_crtc {
...@@ -185,19 +201,13 @@ struct radeon_crtc { ...@@ -185,19 +201,13 @@ struct radeon_crtc {
uint64_t cursor_addr; uint64_t cursor_addr;
int cursor_width; int cursor_width;
int cursor_height; int cursor_height;
}; uint32_t legacy_display_base_addr;
uint32_t legacy_cursor_offset;
#define RADEON_USE_RMX 1 enum radeon_rmx_type rmx_type;
uint32_t devices;
struct radeon_native_mode { fixed20_12 vsc;
/* preferred mode */ fixed20_12 hsc;
uint32_t panel_xres, panel_yres; struct radeon_native_mode native_mode;
uint32_t hoverplus, hsync_width;
uint32_t hblank;
uint32_t voverplus, vsync_width;
uint32_t vblank;
uint32_t dotclock;
uint32_t flags;
}; };
struct radeon_encoder_primary_dac { struct radeon_encoder_primary_dac {
...@@ -383,16 +393,9 @@ void radeon_enc_destroy(struct drm_encoder *encoder); ...@@ -383,16 +393,9 @@ void radeon_enc_destroy(struct drm_encoder *encoder);
void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj); void radeon_copy_fb(struct drm_device *dev, struct drm_gem_object *dst_obj);
void radeon_combios_asic_init(struct drm_device *dev); void radeon_combios_asic_init(struct drm_device *dev);
extern int radeon_static_clocks_init(struct drm_device *dev); extern int radeon_static_clocks_init(struct drm_device *dev);
void radeon_init_disp_bw_legacy(struct drm_device *dev, bool radeon_crtc_scaling_mode_fixup(struct drm_crtc *crtc,
struct drm_display_mode *mode1, struct drm_display_mode *mode,
uint32_t pixel_bytes1, struct drm_display_mode *adjusted_mode);
struct drm_display_mode *mode2, void atom_rv515_force_tv_scaler(struct radeon_device *rdev);
uint32_t pixel_bytes2);
void radeon_init_disp_bw_avivo(struct drm_device *dev,
struct drm_display_mode *mode1,
uint32_t pixel_bytes1,
struct drm_display_mode *mode2,
uint32_t pixel_bytes2);
void radeon_init_disp_bandwidth(struct drm_device *dev);
#endif #endif
...@@ -44,6 +44,9 @@ struct radeon_object { ...@@ -44,6 +44,9 @@ struct radeon_object {
uint64_t gpu_addr; uint64_t gpu_addr;
void *kptr; void *kptr;
bool is_iomem; bool is_iomem;
uint32_t tiling_flags;
uint32_t pitch;
int surface_reg;
}; };
int radeon_ttm_init(struct radeon_device *rdev); int radeon_ttm_init(struct radeon_device *rdev);
...@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj) ...@@ -70,6 +73,7 @@ static void radeon_ttm_object_object_destroy(struct ttm_buffer_object *tobj)
robj = container_of(tobj, struct radeon_object, tobj); robj = container_of(tobj, struct radeon_object, tobj);
list_del_init(&robj->list); list_del_init(&robj->list);
radeon_object_clear_surface_reg(robj);
kfree(robj); kfree(robj);
} }
...@@ -99,16 +103,16 @@ static inline uint32_t radeon_object_flags_from_domain(uint32_t domain) ...@@ -99,16 +103,16 @@ static inline uint32_t radeon_object_flags_from_domain(uint32_t domain)
{ {
uint32_t flags = 0; uint32_t flags = 0;
if (domain & RADEON_GEM_DOMAIN_VRAM) { if (domain & RADEON_GEM_DOMAIN_VRAM) {
flags |= TTM_PL_FLAG_VRAM; flags |= TTM_PL_FLAG_VRAM | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
} }
if (domain & RADEON_GEM_DOMAIN_GTT) { if (domain & RADEON_GEM_DOMAIN_GTT) {
flags |= TTM_PL_FLAG_TT; flags |= TTM_PL_FLAG_TT | TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED;
} }
if (domain & RADEON_GEM_DOMAIN_CPU) { if (domain & RADEON_GEM_DOMAIN_CPU) {
flags |= TTM_PL_FLAG_SYSTEM; flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
} }
if (!flags) { if (!flags) {
flags |= TTM_PL_FLAG_SYSTEM; flags |= TTM_PL_FLAG_SYSTEM | TTM_PL_MASK_CACHING;
} }
return flags; return flags;
} }
...@@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev, ...@@ -141,6 +145,7 @@ int radeon_object_create(struct radeon_device *rdev,
} }
robj->rdev = rdev; robj->rdev = rdev;
robj->gobj = gobj; robj->gobj = gobj;
robj->surface_reg = -1;
INIT_LIST_HEAD(&robj->list); INIT_LIST_HEAD(&robj->list);
flags = radeon_object_flags_from_domain(domain); flags = radeon_object_flags_from_domain(domain);
...@@ -304,7 +309,7 @@ int radeon_object_wait(struct radeon_object *robj) ...@@ -304,7 +309,7 @@ int radeon_object_wait(struct radeon_object *robj)
} }
spin_lock(&robj->tobj.lock); spin_lock(&robj->tobj.lock);
if (robj->tobj.sync_obj) { if (robj->tobj.sync_obj) {
r = ttm_bo_wait(&robj->tobj, true, false, false); r = ttm_bo_wait(&robj->tobj, true, true, false);
} }
spin_unlock(&robj->tobj.lock); spin_unlock(&robj->tobj.lock);
radeon_object_unreserve(robj); radeon_object_unreserve(robj);
...@@ -403,7 +408,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence) ...@@ -403,7 +408,6 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
struct radeon_object *robj; struct radeon_object *robj;
struct radeon_fence *old_fence = NULL; struct radeon_fence *old_fence = NULL;
struct list_head *i; struct list_head *i;
uint32_t flags;
int r; int r;
r = radeon_object_list_reserve(head); r = radeon_object_list_reserve(head);
...@@ -414,27 +418,25 @@ int radeon_object_list_validate(struct list_head *head, void *fence) ...@@ -414,27 +418,25 @@ int radeon_object_list_validate(struct list_head *head, void *fence)
list_for_each(i, head) { list_for_each(i, head) {
lobj = list_entry(i, struct radeon_object_list, list); lobj = list_entry(i, struct radeon_object_list, list);
robj = lobj->robj; robj = lobj->robj;
if (lobj->wdomain) {
flags = radeon_object_flags_from_domain(lobj->wdomain);
flags |= TTM_PL_FLAG_TT;
} else {
flags = radeon_object_flags_from_domain(lobj->rdomain);
flags |= TTM_PL_FLAG_TT;
flags |= TTM_PL_FLAG_VRAM;
}
if (!robj->pin_count) { if (!robj->pin_count) {
robj->tobj.proposed_placement = flags | TTM_PL_MASK_CACHING; if (lobj->wdomain) {
robj->tobj.proposed_placement =
radeon_object_flags_from_domain(lobj->wdomain);
} else {
robj->tobj.proposed_placement =
radeon_object_flags_from_domain(lobj->rdomain);
}
r = ttm_buffer_object_validate(&robj->tobj, r = ttm_buffer_object_validate(&robj->tobj,
robj->tobj.proposed_placement, robj->tobj.proposed_placement,
true, false); true, false);
if (unlikely(r)) { if (unlikely(r)) {
radeon_object_list_unreserve(head);
DRM_ERROR("radeon: failed to validate.\n"); DRM_ERROR("radeon: failed to validate.\n");
return r; return r;
} }
radeon_object_gpu_addr(robj); radeon_object_gpu_addr(robj);
} }
lobj->gpu_offset = robj->gpu_addr; lobj->gpu_offset = robj->gpu_addr;
lobj->tiling_flags = robj->tiling_flags;
if (fence) { if (fence) {
old_fence = (struct radeon_fence *)robj->tobj.sync_obj; old_fence = (struct radeon_fence *)robj->tobj.sync_obj;
robj->tobj.sync_obj = radeon_fence_ref(fence); robj->tobj.sync_obj = radeon_fence_ref(fence);
...@@ -479,3 +481,127 @@ unsigned long radeon_object_size(struct radeon_object *robj) ...@@ -479,3 +481,127 @@ unsigned long radeon_object_size(struct radeon_object *robj)
{ {
return robj->tobj.num_pages << PAGE_SHIFT; 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_surface_reg *reg;
struct radeon_object *old_object;
int steal;
int i;
if (!robj->tiling_flags)
return 0;
if (robj->surface_reg >= 0) {
reg = &rdev->surface_regs[robj->surface_reg];
i = robj->surface_reg;
goto out;
}
steal = -1;
for (i = 0; i < RADEON_GEM_MAX_SURFACES; i++) {
reg = &rdev->surface_regs[i];
if (!reg->robj)
break;
old_object = reg->robj;
if (old_object->pin_count == 0)
steal = i;
}
/* if we are all out */
if (i == RADEON_GEM_MAX_SURFACES) {
if (steal == -1)
return -ENOMEM;
/* find someone with a surface reg and nuke their BO */
reg = &rdev->surface_regs[steal];
old_object = reg->robj;
/* blow away the mapping */
DRM_DEBUG("stealing surface reg %d from %p\n", steal, old_object);
ttm_bo_unmap_virtual(&old_object->tobj);
old_object->surface_reg = -1;
i = steal;
}
robj->surface_reg = i;
reg->robj = robj;
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);
return 0;
}
void radeon_object_clear_surface_reg(struct radeon_object *robj)
{
struct radeon_device *rdev = robj->rdev;
struct radeon_surface_reg *reg;
if (robj->surface_reg == -1)
return;
reg = &rdev->surface_regs[robj->surface_reg];
radeon_clear_surface_reg(rdev, robj->surface_reg);
reg->robj = NULL;
robj->surface_reg = -1;
}
void radeon_object_set_tiling_flags(struct radeon_object *robj,
uint32_t tiling_flags, uint32_t pitch)
{
robj->tiling_flags = tiling_flags;
robj->pitch = pitch;
}
void radeon_object_get_tiling_flags(struct radeon_object *robj,
uint32_t *tiling_flags,
uint32_t *pitch)
{
if (tiling_flags)
*tiling_flags = robj->tiling_flags;
if (pitch)
*pitch = robj->pitch;
}
int radeon_object_check_tiling(struct radeon_object *robj, bool has_moved,
bool force_drop)
{
if (!(robj->tiling_flags & RADEON_TILING_SURFACE))
return 0;
if (force_drop) {
radeon_object_clear_surface_reg(robj);
return 0;
}
if (robj->tobj.mem.mem_type != TTM_PL_VRAM) {
if (!has_moved)
return 0;
if (robj->surface_reg >= 0)
radeon_object_clear_surface_reg(robj);
return 0;
}
if ((robj->surface_reg >= 0) && !has_moved)
return 0;
return radeon_object_get_surface_reg(robj);
}
void radeon_bo_move_notify(struct ttm_buffer_object *bo,
struct ttm_mem_reg *mem)
{
struct radeon_object *robj = container_of(bo, struct radeon_object, tobj);
radeon_object_check_tiling(robj, 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);
}
...@@ -126,32 +126,19 @@ static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib) ...@@ -126,32 +126,19 @@ static void radeon_ib_align(struct radeon_device *rdev, struct radeon_ib *ib)
} }
} }
static void radeon_ib_cpu_flush(struct radeon_device *rdev,
struct radeon_ib *ib)
{
unsigned long tmp;
unsigned i;
/* To force CPU cache flush ugly but seems reliable */
for (i = 0; i < ib->length_dw; i += (rdev->cp.align_mask + 1)) {
tmp = readl(&ib->ptr[i]);
}
}
int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
{ {
int r = 0; int r = 0;
mutex_lock(&rdev->ib_pool.mutex); mutex_lock(&rdev->ib_pool.mutex);
radeon_ib_align(rdev, ib); radeon_ib_align(rdev, ib);
radeon_ib_cpu_flush(rdev, ib);
if (!ib->length_dw || !rdev->cp.ready) { if (!ib->length_dw || !rdev->cp.ready) {
/* TODO: Nothings in the ib we should report. */ /* TODO: Nothings in the ib we should report. */
mutex_unlock(&rdev->ib_pool.mutex); mutex_unlock(&rdev->ib_pool.mutex);
DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx);
return -EINVAL; return -EINVAL;
} }
/* 64 dwords should be enought for fence too */ /* 64 dwords should be enough for fence too */
r = radeon_ring_lock(rdev, 64); r = radeon_ring_lock(rdev, 64);
if (r) { if (r) {
DRM_ERROR("radeon: scheduling IB failled (%d).\n", r); DRM_ERROR("radeon: scheduling IB failled (%d).\n", r);
......
/*
* Copyright 2008 Advanced Micro Devices, Inc.
* Copyright 2008 Red Hat Inc.
* Copyright 2009 Jerome Glisse.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Dave Airlie
* Alex Deucher
* Jerome Glisse
*/
#ifndef __RADEON_SHARE_H__
#define __RADEON_SHARE_H__
void r100_vram_init_sizes(struct radeon_device *rdev);
void rs690_line_buffer_adjust(struct radeon_device *rdev,
struct drm_display_mode *mode1,
struct drm_display_mode *mode2);
void rv515_bandwidth_avivo_update(struct radeon_device *rdev);
#endif
/*
* Copyright 2009 VMware, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Michel Dänzer
*/
#include <drm/drmP.h>
#include <drm/radeon_drm.h>
#include "radeon_reg.h"
#include "radeon.h"
/* 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_fence *fence = NULL;
uint64_t gtt_addr, vram_addr;
unsigned i, n, size;
int r;
size = 1024 * 1024;
/* Number of tests =
* (Total GTT - IB pool - writeback page - ring buffer) / test size
*/
n = (rdev->mc.gtt_size - RADEON_IB_POOL_SIZE*64*1024 - 4096 -
rdev->cp.ring_size) / size;
gtt_obj = kzalloc(n * sizeof(*gtt_obj), GFP_KERNEL);
if (!gtt_obj) {
DRM_ERROR("Failed to allocate %d pointers\n", n);
r = 1;
goto out_cleanup;
}
r = radeon_object_create(rdev, NULL, size, true, RADEON_GEM_DOMAIN_VRAM,
false, &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);
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);
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);
if (r) {
DRM_ERROR("Failed to pin GTT object %d\n", i);
goto out_cleanup;
}
r = radeon_object_kmap(gtt_obj[i], &gtt_map);
if (r) {
DRM_ERROR("Failed to map GTT object %d\n", i);
goto out_cleanup;
}
for (gtt_start = gtt_map, gtt_end = gtt_map + size;
gtt_start < gtt_end;
gtt_start++)
*gtt_start = gtt_start;
radeon_object_kunmap(gtt_obj[i]);
r = radeon_fence_create(rdev, &fence);
if (r) {
DRM_ERROR("Failed to create GTT->VRAM fence %d\n", i);
goto out_cleanup;
}
r = radeon_copy(rdev, gtt_addr, vram_addr, size / 4096, fence);
if (r) {
DRM_ERROR("Failed GTT->VRAM copy %d\n", i);
goto out_cleanup;
}
r = radeon_fence_wait(fence, false);
if (r) {
DRM_ERROR("Failed to wait for GTT->VRAM fence %d\n", i);
goto out_cleanup;
}
radeon_fence_unref(&fence);
r = radeon_object_kmap(vram_obj, &vram_map);
if (r) {
DRM_ERROR("Failed to map VRAM object after copy %d\n", i);
goto out_cleanup;
}
for (gtt_start = gtt_map, gtt_end = gtt_map + size,
vram_start = vram_map, vram_end = vram_map + size;
vram_start < vram_end;
gtt_start++, vram_start++) {
if (*vram_start != gtt_start) {
DRM_ERROR("Incorrect GTT->VRAM copy %d: Got 0x%p, "
"expected 0x%p (GTT map 0x%p-0x%p)\n",
i, *vram_start, gtt_start, gtt_map,
gtt_end);
radeon_object_kunmap(vram_obj);
goto out_cleanup;
}
*vram_start = vram_start;
}
radeon_object_kunmap(vram_obj);
r = radeon_fence_create(rdev, &fence);
if (r) {
DRM_ERROR("Failed to create VRAM->GTT fence %d\n", i);
goto out_cleanup;
}
r = radeon_copy(rdev, vram_addr, gtt_addr, size / 4096, fence);
if (r) {
DRM_ERROR("Failed VRAM->GTT copy %d\n", i);
goto out_cleanup;
}
r = radeon_fence_wait(fence, false);
if (r) {
DRM_ERROR("Failed to wait for VRAM->GTT fence %d\n", i);
goto out_cleanup;
}
radeon_fence_unref(&fence);
r = radeon_object_kmap(gtt_obj[i], &gtt_map);
if (r) {
DRM_ERROR("Failed to map GTT object after copy %d\n", i);
goto out_cleanup;
}
for (gtt_start = gtt_map, gtt_end = gtt_map + size,
vram_start = vram_map, vram_end = vram_map + size;
gtt_start < gtt_end;
gtt_start++, vram_start++) {
if (*gtt_start != vram_start) {
DRM_ERROR("Incorrect VRAM->GTT copy %d: Got 0x%p, "
"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]);
goto out_cleanup;
}
}
radeon_object_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);
}
out_cleanup:
if (vram_obj) {
radeon_object_unpin(vram_obj);
radeon_object_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]);
}
}
kfree(gtt_obj);
}
if (fence) {
radeon_fence_unref(&fence);
}
if (r) {
printk(KERN_WARNING "Error while testing BO move.\n");
}
}
...@@ -355,23 +355,26 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, ...@@ -355,23 +355,26 @@ static int radeon_bo_move(struct ttm_buffer_object *bo,
if (!rdev->cp.ready) { if (!rdev->cp.ready) {
/* use memcpy */ /* use memcpy */
DRM_ERROR("CP is not ready use memcpy.\n"); DRM_ERROR("CP is not ready use memcpy.\n");
return ttm_bo_move_memcpy(bo, evict, no_wait, new_mem); goto memcpy;
} }
if (old_mem->mem_type == TTM_PL_VRAM && if (old_mem->mem_type == TTM_PL_VRAM &&
new_mem->mem_type == TTM_PL_SYSTEM) { new_mem->mem_type == TTM_PL_SYSTEM) {
return radeon_move_vram_ram(bo, evict, interruptible, r = radeon_move_vram_ram(bo, evict, interruptible,
no_wait, new_mem); no_wait, new_mem);
} else if (old_mem->mem_type == TTM_PL_SYSTEM && } else if (old_mem->mem_type == TTM_PL_SYSTEM &&
new_mem->mem_type == TTM_PL_VRAM) { new_mem->mem_type == TTM_PL_VRAM) {
return radeon_move_ram_vram(bo, evict, interruptible, r = radeon_move_ram_vram(bo, evict, interruptible,
no_wait, new_mem); no_wait, new_mem);
} else { } else {
r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem); r = radeon_move_blit(bo, evict, no_wait, new_mem, old_mem);
if (unlikely(r)) {
return r;
}
} }
if (r) {
memcpy:
r = ttm_bo_move_memcpy(bo, evict, no_wait, new_mem);
}
return r; return r;
} }
...@@ -429,6 +432,8 @@ static struct ttm_bo_driver radeon_bo_driver = { ...@@ -429,6 +432,8 @@ static struct ttm_bo_driver radeon_bo_driver = {
.sync_obj_flush = &radeon_sync_obj_flush, .sync_obj_flush = &radeon_sync_obj_flush,
.sync_obj_unref = &radeon_sync_obj_unref, .sync_obj_unref = &radeon_sync_obj_unref,
.sync_obj_ref = &radeon_sync_obj_ref, .sync_obj_ref = &radeon_sync_obj_ref,
.move_notify = &radeon_bo_move_notify,
.fault_reserve_notify = &radeon_bo_fault_reserve_notify,
}; };
int radeon_ttm_init(struct radeon_device *rdev) int radeon_ttm_init(struct radeon_device *rdev)
...@@ -442,13 +447,14 @@ int radeon_ttm_init(struct radeon_device *rdev) ...@@ -442,13 +447,14 @@ int radeon_ttm_init(struct radeon_device *rdev)
/* No others user of address space so set it to 0 */ /* No others user of address space so set it to 0 */
r = ttm_bo_device_init(&rdev->mman.bdev, r = ttm_bo_device_init(&rdev->mman.bdev,
rdev->mman.mem_global_ref.object, rdev->mman.mem_global_ref.object,
&radeon_bo_driver, DRM_FILE_PAGE_OFFSET); &radeon_bo_driver, DRM_FILE_PAGE_OFFSET,
rdev->need_dma32);
if (r) { if (r) {
DRM_ERROR("failed initializing buffer object driver(%d).\n", r); DRM_ERROR("failed initializing buffer object driver(%d).\n", r);
return r; return r;
} }
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0, r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_VRAM, 0,
((rdev->mc.aper_size) >> PAGE_SHIFT)); ((rdev->mc.real_vram_size) >> PAGE_SHIFT));
if (r) { if (r) {
DRM_ERROR("Failed initializing VRAM heap.\n"); DRM_ERROR("Failed initializing VRAM heap.\n");
return r; return r;
...@@ -465,7 +471,7 @@ int radeon_ttm_init(struct radeon_device *rdev) ...@@ -465,7 +471,7 @@ int radeon_ttm_init(struct radeon_device *rdev)
return r; return r;
} }
DRM_INFO("radeon: %uM of VRAM memory ready\n", DRM_INFO("radeon: %uM of VRAM memory ready\n",
rdev->mc.vram_size / (1024 * 1024)); rdev->mc.real_vram_size / (1024 * 1024));
r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0, r = ttm_bo_init_mm(&rdev->mman.bdev, TTM_PL_TT, 0,
((rdev->mc.gtt_size) >> PAGE_SHIFT)); ((rdev->mc.gtt_size) >> PAGE_SHIFT));
if (r) { if (r) {
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include "radeon_reg.h" #include "radeon_reg.h"
#include "radeon.h" #include "radeon.h"
#include "radeon_share.h"
/* rs400,rs480 depends on : */ /* rs400,rs480 depends on : */
void r100_hdp_reset(struct radeon_device *rdev); void r100_hdp_reset(struct radeon_device *rdev);
...@@ -164,7 +165,9 @@ int rs400_gart_enable(struct radeon_device *rdev) ...@@ -164,7 +165,9 @@ int rs400_gart_enable(struct radeon_device *rdev)
WREG32(RADEON_BUS_CNTL, tmp); WREG32(RADEON_BUS_CNTL, tmp);
} }
/* Table should be in 32bits address space so ignore bits above. */ /* Table should be in 32bits address space so ignore bits above. */
tmp = rdev->gart.table_addr & 0xfffff000; tmp = (u32)rdev->gart.table_addr & 0xfffff000;
tmp |= (upper_32_bits(rdev->gart.table_addr) & 0xff) << 4;
WREG32_MC(RS480_GART_BASE, tmp); WREG32_MC(RS480_GART_BASE, tmp);
/* TODO: more tweaking here */ /* TODO: more tweaking here */
WREG32_MC(RS480_GART_FEATURE_ID, WREG32_MC(RS480_GART_FEATURE_ID,
...@@ -201,10 +204,17 @@ void rs400_gart_disable(struct radeon_device *rdev) ...@@ -201,10 +204,17 @@ void rs400_gart_disable(struct radeon_device *rdev)
int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) int rs400_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr)
{ {
uint32_t entry;
if (i < 0 || i > rdev->gart.num_gpu_pages) { if (i < 0 || i > rdev->gart.num_gpu_pages) {
return -EINVAL; return -EINVAL;
} }
rdev->gart.table.ram.ptr[i] = cpu_to_le32(((uint32_t)addr) | 0xC);
entry = (lower_32_bits(addr) & PAGE_MASK) |
((upper_32_bits(addr) & 0xff) << 4) |
0xc;
entry = cpu_to_le32(entry);
rdev->gart.table.ram.ptr[i] = entry;
return 0; return 0;
} }
...@@ -223,10 +233,9 @@ int rs400_mc_init(struct radeon_device *rdev) ...@@ -223,10 +233,9 @@ int rs400_mc_init(struct radeon_device *rdev)
rs400_gpu_init(rdev); rs400_gpu_init(rdev);
rs400_gart_disable(rdev); rs400_gart_disable(rdev);
rdev->mc.gtt_location = rdev->mc.vram_size; rdev->mc.gtt_location = rdev->mc.mc_vram_size;
rdev->mc.gtt_location += (rdev->mc.gtt_size - 1); rdev->mc.gtt_location += (rdev->mc.gtt_size - 1);
rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1); rdev->mc.gtt_location &= ~(rdev->mc.gtt_size - 1);
rdev->mc.vram_location = 0xFFFFFFFFUL;
r = radeon_mc_setup(rdev); r = radeon_mc_setup(rdev);
if (r) { if (r) {
return r; return r;
...@@ -238,7 +247,7 @@ int rs400_mc_init(struct radeon_device *rdev) ...@@ -238,7 +247,7 @@ int rs400_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16); tmp = REG_SET(RADEON_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16); tmp |= REG_SET(RADEON_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32(RADEON_MC_FB_LOCATION, tmp); WREG32(RADEON_MC_FB_LOCATION, tmp);
...@@ -284,21 +293,12 @@ void rs400_gpu_init(struct radeon_device *rdev) ...@@ -284,21 +293,12 @@ void rs400_gpu_init(struct radeon_device *rdev)
*/ */
void rs400_vram_info(struct radeon_device *rdev) void rs400_vram_info(struct radeon_device *rdev)
{ {
uint32_t tom;
rs400_gart_adjust_size(rdev); rs400_gart_adjust_size(rdev);
/* DDR for all card after R300 & IGP */ /* DDR for all card after R300 & IGP */
rdev->mc.vram_is_ddr = true; rdev->mc.vram_is_ddr = true;
rdev->mc.vram_width = 128; rdev->mc.vram_width = 128;
/* read NB_TOM to get the amount of ram stolen for the GPU */ r100_vram_init_sizes(rdev);
tom = RREG32(RADEON_NB_TOM);
rdev->mc.vram_size = (((tom >> 16) - (tom & 0xffff) + 1) << 16);
WREG32(RADEON_CONFIG_MEMSIZE, rdev->mc.vram_size);
/* Could aper size report 0 ? */
rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
} }
......
...@@ -223,7 +223,7 @@ int rs600_mc_init(struct radeon_device *rdev) ...@@ -223,7 +223,7 @@ int rs600_mc_init(struct radeon_device *rdev)
printk(KERN_WARNING "Failed to wait MC idle while " printk(KERN_WARNING "Failed to wait MC idle while "
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16); tmp = REG_SET(RS600_MC_FB_TOP, tmp >> 16);
tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16); tmp |= REG_SET(RS600_MC_FB_START, rdev->mc.vram_location >> 16);
WREG32_MC(RS600_MC_FB_LOCATION, tmp); WREG32_MC(RS600_MC_FB_LOCATION, tmp);
...@@ -301,6 +301,11 @@ void rs600_vram_info(struct radeon_device *rdev) ...@@ -301,6 +301,11 @@ void rs600_vram_info(struct radeon_device *rdev)
rdev->mc.vram_width = 128; rdev->mc.vram_width = 128;
} }
void rs600_bandwidth_update(struct radeon_device *rdev)
{
/* FIXME: implement, should this be like rs690 ? */
}
/* /*
* Indirect registers accessor * Indirect registers accessor
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -67,7 +67,7 @@ int rv770_mc_init(struct radeon_device *rdev) ...@@ -67,7 +67,7 @@ int rv770_mc_init(struct radeon_device *rdev)
"programming pipes. Bad things might happen.\n"); "programming pipes. Bad things might happen.\n");
} }
tmp = rdev->mc.vram_location + rdev->mc.vram_size - 1; tmp = rdev->mc.vram_location + rdev->mc.mc_vram_size - 1;
tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24); tmp = REG_SET(R700_MC_FB_TOP, tmp >> 24);
tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24); tmp |= REG_SET(R700_MC_FB_BASE, rdev->mc.vram_location >> 24);
WREG32(R700_MC_VM_FB_LOCATION, tmp); WREG32(R700_MC_VM_FB_LOCATION, tmp);
......
This diff is collapsed.
This diff is collapsed.
...@@ -101,6 +101,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) ...@@ -101,6 +101,9 @@ static int ttm_bo_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
return VM_FAULT_NOPAGE; return VM_FAULT_NOPAGE;
} }
if (bdev->driver->fault_reserve_notify)
bdev->driver->fault_reserve_notify(bo);
/* /*
* Wait for buffer data in transit, due to a pipelined * Wait for buffer data in transit, due to a pipelined
* move. * move.
......
...@@ -86,10 +86,16 @@ void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages) ...@@ -86,10 +86,16 @@ void ttm_tt_cache_flush(struct page *pages[], unsigned long num_pages)
unsigned long i; unsigned long i;
for (i = 0; i < num_pages; ++i) { for (i = 0; i < num_pages; ++i) {
if (pages[i]) { struct page *page = pages[i];
unsigned long start = (unsigned long)page_address(pages[i]); void *page_virtual;
flush_dcache_range(start, start + PAGE_SIZE);
} if (unlikely(page == NULL))
continue;
page_virtual = kmap_atomic(page, KM_USER0);
flush_dcache_range((unsigned long) page_virtual,
(unsigned long) page_virtual + PAGE_SIZE);
kunmap_atomic(page_virtual, KM_USER0);
} }
#else #else
if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0) if (on_each_cpu(ttm_tt_ipi_handler, NULL, 1) != 0)
...@@ -131,10 +137,17 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm) ...@@ -131,10 +137,17 @@ static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
static struct page *ttm_tt_alloc_page(unsigned page_flags) static struct page *ttm_tt_alloc_page(unsigned page_flags)
{ {
gfp_t gfp_flags = GFP_USER;
if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC) if (page_flags & TTM_PAGE_FLAG_ZERO_ALLOC)
return alloc_page(GFP_HIGHUSER | __GFP_ZERO); gfp_flags |= __GFP_ZERO;
if (page_flags & TTM_PAGE_FLAG_DMA32)
gfp_flags |= __GFP_DMA32;
else
gfp_flags |= __GFP_HIGHMEM;
return alloc_page(GFP_HIGHUSER); return alloc_page(gfp_flags);
} }
static void ttm_tt_free_user_pages(struct ttm_tt *ttm) static void ttm_tt_free_user_pages(struct ttm_tt *ttm)
......
This diff is collapsed.
This diff is collapsed.
...@@ -33,7 +33,7 @@ ...@@ -33,7 +33,7 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#define TTM_PFX "[TTM]" #define TTM_PFX "[TTM] "
enum ttm_global_types { enum ttm_global_types {
TTM_GLOBAL_TTM_MEM = 0, TTM_GLOBAL_TTM_MEM = 0,
......
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