drivers/gpu/drm/radeon/r100.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/radeon/r100.c
Extension
.c
Size
120117 bytes
Lines
4163
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 (i++ % 100 == 0) {
			if (!r100_is_counter_moving(rdev, crtc))
				break;
		}
	}

	while (!r100_is_in_vblank(rdev, crtc)) {
		if (i++ % 100 == 0) {
			if (!r100_is_counter_moving(rdev, crtc))
				break;
		}
	}
}

/**
 * r100_page_flip - pageflip callback.
 *
 * @rdev: radeon_device pointer
 * @crtc_id: crtc to cleanup pageflip on
 * @crtc_base: new address of the crtc (GPU MC address)
 * @async: asynchronous flip
 *
 * Does the actual pageflip (r1xx-r4xx).
 * During vblank we take the crtc lock and wait for the update_pending
 * bit to go high, when it does, we release the lock, and allow the
 * double buffered update to take place.
 */
void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base, bool async)
{
	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
	uint32_t crtc_pitch, pitch_pixels;
	struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;
	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK;
	int i;

	/* Lock the graphics update lock */
	/* update the scanout addresses */
	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);

	/* update pitch */
	pitch_pixels = fb->pitches[0] / fb->format->cpp[0];
	crtc_pitch = DIV_ROUND_UP(pitch_pixels * fb->format->cpp[0] * 8,
				  fb->format->cpp[0] * 8 * 8);
	crtc_pitch |= crtc_pitch << 16;
	WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch);

	/* Wait for update_pending to go high. */
	for (i = 0; i < rdev->usec_timeout; i++) {
		if (RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET)
			break;
		udelay(1);
	}
	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");

	/* Unlock the lock, so double-buffering can take place inside vblank */
	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;
	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp);

}

/**
 * r100_page_flip_pending - check if page flip is still pending
 *
 * @rdev: radeon_device pointer
 * @crtc_id: crtc to check
 *
 * Check if the last pagefilp is still pending (r1xx-r4xx).
 * Returns the current update pending status.
 */
bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id)
{
	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];

	/* Return current update_pending status: */
	return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) &
		RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET);
}

/**
 * r100_pm_get_dynpm_state - look up dynpm power state callback.
 *
 * @rdev: radeon_device pointer
 *
 * Look up the optimal power state based on the
 * current state of the GPU (r1xx-r5xx).
 * Used for dynpm only.
 */
void r100_pm_get_dynpm_state(struct radeon_device *rdev)
{
	int i;

Annotation

Implementation Notes