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