drivers/gpu/drm/gma500/gma_display.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/gma500/gma_display.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/gma500/gma_display.c
Extension
.c
Size
21632 bytes
Lines
812
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->encoder && connector->encoder->crtc == crtc) {
			struct gma_encoder *gma_encoder =
						gma_attached_encoder(connector);
			if (gma_encoder->type == type) {
				drm_connector_list_iter_end(&conn_iter);
				return true;
			}
		}
	}
	drm_connector_list_iter_end(&conn_iter);

	return false;
}

void gma_wait_for_vblank(struct drm_device *dev)
{
	/* Wait for 20ms, i.e. one cycle at 50hz. */
	mdelay(20);
}

int gma_pipe_set_base(struct drm_crtc *crtc, int x, int y,
		      struct drm_framebuffer *old_fb)
{
	struct drm_device *dev = crtc->dev;
	struct drm_psb_private *dev_priv = to_drm_psb_private(dev);
	struct gma_crtc *gma_crtc = to_gma_crtc(crtc);
	struct drm_framebuffer *fb = crtc->primary->fb;
	struct psb_gem_object *pobj;
	int pipe = gma_crtc->pipe;
	const struct psb_offset *map = &dev_priv->regmap[pipe];
	unsigned long start, offset;
	u32 dspcntr;
	int ret = 0;

	if (!gma_power_begin(dev, true))
		return 0;

	/* no fb bound */
	if (!fb) {
		dev_err(dev->dev, "No FB bound\n");
		goto gma_pipe_cleaner;
	}

	pobj = to_psb_gem_object(fb->obj[0]);

	/* We are displaying this buffer, make sure it is actually loaded
	   into the GTT */
	ret = psb_gem_pin(pobj);
	if (ret < 0)
		goto gma_pipe_set_base_exit;
	start = pobj->offset;
	offset = y * fb->pitches[0] + x * fb->format->cpp[0];

	REG_WRITE(map->stride, fb->pitches[0]);

	dspcntr = REG_READ(map->cntr);
	dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;

	switch (fb->format->cpp[0] * 8) {
	case 8:
		dspcntr |= DISPPLANE_8BPP;
		break;
	case 16:
		if (fb->format->depth == 15)
			dspcntr |= DISPPLANE_15_16BPP;
		else
			dspcntr |= DISPPLANE_16BPP;
		break;
	case 24:
	case 32:
		dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
		break;
	default:
		dev_err(dev->dev, "Unknown color depth\n");
		ret = -EINVAL;
		goto gma_pipe_set_base_exit;
	}
	REG_WRITE(map->cntr, dspcntr);

	dev_dbg(dev->dev,
		"Writing base %08lX %08lX %d %d\n", start, offset, x, y);

	/* FIXME: Investigate whether this really is the base for psb and why
		  the linear offset is named base for the other chips. map->surf
		  should be the base and map->linoff the offset for all chips */
	if (IS_PSB(dev)) {
		REG_WRITE(map->base, offset + start);
		REG_READ(map->base);
	} else {
		REG_WRITE(map->base, offset);

Annotation

Implementation Notes