drivers/gpu/drm/radeon/rs400.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/radeon/rs400.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/radeon/rs400.c
Extension
.c
Size
16581 bytes
Lines
600
Domain
Driver Families
Bucket
drivers/gpu
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

if (tmp & RADEON_MC_IDLE) {
			return 0;
		}
		udelay(1);
	}
	return -1;
}

static void rs400_gpu_init(struct radeon_device *rdev)
{
	/* Earlier code was calling r420_pipes_init and then
	 * rs400_mc_wait_for_idle(rdev). The problem is that
	 * at least on my Mobility Radeon Xpress 200M RC410 card
	 * that ends up in this code path ends up num_gb_pipes == 3
	 * while the card seems to have only one pipe. With the
	 * r420 pipe initialization method.
	 *
	 * Problems shown up as HyperZ glitches, see:
	 * https://bugs.freedesktop.org/show_bug.cgi?id=110897
	 *
	 * Delegating initialization to r300 code seems to work
	 * and results in proper pipe numbers. The rs400 cards
	 * are said to be not r400, but r300 kind of cards.
	 */
	r300_gpu_init(rdev);

	if (rs400_mc_wait_for_idle(rdev)) {
		pr_warn("rs400: Failed to wait MC idle while programming pipes. Bad things might happen. %08x\n",
			RREG32(RADEON_MC_STATUS));
	}
}

static void rs400_mc_init(struct radeon_device *rdev)
{
	u64 base;

	rs400_gart_adjust_size(rdev);
	rdev->mc.igp_sideport_enabled = radeon_combios_sideport_present(rdev);
	/* DDR for all card after R300 & IGP */
	rdev->mc.vram_is_ddr = true;
	rdev->mc.vram_width = 128;
	r100_vram_init_sizes(rdev);
	base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
	radeon_vram_location(rdev, &rdev->mc, base);
	rdev->mc.gtt_base_align = rdev->mc.gtt_size - 1;
	radeon_gtt_location(rdev, &rdev->mc);
	radeon_update_bandwidth_info(rdev);
}

uint32_t rs400_mc_rreg(struct radeon_device *rdev, uint32_t reg)
{
	unsigned long flags;
	uint32_t r;

	spin_lock_irqsave(&rdev->mc_idx_lock, flags);
	WREG32(RS480_NB_MC_INDEX, reg & 0xff);
	r = RREG32(RS480_NB_MC_DATA);
	WREG32(RS480_NB_MC_INDEX, 0xff);
	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
	return r;
}

void rs400_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
{
	unsigned long flags;

	spin_lock_irqsave(&rdev->mc_idx_lock, flags);
	WREG32(RS480_NB_MC_INDEX, ((reg) & 0xff) | RS480_NB_MC_IND_WR_EN);
	WREG32(RS480_NB_MC_DATA, (v));
	WREG32(RS480_NB_MC_INDEX, 0xff);
	spin_unlock_irqrestore(&rdev->mc_idx_lock, flags);
}

#if defined(CONFIG_DEBUG_FS)
static int rs400_debugfs_gart_info_show(struct seq_file *m, void *unused)
{
	struct radeon_device *rdev = m->private;
	uint32_t tmp;

	tmp = RREG32(RADEON_HOST_PATH_CNTL);
	seq_printf(m, "HOST_PATH_CNTL 0x%08x\n", tmp);
	tmp = RREG32(RADEON_BUS_CNTL);
	seq_printf(m, "BUS_CNTL 0x%08x\n", tmp);
	tmp = RREG32_MC(RS690_AIC_CTRL_SCRATCH);
	seq_printf(m, "AIC_CTRL_SCRATCH 0x%08x\n", tmp);
	if (rdev->family == CHIP_RS690 || (rdev->family == CHIP_RS740)) {
		tmp = RREG32_MC(RS690_MCCFG_AGP_BASE);
		seq_printf(m, "MCCFG_AGP_BASE 0x%08x\n", tmp);
		tmp = RREG32_MC(RS690_MCCFG_AGP_BASE_2);
		seq_printf(m, "MCCFG_AGP_BASE_2 0x%08x\n", tmp);

Annotation

Implementation Notes