Hi 2009/2/4 Guennadi Liakhovetski <l...@denx.de>: > Add a driver for the Synchronous Display Controller and the Display > Interface on i.MX31, using IPU for DMA channel setup. So far only > displaying of bitmaps is supported, no text output. > > Signed-off-by: Guennadi Liakhovetski <l...@denx.de> > --- > drivers/video/Makefile | 1 + > drivers/video/mx3fb.c | 865 > ++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 866 insertions(+), 0 deletions(-) > create mode 100644 drivers/video/mx3fb.c .... > +/** > + * ipu_enable_channel() - enable an IPU channel. > + * @channel: channel ID. > + * @return: 0 on success or negative error code on failure. > + */ > +static int ipu_enable_channel(enum ipu_channel channel) > +{ > + uint32_t reg; > + > + /* Reset to buffer 0 */ > + reg_write(1UL << channel, IPU_CHA_CUR_BUF); > + > + switch (channel) { > + case IDMAC_SDC_0: > + ipu_channel_set_priority(channel, 1);
Missing break? > + default: > + break; > + } > + > + reg = reg_read(IDMAC_CHA_EN); > + reg_write(reg | (1UL << channel), IDMAC_CHA_EN); > + > + return 0; > +} > + > +static int ipu_update_channel_buffer(enum ipu_channel channel, void *buf) > +{ > + uint32_t reg; > + > + reg = reg_read(IPU_CHA_BUF0_RDY); > + if (reg & (1UL << channel)) > + return -EACCES; > + > + /* 44.3.3.1.9 - Row Number 1 (WORD1, offset 0) */ > + reg_write(dma_param_addr(channel) + 0x0008UL, IPU_IMA_ADDR); > + reg_write((u32)buf, IPU_IMA_DATA); > + > + return 0; > +} > + > +static int idmac_tx_submit(enum ipu_channel channel, void *buf) > +{ > + int ret; > + > + ipu_init_channel_buffer(channel, buf); > + > + > + /* ipu_idmac.c::ipu_submit_channel_buffers() */ > + ret = ipu_update_channel_buffer(channel, buf); > + if (ret < 0) > + return ret; > + > + /* ipu_idmac.c::ipu_select_buffer() */ > + /* Mark buffer 0 as ready. */ > + reg_write(1UL << channel, IPU_CHA_BUF0_RDY); > + > + > + ret = ipu_enable_channel(channel); > + return ret; > +} > + > +static void sdc_enable_channel(void *fbmem) > +{ > + int ret; > + u32 reg; > + > + ret = idmac_tx_submit(IDMAC_SDC_0, fbmem); > + > + /* mx3fb.c::sdc_fb_init() */ > + if (ret >= 0) { > + reg = reg_read(SDC_COM_CONF); > + reg_write(reg | SDC_COM_BG_EN, SDC_COM_CONF); > + } > + > + /* > + * Attention! Without this msleep the channel keeps generating > + * interrupts. Next sdc_set_brightness() is going to be called > + * from mx3fb_blank(). > + */ > + msleep(2); > +} > + > +/** > + * mx3fb_set_par() - set framebuffer parameters and change the operating > mode. > + * @fbi: framebuffer information pointer. > + * @return: 0 on success or negative error code on failure. > + */ > +static int mx3fb_set_par(void *fbmem) > +{ > + int ret; > + > + ret = sdc_init_panel(XRES, YRES, PIXEL_FMT); > + if (ret < 0) > + return ret; > + > + reg_write((H_START_WIDTH << 16) | V_START_WIDTH, SDC_BG_POS); > + > + return 0; > +} > + > +/* References in this function refer to respective Linux kernel sources */ > +void lcd_enable (void) > +{ > + u32 reg; > + > + /* pcm037.c::mxc_board_init() */ Strance comment in a generic file. > + > + /* Display Interface #3 */ > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD0, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD1, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD2, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD3, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD4, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD5, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD6, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD7, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD8, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD9, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD10, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD11, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD12, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD13, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD14, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD15, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD16, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_LD17, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_VSYNC3, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_HSYNC, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_FPSHIFT, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_DRDY0, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_REV, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_CONTRAST, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_SPL, MUX_CTL_FUNC)); > + mx31_gpio_mux(IOMUX_MODE_L(MX31_PIN_D3_CLS, MUX_CTL_FUNC)); The above seems board specific, although most of these pins can only function as IPU pins or SDMA_DEBUG. > + > + > + /* ipu_idmac.c::ipu_probe() */ More odd comments in this functions (more below). > + > + /* Start the clock */ > + __REG(CCM_CGR1) = __REG(CCM_CGR1) | (3 << 22); > + > + > + /* ipu_idmac.c::ipu_idmac_init() */ > + > + /* Service request counter to maximum - shouldn't be needed */ > + reg_write(0x00000070, IDMAC_CONF); > + > + > + /* ipu_idmac.c::ipu_init_channel() */ > + > + /* Enable IPU sub modules */ > + reg = reg_read(IPU_CONF) | IPU_CONF_SDC_EN | IPU_CONF_DI_EN; > + reg_write(reg, IPU_CONF); > + > + > + /* mx3fb.c::init_fb_chan() */ > + > + /* set Display Interface clock period */ > + reg_write(0x00100010L, DI_HSP_CLK_PER); > + /* Might need to trigger HSP clock change - see 44.3.3.8.5 */ > + > + > + /* mx3fb.c::sdc_set_brightness() */ > + > + /* This might be board-specific */ > + reg_write(0x03000000UL | 255 << 16, SDC_PWM_CTRL); > + > + > + /* mx3fb.c::sdc_set_global_alpha() */ > + > + /* Use global - not per-pixel - Alpha-blending */ > + reg = reg_read(SDC_GW_CTRL) & 0x00FFFFFFL; > + reg_write(reg | ((uint32_t) 0xff << 24), SDC_GW_CTRL); > + > + reg = reg_read(SDC_COM_CONF); > + reg_write(reg | SDC_COM_GLB_A, SDC_COM_CONF); > + > + > + /* mx3fb.c::sdc_set_color_key() */ > + > + /* Disable colour-keying for background */ > + reg = reg_read(SDC_COM_CONF) & > + ~(SDC_COM_GWSEL | SDC_COM_KEY_COLOR_G); > + reg_write(reg, SDC_COM_CONF); > + > + > + mx3fb_set_par(lcd_base); > + > + sdc_enable_channel(lcd_base); > + > + /* Linux driver calls sdc_set_brightness() here again, once is enough > for us */ > +} > + > +void lcd_ctrl_init(void *lcdbase) > +{ > + u32 mem_len = XRES * YRES * BIT_PER_PIXEL / 8; > + /* > + * We rely on fbmem being a physical address, i.e., either MMU off, > + * or 1-to-1 mapping. Might want to add some virt2phys here. > + */ > + if (!lcdbase) > + return; > + > + memset(lcdbase, 0, mem_len); > +} > + > +ulong calc_fbsize(void) > +{ > + return ((panel_info.vl_col * panel_info.vl_row * > + NBITS(panel_info.vl_bpix)) / 8) + PAGE_SIZE; > +} > + > +int overwrite_console (void) > +{ > + /* Keep stdout / stderr on serial, our LCD is for splashscreen only */ > + return 1; > +} > -- > 1.5.4 > > _______________________________________________ > U-Boot mailing list > U-Boot@lists.denx.de > http://lists.denx.de/mailman/listinfo/u-boot > Regards, Magnus _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot