drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/renesas/shmobile/shmob_drm_crtc.c
Extension
.c
Size
16757 bytes
Lines
621
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 < ARRAY_SIZE(shmob_drm_bus_fmts)) {
			value = shmob_drm_bus_fmts[i].ldmt1r;
		} else {
			dev_warn(sdev->dev,
				 "unsupported bus format 0x%x, using RGB888\n",
				 info->bus_formats[0]);
			value = LDMT1R_MIFTYP_RGB24;
		}
	}

	if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE)
		value |= LDMT1R_DWPOL;
	if (info->bus_flags & DRM_BUS_FLAG_DE_LOW)
		value |= LDMT1R_DIPOL;
	if (mode->flags & DRM_MODE_FLAG_NVSYNC)
		value |= LDMT1R_VPOL;
	if (mode->flags & DRM_MODE_FLAG_NHSYNC)
		value |= LDMT1R_HPOL;
	lcdc_write(sdev, LDMT1R, value);

	value = ((mode->hdisplay / 8) << 16)			/* HDCN */
	      | (mode->htotal / 8);				/* HTCN */
	lcdc_write(sdev, LDHCNR, value);

	value = (((mode->hsync_end - mode->hsync_start) / 8) << 16) /* HSYNW */
	      | (mode->hsync_start / 8);			/* HSYNP */
	lcdc_write(sdev, LDHSYNR, value);

	value = ((mode->hdisplay & 7) << 24) | ((mode->htotal & 7) << 16)
	      | (((mode->hsync_end - mode->hsync_start) & 7) << 8)
	      | (mode->hsync_start & 7);
	lcdc_write(sdev, LDHAJR, value);

	value = ((mode->vdisplay) << 16)			/* VDLN */
	      | mode->vtotal;					/* VTLN */
	lcdc_write(sdev, LDVLNR, value);

	value = ((mode->vsync_end - mode->vsync_start) << 16)	/* VSYNW */
	      | mode->vsync_start;				/* VSYNP */
	lcdc_write(sdev, LDVSYNR, value);
}

static void shmob_drm_crtc_start_stop(struct shmob_drm_crtc *scrtc, bool start)
{
	struct shmob_drm_device *sdev = to_shmob_device(scrtc->base.dev);
	u32 value;

	value = lcdc_read(sdev, LDCNT2R);
	if (start)
		lcdc_write(sdev, LDCNT2R, value | LDCNT2R_DO);
	else
		lcdc_write(sdev, LDCNT2R, value & ~LDCNT2R_DO);

	/* Wait until power is applied/stopped. */
	while (1) {
		value = lcdc_read(sdev, LDPMR) & LDPMR_LPS;
		if ((start && value) || (!start && !value))
			break;

		cpu_relax();
	}

	if (!start) {
		/* Stop the dot clock. */
		lcdc_write(sdev, LDDCKSTPR, LDDCKSTPR_DCKSTP);
	}
}

static inline struct shmob_drm_crtc *to_shmob_crtc(struct drm_crtc *crtc)
{
	return container_of(crtc, struct shmob_drm_crtc, base);
}

static void shmob_drm_crtc_atomic_enable(struct drm_crtc *crtc,
					 struct drm_atomic_commit *state)
{
	struct shmob_drm_crtc *scrtc = to_shmob_crtc(crtc);
	struct shmob_drm_device *sdev = to_shmob_device(crtc->dev);
	unsigned int clk_div = sdev->config.clk_div;
	struct device *dev = sdev->dev;
	u32 value;
	int ret;

	ret = pm_runtime_resume_and_get(dev);
	if (ret)
		return;

	/* Reset and enable the LCDC. */
	lcdc_write(sdev, LDCNT2R, lcdc_read(sdev, LDCNT2R) | LDCNT2R_BR);
	lcdc_wait_bit(sdev, LDCNT2R, LDCNT2R_BR, 0);

Annotation

Implementation Notes