1 /* 2 * Copyright (C) 2009 3 * Guennadi Liakhovetski, DENX Software Engineering, <lg@denx.de> 4 * Copyright (C) 2011 5 * HALE electronic GmbH, <helmut.raiger@hale.at> 6 * 7 * See file CREDITS for list of people who contributed to this 8 * project. 9 * 10 * This program is free software; you can redistribute it and/or 11 * modify it under the terms of the GNU General Public License as 12 * published by the Free Software Foundation; either version 2 of 13 * the License, or (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 23 * MA 02111-1307 USA 24 */ 25 #include <common.h> 26 #include <malloc.h> 27 #include <video_fb.h> 28 29 #include <asm/arch/imx-regs.h> 30 #include <asm/arch/clock.h> 31 #include <asm/errno.h> 32 #include <asm/io.h> 33 34 #include "videomodes.h" 35 36 /* this might need panel specific set-up as-well */ 37 #define IF_CONF 0 38 39 /* -------------- controller specific stuff -------------- */ 40 41 /* IPU DMA Controller channel definitions. */ 42 enum ipu_channel { 43 IDMAC_IC_0 = 0, /* IC (encoding task) to memory */ 44 IDMAC_IC_1 = 1, /* IC (viewfinder task) to memory */ 45 IDMAC_ADC_0 = 1, 46 IDMAC_IC_2 = 2, 47 IDMAC_ADC_1 = 2, 48 IDMAC_IC_3 = 3, 49 IDMAC_IC_4 = 4, 50 IDMAC_IC_5 = 5, 51 IDMAC_IC_6 = 6, 52 IDMAC_IC_7 = 7, /* IC (sensor data) to memory */ 53 IDMAC_IC_8 = 8, 54 IDMAC_IC_9 = 9, 55 IDMAC_IC_10 = 10, 56 IDMAC_IC_11 = 11, 57 IDMAC_IC_12 = 12, 58 IDMAC_IC_13 = 13, 59 IDMAC_SDC_0 = 14, /* Background synchronous display data */ 60 IDMAC_SDC_1 = 15, /* Foreground data (overlay) */ 61 IDMAC_SDC_2 = 16, 62 IDMAC_SDC_3 = 17, 63 IDMAC_ADC_2 = 18, 64 IDMAC_ADC_3 = 19, 65 IDMAC_ADC_4 = 20, 66 IDMAC_ADC_5 = 21, 67 IDMAC_ADC_6 = 22, 68 IDMAC_ADC_7 = 23, 69 IDMAC_PF_0 = 24, 70 IDMAC_PF_1 = 25, 71 IDMAC_PF_2 = 26, 72 IDMAC_PF_3 = 27, 73 IDMAC_PF_4 = 28, 74 IDMAC_PF_5 = 29, 75 IDMAC_PF_6 = 30, 76 IDMAC_PF_7 = 31, 77 }; 78 79 /* More formats can be copied from the Linux driver if needed */ 80 enum pixel_fmt { 81 /* 2 bytes */ 82 IPU_PIX_FMT_RGB565, 83 IPU_PIX_FMT_RGB666, 84 IPU_PIX_FMT_BGR666, 85 /* 3 bytes */ 86 IPU_PIX_FMT_RGB24, 87 }; 88 89 struct pixel_fmt_cfg { 90 u32 b0; 91 u32 b1; 92 u32 b2; 93 u32 acc; 94 }; 95 96 static struct pixel_fmt_cfg fmt_cfg[] = { 97 [IPU_PIX_FMT_RGB24] = { 98 0x1600AAAA, 0x00E05555, 0x00070000, 3, 99 }, 100 [IPU_PIX_FMT_RGB666] = { 101 0x0005000F, 0x000B000F, 0x0011000F, 1, 102 }, 103 [IPU_PIX_FMT_BGR666] = { 104 0x0011000F, 0x000B000F, 0x0005000F, 1, 105 }, 106 [IPU_PIX_FMT_RGB565] = { 107 0x0004003F, 0x000A000F, 0x000F003F, 1, 108 } 109 }; 110 111 enum ipu_panel { 112 IPU_PANEL_SHARP_TFT, 113 IPU_PANEL_TFT, 114 }; 115 116 /* IPU Common registers */ 117 /* IPU_CONF and its bits already defined in imx-regs.h */ 118 #define IPU_CHA_BUF0_RDY (0x04 + IPU_BASE) 119 #define IPU_CHA_BUF1_RDY (0x08 + IPU_BASE) 120 #define IPU_CHA_DB_MODE_SEL (0x0C + IPU_BASE) 121 #define IPU_CHA_CUR_BUF (0x10 + IPU_BASE) 122 #define IPU_FS_PROC_FLOW (0x14 + IPU_BASE) 123 #define IPU_FS_DISP_FLOW (0x18 + IPU_BASE) 124 #define IPU_TASKS_STAT (0x1C + IPU_BASE) 125 #define IPU_IMA_ADDR (0x20 + IPU_BASE) 126 #define IPU_IMA_DATA (0x24 + IPU_BASE) 127 #define IPU_INT_CTRL_1 (0x28 + IPU_BASE) 128 #define IPU_INT_CTRL_2 (0x2C + IPU_BASE) 129 #define IPU_INT_CTRL_3 (0x30 + IPU_BASE) 130 #define IPU_INT_CTRL_4 (0x34 + IPU_BASE) 131 #define IPU_INT_CTRL_5 (0x38 + IPU_BASE) 132 #define IPU_INT_STAT_1 (0x3C + IPU_BASE) 133 #define IPU_INT_STAT_2 (0x40 + IPU_BASE) 134 #define IPU_INT_STAT_3 (0x44 + IPU_BASE) 135 #define IPU_INT_STAT_4 (0x48 + IPU_BASE) 136 #define IPU_INT_STAT_5 (0x4C + IPU_BASE) 137 #define IPU_BRK_CTRL_1 (0x50 + IPU_BASE) 138 #define IPU_BRK_CTRL_2 (0x54 + IPU_BASE) 139 #define IPU_BRK_STAT (0x58 + IPU_BASE) 140 #define IPU_DIAGB_CTRL (0x5C + IPU_BASE) 141 142 /* Image Converter Registers */ 143 #define IC_CONF (0x88 + IPU_BASE) 144 #define IC_PRP_ENC_RSC (0x8C + IPU_BASE) 145 #define IC_PRP_VF_RSC (0x90 + IPU_BASE) 146 #define IC_PP_RSC (0x94 + IPU_BASE) 147 #define IC_CMBP_1 (0x98 + IPU_BASE) 148 #define IC_CMBP_2 (0x9C + IPU_BASE) 149 #define PF_CONF (0xA0 + IPU_BASE) 150 #define IDMAC_CONF (0xA4 + IPU_BASE) 151 #define IDMAC_CHA_EN (0xA8 + IPU_BASE) 152 #define IDMAC_CHA_PRI (0xAC + IPU_BASE) 153 #define IDMAC_CHA_BUSY (0xB0 + IPU_BASE) 154 155 /* Image Converter Register bits */ 156 #define IC_CONF_PRPENC_EN 0x00000001 157 #define IC_CONF_PRPENC_CSC1 0x00000002 158 #define IC_CONF_PRPENC_ROT_EN 0x00000004 159 #define IC_CONF_PRPVF_EN 0x00000100 160 #define IC_CONF_PRPVF_CSC1 0x00000200 161 #define IC_CONF_PRPVF_CSC2 0x00000400 162 #define IC_CONF_PRPVF_CMB 0x00000800 163 #define IC_CONF_PRPVF_ROT_EN 0x00001000 164 #define IC_CONF_PP_EN 0x00010000 165 #define IC_CONF_PP_CSC1 0x00020000 166 #define IC_CONF_PP_CSC2 0x00040000 167 #define IC_CONF_PP_CMB 0x00080000 168 #define IC_CONF_PP_ROT_EN 0x00100000 169 #define IC_CONF_IC_GLB_LOC_A 0x10000000 170 #define IC_CONF_KEY_COLOR_EN 0x20000000 171 #define IC_CONF_RWS_EN 0x40000000 172 #define IC_CONF_CSI_MEM_WR_EN 0x80000000 173 174 /* SDC Registers */ 175 #define SDC_COM_CONF (0xB4 + IPU_BASE) 176 #define SDC_GW_CTRL (0xB8 + IPU_BASE) 177 #define SDC_FG_POS (0xBC + IPU_BASE) 178 #define SDC_BG_POS (0xC0 + IPU_BASE) 179 #define SDC_CUR_POS (0xC4 + IPU_BASE) 180 #define SDC_PWM_CTRL (0xC8 + IPU_BASE) 181 #define SDC_CUR_MAP (0xCC + IPU_BASE) 182 #define SDC_HOR_CONF (0xD0 + IPU_BASE) 183 #define SDC_VER_CONF (0xD4 + IPU_BASE) 184 #define SDC_SHARP_CONF_1 (0xD8 + IPU_BASE) 185 #define SDC_SHARP_CONF_2 (0xDC + IPU_BASE) 186 187 /* Register bits */ 188 #define SDC_COM_TFT_COLOR 0x00000001UL 189 #define SDC_COM_FG_EN 0x00000010UL 190 #define SDC_COM_GWSEL 0x00000020UL 191 #define SDC_COM_GLB_A 0x00000040UL 192 #define SDC_COM_KEY_COLOR_G 0x00000080UL 193 #define SDC_COM_BG_EN 0x00000200UL 194 #define SDC_COM_SHARP 0x00001000UL 195 196 #define SDC_V_SYNC_WIDTH_L 0x00000001UL 197 198 /* Display Interface registers */ 199 #define DI_DISP_IF_CONF (0x0124 + IPU_BASE) 200 #define DI_DISP_SIG_POL (0x0128 + IPU_BASE) 201 #define DI_SER_DISP1_CONF (0x012C + IPU_BASE) 202 #define DI_SER_DISP2_CONF (0x0130 + IPU_BASE) 203 #define DI_HSP_CLK_PER (0x0134 + IPU_BASE) 204 #define DI_DISP0_TIME_CONF_1 (0x0138 + IPU_BASE) 205 #define DI_DISP0_TIME_CONF_2 (0x013C + IPU_BASE) 206 #define DI_DISP0_TIME_CONF_3 (0x0140 + IPU_BASE) 207 #define DI_DISP1_TIME_CONF_1 (0x0144 + IPU_BASE) 208 #define DI_DISP1_TIME_CONF_2 (0x0148 + IPU_BASE) 209 #define DI_DISP1_TIME_CONF_3 (0x014C + IPU_BASE) 210 #define DI_DISP2_TIME_CONF_1 (0x0150 + IPU_BASE) 211 #define DI_DISP2_TIME_CONF_2 (0x0154 + IPU_BASE) 212 #define DI_DISP2_TIME_CONF_3 (0x0158 + IPU_BASE) 213 #define DI_DISP3_TIME_CONF (0x015C + IPU_BASE) 214 #define DI_DISP0_DB0_MAP (0x0160 + IPU_BASE) 215 #define DI_DISP0_DB1_MAP (0x0164 + IPU_BASE) 216 #define DI_DISP0_DB2_MAP (0x0168 + IPU_BASE) 217 #define DI_DISP0_CB0_MAP (0x016C + IPU_BASE) 218 #define DI_DISP0_CB1_MAP (0x0170 + IPU_BASE) 219 #define DI_DISP0_CB2_MAP (0x0174 + IPU_BASE) 220 #define DI_DISP1_DB0_MAP (0x0178 + IPU_BASE) 221 #define DI_DISP1_DB1_MAP (0x017C + IPU_BASE) 222 #define DI_DISP1_DB2_MAP (0x0180 + IPU_BASE) 223 #define DI_DISP1_CB0_MAP (0x0184 + IPU_BASE) 224 #define DI_DISP1_CB1_MAP (0x0188 + IPU_BASE) 225 #define DI_DISP1_CB2_MAP (0x018C + IPU_BASE) 226 #define DI_DISP2_DB0_MAP (0x0190 + IPU_BASE) 227 #define DI_DISP2_DB1_MAP (0x0194 + IPU_BASE) 228 #define DI_DISP2_DB2_MAP (0x0198 + IPU_BASE) 229 #define DI_DISP2_CB0_MAP (0x019C + IPU_BASE) 230 #define DI_DISP2_CB1_MAP (0x01A0 + IPU_BASE) 231 #define DI_DISP2_CB2_MAP (0x01A4 + IPU_BASE) 232 #define DI_DISP3_B0_MAP (0x01A8 + IPU_BASE) 233 #define DI_DISP3_B1_MAP (0x01AC + IPU_BASE) 234 #define DI_DISP3_B2_MAP (0x01B0 + IPU_BASE) 235 #define DI_DISP_ACC_CC (0x01B4 + IPU_BASE) 236 #define DI_DISP_LLA_CONF (0x01B8 + IPU_BASE) 237 #define DI_DISP_LLA_DATA (0x01BC + IPU_BASE) 238 239 /* DI_DISP_SIG_POL bits */ 240 #define DI_D3_VSYNC_POL (1 << 28) 241 #define DI_D3_HSYNC_POL (1 << 27) 242 #define DI_D3_DRDY_SHARP_POL (1 << 26) 243 #define DI_D3_CLK_POL (1 << 25) 244 #define DI_D3_DATA_POL (1 << 24) 245 246 /* DI_DISP_IF_CONF bits */ 247 #define DI_D3_CLK_IDLE (1 << 26) 248 #define DI_D3_CLK_SEL (1 << 25) 249 #define DI_D3_DATAMSK (1 << 24) 250 251 #define IOMUX_PADNUM_MASK 0x1ff 252 #define IOMUX_GPIONUM_SHIFT 9 253 #define IOMUX_GPIONUM_MASK (0xff << IOMUX_GPIONUM_SHIFT) 254 255 #define IOMUX_PIN(gpionum, padnum) ((padnum) & IOMUX_PADNUM_MASK) 256 257 #define IOMUX_MODE_L(pin, mode) IOMUX_MODE(((pin) + 0xc) ^ 3, mode) 258 259 struct chan_param_mem_planar { 260 /* Word 0 */ 261 u32 xv:10; 262 u32 yv:10; 263 u32 xb:12; 264 265 u32 yb:12; 266 u32 res1:2; 267 u32 nsb:1; 268 u32 lnpb:6; 269 u32 ubo_l:11; 270 271 u32 ubo_h:15; 272 u32 vbo_l:17; 273 274 u32 vbo_h:9; 275 u32 res2:3; 276 u32 fw:12; 277 u32 fh_l:8; 278 279 u32 fh_h:4; 280 u32 res3:28; 281 282 /* Word 1 */ 283 u32 eba0; 284 285 u32 eba1; 286 287 u32 bpp:3; 288 u32 sl:14; 289 u32 pfs:3; 290 u32 bam:3; 291 u32 res4:2; 292 u32 npb:6; 293 u32 res5:1; 294 295 u32 sat:2; 296 u32 res6:30; 297 } __attribute__ ((packed)); 298 299 struct chan_param_mem_interleaved { 300 /* Word 0 */ 301 u32 xv:10; 302 u32 yv:10; 303 u32 xb:12; 304 305 u32 yb:12; 306 u32 sce:1; 307 u32 res1:1; 308 u32 nsb:1; 309 u32 lnpb:6; 310 u32 sx:10; 311 u32 sy_l:1; 312 313 u32 sy_h:9; 314 u32 ns:10; 315 u32 sm:10; 316 u32 sdx_l:3; 317 318 u32 sdx_h:2; 319 u32 sdy:5; 320 u32 sdrx:1; 321 u32 sdry:1; 322 u32 sdr1:1; 323 u32 res2:2; 324 u32 fw:12; 325 u32 fh_l:8; 326 327 u32 fh_h:4; 328 u32 res3:28; 329 330 /* Word 1 */ 331 u32 eba0; 332 333 u32 eba1; 334 335 u32 bpp:3; 336 u32 sl:14; 337 u32 pfs:3; 338 u32 bam:3; 339 u32 res4:2; 340 u32 npb:6; 341 u32 res5:1; 342 343 u32 sat:2; 344 u32 scc:1; 345 u32 ofs0:5; 346 u32 ofs1:5; 347 u32 ofs2:5; 348 u32 ofs3:5; 349 u32 wid0:3; 350 u32 wid1:3; 351 u32 wid2:3; 352 353 u32 wid3:3; 354 u32 dec_sel:1; 355 u32 res6:28; 356 } __attribute__ ((packed)); 357 358 union chan_param_mem { 359 struct chan_param_mem_planar pp; 360 struct chan_param_mem_interleaved ip; 361 }; 362 363 DECLARE_GLOBAL_DATA_PTR; 364 365 /* graphics setup */ 366 static GraphicDevice panel; 367 static struct ctfb_res_modes *mode; 368 static struct ctfb_res_modes var_mode; 369 370 /* 371 * sdc_init_panel() - initialize a synchronous LCD panel. 372 * @width: width of panel in pixels. 373 * @height: height of panel in pixels. 374 * @di_setup: pixel format of the frame buffer 375 * @di_panel: either SHARP or normal TFT 376 * @return: 0 on success or negative error code on failure. 377 */ 378 static int sdc_init_panel(u16 width, u16 height, 379 enum pixel_fmt di_setup, enum ipu_panel di_panel) 380 { 381 u32 reg, div; 382 uint32_t old_conf; 383 int clock; 384 385 debug("%s(width=%d, height=%d)\n", __func__, width, height); 386 387 /* Init clocking, the IPU receives its clock from the hsp divder */ 388 clock = mxc_get_clock(MXC_IPU_CLK); 389 if (clock < 0) 390 return -EACCES; 391 392 /* Init panel size and blanking periods */ 393 reg = width + mode->left_margin + mode->right_margin - 1; 394 if (reg > 1023) { 395 printf("mx3fb: Display width too large, coerced to 1023!"); 396 reg = 1023; 397 } 398 reg = ((mode->hsync_len - 1) << 26) | (reg << 16); 399 writel(reg, SDC_HOR_CONF); 400 401 reg = height + mode->upper_margin + mode->lower_margin - 1; 402 if (reg > 1023) { 403 printf("mx3fb: Display height too large, coerced to 1023!"); 404 reg = 1023; 405 } 406 reg = ((mode->vsync_len - 1) << 26) | SDC_V_SYNC_WIDTH_L | (reg << 16); 407 writel(reg, SDC_VER_CONF); 408 409 switch (di_panel) { 410 case IPU_PANEL_SHARP_TFT: 411 writel(0x00FD0102L, SDC_SHARP_CONF_1); 412 writel(0x00F500F4L, SDC_SHARP_CONF_2); 413 writel(SDC_COM_SHARP | SDC_COM_TFT_COLOR, SDC_COM_CONF); 414 /* TODO: probably IF_CONF must be adapted (see below)! */ 415 break; 416 case IPU_PANEL_TFT: 417 writel(SDC_COM_TFT_COLOR, SDC_COM_CONF); 418 break; 419 default: 420 return -EINVAL; 421 } 422 423 /* 424 * Calculate divider: The fractional part is 4 bits so simply 425 * multiple by 2^4 to get it. 426 * 427 * Opposed to the kernel driver mode->pixclock is the time of one 428 * pixel in pico seconds, so: 429 * pixel_clk = 1e12 / mode->pixclock 430 * div = ipu_clk * 16 / pixel_clk 431 * leads to: 432 * div = ipu_clk * 16 / (1e12 / mode->pixclock) 433 * or: 434 * div = ipu_clk * 16 * mode->pixclock / 1e12 435 * 436 * To avoid integer overflows this is split into 2 shifts and 437 * one divide with sufficient accuracy: 438 * 16*1024*128*476837 = 0.9999996682e12 439 */ 440 div = ((clock/1024) * (mode->pixclock/128)) / 476837; 441 debug("hsp_clk is %d, div=%d\n", clock, div); 442 /* coerce to not less than 4.0, not more than 255.9375 */ 443 if (div < 0x40) 444 div = 0x40; 445 else if (div > 0xFFF) 446 div = 0xFFF; 447 /* DISP3_IF_CLK_DOWN_WR is half the divider value and 2 less 448 * fraction bits. Subtract 1 extra from DISP3_IF_CLK_DOWN_WR 449 * based on timing debug DISP3_IF_CLK_UP_WR is 0 450 */ 451 writel((((div / 8) - 1) << 22) | div, DI_DISP3_TIME_CONF); 452 453 /* DI settings for display 3: clock idle (bit 26) during vsync */ 454 old_conf = readl(DI_DISP_IF_CONF) & 0x78FFFFFF; 455 writel(old_conf | IF_CONF, DI_DISP_IF_CONF); 456 457 /* only set display 3 polarity bits */ 458 old_conf = readl(DI_DISP_SIG_POL) & 0xE0FFFFFF; 459 writel(old_conf | mode->sync, DI_DISP_SIG_POL); 460 461 writel(fmt_cfg[di_setup].b0, DI_DISP3_B0_MAP); 462 writel(fmt_cfg[di_setup].b1, DI_DISP3_B1_MAP); 463 writel(fmt_cfg[di_setup].b2, DI_DISP3_B2_MAP); 464 writel(readl(DI_DISP_ACC_CC) | 465 ((fmt_cfg[di_setup].acc - 1) << 12), DI_DISP_ACC_CC); 466 467 debug("DI_DISP_IF_CONF = 0x%08X\n", readl(DI_DISP_IF_CONF)); 468 debug("DI_DISP_SIG_POL = 0x%08X\n", readl(DI_DISP_SIG_POL)); 469 debug("DI_DISP3_TIME_CONF = 0x%08X\n", readl(DI_DISP3_TIME_CONF)); 470 debug("SDC_HOR_CONF = 0x%08X\n", readl(SDC_HOR_CONF)); 471 debug("SDC_VER_CONF = 0x%08X\n", readl(SDC_VER_CONF)); 472 473 return 0; 474 } 475 476 static void ipu_ch_param_set_size(union chan_param_mem *params, 477 uint pixelfmt, uint16_t width, 478 uint16_t height, uint16_t stride) 479 { 480 debug("%s(pixelfmt=%d, width=%d, height=%d, stride=%d)\n", 481 __func__, pixelfmt, width, height, stride); 482 483 params->pp.fw = width - 1; 484 params->pp.fh_l = height - 1; 485 params->pp.fh_h = (height - 1) >> 8; 486 params->pp.sl = stride - 1; 487 488 /* See above, for further formats see the Linux driver */ 489 switch (pixelfmt) { 490 case GDF_16BIT_565RGB: 491 params->ip.bpp = 2; 492 params->ip.pfs = 4; 493 params->ip.npb = 7; 494 params->ip.sat = 2; /* SAT = 32-bit access */ 495 params->ip.ofs0 = 0; /* Red bit offset */ 496 params->ip.ofs1 = 5; /* Green bit offset */ 497 params->ip.ofs2 = 11; /* Blue bit offset */ 498 params->ip.ofs3 = 16; /* Alpha bit offset */ 499 params->ip.wid0 = 4; /* Red bit width - 1 */ 500 params->ip.wid1 = 5; /* Green bit width - 1 */ 501 params->ip.wid2 = 4; /* Blue bit width - 1 */ 502 break; 503 case GDF_32BIT_X888RGB: 504 params->ip.bpp = 1; /* 24 BPP & RGB PFS */ 505 params->ip.pfs = 4; 506 params->ip.npb = 7; 507 params->ip.sat = 2; /* SAT = 32-bit access */ 508 params->ip.ofs0 = 16; /* Red bit offset */ 509 params->ip.ofs1 = 8; /* Green bit offset */ 510 params->ip.ofs2 = 0; /* Blue bit offset */ 511 params->ip.ofs3 = 24; /* Alpha bit offset */ 512 params->ip.wid0 = 7; /* Red bit width - 1 */ 513 params->ip.wid1 = 7; /* Green bit width - 1 */ 514 params->ip.wid2 = 7; /* Blue bit width - 1 */ 515 break; 516 default: 517 printf("mx3fb: Pixel format not supported!\n"); 518 break; 519 } 520 521 params->pp.nsb = 1; 522 } 523 524 static void ipu_ch_param_set_buffer(union chan_param_mem *params, 525 void *buf0, void *buf1) 526 { 527 params->pp.eba0 = (u32)buf0; 528 params->pp.eba1 = (u32)buf1; 529 } 530 531 static void ipu_write_param_mem(uint32_t addr, uint32_t *data, 532 uint32_t num_words) 533 { 534 for (; num_words > 0; num_words--) { 535 writel(addr, IPU_IMA_ADDR); 536 writel(*data++, IPU_IMA_DATA); 537 addr++; 538 if ((addr & 0x7) == 5) { 539 addr &= ~0x7; /* set to word 0 */ 540 addr += 8; /* increment to next row */ 541 } 542 } 543 } 544 545 static uint32_t dma_param_addr(enum ipu_channel channel) 546 { 547 /* Channel Parameter Memory */ 548 return 0x10000 | (channel << 4); 549 } 550 551 static void ipu_init_channel_buffer(enum ipu_channel channel, void *fbmem) 552 { 553 union chan_param_mem params = {}; 554 uint32_t reg; 555 uint32_t stride_bytes; 556 557 stride_bytes = (panel.plnSizeX * panel.gdfBytesPP + 3) & ~3; 558 559 debug("%s(channel=%d, fbmem=%p)\n", __func__, channel, fbmem); 560 561 /* Build parameter memory data for DMA channel */ 562 ipu_ch_param_set_size(¶ms, panel.gdfIndex, 563 panel.plnSizeX, panel.plnSizeY, stride_bytes); 564 ipu_ch_param_set_buffer(¶ms, fbmem, NULL); 565 params.pp.bam = 0; 566 /* Some channels (rotation) have restriction on burst length */ 567 568 switch (channel) { 569 case IDMAC_SDC_0: 570 /* In original code only IPU_PIX_FMT_RGB565 was setting burst */ 571 params.pp.npb = 16 - 1; 572 break; 573 default: 574 break; 575 } 576 577 ipu_write_param_mem(dma_param_addr(channel), (uint32_t *)¶ms, 10); 578 579 /* Disable double-buffering */ 580 reg = readl(IPU_CHA_DB_MODE_SEL); 581 reg &= ~(1UL << channel); 582 writel(reg, IPU_CHA_DB_MODE_SEL); 583 } 584 585 static void ipu_channel_set_priority(enum ipu_channel channel, 586 int prio) 587 { 588 u32 reg = readl(IDMAC_CHA_PRI); 589 590 if (prio) 591 reg |= 1UL << channel; 592 else 593 reg &= ~(1UL << channel); 594 595 writel(reg, IDMAC_CHA_PRI); 596 } 597 598 /* 599 * ipu_enable_channel() - enable an IPU channel. 600 * @channel: channel ID. 601 * @return: 0 on success or negative error code on failure. 602 */ 603 static int ipu_enable_channel(enum ipu_channel channel) 604 { 605 uint32_t reg; 606 607 /* Reset to buffer 0 */ 608 writel(1UL << channel, IPU_CHA_CUR_BUF); 609 610 switch (channel) { 611 case IDMAC_SDC_0: 612 ipu_channel_set_priority(channel, 1); 613 break; 614 default: 615 break; 616 } 617 618 reg = readl(IDMAC_CHA_EN); 619 writel(reg | (1UL << channel), IDMAC_CHA_EN); 620 621 return 0; 622 } 623 624 static int ipu_update_channel_buffer(enum ipu_channel channel, void *buf) 625 { 626 uint32_t reg; 627 628 reg = readl(IPU_CHA_BUF0_RDY); 629 if (reg & (1UL << channel)) 630 return -EACCES; 631 632 /* 44.3.3.1.9 - Row Number 1 (WORD1, offset 0) */ 633 writel(dma_param_addr(channel) + 0x0008UL, IPU_IMA_ADDR); 634 writel((u32)buf, IPU_IMA_DATA); 635 636 return 0; 637 } 638 639 static int idmac_tx_submit(enum ipu_channel channel, void *buf) 640 { 641 int ret; 642 643 ipu_init_channel_buffer(channel, buf); 644 645 646 /* ipu_idmac.c::ipu_submit_channel_buffers() */ 647 ret = ipu_update_channel_buffer(channel, buf); 648 if (ret < 0) 649 return ret; 650 651 /* ipu_idmac.c::ipu_select_buffer() */ 652 /* Mark buffer 0 as ready. */ 653 writel(1UL << channel, IPU_CHA_BUF0_RDY); 654 655 656 ret = ipu_enable_channel(channel); 657 return ret; 658 } 659 660 static void sdc_enable_channel(void *fbmem) 661 { 662 int ret; 663 u32 reg; 664 665 ret = idmac_tx_submit(IDMAC_SDC_0, fbmem); 666 667 /* mx3fb.c::sdc_fb_init() */ 668 if (ret >= 0) { 669 reg = readl(SDC_COM_CONF); 670 writel(reg | SDC_COM_BG_EN, SDC_COM_CONF); 671 } 672 673 /* 674 * Attention! Without this msleep the channel keeps generating 675 * interrupts. Next sdc_set_brightness() is going to be called 676 * from mx3fb_blank(). 677 */ 678 udelay(2000); 679 } 680 681 /* 682 * mx3fb_set_par() - set framebuffer parameters and change the operating mode. 683 * @return: 0 on success or negative error code on failure. 684 * TODO: currently only 666 and TFT as DI setup supported 685 */ 686 static int mx3fb_set_par(void) 687 { 688 int ret; 689 690 ret = sdc_init_panel(panel.plnSizeX, panel.plnSizeY, 691 IPU_PIX_FMT_RGB666, IPU_PANEL_TFT); 692 if (ret < 0) 693 return ret; 694 695 writel((mode->left_margin << 16) | mode->upper_margin, SDC_BG_POS); 696 697 return 0; 698 } 699 700 static void ll_disp3_enable(void *base) 701 { 702 u32 reg; 703 704 debug("%s(base=0x%x)\n", __func__, (u32) base); 705 /* pcm037.c::mxc_board_init() */ 706 707 /* Display Interface #3 */ 708 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD0, MUX_CTL_FUNC)); 709 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD1, MUX_CTL_FUNC)); 710 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD2, MUX_CTL_FUNC)); 711 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD3, MUX_CTL_FUNC)); 712 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD4, MUX_CTL_FUNC)); 713 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD5, MUX_CTL_FUNC)); 714 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD6, MUX_CTL_FUNC)); 715 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD7, MUX_CTL_FUNC)); 716 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD8, MUX_CTL_FUNC)); 717 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD9, MUX_CTL_FUNC)); 718 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD10, MUX_CTL_FUNC)); 719 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD11, MUX_CTL_FUNC)); 720 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD12, MUX_CTL_FUNC)); 721 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD13, MUX_CTL_FUNC)); 722 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD14, MUX_CTL_FUNC)); 723 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD15, MUX_CTL_FUNC)); 724 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD16, MUX_CTL_FUNC)); 725 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD17, MUX_CTL_FUNC)); 726 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_VSYNC3, MUX_CTL_FUNC)); 727 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_HSYNC, MUX_CTL_FUNC)); 728 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_FPSHIFT, MUX_CTL_FUNC)); 729 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_DRDY0, MUX_CTL_FUNC)); 730 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_REV, MUX_CTL_FUNC)); 731 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_CONTRAST, MUX_CTL_FUNC)); 732 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_SPL, MUX_CTL_FUNC)); 733 mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_CLS, MUX_CTL_FUNC)); 734 735 736 /* ipu_idmac.c::ipu_probe() */ 737 738 /* Start the clock */ 739 __REG(CCM_CGR1) = __REG(CCM_CGR1) | (3 << 22); 740 741 742 /* ipu_idmac.c::ipu_idmac_init() */ 743 744 /* Service request counter to maximum - shouldn't be needed */ 745 writel(0x00000070, IDMAC_CONF); 746 747 748 /* ipu_idmac.c::ipu_init_channel() */ 749 750 /* Enable IPU sub modules */ 751 reg = readl(IPU_CONF) | IPU_CONF_SDC_EN | IPU_CONF_DI_EN; 752 writel(reg, IPU_CONF); 753 754 755 /* mx3fb.c::init_fb_chan() */ 756 757 /* set Display Interface clock period */ 758 writel(0x00100010L, DI_HSP_CLK_PER); 759 /* Might need to trigger HSP clock change - see 44.3.3.8.5 */ 760 761 762 /* mx3fb.c::sdc_set_brightness() */ 763 764 /* This might be board-specific */ 765 writel(0x03000000UL | 255 << 16, SDC_PWM_CTRL); 766 767 768 /* mx3fb.c::sdc_set_global_alpha() */ 769 770 /* Use global - not per-pixel - Alpha-blending */ 771 reg = readl(SDC_GW_CTRL) & 0x00FFFFFFL; 772 writel(reg | ((uint32_t) 0xff << 24), SDC_GW_CTRL); 773 774 reg = readl(SDC_COM_CONF); 775 writel(reg | SDC_COM_GLB_A, SDC_COM_CONF); 776 777 778 /* mx3fb.c::sdc_set_color_key() */ 779 780 /* Disable colour-keying for background */ 781 reg = readl(SDC_COM_CONF) & 782 ~(SDC_COM_GWSEL | SDC_COM_KEY_COLOR_G); 783 writel(reg, SDC_COM_CONF); 784 785 786 mx3fb_set_par(); 787 788 sdc_enable_channel(base); 789 790 /* 791 * Linux driver calls sdc_set_brightness() here again, 792 * once is enough for us 793 */ 794 debug("%s() done\n", __func__); 795 } 796 797 /* ------------------------ public part ------------------- */ 798 ulong calc_fbsize(void) 799 { 800 return panel.plnSizeX * panel.plnSizeY * panel.gdfBytesPP; 801 } 802 803 /* 804 * The current implementation is only tested for GDF_16BIT_565RGB! 805 * It was switched from the original CONFIG_LCD setup to CONFIG_VIDEO, 806 * because the lcd code seemed loaded with color table stuff, that 807 * does not relate to most modern TFTs. cfb_console.c looks more 808 * straight forward. 809 * This is the environment setting for the original setup 810 * "unknown=video=ctfb:x:240,y:320,depth:16,mode:0,pclk:185925,le:9,ri:17, 811 * up:7,lo:10,hs:1,vs:1,sync:100663296,vmode:0" 812 * "videomode=unknown" 813 * 814 * Settings for VBEST VGG322403 display: 815 * "videomode=video=ctfb:x:320,y:240,depth:16,mode:0,pclk:156000, 816 * "le:20,ri:68,up:7,lo:29,hs:30,vs:3,sync:100663296,vmode:0" 817 * 818 * Settings for COM57H5M10XRC display: 819 * "videomode=video=ctfb:x:640,y:480,depth:16,mode:0,pclk:40000, 820 * "le:120,ri:40,up:35,lo:10,hs:30,vs:3,sync:100663296,vmode:0" 821 */ 822 void *video_hw_init(void) 823 { 824 char *penv; 825 u32 memsize; 826 unsigned long t1, hsynch, vsynch; 827 int bits_per_pixel, i, tmp, videomode; 828 829 tmp = 0; 830 831 puts("Video: "); 832 833 videomode = CONFIG_SYS_DEFAULT_VIDEO_MODE; 834 /* get video mode via environment */ 835 penv = getenv("videomode"); 836 if (penv) { 837 /* decide if it is a string */ 838 if (penv[0] <= '9') { 839 videomode = (int) simple_strtoul(penv, NULL, 16); 840 tmp = 1; 841 } 842 } else { 843 tmp = 1; 844 } 845 if (tmp) { 846 /* parameter are vesa modes */ 847 /* search params */ 848 for (i = 0; i < VESA_MODES_COUNT; i++) { 849 if (vesa_modes[i].vesanr == videomode) 850 break; 851 } 852 if (i == VESA_MODES_COUNT) { 853 printf("No VESA Mode found, switching to mode 0x%x ", 854 CONFIG_SYS_DEFAULT_VIDEO_MODE); 855 i = 0; 856 } 857 mode = (struct ctfb_res_modes *) 858 &res_mode_init[vesa_modes[i].resindex]; 859 bits_per_pixel = vesa_modes[i].bits_per_pixel; 860 } else { 861 mode = (struct ctfb_res_modes *) &var_mode; 862 bits_per_pixel = video_get_params(mode, penv); 863 } 864 865 /* calculate hsynch and vsynch freq (info only) */ 866 t1 = (mode->left_margin + mode->xres + 867 mode->right_margin + mode->hsync_len) / 8; 868 t1 *= 8; 869 t1 *= mode->pixclock; 870 t1 /= 1000; 871 hsynch = 1000000000L / t1; 872 t1 *= (mode->upper_margin + mode->yres + 873 mode->lower_margin + mode->vsync_len); 874 t1 /= 1000; 875 vsynch = 1000000000L / t1; 876 877 /* fill in Graphic device struct */ 878 sprintf(panel.modeIdent, "%dx%dx%d %ldkHz %ldHz", 879 mode->xres, mode->yres, 880 bits_per_pixel, (hsynch / 1000), (vsynch / 1000)); 881 printf("%s\n", panel.modeIdent); 882 panel.winSizeX = mode->xres; 883 panel.winSizeY = mode->yres; 884 panel.plnSizeX = mode->xres; 885 panel.plnSizeY = mode->yres; 886 887 switch (bits_per_pixel) { 888 case 24: 889 panel.gdfBytesPP = 4; 890 panel.gdfIndex = GDF_32BIT_X888RGB; 891 break; 892 case 16: 893 panel.gdfBytesPP = 2; 894 panel.gdfIndex = GDF_16BIT_565RGB; 895 break; 896 default: 897 panel.gdfBytesPP = 1; 898 panel.gdfIndex = GDF__8BIT_INDEX; 899 break; 900 } 901 902 /* set up Hardware */ 903 memsize = calc_fbsize(); 904 905 debug("%s() allocating %d bytes\n", __func__, memsize); 906 907 /* fill in missing Graphic device struct */ 908 panel.frameAdrs = (u32) malloc(memsize); 909 if (panel.frameAdrs == 0) { 910 printf("%s() malloc(%d) failed\n", __func__, memsize); 911 return 0; 912 } 913 panel.memSize = memsize; 914 915 ll_disp3_enable((void *) panel.frameAdrs); 916 memset((void *) panel.frameAdrs, 0, memsize); 917 918 debug("%s() done, framebuffer at 0x%x, size=%d cleared\n", 919 __func__, panel.frameAdrs, memsize); 920 921 return (void *) &panel; 922 } 923 924 void video_set_lut(unsigned int index, /* color number */ 925 unsigned char r, /* red */ 926 unsigned char g, /* green */ 927 unsigned char b /* blue */ 928 ) 929 { 930 return; 931 } 932