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@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(¶ms, 0, sizeof(params)); 825 826 ipu_ch_param_set_field(¶ms, 0, 125, 13, width - 1); 827 828 if ((ch == 8) || (ch == 9) || (ch == 10)) { 829 ipu_ch_param_set_field(¶ms, 0, 138, 12, (height / 2) - 1); 830 ipu_ch_param_set_field(¶ms, 1, 102, 14, (stride * 2) - 1); 831 } else { 832 ipu_ch_param_set_field(¶ms, 0, 138, 12, height - 1); 833 ipu_ch_param_set_field(¶ms, 1, 102, 14, stride - 1); 834 } 835 836 ipu_ch_param_set_field(¶ms, 1, 0, 29, addr0 >> 3); 837 ipu_ch_param_set_field(¶ms, 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(¶ms, 0, 107, 3, 5); /* bits/pixel */ 843 ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */ 844 ipu_ch_param_set_field(¶ms, 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(¶ms, 0, 107, 3, 3); /* bits/pixel */ 852 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ 853 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */ 854 855 ipu_ch_params_set_packing(¶ms, 5, 0, 6, 5, 5, 11, 8, 16); 856 break; 857 case IPU_PIX_FMT_BGR24: 858 ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */ 859 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ 860 ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */ 861 862 ipu_ch_params_set_packing(¶ms, 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(¶ms, 0, 107, 3, 1); /* bits/pixel */ 867 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ 868 ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */ 869 870 ipu_ch_params_set_packing(¶ms, 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(¶ms, 0, 107, 3, 0); /* bits/pixel */ 875 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ 876 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */ 877 878 ipu_ch_params_set_packing(¶ms, 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(¶ms, 0, 107, 3, 0); /* bits/pixel */ 883 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ 884 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */ 885 886 ipu_ch_params_set_packing(¶ms, 8, 24, 8, 16, 8, 8, 8, 0); 887 break; 888 case IPU_PIX_FMT_ABGR32: 889 ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */ 890 ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */ 891 892 ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24); 893 break; 894 case IPU_PIX_FMT_UYVY: 895 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */ 896 ipu_ch_param_set_field(¶ms, 1, 85, 4, 0xA); /* pix format */ 897 ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */ 898 break; 899 case IPU_PIX_FMT_YUYV: 900 ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */ 901 ipu_ch_param_set_field(¶ms, 1, 85, 4, 0x8); /* pix format */ 902 ipu_ch_param_set_field(¶ms, 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(¶ms, 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(¶ms, 1, 78, 7, 15); 916 uv_stride = uv_stride*2; 917 } else { 918 ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); 919 } 920 break; 921 case IPU_PIX_FMT_YVU422P: 922 /* BPP & pixel format */ 923 ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */ 924 ipu_ch_param_set_field(¶ms, 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(¶ms, 1, 85, 4, 1); /* pix format */ 935 ipu_ch_param_set_field(¶ms, 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(¶ms, 1, 85, 4, 4); /* pix format */ 946 ipu_ch_param_set_field(¶ms, 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(¶ms, 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(¶ms, 0, 46, 22, u_offset / 8); 972 ipu_ch_param_set_field(¶ms, 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), ¶ms, 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