drivers/gpu/ipu-v3/ipu-pre.c

Source file repositories/reference/linux-study-clean/drivers/gpu/ipu-v3/ipu-pre.c

File Facts

System
Linux kernel
Corpus path
drivers/gpu/ipu-v3/ipu-pre.c
Extension
.c
Size
10943 bytes
Lines
383
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 ipu_pre {
	struct list_head	list;
	struct device		*dev;

	void __iomem		*regs;
	struct clk		*clk_axi;
	struct gen_pool		*iram;

	dma_addr_t		buffer_paddr;
	void			*buffer_virt;

	struct {
		bool		in_use;
		uint64_t	modifier;
		unsigned int	height;
		unsigned int	safe_window_end;
		unsigned int	bufaddr;
		u32		ctrl;
		u8		cpp;
	} cur;
};

static DEFINE_MUTEX(ipu_pre_list_mutex);
static LIST_HEAD(ipu_pre_list);
static int available_pres;

int ipu_pre_get_available_count(void)
{
	return available_pres;
}

struct ipu_pre *
ipu_pre_lookup_by_phandle(struct device *dev, const char *name, int index)
{
	struct device_node *pre_node __free(device_node) =
		of_parse_phandle(dev->of_node, name, index);
	struct ipu_pre *pre;

	mutex_lock(&ipu_pre_list_mutex);
	list_for_each_entry(pre, &ipu_pre_list, list) {
		if (pre_node == pre->dev->of_node) {
			mutex_unlock(&ipu_pre_list_mutex);
			device_link_add(dev, pre->dev,
					DL_FLAG_AUTOREMOVE_CONSUMER);
			return pre;
		}
	}
	mutex_unlock(&ipu_pre_list_mutex);

	return NULL;
}

int ipu_pre_get(struct ipu_pre *pre)
{
	u32 val;

	if (pre->cur.in_use)
		return -EBUSY;

	/* first get the engine out of reset and remove clock gating */
	writel(0, pre->regs + IPU_PRE_CTRL);

	/* init defaults that should be applied to all streams */
	val = IPU_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN |
	      IPU_PRE_CTRL_HANDSHAKE_EN |
	      IPU_PRE_CTRL_TPR_REST_SEL |
	      IPU_PRE_CTRL_SDW_UPDATE;
	writel(val, pre->regs + IPU_PRE_CTRL);

	pre->cur.in_use = true;
	return 0;
}

void ipu_pre_put(struct ipu_pre *pre)
{
	writel(IPU_PRE_CTRL_SFTRST, pre->regs + IPU_PRE_CTRL);

	pre->cur.in_use = false;
}

static inline void
ipu_pre_update_safe_window(struct ipu_pre *pre)
{
	if (pre->cur.modifier == DRM_FORMAT_MOD_LINEAR)
		pre->cur.safe_window_end = pre->cur.height - 2;
	else
		pre->cur.safe_window_end = DIV_ROUND_UP(pre->cur.height, 4) - 1;
}

static void

Annotation

Implementation Notes