# HG changeset patch # User Paul Boddie # Date 1499557622 -7200 # Node ID d41c05accd390d4923fb5b8fdcf9cd5a7d7210e5 # Parent 61ef56dfab174053e84ff22b6d4b4c1582104c59 Parameterised LCD controller initialisation, allowing addresses to be passed in rather than being calculated within the function. Changed various descriptor structure member names. diff -r 61ef56dfab17 -r d41c05accd39 stage2/jzlcd.c --- a/stage2/jzlcd.c Sun Jul 09 00:36:42 2017 +0200 +++ b/stage2/jzlcd.c Sun Jul 09 01:47:02 2017 +0200 @@ -1,5 +1,5 @@ /* - * JzRISC LCD controller + * jz4740 LCD controller configuration. * * Copyright (C) Xiangfu Liu * Copyright (C) 2015, 2016, 2017 Paul Boddie @@ -64,7 +64,7 @@ /* Return the number of panels available. */ -static uint16_t lcd_get_panels(vidinfo_t *vid) +static uint8_t lcd_get_panels(vidinfo_t *vid) { struct jzfb_info *jzfb = vid->jz_fb; return ((jzfb->cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || @@ -73,7 +73,7 @@ /* Calculate and return the pixel clock frequency. */ -static uint32_t jz_lcd_get_pixel_clock(vidinfo_t *vid) +static uint32_t lcd_get_pixel_clock(vidinfo_t *vid) { struct jzfb_info *jzfb = vid->jz_fb; uint32_t pclk, width_cycles, mode = jzfb->cfg & MODE_MASK; @@ -139,6 +139,8 @@ static uint32_t lcd_get_palette_size(vidinfo_t *vid) { + /* Get a collection of two-byte entries, one per colour. */ + if (vid->jz_fb->bpp < 12) return (1 << (vid->jz_fb->bpp)) * sizeof(uint16_t); else @@ -169,78 +171,31 @@ /* Functions returning addresses of each data region. */ -static uint32_t lcd_get_palette(uint32_t addr, vidinfo_t *vid) +static uint32_t lcd_get_palette(vidinfo_t *vid) { - /* Allocate memory at the end of the region for the palette. */ - return addr - lcd_get_aligned_palette_size(vid); + /* Use memory at the end of the allocated region for the palette. */ + + return get_memory_size() - lcd_get_aligned_palette_size(vid); } -static uint32_t lcd_get_descriptors(uint32_t addr, vidinfo_t *vid) +static uint32_t lcd_get_descriptors(vidinfo_t *vid) { - /* Allocate memory before the palette for the descriptor array. */ - return lcd_get_palette(addr, vid) - lcd_get_descriptors_size(); + /* Use memory before the palette for the descriptor array. */ + + return lcd_get_palette(vid) - lcd_get_descriptors_size(); } -static uint32_t lcd_get_framebuffer(uint32_t addr, uint16_t panel, vidinfo_t *vid) +static uint32_t lcd_get_framebuffer(uint16_t panel, vidinfo_t *vid) { - /* Allocate pages for the frame buffer and palette. */ - return addr - lcd_get_total_size(vid) + (panel * lcd_get_aligned_size(vid)); + /* Framebuffers for panels are allocated at the start of the region. */ + + return get_memory_size() - lcd_get_total_size(vid) + (panel * lcd_get_aligned_size(vid)); } /* Initialisation functions. */ -static void jz_lcd_desc_init(vidinfo_t *vid) -{ - struct jz_fb_dma_descriptor *descriptors; - struct jz_mem_info * fbi; - - fbi = &vid->jz_mem; - - /* Allocate space for descriptors before the palette entries. */ - - descriptors = (struct jz_fb_dma_descriptor *) lcd_get_descriptors(get_memory_size(), vid); - fbi->dmadesc_fblow = (struct jz_fb_dma_descriptor *) &descriptors[0]; - fbi->dmadesc_fbhigh = (struct jz_fb_dma_descriptor *) &descriptors[1]; - fbi->dmadesc_palette = (struct jz_fb_dma_descriptor *) &descriptors[2]; - - /* Populate descriptors. */ - - if (lcd_get_panels(vid) == 2) - { - fbi->dmadesc_fblow->fdadr = fbi->dmadesc_fblow; - fbi->dmadesc_fblow->fsadr = lcd_get_framebuffer(get_memory_size(), 1, vid); - fbi->dmadesc_fblow->fidr = 0; - fbi->dmadesc_fblow->ldcmd = lcd_get_size(vid) / 4 ; - - fbi->fdadr1 = fbi->dmadesc_fblow; /* only used in dual-panel mode */ - } - - fbi->dmadesc_fbhigh->fsadr = fbi->screen; - fbi->dmadesc_fbhigh->fidr = 0; - fbi->dmadesc_fbhigh->ldcmd = lcd_get_size(vid) / 4; /* length in words */ - - if (vid->jz_fb->bpp < 12) - { - fbi->dmadesc_palette->fsadr = fbi->palette; - fbi->dmadesc_palette->fidr = 0; - fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size(vid) / 4) | (1<<28); - - /* assume any mode with <12 bpp is palette driven */ - fbi->dmadesc_palette->fdadr = fbi->dmadesc_fbhigh; - fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_palette; - /* flips back and forth between pal and fbhigh */ - fbi->fdadr0 = fbi->dmadesc_palette; - } else { - /* palette shouldn't be loaded in true-color mode */ - fbi->dmadesc_fbhigh->fdadr = fbi->dmadesc_fbhigh; - fbi->fdadr0 = fbi->dmadesc_fbhigh; /* no pal just fbhigh */ - } - - flush_cache_all(); -} - static uint32_t jz_lcd_stn_init(uint32_t stnH, vidinfo_t *vid) { struct jzfb_info *jzfb = vid->jz_fb; @@ -288,7 +243,7 @@ } lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw); - lcd_ctrl_set(vid, LCD_HSYNC, ((jzfb->blw+jzfb->w) << 16) | (jzfb->blw+jzfb->w+jzfb->hsw)); + lcd_ctrl_set(vid, LCD_HSYNC, ((jzfb->blw + jzfb->w) << 16) | (jzfb->blw + jzfb->w + jzfb->hsw)); /* Screen setting */ lcd_ctrl_set(vid, LCD_VAT, ((jzfb->blw + jzfb->w + jzfb->hsw + jzfb->elw) << 16) | (stnH + jzfb->vsw + jzfb->bfw + jzfb->efw)); @@ -304,9 +259,10 @@ static void jz_lcd_tft_init(vidinfo_t *vid) { struct jzfb_info *jzfb = vid->jz_fb; + lcd_ctrl_set(vid, LCD_VSYNC, jzfb->vsw); lcd_ctrl_set(vid, LCD_HSYNC, jzfb->hsw); - lcd_ctrl_set(vid, LCD_DAV, ((jzfb->vsw+jzfb->bfw) << 16) | (jzfb->vsw +jzfb->bfw+jzfb->h)); + lcd_ctrl_set(vid, LCD_DAV, ((jzfb->vsw + jzfb->bfw) << 16) | (jzfb->vsw + jzfb->bfw + jzfb->h)); lcd_ctrl_set(vid, LCD_DAH, ((jzfb->hsw + jzfb->blw) << 16) | (jzfb->hsw + jzfb->blw + jzfb->w)); lcd_ctrl_set(vid, LCD_VAT, (((jzfb->blw + jzfb->w + jzfb->elw + jzfb->hsw)) << 16) | (jzfb->vsw + jzfb->bfw + jzfb->h + jzfb->efw)); @@ -315,7 +271,7 @@ static void jz_lcd_samsung_init(vidinfo_t *vid) { struct jzfb_info *jzfb = vid->jz_fb; - uint32_t pclk = jz_lcd_get_pixel_clock(vid); + uint32_t pclk = lcd_get_pixel_clock(vid); uint32_t total, tp_s, tp_e, ckv_s, ckv_e; uint32_t rev_s, rev_e, inv_s, inv_e; @@ -405,7 +361,7 @@ static void jz_lcd_set_timing(vidinfo_t *vid) { - uint32_t pclk = jz_lcd_get_pixel_clock(vid); + uint32_t pclk = lcd_get_pixel_clock(vid); uint32_t val; #ifdef CONFIG_CPU_JZ4730 @@ -445,6 +401,89 @@ lcd_ctrl_set(vid, CPM_CPCCR, lcd_ctrl_get(vid, CPM_CPCCR) | CPM_CPCCR_CE); /* update divide */ } +/* Initialise the LCD controller with the memory, panel and framebuffer details. + Return the pixel clock frequency. */ + +static void jz_lcd_ctrl_init(void *lcd_base, void *fb_vaddr, vidinfo_t *vid) +{ + struct jz_mem_info *fbi = &vid->jz_mem; + struct jz_fb_dma_descriptor *descriptors = (struct jz_fb_dma_descriptor *) lcd_get_descriptors(vid); + + /* Set the LCD controller address. */ + + vid->lcd = lcd_base; + + /* Position framebuffer regions at the given address. */ + + fbi->screen = (uint32_t) fb_vaddr; + + /* Obtain the palette address. */ + + fbi->palette = lcd_get_palette(vid); + + /* Initialise a palette for lower colour depths. */ + + if (vid->jz_fb->bpp < 12) + lcd_init_palette(vid); + + /* Reference the descriptors in memory. */ + + fbi->dmadesc_fb0 = &descriptors[0]; + fbi->dmadesc_fb1 = &descriptors[1]; + fbi->dmadesc_palette = &descriptors[2]; + + /* Populate descriptors. */ + + /* Provide the first framebuffer descriptor in single and dual modes. */ + + fbi->dmadesc_fb0->fsadr = lcd_get_framebuffer(0, vid); + fbi->dmadesc_fb0->fidr = 0; + fbi->dmadesc_fb0->ldcmd = lcd_get_size(vid) / 4; /* length in words */ + + /* Provide the second framebuffer descriptor only in dual-panel mode. */ + + if (lcd_get_panels(vid) == 2) + { + fbi->dmadesc_fb1->fdadr = fbi->dmadesc_fb1; + fbi->dmadesc_fb1->fsadr = lcd_get_framebuffer(1, vid); + fbi->dmadesc_fb1->fidr = 0; + fbi->dmadesc_fb1->ldcmd = lcd_get_size(vid) / 4; + + /* Note the address to be provided for the second channel. */ + + fbi->fdadr1 = fbi->dmadesc_fb1; + } + + /* Initialise palette descriptor details if a palette is to be used. */ + + /* Assume any mode with <12 bpp is palette driven. */ + + if (vid->jz_fb->bpp < 12) + { + fbi->dmadesc_palette->fsadr = fbi->palette; + fbi->dmadesc_palette->fidr = 0; + fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size(vid) / 4) | LCD_CMD_PAL; + + /* Flip back and forth between the palette and framebuffer. */ + + fbi->dmadesc_palette->fdadr = fbi->dmadesc_fb0; + fbi->dmadesc_fb0->fdadr = fbi->dmadesc_palette; + + /* Provide the palette descriptor address first. */ + + fbi->fdadr0 = fbi->dmadesc_palette; + } + else + { + /* No palette: always use the framebuffer descriptor. */ + + fbi->dmadesc_fb0->fdadr = fbi->dmadesc_fb0; + fbi->fdadr0 = fbi->dmadesc_fb0; + } +} + +/* Initialise the LCD registers. */ + static void jz_lcd_hw_init(vidinfo_t *vid) { struct jzfb_info *jzfb = vid->jz_fb; @@ -516,7 +555,7 @@ break; } - /* Further control register and panel configuration. */ + /* Further control register and panel configuration. */ val |= LCD_CTRL_BST_16; /* Burst Length is 16WORD=64Byte */ val |= LCD_CTRL_OFUP; /* OutFIFO underrun protect */ @@ -537,10 +576,10 @@ static void jz_lcd_dma_init(vidinfo_t *vid) { - struct jz_mem_info *fbi = &vid->jz_mem; - uint32_t mode = vid->jz_fb->cfg & MODE_MASK; + struct jz_mem_info *fbi = &vid->jz_mem; + uint32_t mode = vid->jz_fb->cfg & MODE_MASK; - /* Configure DMA by setting frame descriptor addresses. */ + /* Configure DMA by setting frame descriptor addresses. */ lcd_ctrl_set(vid, LCD_DA0, (uint32_t) fbi->fdadr0); @@ -548,13 +587,12 @@ lcd_ctrl_set(vid, LCD_DA1, (uint32_t) fbi->fdadr1); } -/* Public operations. */ +/* Set the colour depth. */ void lcd_set_bpp(uint8_t bpp) { vidinfo_t *vid = &panel_info; - struct jzfb_info *jzfb = vid->jz_fb; - jzfb->bpp = bpp; + vid->jz_fb->bpp = bpp; } void lcd_enable() @@ -588,16 +626,14 @@ { vidinfo_t *vid = &panel_info; struct jz_mem_info *fbi = &vid->jz_mem; + void *fb_vaddr; - /* Start from the top of memory and obtain palette and framebuffer regions. */ + /* Start from the top of memory and obtain the framebuffer region. */ - fbi->screen = lcd_get_framebuffer(get_memory_size(), 0, vid); - fbi->palette = lcd_get_palette(get_memory_size(), vid); + fb_vaddr = (void *) lcd_get_framebuffer(0, vid); - if (vid->jz_fb->bpp < 12) - lcd_init_palette(vid); - - jz_lcd_desc_init(vid); + jz_lcd_ctrl_init(0, fb_vaddr, vid); + flush_cache_all(); jz_lcd_hw_init(vid); jz_lcd_timing_init(vid); jz_lcd_dma_init(vid); diff -r 61ef56dfab17 -r d41c05accd39 stage2/jzlcd.h --- a/stage2/jzlcd.h Sun Jul 09 00:36:42 2017 +0200 +++ b/stage2/jzlcd.h Sun Jul 09 01:47:02 2017 +0200 @@ -63,13 +63,13 @@ /* DMA descriptor references (updated for transfers). */ - struct jz_fb_dma_descriptor *fdadr0; /* physical address of frame/palette descriptor */ - struct jz_fb_dma_descriptor *fdadr1; /* physical address of frame descriptor */ + struct jz_fb_dma_descriptor *fdadr0; /* physical address of frame descriptor */ + struct jz_fb_dma_descriptor *fdadr1; /* physical address of frame/palette descriptor */ /* DMA descriptor references (indicating allocated regions). */ - struct jz_fb_dma_descriptor *dmadesc_fblow; - struct jz_fb_dma_descriptor *dmadesc_fbhigh; + struct jz_fb_dma_descriptor *dmadesc_fb0; + struct jz_fb_dma_descriptor *dmadesc_fb1; struct jz_fb_dma_descriptor *dmadesc_palette; uint32_t screen; /* address of first frame buffer (base of memory used) */ @@ -136,4 +136,8 @@ #define DATA_NORMAL (0 << 17) #define DATA_INVERSE (1 << 17) +/* Palette buffer (LCD_CMDx.PAL). */ + +#define LCD_CMD_PAL (1 << 28) + #endif /* __JZLCD_H__ */