drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
Extension
.c
Size
18823 bytes
Lines
662
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 atmel_hlcdc_crtc_state {
	struct drm_crtc_state base;
	unsigned int output_mode;
	u8 dpi;
};

static inline struct atmel_hlcdc_crtc_state *
drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state)
{
	return container_of(state, struct atmel_hlcdc_crtc_state, base);
}

/**
 * struct atmel_hlcdc_crtc - Atmel HLCDC CRTC structure
 *
 * @base: base DRM CRTC structure
 * @dc: pointer to the atmel_hlcdc structure provided by the MFD device
 * @event: pointer to the current page flip event
 * @id: CRTC id (returned by drm_crtc_index)
 */
struct atmel_hlcdc_crtc {
	struct drm_crtc base;
	struct atmel_hlcdc_dc *dc;
	struct drm_pending_vblank_event *event;
	int id;
};

static inline struct atmel_hlcdc_crtc *
drm_crtc_to_atmel_hlcdc_crtc(struct drm_crtc *crtc)
{
	return container_of(crtc, struct atmel_hlcdc_crtc, base);
}

static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
{
	struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
	struct regmap *regmap = crtc->dc->hlcdc->regmap;
	struct drm_display_mode *adj = &c->state->adjusted_mode;
	struct drm_encoder *encoder = NULL, *en_iter;
	struct drm_connector *connector = NULL;
	struct atmel_hlcdc_crtc_state *state;
	struct drm_device *ddev = c->dev;
	struct drm_connector_list_iter iter;
	unsigned long mode_rate;
	struct videomode vm;
	unsigned long prate;
	unsigned int mask = ATMEL_HLCDC_CLKDIV_MASK | ATMEL_HLCDC_CLKPOL;
	unsigned int cfg = 0;
	int div, ret;

	/* get encoder from crtc */
	drm_for_each_encoder(en_iter, ddev) {
		if (en_iter->crtc == c) {
			encoder = en_iter;
			break;
		}
	}

	if (encoder) {
		/* Get the connector from encoder */
		drm_connector_list_iter_begin(ddev, &iter);
		drm_for_each_connector_iter(connector, &iter)
			if (connector->encoder == encoder)
				break;
		drm_connector_list_iter_end(&iter);
	}

	ret = clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
	if (ret)
		return;

	vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay;
	vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end;
	vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start;
	vm.hfront_porch = adj->crtc_hsync_start - adj->crtc_hdisplay;
	vm.hback_porch = adj->crtc_htotal - adj->crtc_hsync_end;
	vm.hsync_len = adj->crtc_hsync_end - adj->crtc_hsync_start;

	regmap_write(regmap, ATMEL_HLCDC_CFG(1),
		     (vm.hsync_len - 1) | ((vm.vsync_len - 1) << 16));

	regmap_write(regmap, ATMEL_HLCDC_CFG(2),
		     (vm.vfront_porch - 1) | (vm.vback_porch << 16));

	regmap_write(regmap, ATMEL_HLCDC_CFG(3),
		     (vm.hfront_porch - 1) | ((vm.hback_porch - 1) << 16));

	regmap_write(regmap, ATMEL_HLCDC_CFG(4),
		     (adj->crtc_hdisplay - 1) |
		     ((adj->crtc_vdisplay - 1) << 16));

Annotation

Implementation Notes