예제 #1
0
/*
 * This function enables a logical channel.
 *
 * @param       channel         Input parameter for the logical channel ID.
 *
 * @return      This function returns 0 on success or negative error code on
 *              fail.
 */
int32_t ipu_enable_channel(ipu_channel_t channel)
{
	uint32_t reg;
	uint32_t in_dma;
	uint32_t out_dma;

	if (g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
		printf("Warning: channel already enabled %d\n",
			IPU_CHAN_ID(channel));
	}

	/* Get input and output dma channels */
	out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
	in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);

	if (idma_is_valid(in_dma)) {
		reg = __raw_readl(IDMAC_CHA_EN(in_dma));
		__raw_writel(reg | idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
	}
	if (idma_is_valid(out_dma)) {
		reg = __raw_readl(IDMAC_CHA_EN(out_dma));
		__raw_writel(reg | idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
	}

	if ((channel == MEM_DC_SYNC) || (channel == MEM_BG_SYNC) ||
	    (channel == MEM_FG_SYNC))
		ipu_dp_dc_enable(channel);

	g_channel_enable_mask |= 1L << IPU_CHAN_ID(channel);

	return 0;
}
예제 #2
0
/*
 * This function is called to initialize a buffer for logical IPU channel.
 *
 * @param       channel         Input parameter for the logical channel ID.
 *
 * @param       type            Input parameter which buffer to initialize.
 *
 * @param       pixel_fmt       Input parameter for pixel format of buffer.
 *                              Pixel format is a FOURCC ASCII code.
 *
 * @param       width           Input parameter for width of buffer in pixels.
 *
 * @param       height          Input parameter for height of buffer in pixels.
 *
 * @param       stride          Input parameter for stride length of buffer
 *                              in pixels.
 *
 * @param       phyaddr_0       Input parameter buffer 0 physical address.
 *
 * @param       phyaddr_1       Input parameter buffer 1 physical address.
 *                              Setting this to a value other than NULL enables
 *                              double buffering mode.
 *
 * @param       u		private u offset for additional cropping,
 *				zero if not used.
 *
 * @param       v		private v offset for additional cropping,
 *				zero if not used.
 *
 * @return      Returns 0 on success or negative error code on fail
 */
int32_t ipu_init_channel_buffer(ipu_channel_t channel, ipu_buffer_t type,
				uint32_t pixel_fmt,
				uint16_t width, uint16_t height,
				uint32_t stride,
				dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
				uint32_t u, uint32_t v)
{
	uint32_t reg;
	uint32_t dma_chan;

	dma_chan = channel_2_dma(channel, type);
	if (!idma_is_valid(dma_chan))
		return -EINVAL;

	if (stride < width * bytes_per_pixel(pixel_fmt))
		stride = width * bytes_per_pixel(pixel_fmt);

	if (stride % 4) {
		printf(
			"Stride not 32-bit aligned, stride = %d\n", stride);
		return -EINVAL;
	}
	/* Build parameter memory data for DMA channel */
	ipu_ch_param_init(dma_chan, pixel_fmt, width, height, stride, u, v, 0,
			   phyaddr_0, phyaddr_1);

	if (ipu_is_dmfc_chan(dma_chan)) {
		ipu_dmfc_set_wait4eot(dma_chan, width);
	}

	if (idma_is_set(IDMAC_CHA_PRI, dma_chan))
		ipu_ch_param_set_high_priority(dma_chan);

	ipu_ch_param_dump(dma_chan);

	reg = __raw_readl(IPU_CHA_DB_MODE_SEL(dma_chan));
	if (phyaddr_1)
		reg |= idma_mask(dma_chan);
	else
		reg &= ~idma_mask(dma_chan);
	__raw_writel(reg, IPU_CHA_DB_MODE_SEL(dma_chan));

	/* Reset to buffer 0 */
	__raw_writel(idma_mask(dma_chan), IPU_CHA_CUR_BUF(dma_chan));

	return 0;
}
예제 #3
0
/*
 * This function disables a logical channel.
 *
 * @param       channel         Input parameter for the logical channel ID.
 *
 * @param       wait_for_stop   Flag to set whether to wait for channel end
 *                              of frame or return immediately.
 *
 * @return      This function returns 0 on success or negative error code on
 *              fail.
 */
int32_t ipu_disable_channel(ipu_channel_t channel)
{
	uint32_t reg;
	uint32_t in_dma;
	uint32_t out_dma;

	if ((g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
		debug("Channel already disabled %d\n",
			IPU_CHAN_ID(channel));
		return 0;
	}

	/* Get input and output dma channels */
	out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
	in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);

	if ((idma_is_valid(in_dma) &&
		!idma_is_set(IDMAC_CHA_EN, in_dma))
		&& (idma_is_valid(out_dma) &&
		!idma_is_set(IDMAC_CHA_EN, out_dma)))
		return -EINVAL;

	if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
	    (channel == MEM_DC_SYNC)) {
		ipu_dp_dc_disable(channel, 0);
	}

	/* Disable DMA channel(s) */
	if (idma_is_valid(in_dma)) {
		reg = __raw_readl(IDMAC_CHA_EN(in_dma));
		__raw_writel(reg & ~idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
		__raw_writel(idma_mask(in_dma), IPU_CHA_CUR_BUF(in_dma));
	}
	if (idma_is_valid(out_dma)) {
		reg = __raw_readl(IDMAC_CHA_EN(out_dma));
		__raw_writel(reg & ~idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
		__raw_writel(idma_mask(out_dma), IPU_CHA_CUR_BUF(out_dma));
	}

	g_channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));

	/* Set channel buffers NOT to be ready */
	if (idma_is_valid(in_dma)) {
		ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 0);
		ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 1);
	}
	if (idma_is_valid(out_dma)) {
		ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 0);
		ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 1);
	}

	return 0;
}
예제 #4
0
/*
 * This function clear buffer ready for a logical channel.
 *
 * @param       channel         Input parameter for the logical channel ID.
 *
 * @param       type            Input parameter which buffer to clear.
 *
 * @param       bufNum          Input parameter for which buffer number clear
 *				ready state.
 *
 */
void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
		uint32_t bufNum)
{
	uint32_t dma_ch = channel_2_dma(channel, type);

	if (!idma_is_valid(dma_ch))
		return;

	__raw_writel(0xF0000000, IPU_GPR); /* write one to clear */
	if (bufNum == 0) {
		if (idma_is_set(IPU_CHA_BUF0_RDY, dma_ch)) {
			__raw_writel(idma_mask(dma_ch),
					IPU_CHA_BUF0_RDY(dma_ch));
		}
	} else {
		if (idma_is_set(IPU_CHA_BUF1_RDY, dma_ch)) {
			__raw_writel(idma_mask(dma_ch),
					IPU_CHA_BUF1_RDY(dma_ch));
		}
	}
	__raw_writel(0x0, IPU_GPR); /* write one to set */
}
예제 #5
0
/*
 * This function is called to initialize a buffer for logical IPU channel.
 *
 * @param       channel         Input parameter for the logical channel ID.
 *
 * @param       type            Input parameter which buffer to initialize.
 *
 * @param       pixel_fmt       Input parameter for pixel format of buffer.
 *                              Pixel format is a FOURCC ASCII code.
 *
 * @param       width           Input parameter for width of buffer in pixels.
 *
 * @param       height          Input parameter for height of buffer in pixels.
 *
 * @param       stride          Input parameter for stride length of buffer
 *                              in pixels.
 *
 * @param       phyaddr_0       Input parameter buffer 0 physical address.
 *
 * @param       phyaddr_1       Input parameter buffer 1 physical address.
 *                              Setting this to a value other than NULL enables
 *                              double buffering mode.
 *
 * @param       u		private u offset for additional cropping,
 *				zero if not used.
 *
 * @param       v		private v offset for additional cropping,
 *				zero if not used.
 *
 * @return      Returns 0 on success or negative error code on fail
 */
int32_t ipu_init_channel_buffer(ipu_channel_t channel, ipu_buffer_t type,
				uint32_t pixel_fmt,
				uint16_t width, uint16_t height,
				uint32_t stride,
				dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
				uint32_t u, uint32_t v)
{
	uint32_t reg;
	uint32_t dma_chan;
	uint32_t burst_size;

	static int once = 0;
	if(IPU_CHAN_ID(channel) == 19){
		if (once == 0){
			once++;
		}else{
			printf("ipu_init_channel_buffer fake reinit\n");
			return 0;
		}
	}

	//printf("ipu_init_channel_buffer: channel: %d, type: %d, pixel_fmt: 0x%x, width: %d, height: %d, stride: %d, phyaddr_0: 0x%x, phyaddr_1: 0x%x, u: 0x%x, v: 0x%x\r\n",
	//	IPU_CHAN_ID(channel), type, pixel_fmt, width, height,stride, phyaddr_0, phyaddr_1, u,v);
	
	dma_chan = channel_2_dma(channel, type);
	if (!idma_is_valid(dma_chan))
		return -EINVAL;

	if (stride < width * bytes_per_pixel(pixel_fmt)){
		stride = width * bytes_per_pixel(pixel_fmt);
//		printf("stride is update with bpp: 0x%x\n", bytes_per_pixel(pixel_fmt));
	}

	if (stride % 4) {
		printf(
			"Stride not 32-bit aligned, stride = %d\n", stride);
		return -EINVAL;
	}
	/* Build parameter memory data for DMA channel */
	ipu_ch_param_init(dma_chan, pixel_fmt, width, height, stride, u, v, 0,
			   phyaddr_0, phyaddr_1);

	if (ipu_is_dmfc_chan(dma_chan)) {
		burst_size = _ipu_ch_param_get_burst_size(dma_chan);
		//printf("burst_size: 0x%x\n", burst_size);
		ipu_dmfc_set_wait4eot(dma_chan, width);
		ipu_dmfc_set_burst_size(dma_chan, burst_size);
	}

	/* IC and ROT channels have restriction of 8 or 16 pix burst length */
	if (_ipu_is_ic_chan(dma_chan)) {
		if ((width % 16) == 0)
			_ipu_ch_param_set_burst_size(dma_chan, 16);
		else
			_ipu_ch_param_set_burst_size(dma_chan, 8);
	} 

	if (_ipu_is_ic_chan(dma_chan) ) {
		burst_size = _ipu_ch_param_get_burst_size(dma_chan);
		_ipu_ic_idma_init(dma_chan, width, height, burst_size);
	} else if (_ipu_is_smfc_chan(dma_chan)) {
		burst_size = _ipu_ch_param_get_burst_size(dma_chan);
		if ((pixel_fmt == IPU_PIX_FMT_GENERIC) &&
			((_ipu_ch_param_get_bpp(dma_chan) == 5) ||
			(_ipu_ch_param_get_bpp(dma_chan) == 3)))
			burst_size = burst_size >> 4;
		else
			burst_size = burst_size >> 2;
		_ipu_smfc_set_burst_size(channel, burst_size-1);
	}