drivers/gpu/drm/radeon/radeon_display.c

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

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/radeon/radeon_display.c
Extension
.c
Size
62211 bytes
Lines
2006
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 (fence && fence->rdev == rdev) {
			r = radeon_fence_wait(fence, false);
			if (r == -EDEADLK) {
				up_read(&rdev->exclusive_lock);
				do {
					r = radeon_gpu_reset(rdev);
				} while (r == -EAGAIN);
				down_read(&rdev->exclusive_lock);
			}
		} else
			r = dma_fence_wait(work->fence, false);

		if (r)
			drm_err(dev, "failed to wait on page flip fence (%d)!\n", r);

		/* We continue with the page flip even if we failed to wait on
		 * the fence, otherwise the DRM core and userspace will be
		 * confused about which BO the CRTC is scanning out
		 */

		dma_fence_put(work->fence);
		work->fence = NULL;
	}

	/* Wait until we're out of the vertical blank period before the one
	 * targeted by the flip. Always wait on pre DCE4 to avoid races with
	 * flip completion handling from vblank irq, as these old asics don't
	 * have reliable pageflip completion interrupts.
	 */
	while (radeon_crtc->enabled &&
		(radeon_get_crtc_scanoutpos(dev, work->crtc_id, 0,
					    &vpos, &hpos, NULL, NULL,
					    &crtc->hwmode)
		& (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK)) ==
		(DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_IN_VBLANK) &&
		(!ASIC_IS_AVIVO(rdev) ||
		((int) (work->target_vblank -
		crtc->funcs->get_vblank_counter(crtc)) > 0)))
		usleep_range(1000, 2000);

	/* We borrow the event spin lock for protecting flip_status */
	spin_lock_irqsave(&crtc->dev->event_lock, flags);

	/* set the proper interrupt */
	radeon_irq_kms_pflip_irq_get(rdev, radeon_crtc->crtc_id);

	/* do the flip (mmio) */
	radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base, work->async);

	radeon_crtc->flip_status = RADEON_FLIP_SUBMITTED;
	spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
	up_read(&rdev->exclusive_lock);
}

static int radeon_crtc_page_flip_target(struct drm_crtc *crtc,
					struct drm_framebuffer *fb,
					struct drm_pending_vblank_event *event,
					uint32_t page_flip_flags,
					uint32_t target,
					struct drm_modeset_acquire_ctx *ctx)
{
	struct drm_device *dev = crtc->dev;
	struct radeon_device *rdev = dev->dev_private;
	struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
	struct drm_gem_object *obj;
	struct radeon_flip_work *work;
	struct radeon_bo *new_rbo;
	uint32_t tiling_flags, pitch_pixels;
	uint64_t base;
	unsigned long flags;
	int r;

	work = kzalloc_obj(*work);
	if (work == NULL)
		return -ENOMEM;

	INIT_WORK(&work->flip_work, radeon_flip_work_func);
	INIT_WORK(&work->unpin_work, radeon_unpin_work_func);

	work->rdev = rdev;
	work->crtc_id = radeon_crtc->crtc_id;
	work->event = event;
	work->async = (page_flip_flags & DRM_MODE_PAGE_FLIP_ASYNC) != 0;

	/* schedule unpin of the old buffer */
	obj = crtc->primary->fb->obj[0];

	/* take a reference to the old object */
	drm_gem_object_get(obj);
	work->old_rbo = gem_to_radeon_bo(obj);

Annotation

Implementation Notes