Ejemplo n.º 1
0
void lcd_set_contrast(int val)
{
    // NOTE: this should not interfere with lcd_update_rect
    imx233_lcdif_wait_ready();
    imx233_lcdif_set_word_length(8);
    // set contrast
    lcd_send(false, 0xc7); lcd_send(true, val);
}
Ejemplo n.º 2
0
void lcd_update_rect(int x, int y, int w, int h)
{
    #ifdef HAVE_LCD_ENABLE
    if(!lcd_on)
        return;
    #endif

    imx233_lcdif_wait_ready();
    lcd_write_reg(0x16, x | (x + w - 1) << 8);
    lcd_write_reg(0x17, y | (y + h - 1) << 8);
    lcd_write_reg(0x21, y * LCD_WIDTH + x);
    lcd_write_reg(0x22, 0);
    for(int yy = y; yy < y + h; yy++)
        imx233_lcdif_pio_send(true, 2 * w, FBADDR(x, yy));
}
Ejemplo n.º 3
0
// bbp = bytes per pixel
static void pio_send(unsigned len, unsigned bpp, uint8_t *buf)
{
    /* WARNING: the imx233 has a limitation on count wrt to byte packing, the
     * count must be a multiple of 2 with maximum packing when word-length is
     * 16-bit!
     * On the other hand, 8-bit word length doesn't seem to have any limitations,
     * for example one can send 3 bytes with a packing format of 0xf
     * WARNING for this function to work properly with any swizzle, we have to
     * make sure we pack as many 32-bits as possible even when the data is not
     * word-aligned */
    imx233_lcdif_set_byte_packing_format(0xf);
    /* compute shift between buf and next word-aligned pointer */
    int shift = 0;
    uint32_t temp_buf = 0;
    int count = len * bpp; // number of bytes
    while(0x3 & (intptr_t)buf)
    {
        temp_buf = temp_buf | *buf++ << shift;
        shift += 8;
        count--;
    }
    /* starting from now, all read are 32-bit */
    uint32_t *wbuf = (void *)buf;
#if IMX233_SUBTARGET >= 3780
    HW_LCDIF_TRANSFER_COUNT = BF_OR2(LCDIF_TRANSFER_COUNT, V_COUNT(1), H_COUNT(len));
#else
    BF_WR(LCDIF_CTRL, COUNT, len);
#endif
    BF_SET(LCDIF_CTRL, RUN);
    while(count > 0)
    {
        uint32_t val = *wbuf++;
        imx233_lcdif_wait_fifo();
        HW_LCDIF_DATA = temp_buf | val << shift;
        if(shift != 0)
            temp_buf = val >> (32 - shift);
        count -= 4;
    }
    /* send remaining bytes if any */
    if(shift != 0)
    {
        imx233_lcdif_wait_fifo();
        HW_LCDIF_DATA = temp_buf;
    }
    imx233_lcdif_wait_ready();
}
Ejemplo n.º 4
0
void lcd_update_rect(int x, int y, int w, int h)
{
    #ifdef HAVE_LCD_ENABLE
    if(!lcd_on)
        return;
    #endif

    imx233_lcdif_wait_ready();
    imx233_lcdif_set_word_length(8);
    // set column address
    lcd_send(false, 0x15); lcd_send(true, x); lcd_send(true, x + w - 1);
    // set row address
    lcd_send(false, 0x75); lcd_send(true, y); lcd_send(true, y + h - 1);
    lcd_send(false, 0x5c);
    imx233_lcdif_set_word_length(16);
    for(int yy = y; yy < y + h; yy++)
        imx233_lcdif_pio_send(true, w, FBADDR(x, yy));
}
Ejemplo n.º 5
0
void imx233_lcdif_pio_send(bool data_mode, unsigned len, uint32_t *buf)
{
    unsigned max_xfer_size = 0xffff;
    if(len == 0)
        return;
    if(lcdif_word_length == HW_LCDIF_CTRL__WORD_LENGTH_16_BIT)
        max_xfer_size = 0x1fffe;
    imx233_lcdif_wait_ready();
    unsigned msk = imx233_lcdif_enable_irqs(0);
    imx233_lcdif_enable_bus_master(false);

    do
    {
        unsigned burst = MIN(len, max_xfer_size);
        len -= burst;
        unsigned count = burst;
        if(lcdif_word_length != HW_LCDIF_CTRL__WORD_LENGTH_8_BIT)
        {
            if(burst & 1)
                burst++;
            count = burst / 2;
        }
        else
            count = burst;
        HW_LCDIF_TRANSFER_COUNT = 0;
        HW_LCDIF_TRANSFER_COUNT = 0x10000 | count;
        __REG_CLR(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT | HW_LCDIF_CTRL__RUN;
        if(data_mode)
            __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__DATA_SELECT;
        __REG_SET(HW_LCDIF_CTRL) = HW_LCDIF_CTRL__RUN;
        burst = (burst + 3) / 4;
        while(burst-- > 0)
        {
            while(HW_LCDIF_STAT & HW_LCDIF_STAT__LFIFO_FULL);
            HW_LCDIF_DATA = *buf++;
        }
        while(HW_LCDIF_CTRL & HW_LCDIF_CTRL__RUN);
    }while(len > 0);
    imx233_lcdif_enable_bus_master(true);
    imx233_lcdif_enable_irqs(msk);
}
Ejemplo n.º 6
0
void imx233_lcdif_pio_send(bool data_mode, unsigned len, void *buf)
{
    imx233_lcdif_wait_ready();
    if(len == 0)
        return;
#if IMX233_SUBTARGET >= 3780
    imx233_lcdif_enable_bus_master(false);
#endif
    if(data_mode)
        BF_SET(LCDIF_CTRL, DATA_SELECT);
    else
        BF_CLR(LCDIF_CTRL, DATA_SELECT);

    switch(BF_RD(LCDIF_CTRL, WORD_LENGTH))
    {
        case BV_LCDIF_CTRL_WORD_LENGTH__8_BIT: pio_send(len, 1, buf); break;
        case BV_LCDIF_CTRL_WORD_LENGTH__16_BIT: pio_send(len, 2, buf); break;
#if IMX233_SUBTARGET >= 3780
        case BV_LCDIF_CTRL_WORD_LENGTH__18_BIT: pio_send(len, 4, buf); break;
#endif
        default: panicf("Don't know how to handle this word length");
    }
}
Ejemplo n.º 7
0
void lcd_update_rect(int x, int y, int w, int h)
{
#ifdef HAVE_LCD_ENABLE
    if(!lcd_on)
        return;
#endif
    /* make sure the rectangle is included in the screen */
    x = MIN(x, LCD_WIDTH);
    y = MIN(y, LCD_HEIGHT);
    w = MIN(w, LCD_WIDTH - x);
    h = MIN(h, LCD_HEIGHT - y);

    imx233_lcdif_wait_ready();
    uint32_t window = x << 8 | (x + w - 1) << 24;
    lcd_write_reg(0x2a, &window, sizeof(window));
    window = y << 8 | (y + h - 1) << 24;
    lcd_write_reg(0x2b, &window, sizeof(window));
    lcd_write_reg(0x2c, NULL, 0);

    imx233_lcdif_wait_ready();
    imx233_lcdif_set_data_swizzle(3);
    imx233_lcdif_set_word_length(8);
    /* there are two cases here:
     * - either width = LCD_WIDTH and we can directly memcopy a part of lcd_framebuffer to FRAME
     *   and send it
     * - either width != LCD_WIDTH and we have to build a contiguous copy of the rectangular area
     *   into FRAME before sending it (which is slower and doesn't use the hardware)
     * In all cases, FRAME just acts as a temporary buffer.
     * NOTE It's more interesting to do a copy to FRAME in all cases since in system mode
     * the clock runs at 24MHz which provides barely 10MB/s bandwidth compared to >100MB/s
     * for memcopy operations
     */
    if(w == LCD_WIDTH)
    {
        memcpy((void *)FRAME, FBADDR(x,y), w * h * sizeof(fb_data));
    }
    else
    {
        for(int i = 0; i < h; i++)
            memcpy((fb_data *)FRAME + i * w, FBADDR(x,y + i), w * sizeof(fb_data));
    }
    /* WARNING The LCDIF has a limitation on the vertical count ! In 16-bit packed mode
     * (which we used, ie 16-bit per pixel, 2 pixels per 32-bit words), the v_count
     * field must be a multiple of 2. Furthermore, it seems the lcd controller doesn't
     * really like when both w and h are even, probably because the writes to the GRAM
     * are done on several words and the controller requires dummy writes.
     * The workaround is to always make sure that we send a number of pixels which is
     * a multiple of 4 so that both the lcdif and the controller are happy. If any
     * of w or h is odd, we will send a copy of the first pixels as dummy writes. We will
     * send at most 3 bytes. We then send (w * h + 3) / 4 x 4 bytes.
     */
    if(w % 2 == 1 || h % 2 == 1)
    {
        /* copy three pixel after the last one */
        for(int i = 0; i < 3; i++)
            *((fb_data *)FRAME + w * h + i) = *((fb_data *)FRAME + i);
        /* WARNING we need to update w and h to reflect the pixel count BUT it
         * has no relation to w * h (it can even be 2 * prime). Hopefully, w <= 240 and
         * h <= 320 so w * h <= 76800 and (w * h + 3) / 4 <= 38400 which fits into
         * a 16-bit integer (horizontal count). */
        h = (w * h + 3) / 4;
        w = 4;
    }
    imx233_lcdif_dma_send((void *)FRAME_PHYS_ADDR, w * 2, h);
}