drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c
Extension
.c
Size
16108 bytes
Lines
549
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

struct hibmc_display_panel_pll {
	u64 M;
	u64 N;
	u64 OD;
	u64 POD;
};

struct hibmc_dislay_pll_config {
	u64 hdisplay;
	u64 vdisplay;
	int clock;
	u32 pll1_config_value;
	u32 pll2_config_value;
};

static const struct hibmc_dislay_pll_config hibmc_pll_table[] = {
	{640, 480, 25000, CRT_PLL1_HS_25MHZ, CRT_PLL2_HS_25MHZ},
	{800, 600, 40000, CRT_PLL1_HS_40MHZ, CRT_PLL2_HS_40MHZ},
	{1024, 768, 65000, CRT_PLL1_HS_65MHZ, CRT_PLL2_HS_65MHZ},
	{1152, 864, 78750, CRT_PLL1_HS_80MHZ_1152, CRT_PLL2_HS_80MHZ},
	{1280, 768, 80000, CRT_PLL1_HS_80MHZ, CRT_PLL2_HS_80MHZ},
	{1280, 720, 74375, CRT_PLL1_HS_74MHZ, CRT_PLL2_HS_74MHZ},
	{1280, 960, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
	{1280, 1024, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
	{1440, 900, 105952, CRT_PLL1_HS_106MHZ, CRT_PLL2_HS_106MHZ},
	{1600, 900, 108000, CRT_PLL1_HS_108MHZ, CRT_PLL2_HS_108MHZ},
	{1600, 1200, 162500, CRT_PLL1_HS_162MHZ, CRT_PLL2_HS_162MHZ},
	{1920, 1080, 148750, CRT_PLL1_HS_148MHZ, CRT_PLL2_HS_148MHZ},
	{1920, 1200, 193750, CRT_PLL1_HS_193MHZ, CRT_PLL2_HS_193MHZ},
};

static int hibmc_get_best_clock_idx(const struct drm_display_mode *mode)
{
	int i, diff;

	for (i = 0; i < ARRAY_SIZE(hibmc_pll_table); i++) {
		if (hibmc_pll_table[i].hdisplay == mode->hdisplay &&
		    hibmc_pll_table[i].vdisplay == mode->vdisplay) {
			diff = abs(mode->clock - hibmc_pll_table[i].clock);
			if (diff < mode->clock / 100) /* tolerance 1/100 */
				return i;
		}
	}

	return -MODE_CLOCK_RANGE;
}

static int hibmc_plane_atomic_check(struct drm_plane *plane,
				    struct drm_atomic_commit *state)
{
	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,
										 plane);
	struct drm_framebuffer *fb = new_plane_state->fb;
	struct drm_crtc *crtc = new_plane_state->crtc;
	struct drm_crtc_state *crtc_state;
	u32 src_w = new_plane_state->src_w >> 16;
	u32 src_h = new_plane_state->src_h >> 16;

	if (!crtc || !fb)
		return 0;

	crtc_state = drm_atomic_get_crtc_state(state, crtc);
	if (IS_ERR(crtc_state))
		return PTR_ERR(crtc_state);

	if (src_w != new_plane_state->crtc_w || src_h != new_plane_state->crtc_h) {
		drm_dbg_atomic(plane->dev, "scale not support\n");
		return -EINVAL;
	}

	if (new_plane_state->crtc_x < 0 || new_plane_state->crtc_y < 0) {
		drm_dbg_atomic(plane->dev, "crtc_x/y of drm_plane state is invalid\n");
		return -EINVAL;
	}

	if (!crtc_state->enable)
		return 0;

	if (new_plane_state->crtc_x + new_plane_state->crtc_w >
	    crtc_state->adjusted_mode.hdisplay ||
	    new_plane_state->crtc_y + new_plane_state->crtc_h >
	    crtc_state->adjusted_mode.vdisplay) {
		drm_dbg_atomic(plane->dev, "visible portion of plane is invalid\n");
		return -EINVAL;
	}

	if (new_plane_state->fb->pitches[0] % 128 != 0) {
		drm_dbg_atomic(plane->dev, "wrong stride with 128-byte aligned\n");
		return -EINVAL;
	}

Annotation

Implementation Notes