drivers/gpu/drm/verisilicon/vs_crtc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/verisilicon/vs_crtc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/verisilicon/vs_crtc.c
Extension
.c
Size
5561 bytes
Lines
199
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

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2025 Icenowy Zheng <uwu@icenowy.me>
 */

#include <linux/clk.h>
#include <linux/regmap.h>
#include <linux/units.h>

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_print.h>
#include <drm/drm_managed.h>
#include <drm/drm_vblank_helper.h>

#include "vs_crtc_regs.h"
#include "vs_crtc.h"
#include "vs_dc.h"
#include "vs_dc_top_regs.h"
#include "vs_drm.h"
#include "vs_plane.h"

static void vs_crtc_atomic_disable(struct drm_crtc *crtc,
				   struct drm_atomic_commit *state)
{
	struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
	struct vs_dc *dc = vcrtc->dc;
	unsigned int output = vcrtc->id;

	drm_crtc_vblank_off(crtc);

	clk_disable_unprepare(dc->pix_clk[output]);
}

static void vs_crtc_atomic_enable(struct drm_crtc *crtc,
				  struct drm_atomic_commit *state)
{
	struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
	struct vs_dc *dc = vcrtc->dc;
	unsigned int output = vcrtc->id;

	drm_WARN_ON(&dc->drm_dev->base,
		    clk_prepare_enable(dc->pix_clk[output]));

	drm_crtc_vblank_on(crtc);
}

static void vs_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
	struct drm_display_mode *mode = &crtc->state->adjusted_mode;
	struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
	struct vs_dc *dc = vcrtc->dc;
	unsigned int output = vcrtc->id;

	regmap_write(dc->regs, VSDC_DISP_HSIZE(output),
		     VSDC_DISP_HSIZE_DISP(mode->hdisplay) |
		     VSDC_DISP_HSIZE_TOTAL(mode->htotal));
	regmap_write(dc->regs, VSDC_DISP_VSIZE(output),
		     VSDC_DISP_VSIZE_DISP(mode->vdisplay) |
		     VSDC_DISP_VSIZE_TOTAL(mode->vtotal));
	regmap_write(dc->regs, VSDC_DISP_HSYNC(output),
		     VSDC_DISP_HSYNC_START(mode->hsync_start) |
		     VSDC_DISP_HSYNC_END(mode->hsync_end) |
		     VSDC_DISP_HSYNC_EN);
	if (!(mode->flags & DRM_MODE_FLAG_PHSYNC))
		regmap_set_bits(dc->regs, VSDC_DISP_HSYNC(output),
				VSDC_DISP_HSYNC_POL);
	regmap_write(dc->regs, VSDC_DISP_VSYNC(output),
		     VSDC_DISP_VSYNC_START(mode->vsync_start) |
		     VSDC_DISP_VSYNC_END(mode->vsync_end) |
		     VSDC_DISP_VSYNC_EN);
	if (!(mode->flags & DRM_MODE_FLAG_PVSYNC))
		regmap_set_bits(dc->regs, VSDC_DISP_VSYNC(output),
				VSDC_DISP_VSYNC_POL);

	WARN_ON(clk_set_rate(dc->pix_clk[output], mode->crtc_clock * 1000));
}

static enum drm_mode_status
vs_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *mode)
{
	struct vs_crtc *vcrtc = drm_crtc_to_vs_crtc(crtc);
	struct vs_dc *dc = vcrtc->dc;
	unsigned int output = vcrtc->id;
	long rate;

	if (mode->htotal > VSDC_DISP_TIMING_VALUE_MAX)
		return MODE_BAD_HVALUE;
	if (mode->vtotal > VSDC_DISP_TIMING_VALUE_MAX)
		return MODE_BAD_VVALUE;

Annotation

Implementation Notes