Home | History | Annotate | Download | only in video
      1 // SPDX-License-Identifier: GPL-2.0+
      2 /*
      3  * Porting to u-boot:
      4  *
      5  * (C) Copyright 2010
      6  * Stefano Babic, DENX Software Engineering, sbabic (at) denx.de
      7  *
      8  * Linux IPU driver for MX51:
      9  *
     10  * (C) Copyright 2005-2010 Freescale Semiconductor, Inc.
     11  */
     12 
     13 /* #define DEBUG */
     14 #include <common.h>
     15 #include <linux/types.h>
     16 #include <linux/err.h>
     17 #include <asm/io.h>
     18 #include <linux/errno.h>
     19 #include <asm/arch/imx-regs.h>
     20 #include <asm/arch/crm_regs.h>
     21 #include <asm/arch/sys_proto.h>
     22 #include <div64.h>
     23 #include "ipu.h"
     24 #include "ipu_regs.h"
     25 
     26 extern struct mxc_ccm_reg *mxc_ccm;
     27 extern u32 *ipu_cpmem_base;
     28 
     29 struct ipu_ch_param_word {
     30 	uint32_t data[5];
     31 	uint32_t res[3];
     32 };
     33 
     34 struct ipu_ch_param {
     35 	struct ipu_ch_param_word word[2];
     36 };
     37 
     38 #define ipu_ch_param_addr(ch) (((struct ipu_ch_param *)ipu_cpmem_base) + (ch))
     39 
     40 #define _param_word(base, w) \
     41 	(((struct ipu_ch_param *)(base))->word[(w)].data)
     42 
     43 #define ipu_ch_param_set_field(base, w, bit, size, v) { \
     44 	int i = (bit) / 32; \
     45 	int off = (bit) % 32; \
     46 	_param_word(base, w)[i] |= (v) << off; \
     47 	if (((bit) + (size) - 1) / 32 > i) { \
     48 		_param_word(base, w)[i + 1] |= (v) >> (off ? (32 - off) : 0); \
     49 	} \
     50 }
     51 
     52 #define ipu_ch_param_mod_field(base, w, bit, size, v) { \
     53 	int i = (bit) / 32; \
     54 	int off = (bit) % 32; \
     55 	u32 mask = (1UL << size) - 1; \
     56 	u32 temp = _param_word(base, w)[i]; \
     57 	temp &= ~(mask << off); \
     58 	_param_word(base, w)[i] = temp | (v) << off; \
     59 	if (((bit) + (size) - 1) / 32 > i) { \
     60 		temp = _param_word(base, w)[i + 1]; \
     61 		temp &= ~(mask >> (32 - off)); \
     62 		_param_word(base, w)[i + 1] = \
     63 			temp | ((v) >> (off ? (32 - off) : 0)); \
     64 	} \
     65 }
     66 
     67 #define ipu_ch_param_read_field(base, w, bit, size) ({ \
     68 	u32 temp2; \
     69 	int i = (bit) / 32; \
     70 	int off = (bit) % 32; \
     71 	u32 mask = (1UL << size) - 1; \
     72 	u32 temp1 = _param_word(base, w)[i]; \
     73 	temp1 = mask & (temp1 >> off); \
     74 	if (((bit)+(size) - 1) / 32 > i) { \
     75 		temp2 = _param_word(base, w)[i + 1]; \
     76 		temp2 &= mask >> (off ? (32 - off) : 0); \
     77 		temp1 |= temp2 << (off ? (32 - off) : 0); \
     78 	} \
     79 	temp1; \
     80 })
     81 
     82 #define IPU_SW_RST_TOUT_USEC	(10000)
     83 
     84 #define IPUV3_CLK_MX51		133000000
     85 #define IPUV3_CLK_MX53		200000000
     86 #define IPUV3_CLK_MX6Q		264000000
     87 #define IPUV3_CLK_MX6DL		198000000
     88 
     89 void clk_enable(struct clk *clk)
     90 {
     91 	if (clk) {
     92 		if (clk->usecount++ == 0) {
     93 			clk->enable(clk);
     94 		}
     95 	}
     96 }
     97 
     98 void clk_disable(struct clk *clk)
     99 {
    100 	if (clk) {
    101 		if (!(--clk->usecount)) {
    102 			if (clk->disable)
    103 				clk->disable(clk);
    104 		}
    105 	}
    106 }
    107 
    108 int clk_get_usecount(struct clk *clk)
    109 {
    110 	if (clk == NULL)
    111 		return 0;
    112 
    113 	return clk->usecount;
    114 }
    115 
    116 u32 clk_get_rate(struct clk *clk)
    117 {
    118 	if (!clk)
    119 		return 0;
    120 
    121 	return clk->rate;
    122 }
    123 
    124 struct clk *clk_get_parent(struct clk *clk)
    125 {
    126 	if (!clk)
    127 		return 0;
    128 
    129 	return clk->parent;
    130 }
    131 
    132 int clk_set_rate(struct clk *clk, unsigned long rate)
    133 {
    134 	if (!clk)
    135 		return 0;
    136 
    137 	if (clk->set_rate)
    138 		clk->set_rate(clk, rate);
    139 
    140 	return clk->rate;
    141 }
    142 
    143 long clk_round_rate(struct clk *clk, unsigned long rate)
    144 {
    145 	if (clk == NULL || !clk->round_rate)
    146 		return 0;
    147 
    148 	return clk->round_rate(clk, rate);
    149 }
    150 
    151 int clk_set_parent(struct clk *clk, struct clk *parent)
    152 {
    153 	clk->parent = parent;
    154 	if (clk->set_parent)
    155 		return clk->set_parent(clk, parent);
    156 	return 0;
    157 }
    158 
    159 static int clk_ipu_enable(struct clk *clk)
    160 {
    161 	u32 reg;
    162 
    163 	reg = __raw_readl(clk->enable_reg);
    164 	reg |= MXC_CCM_CCGR_CG_MASK << clk->enable_shift;
    165 	__raw_writel(reg, clk->enable_reg);
    166 
    167 #if defined(CONFIG_MX51) || defined(CONFIG_MX53)
    168 	/* Handshake with IPU when certain clock rates are changed. */
    169 	reg = __raw_readl(&mxc_ccm->ccdr);
    170 	reg &= ~MXC_CCM_CCDR_IPU_HS_MASK;
    171 	__raw_writel(reg, &mxc_ccm->ccdr);
    172 
    173 	/* Handshake with IPU when LPM is entered as its enabled. */
    174 	reg = __raw_readl(&mxc_ccm->clpcr);
    175 	reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
    176 	__raw_writel(reg, &mxc_ccm->clpcr);
    177 #endif
    178 	return 0;
    179 }
    180 
    181 static void clk_ipu_disable(struct clk *clk)
    182 {
    183 	u32 reg;
    184 
    185 	reg = __raw_readl(clk->enable_reg);
    186 	reg &= ~(MXC_CCM_CCGR_CG_MASK << clk->enable_shift);
    187 	__raw_writel(reg, clk->enable_reg);
    188 
    189 #if defined(CONFIG_MX51) || defined(CONFIG_MX53)
    190 	/*
    191 	 * No handshake with IPU whe dividers are changed
    192 	 * as its not enabled.
    193 	 */
    194 	reg = __raw_readl(&mxc_ccm->ccdr);
    195 	reg |= MXC_CCM_CCDR_IPU_HS_MASK;
    196 	__raw_writel(reg, &mxc_ccm->ccdr);
    197 
    198 	/* No handshake with IPU when LPM is entered as its not enabled. */
    199 	reg = __raw_readl(&mxc_ccm->clpcr);
    200 	reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS;
    201 	__raw_writel(reg, &mxc_ccm->clpcr);
    202 #endif
    203 }
    204 
    205 
    206 static struct clk ipu_clk = {
    207 	.name = "ipu_clk",
    208 #if defined(CONFIG_MX51) || defined(CONFIG_MX53)
    209 	.enable_reg = (u32 *)(CCM_BASE_ADDR +
    210 		offsetof(struct mxc_ccm_reg, CCGR5)),
    211 	.enable_shift = MXC_CCM_CCGR5_IPU_OFFSET,
    212 #else
    213 	.enable_reg = (u32 *)(CCM_BASE_ADDR +
    214 		offsetof(struct mxc_ccm_reg, CCGR3)),
    215 	.enable_shift = MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET,
    216 #endif
    217 	.enable = clk_ipu_enable,
    218 	.disable = clk_ipu_disable,
    219 	.usecount = 0,
    220 };
    221 
    222 #if !defined CONFIG_SYS_LDB_CLOCK
    223 #define CONFIG_SYS_LDB_CLOCK 65000000
    224 #endif
    225 
    226 static struct clk ldb_clk = {
    227 	.name = "ldb_clk",
    228 	.rate = CONFIG_SYS_LDB_CLOCK,
    229 	.usecount = 0,
    230 };
    231 
    232 /* Globals */
    233 struct clk *g_ipu_clk;
    234 struct clk *g_ldb_clk;
    235 unsigned char g_ipu_clk_enabled;
    236 struct clk *g_di_clk[2];
    237 struct clk *g_pixel_clk[2];
    238 unsigned char g_dc_di_assignment[10];
    239 uint32_t g_channel_init_mask;
    240 uint32_t g_channel_enable_mask;
    241 
    242 static int ipu_dc_use_count;
    243 static int ipu_dp_use_count;
    244 static int ipu_dmfc_use_count;
    245 static int ipu_di_use_count[2];
    246 
    247 u32 *ipu_cpmem_base;
    248 u32 *ipu_dc_tmpl_reg;
    249 
    250 /* Static functions */
    251 
    252 static inline void ipu_ch_param_set_high_priority(uint32_t ch)
    253 {
    254 	ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 1, 93, 2, 1);
    255 };
    256 
    257 static inline uint32_t channel_2_dma(ipu_channel_t ch, ipu_buffer_t type)
    258 {
    259 	return ((uint32_t) ch >> (6 * type)) & 0x3F;
    260 };
    261 
    262 /* Either DP BG or DP FG can be graphic window */
    263 static inline int ipu_is_dp_graphic_chan(uint32_t dma_chan)
    264 {
    265 	return (dma_chan == 23 || dma_chan == 27);
    266 }
    267 
    268 static inline int ipu_is_dmfc_chan(uint32_t dma_chan)
    269 {
    270 	return ((dma_chan >= 23) && (dma_chan <= 29));
    271 }
    272 
    273 
    274 static inline void ipu_ch_param_set_buffer(uint32_t ch, int bufNum,
    275 					    dma_addr_t phyaddr)
    276 {
    277 	ipu_ch_param_mod_field(ipu_ch_param_addr(ch), 1, 29 * bufNum, 29,
    278 			       phyaddr / 8);
    279 };
    280 
    281 #define idma_is_valid(ch)	(ch != NO_DMA)
    282 #define idma_mask(ch)		(idma_is_valid(ch) ? (1UL << (ch & 0x1F)) : 0)
    283 #define idma_is_set(reg, dma)	(__raw_readl(reg(dma)) & idma_mask(dma))
    284 
    285 static void ipu_pixel_clk_recalc(struct clk *clk)
    286 {
    287 	u32 div;
    288 	u64 final_rate = (unsigned long long)clk->parent->rate * 16;
    289 
    290 	div = __raw_readl(DI_BS_CLKGEN0(clk->id));
    291 	debug("read BS_CLKGEN0 div:%d, final_rate:%lld, prate:%ld\n",
    292 	      div, final_rate, clk->parent->rate);
    293 
    294 	clk->rate = 0;
    295 	if (div != 0) {
    296 		do_div(final_rate, div);
    297 		clk->rate = final_rate;
    298 	}
    299 }
    300 
    301 static unsigned long ipu_pixel_clk_round_rate(struct clk *clk,
    302 	unsigned long rate)
    303 {
    304 	u64 div, final_rate;
    305 	u32 remainder;
    306 	u64 parent_rate = (unsigned long long)clk->parent->rate * 16;
    307 
    308 	/*
    309 	 * Calculate divider
    310 	 * Fractional part is 4 bits,
    311 	 * so simply multiply by 2^4 to get fractional part.
    312 	 */
    313 	div = parent_rate;
    314 	remainder = do_div(div, rate);
    315 	/* Round the divider value */
    316 	if (remainder > (rate / 2))
    317 		div++;
    318 	if (div < 0x10)            /* Min DI disp clock divider is 1 */
    319 		div = 0x10;
    320 	if (div & ~0xFEF)
    321 		div &= 0xFF8;
    322 	else {
    323 		/* Round up divider if it gets us closer to desired pix clk */
    324 		if ((div & 0xC) == 0xC) {
    325 			div += 0x10;
    326 			div &= ~0xF;
    327 		}
    328 	}
    329 	final_rate = parent_rate;
    330 	do_div(final_rate, div);
    331 
    332 	return final_rate;
    333 }
    334 
    335 static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate)
    336 {
    337 	u64 div, parent_rate;
    338 	u32 remainder;
    339 
    340 	parent_rate = (unsigned long long)clk->parent->rate * 16;
    341 	div = parent_rate;
    342 	remainder = do_div(div, rate);
    343 	/* Round the divider value */
    344 	if (remainder > (rate / 2))
    345 		div++;
    346 
    347 	/* Round up divider if it gets us closer to desired pix clk */
    348 	if ((div & 0xC) == 0xC) {
    349 		div += 0x10;
    350 		div &= ~0xF;
    351 	}
    352 	if (div > 0x1000)
    353 		debug("Overflow, DI_BS_CLKGEN0 div:0x%x\n", (u32)div);
    354 
    355 	__raw_writel(div, DI_BS_CLKGEN0(clk->id));
    356 
    357 	/*
    358 	 * Setup pixel clock timing
    359 	 * Down time is half of period
    360 	 */
    361 	__raw_writel((div / 16) << 16, DI_BS_CLKGEN1(clk->id));
    362 
    363 	do_div(parent_rate, div);
    364 
    365 	clk->rate = parent_rate;
    366 
    367 	return 0;
    368 }
    369 
    370 static int ipu_pixel_clk_enable(struct clk *clk)
    371 {
    372 	u32 disp_gen = __raw_readl(IPU_DISP_GEN);
    373 	disp_gen |= clk->id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
    374 	__raw_writel(disp_gen, IPU_DISP_GEN);
    375 
    376 	return 0;
    377 }
    378 
    379 static void ipu_pixel_clk_disable(struct clk *clk)
    380 {
    381 	u32 disp_gen = __raw_readl(IPU_DISP_GEN);
    382 	disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
    383 	__raw_writel(disp_gen, IPU_DISP_GEN);
    384 
    385 }
    386 
    387 static int ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent)
    388 {
    389 	u32 di_gen = __raw_readl(DI_GENERAL(clk->id));
    390 
    391 	if (parent == g_ipu_clk)
    392 		di_gen &= ~DI_GEN_DI_CLK_EXT;
    393 	else if (!IS_ERR(g_di_clk[clk->id]) && parent == g_ldb_clk)
    394 		di_gen |= DI_GEN_DI_CLK_EXT;
    395 	else
    396 		return -EINVAL;
    397 
    398 	__raw_writel(di_gen, DI_GENERAL(clk->id));
    399 	ipu_pixel_clk_recalc(clk);
    400 	return 0;
    401 }
    402 
    403 static struct clk pixel_clk[] = {
    404 	{
    405 	.name = "pixel_clk",
    406 	.id = 0,
    407 	.recalc = ipu_pixel_clk_recalc,
    408 	.set_rate = ipu_pixel_clk_set_rate,
    409 	.round_rate = ipu_pixel_clk_round_rate,
    410 	.set_parent = ipu_pixel_clk_set_parent,
    411 	.enable = ipu_pixel_clk_enable,
    412 	.disable = ipu_pixel_clk_disable,
    413 	.usecount = 0,
    414 	},
    415 	{
    416 	.name = "pixel_clk",
    417 	.id = 1,
    418 	.recalc = ipu_pixel_clk_recalc,
    419 	.set_rate = ipu_pixel_clk_set_rate,
    420 	.round_rate = ipu_pixel_clk_round_rate,
    421 	.set_parent = ipu_pixel_clk_set_parent,
    422 	.enable = ipu_pixel_clk_enable,
    423 	.disable = ipu_pixel_clk_disable,
    424 	.usecount = 0,
    425 	},
    426 };
    427 
    428 /*
    429  * This function resets IPU
    430  */
    431 static void ipu_reset(void)
    432 {
    433 	u32 *reg;
    434 	u32 value;
    435 	int timeout = IPU_SW_RST_TOUT_USEC;
    436 
    437 	reg = (u32 *)SRC_BASE_ADDR;
    438 	value = __raw_readl(reg);
    439 	value = value | SW_IPU_RST;
    440 	__raw_writel(value, reg);
    441 
    442 	while (__raw_readl(reg) & SW_IPU_RST) {
    443 		udelay(1);
    444 		if (!(timeout--)) {
    445 			printf("ipu software reset timeout\n");
    446 			break;
    447 		}
    448 	};
    449 }
    450 
    451 /*
    452  * This function is called by the driver framework to initialize the IPU
    453  * hardware.
    454  *
    455  * @param	dev	The device structure for the IPU passed in by the
    456  *			driver framework.
    457  *
    458  * @return      Returns 0 on success or negative error code on error
    459  */
    460 int ipu_probe(void)
    461 {
    462 	unsigned long ipu_base;
    463 #if defined CONFIG_MX51
    464 	u32 temp;
    465 
    466 	u32 *reg_hsc_mcd = (u32 *)MIPI_HSC_BASE_ADDR;
    467 	u32 *reg_hsc_mxt_conf = (u32 *)(MIPI_HSC_BASE_ADDR + 0x800);
    468 
    469 	 __raw_writel(0xF00, reg_hsc_mcd);
    470 
    471 	/* CSI mode reserved*/
    472 	temp = __raw_readl(reg_hsc_mxt_conf);
    473 	 __raw_writel(temp | 0x0FF, reg_hsc_mxt_conf);
    474 
    475 	temp = __raw_readl(reg_hsc_mxt_conf);
    476 	__raw_writel(temp | 0x10000, reg_hsc_mxt_conf);
    477 #endif
    478 
    479 	ipu_base = IPU_CTRL_BASE_ADDR;
    480 	ipu_cpmem_base = (u32 *)(ipu_base + IPU_CPMEM_REG_BASE);
    481 	ipu_dc_tmpl_reg = (u32 *)(ipu_base + IPU_DC_TMPL_REG_BASE);
    482 
    483 	g_pixel_clk[0] = &pixel_clk[0];
    484 	g_pixel_clk[1] = &pixel_clk[1];
    485 
    486 	g_ipu_clk = &ipu_clk;
    487 #if defined(CONFIG_MX51)
    488 	g_ipu_clk->rate = IPUV3_CLK_MX51;
    489 #elif defined(CONFIG_MX53)
    490 	g_ipu_clk->rate = IPUV3_CLK_MX53;
    491 #else
    492 	g_ipu_clk->rate = is_mx6sdl() ? IPUV3_CLK_MX6DL : IPUV3_CLK_MX6Q;
    493 #endif
    494 	debug("ipu_clk = %u\n", clk_get_rate(g_ipu_clk));
    495 	g_ldb_clk = &ldb_clk;
    496 	debug("ldb_clk = %u\n", clk_get_rate(g_ldb_clk));
    497 	ipu_reset();
    498 
    499 	clk_set_parent(g_pixel_clk[0], g_ipu_clk);
    500 	clk_set_parent(g_pixel_clk[1], g_ipu_clk);
    501 	clk_enable(g_ipu_clk);
    502 
    503 	g_di_clk[0] = NULL;
    504 	g_di_clk[1] = NULL;
    505 
    506 	__raw_writel(0x807FFFFF, IPU_MEM_RST);
    507 	while (__raw_readl(IPU_MEM_RST) & 0x80000000)
    508 		;
    509 
    510 	ipu_init_dc_mappings();
    511 
    512 	__raw_writel(0, IPU_INT_CTRL(5));
    513 	__raw_writel(0, IPU_INT_CTRL(6));
    514 	__raw_writel(0, IPU_INT_CTRL(9));
    515 	__raw_writel(0, IPU_INT_CTRL(10));
    516 
    517 	/* DMFC Init */
    518 	ipu_dmfc_init(DMFC_NORMAL, 1);
    519 
    520 	/* Set sync refresh channels as high priority */
    521 	__raw_writel(0x18800000L, IDMAC_CHA_PRI(0));
    522 
    523 	/* Set MCU_T to divide MCU access window into 2 */
    524 	__raw_writel(0x00400000L | (IPU_MCU_T_DEFAULT << 18), IPU_DISP_GEN);
    525 
    526 	clk_disable(g_ipu_clk);
    527 
    528 	return 0;
    529 }
    530 
    531 void ipu_dump_registers(void)
    532 {
    533 	debug("IPU_CONF = \t0x%08X\n", __raw_readl(IPU_CONF));
    534 	debug("IDMAC_CONF = \t0x%08X\n", __raw_readl(IDMAC_CONF));
    535 	debug("IDMAC_CHA_EN1 = \t0x%08X\n",
    536 	       __raw_readl(IDMAC_CHA_EN(0)));
    537 	debug("IDMAC_CHA_EN2 = \t0x%08X\n",
    538 	       __raw_readl(IDMAC_CHA_EN(32)));
    539 	debug("IDMAC_CHA_PRI1 = \t0x%08X\n",
    540 	       __raw_readl(IDMAC_CHA_PRI(0)));
    541 	debug("IDMAC_CHA_PRI2 = \t0x%08X\n",
    542 	       __raw_readl(IDMAC_CHA_PRI(32)));
    543 	debug("IPU_CHA_DB_MODE_SEL0 = \t0x%08X\n",
    544 	       __raw_readl(IPU_CHA_DB_MODE_SEL(0)));
    545 	debug("IPU_CHA_DB_MODE_SEL1 = \t0x%08X\n",
    546 	       __raw_readl(IPU_CHA_DB_MODE_SEL(32)));
    547 	debug("DMFC_WR_CHAN = \t0x%08X\n",
    548 	       __raw_readl(DMFC_WR_CHAN));
    549 	debug("DMFC_WR_CHAN_DEF = \t0x%08X\n",
    550 	       __raw_readl(DMFC_WR_CHAN_DEF));
    551 	debug("DMFC_DP_CHAN = \t0x%08X\n",
    552 	       __raw_readl(DMFC_DP_CHAN));
    553 	debug("DMFC_DP_CHAN_DEF = \t0x%08X\n",
    554 	       __raw_readl(DMFC_DP_CHAN_DEF));
    555 	debug("DMFC_IC_CTRL = \t0x%08X\n",
    556 	       __raw_readl(DMFC_IC_CTRL));
    557 	debug("IPU_FS_PROC_FLOW1 = \t0x%08X\n",
    558 	       __raw_readl(IPU_FS_PROC_FLOW1));
    559 	debug("IPU_FS_PROC_FLOW2 = \t0x%08X\n",
    560 	       __raw_readl(IPU_FS_PROC_FLOW2));
    561 	debug("IPU_FS_PROC_FLOW3 = \t0x%08X\n",
    562 	       __raw_readl(IPU_FS_PROC_FLOW3));
    563 	debug("IPU_FS_DISP_FLOW1 = \t0x%08X\n",
    564 	       __raw_readl(IPU_FS_DISP_FLOW1));
    565 }
    566 
    567 /*
    568  * This function is called to initialize a logical IPU channel.
    569  *
    570  * @param       channel Input parameter for the logical channel ID to init.
    571  *
    572  * @param       params  Input parameter containing union of channel
    573  *                      initialization parameters.
    574  *
    575  * @return      Returns 0 on success or negative error code on fail
    576  */
    577 int32_t ipu_init_channel(ipu_channel_t channel, ipu_channel_params_t *params)
    578 {
    579 	int ret = 0;
    580 	uint32_t ipu_conf;
    581 
    582 	debug("init channel = %d\n", IPU_CHAN_ID(channel));
    583 
    584 	if (g_ipu_clk_enabled == 0) {
    585 		g_ipu_clk_enabled = 1;
    586 		clk_enable(g_ipu_clk);
    587 	}
    588 
    589 
    590 	if (g_channel_init_mask & (1L << IPU_CHAN_ID(channel))) {
    591 		printf("Warning: channel already initialized %d\n",
    592 			IPU_CHAN_ID(channel));
    593 	}
    594 
    595 	ipu_conf = __raw_readl(IPU_CONF);
    596 
    597 	switch (channel) {
    598 	case MEM_DC_SYNC:
    599 		if (params->mem_dc_sync.di > 1) {
    600 			ret = -EINVAL;
    601 			goto err;
    602 		}
    603 
    604 		g_dc_di_assignment[1] = params->mem_dc_sync.di;
    605 		ipu_dc_init(1, params->mem_dc_sync.di,
    606 			     params->mem_dc_sync.interlaced);
    607 		ipu_di_use_count[params->mem_dc_sync.di]++;
    608 		ipu_dc_use_count++;
    609 		ipu_dmfc_use_count++;
    610 		break;
    611 	case MEM_BG_SYNC:
    612 		if (params->mem_dp_bg_sync.di > 1) {
    613 			ret = -EINVAL;
    614 			goto err;
    615 		}
    616 
    617 		g_dc_di_assignment[5] = params->mem_dp_bg_sync.di;
    618 		ipu_dp_init(channel, params->mem_dp_bg_sync.in_pixel_fmt,
    619 			     params->mem_dp_bg_sync.out_pixel_fmt);
    620 		ipu_dc_init(5, params->mem_dp_bg_sync.di,
    621 			     params->mem_dp_bg_sync.interlaced);
    622 		ipu_di_use_count[params->mem_dp_bg_sync.di]++;
    623 		ipu_dc_use_count++;
    624 		ipu_dp_use_count++;
    625 		ipu_dmfc_use_count++;
    626 		break;
    627 	case MEM_FG_SYNC:
    628 		ipu_dp_init(channel, params->mem_dp_fg_sync.in_pixel_fmt,
    629 			     params->mem_dp_fg_sync.out_pixel_fmt);
    630 
    631 		ipu_dc_use_count++;
    632 		ipu_dp_use_count++;
    633 		ipu_dmfc_use_count++;
    634 		break;
    635 	default:
    636 		printf("Missing channel initialization\n");
    637 		break;
    638 	}
    639 
    640 	/* Enable IPU sub module */
    641 	g_channel_init_mask |= 1L << IPU_CHAN_ID(channel);
    642 	if (ipu_dc_use_count == 1)
    643 		ipu_conf |= IPU_CONF_DC_EN;
    644 	if (ipu_dp_use_count == 1)
    645 		ipu_conf |= IPU_CONF_DP_EN;
    646 	if (ipu_dmfc_use_count == 1)
    647 		ipu_conf |= IPU_CONF_DMFC_EN;
    648 	if (ipu_di_use_count[0] == 1) {
    649 		ipu_conf |= IPU_CONF_DI0_EN;
    650 	}
    651 	if (ipu_di_use_count[1] == 1) {
    652 		ipu_conf |= IPU_CONF_DI1_EN;
    653 	}
    654 
    655 	__raw_writel(ipu_conf, IPU_CONF);
    656 
    657 err:
    658 	return ret;
    659 }
    660 
    661 /*
    662  * This function is called to uninitialize a logical IPU channel.
    663  *
    664  * @param       channel Input parameter for the logical channel ID to uninit.
    665  */
    666 void ipu_uninit_channel(ipu_channel_t channel)
    667 {
    668 	uint32_t reg;
    669 	uint32_t in_dma, out_dma = 0;
    670 	uint32_t ipu_conf;
    671 
    672 	if ((g_channel_init_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
    673 		debug("Channel already uninitialized %d\n",
    674 			IPU_CHAN_ID(channel));
    675 		return;
    676 	}
    677 
    678 	/*
    679 	 * Make sure channel is disabled
    680 	 * Get input and output dma channels
    681 	 */
    682 	in_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
    683 	out_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
    684 
    685 	if (idma_is_set(IDMAC_CHA_EN, in_dma) ||
    686 	    idma_is_set(IDMAC_CHA_EN, out_dma)) {
    687 		printf(
    688 			"Channel %d is not disabled, disable first\n",
    689 			IPU_CHAN_ID(channel));
    690 		return;
    691 	}
    692 
    693 	ipu_conf = __raw_readl(IPU_CONF);
    694 
    695 	/* Reset the double buffer */
    696 	reg = __raw_readl(IPU_CHA_DB_MODE_SEL(in_dma));
    697 	__raw_writel(reg & ~idma_mask(in_dma), IPU_CHA_DB_MODE_SEL(in_dma));
    698 	reg = __raw_readl(IPU_CHA_DB_MODE_SEL(out_dma));
    699 	__raw_writel(reg & ~idma_mask(out_dma), IPU_CHA_DB_MODE_SEL(out_dma));
    700 
    701 	switch (channel) {
    702 	case MEM_DC_SYNC:
    703 		ipu_dc_uninit(1);
    704 		ipu_di_use_count[g_dc_di_assignment[1]]--;
    705 		ipu_dc_use_count--;
    706 		ipu_dmfc_use_count--;
    707 		break;
    708 	case MEM_BG_SYNC:
    709 		ipu_dp_uninit(channel);
    710 		ipu_dc_uninit(5);
    711 		ipu_di_use_count[g_dc_di_assignment[5]]--;
    712 		ipu_dc_use_count--;
    713 		ipu_dp_use_count--;
    714 		ipu_dmfc_use_count--;
    715 		break;
    716 	case MEM_FG_SYNC:
    717 		ipu_dp_uninit(channel);
    718 		ipu_dc_use_count--;
    719 		ipu_dp_use_count--;
    720 		ipu_dmfc_use_count--;
    721 		break;
    722 	default:
    723 		break;
    724 	}
    725 
    726 	g_channel_init_mask &= ~(1L << IPU_CHAN_ID(channel));
    727 
    728 	if (ipu_dc_use_count == 0)
    729 		ipu_conf &= ~IPU_CONF_DC_EN;
    730 	if (ipu_dp_use_count == 0)
    731 		ipu_conf &= ~IPU_CONF_DP_EN;
    732 	if (ipu_dmfc_use_count == 0)
    733 		ipu_conf &= ~IPU_CONF_DMFC_EN;
    734 	if (ipu_di_use_count[0] == 0) {
    735 		ipu_conf &= ~IPU_CONF_DI0_EN;
    736 	}
    737 	if (ipu_di_use_count[1] == 0) {
    738 		ipu_conf &= ~IPU_CONF_DI1_EN;
    739 	}
    740 
    741 	__raw_writel(ipu_conf, IPU_CONF);
    742 
    743 	if (ipu_conf == 0) {
    744 		clk_disable(g_ipu_clk);
    745 		g_ipu_clk_enabled = 0;
    746 	}
    747 
    748 }
    749 
    750 static inline void ipu_ch_param_dump(int ch)
    751 {
    752 #ifdef DEBUG
    753 	struct ipu_ch_param *p = ipu_ch_param_addr(ch);
    754 	debug("ch %d word 0 - %08X %08X %08X %08X %08X\n", ch,
    755 		 p->word[0].data[0], p->word[0].data[1], p->word[0].data[2],
    756 		 p->word[0].data[3], p->word[0].data[4]);
    757 	debug("ch %d word 1 - %08X %08X %08X %08X %08X\n", ch,
    758 		 p->word[1].data[0], p->word[1].data[1], p->word[1].data[2],
    759 		 p->word[1].data[3], p->word[1].data[4]);
    760 	debug("PFS 0x%x, ",
    761 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 85, 4));
    762 	debug("BPP 0x%x, ",
    763 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 0, 107, 3));
    764 	debug("NPB 0x%x\n",
    765 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 78, 7));
    766 
    767 	debug("FW %d, ",
    768 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 0, 125, 13));
    769 	debug("FH %d, ",
    770 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 0, 138, 12));
    771 	debug("Stride %d\n",
    772 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 102, 14));
    773 
    774 	debug("Width0 %d+1, ",
    775 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 116, 3));
    776 	debug("Width1 %d+1, ",
    777 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 119, 3));
    778 	debug("Width2 %d+1, ",
    779 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 122, 3));
    780 	debug("Width3 %d+1, ",
    781 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 125, 3));
    782 	debug("Offset0 %d, ",
    783 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 128, 5));
    784 	debug("Offset1 %d, ",
    785 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 133, 5));
    786 	debug("Offset2 %d, ",
    787 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 138, 5));
    788 	debug("Offset3 %d\n",
    789 		 ipu_ch_param_read_field(ipu_ch_param_addr(ch), 1, 143, 5));
    790 #endif
    791 }
    792 
    793 static inline void ipu_ch_params_set_packing(struct ipu_ch_param *p,
    794 					      int red_width, int red_offset,
    795 					      int green_width, int green_offset,
    796 					      int blue_width, int blue_offset,
    797 					      int alpha_width, int alpha_offset)
    798 {
    799 	/* Setup red width and offset */
    800 	ipu_ch_param_set_field(p, 1, 116, 3, red_width - 1);
    801 	ipu_ch_param_set_field(p, 1, 128, 5, red_offset);
    802 	/* Setup green width and offset */
    803 	ipu_ch_param_set_field(p, 1, 119, 3, green_width - 1);
    804 	ipu_ch_param_set_field(p, 1, 133, 5, green_offset);
    805 	/* Setup blue width and offset */
    806 	ipu_ch_param_set_field(p, 1, 122, 3, blue_width - 1);
    807 	ipu_ch_param_set_field(p, 1, 138, 5, blue_offset);
    808 	/* Setup alpha width and offset */
    809 	ipu_ch_param_set_field(p, 1, 125, 3, alpha_width - 1);
    810 	ipu_ch_param_set_field(p, 1, 143, 5, alpha_offset);
    811 }
    812 
    813 static void ipu_ch_param_init(int ch,
    814 			      uint32_t pixel_fmt, uint32_t width,
    815 			      uint32_t height, uint32_t stride,
    816 			      uint32_t u, uint32_t v,
    817 			      uint32_t uv_stride, dma_addr_t addr0,
    818 			      dma_addr_t addr1)
    819 {
    820 	uint32_t u_offset = 0;
    821 	uint32_t v_offset = 0;
    822 	struct ipu_ch_param params;
    823 
    824 	memset(&params, 0, sizeof(params));
    825 
    826 	ipu_ch_param_set_field(&params, 0, 125, 13, width - 1);
    827 
    828 	if ((ch == 8) || (ch == 9) || (ch == 10)) {
    829 		ipu_ch_param_set_field(&params, 0, 138, 12, (height / 2) - 1);
    830 		ipu_ch_param_set_field(&params, 1, 102, 14, (stride * 2) - 1);
    831 	} else {
    832 		ipu_ch_param_set_field(&params, 0, 138, 12, height - 1);
    833 		ipu_ch_param_set_field(&params, 1, 102, 14, stride - 1);
    834 	}
    835 
    836 	ipu_ch_param_set_field(&params, 1, 0, 29, addr0 >> 3);
    837 	ipu_ch_param_set_field(&params, 1, 29, 29, addr1 >> 3);
    838 
    839 	switch (pixel_fmt) {
    840 	case IPU_PIX_FMT_GENERIC:
    841 		/*Represents 8-bit Generic data */
    842 		ipu_ch_param_set_field(&params, 0, 107, 3, 5);	/* bits/pixel */
    843 		ipu_ch_param_set_field(&params, 1, 85, 4, 6);	/* pix format */
    844 		ipu_ch_param_set_field(&params, 1, 78, 7, 63);	/* burst size */
    845 
    846 		break;
    847 	case IPU_PIX_FMT_GENERIC_32:
    848 		/*Represents 32-bit Generic data */
    849 		break;
    850 	case IPU_PIX_FMT_RGB565:
    851 		ipu_ch_param_set_field(&params, 0, 107, 3, 3);	/* bits/pixel */
    852 		ipu_ch_param_set_field(&params, 1, 85, 4, 7);	/* pix format */
    853 		ipu_ch_param_set_field(&params, 1, 78, 7, 15);	/* burst size */
    854 
    855 		ipu_ch_params_set_packing(&params, 5, 0, 6, 5, 5, 11, 8, 16);
    856 		break;
    857 	case IPU_PIX_FMT_BGR24:
    858 		ipu_ch_param_set_field(&params, 0, 107, 3, 1);	/* bits/pixel */
    859 		ipu_ch_param_set_field(&params, 1, 85, 4, 7);	/* pix format */
    860 		ipu_ch_param_set_field(&params, 1, 78, 7, 19);	/* burst size */
    861 
    862 		ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
    863 		break;
    864 	case IPU_PIX_FMT_RGB24:
    865 	case IPU_PIX_FMT_YUV444:
    866 		ipu_ch_param_set_field(&params, 0, 107, 3, 1);	/* bits/pixel */
    867 		ipu_ch_param_set_field(&params, 1, 85, 4, 7);	/* pix format */
    868 		ipu_ch_param_set_field(&params, 1, 78, 7, 19);	/* burst size */
    869 
    870 		ipu_ch_params_set_packing(&params, 8, 16, 8, 8, 8, 0, 8, 24);
    871 		break;
    872 	case IPU_PIX_FMT_BGRA32:
    873 	case IPU_PIX_FMT_BGR32:
    874 		ipu_ch_param_set_field(&params, 0, 107, 3, 0);	/* bits/pixel */
    875 		ipu_ch_param_set_field(&params, 1, 85, 4, 7);	/* pix format */
    876 		ipu_ch_param_set_field(&params, 1, 78, 7, 15);	/* burst size */
    877 
    878 		ipu_ch_params_set_packing(&params, 8, 8, 8, 16, 8, 24, 8, 0);
    879 		break;
    880 	case IPU_PIX_FMT_RGBA32:
    881 	case IPU_PIX_FMT_RGB32:
    882 		ipu_ch_param_set_field(&params, 0, 107, 3, 0);	/* bits/pixel */
    883 		ipu_ch_param_set_field(&params, 1, 85, 4, 7);	/* pix format */
    884 		ipu_ch_param_set_field(&params, 1, 78, 7, 15);	/* burst size */
    885 
    886 		ipu_ch_params_set_packing(&params, 8, 24, 8, 16, 8, 8, 8, 0);
    887 		break;
    888 	case IPU_PIX_FMT_ABGR32:
    889 		ipu_ch_param_set_field(&params, 0, 107, 3, 0);	/* bits/pixel */
    890 		ipu_ch_param_set_field(&params, 1, 85, 4, 7);	/* pix format */
    891 
    892 		ipu_ch_params_set_packing(&params, 8, 0, 8, 8, 8, 16, 8, 24);
    893 		break;
    894 	case IPU_PIX_FMT_UYVY:
    895 		ipu_ch_param_set_field(&params, 0, 107, 3, 3);	/* bits/pixel */
    896 		ipu_ch_param_set_field(&params, 1, 85, 4, 0xA);	/* pix format */
    897 		ipu_ch_param_set_field(&params, 1, 78, 7, 15);	/* burst size */
    898 		break;
    899 	case IPU_PIX_FMT_YUYV:
    900 		ipu_ch_param_set_field(&params, 0, 107, 3, 3);	/* bits/pixel */
    901 		ipu_ch_param_set_field(&params, 1, 85, 4, 0x8);	/* pix format */
    902 		ipu_ch_param_set_field(&params, 1, 78, 7, 31);	/* burst size */
    903 		break;
    904 	case IPU_PIX_FMT_YUV420P2:
    905 	case IPU_PIX_FMT_YUV420P:
    906 		ipu_ch_param_set_field(&params, 1, 85, 4, 2);	/* pix format */
    907 
    908 		if (uv_stride < stride / 2)
    909 			uv_stride = stride / 2;
    910 
    911 		u_offset = stride * height;
    912 		v_offset = u_offset + (uv_stride * height / 2);
    913 		/* burst size */
    914 		if ((ch == 8) || (ch == 9) || (ch == 10)) {
    915 			ipu_ch_param_set_field(&params, 1, 78, 7, 15);
    916 			uv_stride = uv_stride*2;
    917 		} else {
    918 			ipu_ch_param_set_field(&params, 1, 78, 7, 31);
    919 		}
    920 		break;
    921 	case IPU_PIX_FMT_YVU422P:
    922 		/* BPP & pixel format */
    923 		ipu_ch_param_set_field(&params, 1, 85, 4, 1);	/* pix format */
    924 		ipu_ch_param_set_field(&params, 1, 78, 7, 31);	/* burst size */
    925 
    926 		if (uv_stride < stride / 2)
    927 			uv_stride = stride / 2;
    928 
    929 		v_offset = (v == 0) ? stride * height : v;
    930 		u_offset = (u == 0) ? v_offset + v_offset / 2 : u;
    931 		break;
    932 	case IPU_PIX_FMT_YUV422P:
    933 		/* BPP & pixel format */
    934 		ipu_ch_param_set_field(&params, 1, 85, 4, 1);	/* pix format */
    935 		ipu_ch_param_set_field(&params, 1, 78, 7, 31);	/* burst size */
    936 
    937 		if (uv_stride < stride / 2)
    938 			uv_stride = stride / 2;
    939 
    940 		u_offset = (u == 0) ? stride * height : u;
    941 		v_offset = (v == 0) ? u_offset + u_offset / 2 : v;
    942 		break;
    943 	case IPU_PIX_FMT_NV12:
    944 		/* BPP & pixel format */
    945 		ipu_ch_param_set_field(&params, 1, 85, 4, 4);	/* pix format */
    946 		ipu_ch_param_set_field(&params, 1, 78, 7, 31);	/* burst size */
    947 		uv_stride = stride;
    948 		u_offset = (u == 0) ? stride * height : u;
    949 		break;
    950 	default:
    951 		puts("mxc ipu: unimplemented pixel format\n");
    952 		break;
    953 	}
    954 
    955 
    956 	if (uv_stride)
    957 		ipu_ch_param_set_field(&params, 1, 128, 14, uv_stride - 1);
    958 
    959 	/* Get the uv offset from user when need cropping */
    960 	if (u || v) {
    961 		u_offset = u;
    962 		v_offset = v;
    963 	}
    964 
    965 	/* UBO and VBO are 22-bit */
    966 	if (u_offset/8 > 0x3fffff)
    967 		puts("The value of U offset exceeds IPU limitation\n");
    968 	if (v_offset/8 > 0x3fffff)
    969 		puts("The value of V offset exceeds IPU limitation\n");
    970 
    971 	ipu_ch_param_set_field(&params, 0, 46, 22, u_offset / 8);
    972 	ipu_ch_param_set_field(&params, 0, 68, 22, v_offset / 8);
    973 
    974 	debug("initializing idma ch %d @ %p\n", ch, ipu_ch_param_addr(ch));
    975 	memcpy(ipu_ch_param_addr(ch), &params, sizeof(params));
    976 };
    977 
    978 /*
    979  * This function is called to initialize a buffer for logical IPU channel.
    980  *
    981  * @param       channel         Input parameter for the logical channel ID.
    982  *
    983  * @param       type            Input parameter which buffer to initialize.
    984  *
    985  * @param       pixel_fmt       Input parameter for pixel format of buffer.
    986  *                              Pixel format is a FOURCC ASCII code.
    987  *
    988  * @param       width           Input parameter for width of buffer in pixels.
    989  *
    990  * @param       height          Input parameter for height of buffer in pixels.
    991  *
    992  * @param       stride          Input parameter for stride length of buffer
    993  *                              in pixels.
    994  *
    995  * @param       phyaddr_0       Input parameter buffer 0 physical address.
    996  *
    997  * @param       phyaddr_1       Input parameter buffer 1 physical address.
    998  *                              Setting this to a value other than NULL enables
    999  *                              double buffering mode.
   1000  *
   1001  * @param       u		private u offset for additional cropping,
   1002  *				zero if not used.
   1003  *
   1004  * @param       v		private v offset for additional cropping,
   1005  *				zero if not used.
   1006  *
   1007  * @return      Returns 0 on success or negative error code on fail
   1008  */
   1009 int32_t ipu_init_channel_buffer(ipu_channel_t channel, ipu_buffer_t type,
   1010 				uint32_t pixel_fmt,
   1011 				uint16_t width, uint16_t height,
   1012 				uint32_t stride,
   1013 				dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
   1014 				uint32_t u, uint32_t v)
   1015 {
   1016 	uint32_t reg;
   1017 	uint32_t dma_chan;
   1018 
   1019 	dma_chan = channel_2_dma(channel, type);
   1020 	if (!idma_is_valid(dma_chan))
   1021 		return -EINVAL;
   1022 
   1023 	if (stride < width * bytes_per_pixel(pixel_fmt))
   1024 		stride = width * bytes_per_pixel(pixel_fmt);
   1025 
   1026 	if (stride % 4) {
   1027 		printf(
   1028 			"Stride not 32-bit aligned, stride = %d\n", stride);
   1029 		return -EINVAL;
   1030 	}
   1031 	/* Build parameter memory data for DMA channel */
   1032 	ipu_ch_param_init(dma_chan, pixel_fmt, width, height, stride, u, v, 0,
   1033 			   phyaddr_0, phyaddr_1);
   1034 
   1035 	if (ipu_is_dmfc_chan(dma_chan)) {
   1036 		ipu_dmfc_set_wait4eot(dma_chan, width);
   1037 	}
   1038 
   1039 	if (idma_is_set(IDMAC_CHA_PRI, dma_chan))
   1040 		ipu_ch_param_set_high_priority(dma_chan);
   1041 
   1042 	ipu_ch_param_dump(dma_chan);
   1043 
   1044 	reg = __raw_readl(IPU_CHA_DB_MODE_SEL(dma_chan));
   1045 	if (phyaddr_1)
   1046 		reg |= idma_mask(dma_chan);
   1047 	else
   1048 		reg &= ~idma_mask(dma_chan);
   1049 	__raw_writel(reg, IPU_CHA_DB_MODE_SEL(dma_chan));
   1050 
   1051 	/* Reset to buffer 0 */
   1052 	__raw_writel(idma_mask(dma_chan), IPU_CHA_CUR_BUF(dma_chan));
   1053 
   1054 	return 0;
   1055 }
   1056 
   1057 /*
   1058  * This function enables a logical channel.
   1059  *
   1060  * @param       channel         Input parameter for the logical channel ID.
   1061  *
   1062  * @return      This function returns 0 on success or negative error code on
   1063  *              fail.
   1064  */
   1065 int32_t ipu_enable_channel(ipu_channel_t channel)
   1066 {
   1067 	uint32_t reg;
   1068 	uint32_t in_dma;
   1069 	uint32_t out_dma;
   1070 
   1071 	if (g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) {
   1072 		printf("Warning: channel already enabled %d\n",
   1073 			IPU_CHAN_ID(channel));
   1074 	}
   1075 
   1076 	/* Get input and output dma channels */
   1077 	out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
   1078 	in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
   1079 
   1080 	if (idma_is_valid(in_dma)) {
   1081 		reg = __raw_readl(IDMAC_CHA_EN(in_dma));
   1082 		__raw_writel(reg | idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
   1083 	}
   1084 	if (idma_is_valid(out_dma)) {
   1085 		reg = __raw_readl(IDMAC_CHA_EN(out_dma));
   1086 		__raw_writel(reg | idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
   1087 	}
   1088 
   1089 	if ((channel == MEM_DC_SYNC) || (channel == MEM_BG_SYNC) ||
   1090 	    (channel == MEM_FG_SYNC))
   1091 		ipu_dp_dc_enable(channel);
   1092 
   1093 	g_channel_enable_mask |= 1L << IPU_CHAN_ID(channel);
   1094 
   1095 	return 0;
   1096 }
   1097 
   1098 /*
   1099  * This function clear buffer ready for a logical channel.
   1100  *
   1101  * @param       channel         Input parameter for the logical channel ID.
   1102  *
   1103  * @param       type            Input parameter which buffer to clear.
   1104  *
   1105  * @param       bufNum          Input parameter for which buffer number clear
   1106  *				ready state.
   1107  *
   1108  */
   1109 void ipu_clear_buffer_ready(ipu_channel_t channel, ipu_buffer_t type,
   1110 		uint32_t bufNum)
   1111 {
   1112 	uint32_t dma_ch = channel_2_dma(channel, type);
   1113 
   1114 	if (!idma_is_valid(dma_ch))
   1115 		return;
   1116 
   1117 	__raw_writel(0xF0000000, IPU_GPR); /* write one to clear */
   1118 	if (bufNum == 0) {
   1119 		if (idma_is_set(IPU_CHA_BUF0_RDY, dma_ch)) {
   1120 			__raw_writel(idma_mask(dma_ch),
   1121 					IPU_CHA_BUF0_RDY(dma_ch));
   1122 		}
   1123 	} else {
   1124 		if (idma_is_set(IPU_CHA_BUF1_RDY, dma_ch)) {
   1125 			__raw_writel(idma_mask(dma_ch),
   1126 					IPU_CHA_BUF1_RDY(dma_ch));
   1127 		}
   1128 	}
   1129 	__raw_writel(0x0, IPU_GPR); /* write one to set */
   1130 }
   1131 
   1132 /*
   1133  * This function disables a logical channel.
   1134  *
   1135  * @param       channel         Input parameter for the logical channel ID.
   1136  *
   1137  * @param       wait_for_stop   Flag to set whether to wait for channel end
   1138  *                              of frame or return immediately.
   1139  *
   1140  * @return      This function returns 0 on success or negative error code on
   1141  *              fail.
   1142  */
   1143 int32_t ipu_disable_channel(ipu_channel_t channel)
   1144 {
   1145 	uint32_t reg;
   1146 	uint32_t in_dma;
   1147 	uint32_t out_dma;
   1148 
   1149 	if ((g_channel_enable_mask & (1L << IPU_CHAN_ID(channel))) == 0) {
   1150 		debug("Channel already disabled %d\n",
   1151 			IPU_CHAN_ID(channel));
   1152 		return 0;
   1153 	}
   1154 
   1155 	/* Get input and output dma channels */
   1156 	out_dma = channel_2_dma(channel, IPU_OUTPUT_BUFFER);
   1157 	in_dma = channel_2_dma(channel, IPU_VIDEO_IN_BUFFER);
   1158 
   1159 	if ((idma_is_valid(in_dma) &&
   1160 		!idma_is_set(IDMAC_CHA_EN, in_dma))
   1161 		&& (idma_is_valid(out_dma) &&
   1162 		!idma_is_set(IDMAC_CHA_EN, out_dma)))
   1163 		return -EINVAL;
   1164 
   1165 	if ((channel == MEM_BG_SYNC) || (channel == MEM_FG_SYNC) ||
   1166 	    (channel == MEM_DC_SYNC)) {
   1167 		ipu_dp_dc_disable(channel, 0);
   1168 	}
   1169 
   1170 	/* Disable DMA channel(s) */
   1171 	if (idma_is_valid(in_dma)) {
   1172 		reg = __raw_readl(IDMAC_CHA_EN(in_dma));
   1173 		__raw_writel(reg & ~idma_mask(in_dma), IDMAC_CHA_EN(in_dma));
   1174 		__raw_writel(idma_mask(in_dma), IPU_CHA_CUR_BUF(in_dma));
   1175 	}
   1176 	if (idma_is_valid(out_dma)) {
   1177 		reg = __raw_readl(IDMAC_CHA_EN(out_dma));
   1178 		__raw_writel(reg & ~idma_mask(out_dma), IDMAC_CHA_EN(out_dma));
   1179 		__raw_writel(idma_mask(out_dma), IPU_CHA_CUR_BUF(out_dma));
   1180 	}
   1181 
   1182 	g_channel_enable_mask &= ~(1L << IPU_CHAN_ID(channel));
   1183 
   1184 	/* Set channel buffers NOT to be ready */
   1185 	if (idma_is_valid(in_dma)) {
   1186 		ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 0);
   1187 		ipu_clear_buffer_ready(channel, IPU_VIDEO_IN_BUFFER, 1);
   1188 	}
   1189 	if (idma_is_valid(out_dma)) {
   1190 		ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 0);
   1191 		ipu_clear_buffer_ready(channel, IPU_OUTPUT_BUFFER, 1);
   1192 	}
   1193 
   1194 	return 0;
   1195 }
   1196 
   1197 uint32_t bytes_per_pixel(uint32_t fmt)
   1198 {
   1199 	switch (fmt) {
   1200 	case IPU_PIX_FMT_GENERIC:	/*generic data */
   1201 	case IPU_PIX_FMT_RGB332:
   1202 	case IPU_PIX_FMT_YUV420P:
   1203 	case IPU_PIX_FMT_YUV422P:
   1204 		return 1;
   1205 		break;
   1206 	case IPU_PIX_FMT_RGB565:
   1207 	case IPU_PIX_FMT_YUYV:
   1208 	case IPU_PIX_FMT_UYVY:
   1209 		return 2;
   1210 		break;
   1211 	case IPU_PIX_FMT_BGR24:
   1212 	case IPU_PIX_FMT_RGB24:
   1213 		return 3;
   1214 		break;
   1215 	case IPU_PIX_FMT_GENERIC_32:	/*generic data */
   1216 	case IPU_PIX_FMT_BGR32:
   1217 	case IPU_PIX_FMT_BGRA32:
   1218 	case IPU_PIX_FMT_RGB32:
   1219 	case IPU_PIX_FMT_RGBA32:
   1220 	case IPU_PIX_FMT_ABGR32:
   1221 		return 4;
   1222 		break;
   1223 	default:
   1224 		return 1;
   1225 		break;
   1226 	}
   1227 	return 0;
   1228 }
   1229 
   1230 ipu_color_space_t format_to_colorspace(uint32_t fmt)
   1231 {
   1232 	switch (fmt) {
   1233 	case IPU_PIX_FMT_RGB666:
   1234 	case IPU_PIX_FMT_RGB565:
   1235 	case IPU_PIX_FMT_BGR24:
   1236 	case IPU_PIX_FMT_RGB24:
   1237 	case IPU_PIX_FMT_BGR32:
   1238 	case IPU_PIX_FMT_BGRA32:
   1239 	case IPU_PIX_FMT_RGB32:
   1240 	case IPU_PIX_FMT_RGBA32:
   1241 	case IPU_PIX_FMT_ABGR32:
   1242 	case IPU_PIX_FMT_LVDS666:
   1243 	case IPU_PIX_FMT_LVDS888:
   1244 		return RGB;
   1245 		break;
   1246 
   1247 	default:
   1248 		return YCbCr;
   1249 		break;
   1250 	}
   1251 	return RGB;
   1252 }
   1253 
   1254 /* should be removed when clk framework is availiable */
   1255 int ipu_set_ldb_clock(int rate)
   1256 {
   1257 	ldb_clk.rate = rate;
   1258 
   1259 	return 0;
   1260 }
   1261 
   1262 bool ipu_clk_enabled(void)
   1263 {
   1264 	return g_ipu_clk_enabled;
   1265 }
   1266