/* * 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; }
/* * 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; }
/* * 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; }
/* * 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 */ }
/* * 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); }