drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c

Source file repositories/reference/linux-study-clean/drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c

File Facts

System
Linux kernel
Corpus path
drivers/media/platform/nxp/imx8-isi/imx8-isi-hw.c
Extension
.c
Size
17289 bytes
Lines
655
Domain
Driver Families
Bucket
drivers/media
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 (pipe->isi->pdata->has_36bit_dma) {
			mxc_isi_write(pipe, CHNL_Y_BUF1_XTND_ADDR,
				      upper_32_bits(dma_addrs[0]));
			mxc_isi_write(pipe, CHNL_U_BUF1_XTND_ADDR,
				      upper_32_bits(dma_addrs[1]));
			mxc_isi_write(pipe, CHNL_V_BUF1_XTND_ADDR,
				      upper_32_bits(dma_addrs[2]));
		}
		val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR;
	} else  {
		mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_Y,
			      lower_32_bits(dma_addrs[0]));
		mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_U,
			      lower_32_bits(dma_addrs[1]));
		mxc_isi_write(pipe, CHNL_OUT_BUF2_ADDR_V,
			      lower_32_bits(dma_addrs[2]));
		if (pipe->isi->pdata->has_36bit_dma) {
			mxc_isi_write(pipe, CHNL_Y_BUF2_XTND_ADDR,
				      upper_32_bits(dma_addrs[0]));
			mxc_isi_write(pipe, CHNL_U_BUF2_XTND_ADDR,
				      upper_32_bits(dma_addrs[1]));
			mxc_isi_write(pipe, CHNL_V_BUF2_XTND_ADDR,
				      upper_32_bits(dma_addrs[2]));
		}
		val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR;
	}

	mxc_isi_write(pipe, CHNL_OUT_BUF_CTRL, val);
}

void mxc_isi_channel_m2m_start(struct mxc_isi_pipe *pipe)
{
	u32 val;

	val = mxc_isi_read(pipe, CHNL_MEM_RD_CTRL);
	val &= ~CHNL_MEM_RD_CTRL_READ_MEM;
	mxc_isi_write(pipe, CHNL_MEM_RD_CTRL, val);

	fsleep(300);

	val |= CHNL_MEM_RD_CTRL_READ_MEM;
	mxc_isi_write(pipe, CHNL_MEM_RD_CTRL, val);
}

/* -----------------------------------------------------------------------------
 * Pipeline configuration
 */

static u32 mxc_isi_channel_scaling_ratio(unsigned int from, unsigned int to,
					 u32 *dec)
{
	unsigned int ratio = from / to;

	if (ratio < 2)
		*dec = 1;
	else if (ratio < 4)
		*dec = 2;
	else if (ratio < 8)
		*dec = 4;
	else
		*dec = 8;

	/*
	 * The ISI rounds output dimensions up to the next integer (i.MX93 RM
	 * section 57.7.8). Calculate the scale factor such that the theoretical
	 * output (input / scale_factor) rounds up to exactly the desired
	 * output.
	 */
	return min_t(u32, DIV_ROUND_UP(from * 0x1000, to * *dec),
		     ISI_DOWNSCALE_THRESHOLD);
}

static void mxc_isi_channel_set_scaling(struct mxc_isi_pipe *pipe,
					enum mxc_isi_encoding encoding,
					const struct v4l2_area *in_size,
					const struct v4l2_area *out_size,
					bool *bypass)
{
	u32 xscale, yscale;
	u32 decx, decy;
	u32 val;

	dev_dbg(pipe->isi->dev, "input %ux%u, output %ux%u\n",
		in_size->width, in_size->height,
		out_size->width, out_size->height);

	xscale = mxc_isi_channel_scaling_ratio(in_size->width, out_size->width,
					       &decx);
	yscale = mxc_isi_channel_scaling_ratio(in_size->height, out_size->height,
					       &decy);

Annotation

Implementation Notes