drivers/gpu/drm/tilcdc/tilcdc_crtc.c

Source file repositories/reference/linux-study-clean/drivers/gpu/drm/tilcdc/tilcdc_crtc.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/drm/tilcdc/tilcdc_crtc.c
Extension
.c
Size
27891 bytes
Lines
1010
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 tilcdc_crtc {
	struct drm_crtc base;

	struct tilcdc_plane *primary;
	struct drm_pending_vblank_event *event;
	struct mutex enable_lock;
	bool enabled;
	bool shutdown;
	wait_queue_head_t frame_done_wq;
	bool frame_done;
	spinlock_t irq_lock;

	unsigned int lcd_fck_rate;

	ktime_t last_vblank;
	unsigned int hvtotal_us;

	struct drm_framebuffer *next_fb;

	int sync_lost_count;
	bool frame_intact;
	struct work_struct recover_work;

	dma_addr_t palette_dma_handle;
	u16 *palette_base;
	struct completion palette_loaded;
};
#define to_tilcdc_crtc(x) container_of(x, struct tilcdc_crtc, base)

static void set_scanout(struct drm_crtc *crtc, struct drm_framebuffer *fb)
{
	struct drm_device *dev = crtc->dev;
	struct tilcdc_drm_private *priv = ddev_to_tilcdc_priv(dev);
	struct drm_gem_dma_object *gem;
	dma_addr_t start, end;
	u64 dma_base_and_ceiling;

	gem = drm_fb_dma_get_gem_obj(fb, 0);

	start = gem->dma_addr + fb->offsets[0] +
		crtc->y * fb->pitches[0] +
		crtc->x * fb->format->cpp[0];

	end = start + (crtc->mode.vdisplay * fb->pitches[0]);

	/* Write LCDC_DMA_FB_BASE_ADDR_0_REG and LCDC_DMA_FB_CEILING_ADDR_0_REG
	 * with a single insruction, if available. This should make it more
	 * unlikely that LCDC would fetch the DMA addresses in the middle of
	 * an update.
	 */
	if (priv->rev == 1)
		end -= 1;

	dma_base_and_ceiling = (u64)end << 32 | start;
	tilcdc_write64(dev, LCDC_DMA_FB_BASE_ADDR_0_REG, dma_base_and_ceiling);
}

/*
 * The driver currently only supports only true color formats. For
 * true color the palette block is bypassed, but a 32 byte palette
 * should still be loaded. The first 16-bit entry must be 0x4000 while
 * all other entries must be zeroed.
 */
static void tilcdc_crtc_load_palette(struct drm_crtc *crtc)
{
	struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc);
	struct drm_device *dev = crtc->dev;
	struct tilcdc_drm_private *priv = ddev_to_tilcdc_priv(dev);
	int ret;

	reinit_completion(&tilcdc_crtc->palette_loaded);

	/* Tell the LCDC where the palette is located. */
	tilcdc_write(dev, LCDC_DMA_FB_BASE_ADDR_0_REG,
		     tilcdc_crtc->palette_dma_handle);
	tilcdc_write(dev, LCDC_DMA_FB_CEILING_ADDR_0_REG,
		     (u32) tilcdc_crtc->palette_dma_handle +
		     TILCDC_PALETTE_SIZE - 1);

	/* Set dma load mode for palette loading only. */
	tilcdc_write_mask(dev, LCDC_RASTER_CTRL_REG,
			  LCDC_PALETTE_LOAD_MODE(PALETTE_ONLY),
			  LCDC_PALETTE_LOAD_MODE_MASK);

	/* Enable DMA Palette Loaded Interrupt */
	if (priv->rev == 1)
		tilcdc_set(dev, LCDC_RASTER_CTRL_REG, LCDC_V1_PL_INT_ENA);
	else
		tilcdc_write(dev, LCDC_INT_ENABLE_SET_REG, LCDC_V2_PL_INT_ENA);

Annotation

Implementation Notes