[U-Boot] [PATCH 8/9] video: add a i.MX31 framebuffer driver only for bitmaps so far

Magnus Lilja lilja.magnus at gmail.com
Wed Feb 4 19:54:40 CET 2009


Hi

2009/2/4 Guennadi Liakhovetski <lg at 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 <lg at 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 at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot
>


Regards, Magnus


More information about the U-Boot mailing list