drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_crtc.c
Extension
.c
Size
22628 bytes
Lines
778
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 (connector->status == connector_status_connected) {
			is_headless = false;
			break;
		}
	}
	drm_connector_list_iter_end(&iter);
	return is_headless;
}

static void amdgpu_dm_idle_worker(struct work_struct *work)
{
	struct idle_workqueue *idle_work;

	idle_work = container_of(work, struct idle_workqueue, work);
	idle_work->dm->idle_workqueue->running = true;

	while (idle_work->enable) {
		fsleep(HPD_DETECTION_PERIOD_uS);
		mutex_lock(&idle_work->dm->dc_lock);
		if (!idle_work->dm->dc->idle_optimizations_allowed) {
			mutex_unlock(&idle_work->dm->dc_lock);
			break;
		}
		dc_allow_idle_optimizations(idle_work->dm->dc, false);

		mutex_unlock(&idle_work->dm->dc_lock);
		fsleep(HPD_DETECTION_TIME_uS);
		mutex_lock(&idle_work->dm->dc_lock);

		if (!amdgpu_dm_is_headless(idle_work->dm->adev) &&
		    !amdgpu_dm_psr_is_active_allowed(idle_work->dm)) {
			mutex_unlock(&idle_work->dm->dc_lock);
			break;
		}

		if (idle_work->enable) {
			dc_post_update_surfaces_to_stream(idle_work->dm->dc);
			dc_allow_idle_optimizations(idle_work->dm->dc, true);
		}
		mutex_unlock(&idle_work->dm->dc_lock);
	}
	idle_work->dm->idle_workqueue->running = false;
}

struct idle_workqueue *idle_create_workqueue(struct amdgpu_device *adev)
{
	struct idle_workqueue *idle_work;

	idle_work = kzalloc_obj(*idle_work);
	if (ZERO_OR_NULL_PTR(idle_work))
		return NULL;

	idle_work->dm = &adev->dm;
	idle_work->enable = false;
	idle_work->running = false;
	INIT_WORK(&idle_work->work, amdgpu_dm_idle_worker);

	return idle_work;
}

static void amdgpu_dm_crtc_vblank_control_worker(struct work_struct *work)
{
	struct vblank_control_work *vblank_work =
		container_of(work, struct vblank_control_work, work);
	struct amdgpu_display_manager *dm = vblank_work->dm;

	mutex_lock(&dm->dc_lock);

	if (vblank_work->enable) {
		dm->active_vblank_irq_count++;
		amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
				DM_ISM_EVENT_EXIT_IDLE_REQUESTED);
	} else {
		if (dm->active_vblank_irq_count > 0)
			dm->active_vblank_irq_count--;
		amdgpu_dm_ism_commit_event(&vblank_work->acrtc->ism,
				DM_ISM_EVENT_ENTER_IDLE_REQUESTED);
	}

	mutex_unlock(&dm->dc_lock);

	dc_stream_release(vblank_work->stream);

	kfree(vblank_work);
}

static inline int amdgpu_dm_crtc_set_vblank(struct drm_crtc *crtc, bool enable)
{
	struct amdgpu_crtc *acrtc = to_amdgpu_crtc(crtc);
	struct amdgpu_device *adev = drm_to_adev(crtc->dev);

Annotation

Implementation Notes