# HG changeset patch # User Paul Boddie # Date 1453741461 -3600 # Node ID d57753b571627b563dea35497bc83825e4be3d32 # Parent afb03fdeafc460a8959a98cb8efc9021bba7d149 Added 16bpp support, fixed/improved dual panel support, handled apparent framebuffer positioning limitations and line positioning constraints. Removed old test code in the LCD demonstration. diff -r afb03fdeafc4 -r d57753b57162 include/minipc.h --- a/include/minipc.h Mon Jan 25 18:01:52 2016 +0100 +++ b/include/minipc.h Mon Jan 25 18:04:21 2016 +0100 @@ -3,7 +3,7 @@ * * Copyright (C) 2009 Qi Hardware Inc. * Authors: Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,11 +23,6 @@ #define __MINIPC_H__ /* - * Display configuration - */ -#define LCD_BPP LCD_COLOR32 - -/* * GPIO definition */ #define GPIO_LED_EN 92 diff -r afb03fdeafc4 -r d57753b57162 include/nanonote.h --- a/include/nanonote.h Mon Jan 25 18:01:52 2016 +0100 +++ b/include/nanonote.h Mon Jan 25 18:04:21 2016 +0100 @@ -3,7 +3,7 @@ * * Copyright (C) 2009 Qi Hardware Inc. * Authors: Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,11 +23,6 @@ #define __NANONOTE_H__ /* - * Display configuration - */ -#define LCD_BPP LCD_COLOR32 - -/* * GPIO definition * See: http://en.qi-hardware.com/wiki/Hardware_basics */ diff -r afb03fdeafc4 -r d57753b57162 stage2/jzlcd.c --- a/stage2/jzlcd.c Mon Jan 25 18:01:52 2016 +0100 +++ b/stage2/jzlcd.c Mon Jan 25 18:04:21 2016 +0100 @@ -25,9 +25,6 @@ #include "cpu.h" #include "board.h" -#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) -#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) - #define align2(n) (n)=((((n)+1)>>1)<<1) #define align4(n) (n)=((((n)+3)>>2)<<2) #define align8(n) (n)=((((n)+7)>>3)<<3) @@ -35,44 +32,79 @@ extern struct jzfb_info jzfb; extern vidinfo_t panel_info; +static unsigned short lcd_get_panels() +{ + return ((jzfb.cfg & MODE_MASK) == MODE_STN_MONO_DUAL) || + ((jzfb.cfg & MODE_MASK) == MODE_STN_COLOR_DUAL) ? 2 : 1; +} + static unsigned long lcd_get_size(vidinfo_t *vid) { - int line_length = (vid->vl_col * NBITS(vid->vl_bpix)) / 8; + /* Lines must be aligned to a word boundary. */ + unsigned long line_length = ALIGN((vid->vl_col * NBITS(vid->vl_bpix)) / 8, sizeof(u32)); return line_length * vid->vl_row; } +static unsigned long lcd_get_aligned_size(vidinfo_t *vid) +{ + /* LCD_CTRL_BST_16 requires 16-word alignment. */ + return ALIGN(lcd_get_size(vid), 16 * sizeof(u32)); +} + +static unsigned long lcd_get_min_size(vidinfo_t *vid) +{ + /* Lines must be aligned to a word boundary. */ + unsigned long line_length = ALIGN((vid->vl_col * 32) / 8, sizeof(u32)); + return line_length * vid->vl_row; +} + +static unsigned long lcd_get_aligned_min_size(vidinfo_t *vid) +{ + /* LCD_CTRL_BST_16 requires 16-word alignment. */ + return ALIGN(lcd_get_min_size(vid), 16 * sizeof(u32)); +} + static unsigned long lcd_get_palette_size() { return 256 * sizeof(u16); } +static unsigned long lcd_get_aligned_palette_size() +{ + /* LCD_CTRL_BST_16 requires 16-word alignment. */ + return ALIGN(lcd_get_palette_size(), 16 * sizeof(u32)); +} + static unsigned long lcd_get_descriptors_size() { return 3 * sizeof(struct jz_fb_dma_descriptor); } -static unsigned long lcd_get_aligned_size(vidinfo_t *vid) +static unsigned long lcd_get_total_size(vidinfo_t *vid) { - /* Round up to nearest full page, or MMU section if defined */ - return ALIGN(lcd_get_size(vid) + lcd_get_palette_size() + lcd_get_descriptors_size(), PAGE_SIZE); + unsigned long size = lcd_get_aligned_size(vid) * lcd_get_panels(); + unsigned long min_size = lcd_get_aligned_min_size(vid); + + /* Round up to nearest full page, or MMU section if defined. */ + return ALIGN((size >= min_size ? size : min_size) + lcd_get_aligned_palette_size() + lcd_get_descriptors_size(), PAGE_SIZE); } static unsigned long lcd_get_palette(unsigned long addr) { /* Allocate memory at the end of the region for the palette. */ - return addr - lcd_get_palette_size(); + return addr - lcd_get_aligned_palette_size(); } static unsigned long lcd_get_descriptors(unsigned long addr) { /* Allocate memory before the palette for the descriptor array. */ - return addr - lcd_get_palette_size() - lcd_get_descriptors_size(); + return lcd_get_palette(addr) - lcd_get_descriptors_size(); } -static unsigned long lcd_get_framebuffer(unsigned long addr) +static unsigned long lcd_get_framebuffer(unsigned long addr, unsigned short panel) { /* Allocate pages for the frame buffer and palette. */ - return addr - lcd_get_aligned_size(&panel_info); + return addr - lcd_get_total_size(&panel_info) + (panel * lcd_get_aligned_size(&panel_info)); } static void jz_lcd_desc_init(vidinfo_t *vid); @@ -84,9 +116,8 @@ /* Start from the top of memory and obtain palette and framebuffer regions. */ - fbi->screen = lcd_get_framebuffer(get_memory_size()); + fbi->screen = lcd_get_framebuffer(get_memory_size(), 0); fbi->palette = lcd_get_palette(get_memory_size()); - fbi->palette_size = 256; jz_lcd_desc_init(&panel_info); jz_lcd_hw_init(&panel_info); @@ -124,22 +155,25 @@ /* Populate descriptors. */ - fbi->dmadesc_fblow->fdadr = fbi->dmadesc_fblow; - fbi->dmadesc_fblow->fsadr = fbi->screen + lcd_get_size(vid); - fbi->dmadesc_fblow->fidr = 0; - fbi->dmadesc_fblow->ldcmd = lcd_get_size(vid) / 4 ; + if (lcd_get_panels() == 2) + { + fbi->dmadesc_fblow->fdadr = fbi->dmadesc_fblow; + fbi->dmadesc_fblow->fsadr = lcd_get_framebuffer(get_memory_size(), 1); + 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->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 word */ + fbi->dmadesc_fbhigh->ldcmd = lcd_get_size(vid) / 4; /* length in words */ fbi->dmadesc_palette->fsadr = fbi->palette; fbi->dmadesc_palette->fidr = 0; - fbi->dmadesc_palette->ldcmd = (fbi->palette_size * 2)/4 | (1<<28); + fbi->dmadesc_palette->ldcmd = (lcd_get_palette_size() / 4) | (1<<28); - if(NBITS(vid->vl_bpix) < 12) + if (NBITS(vid->vl_bpix) < 12) { /* assume any mode with <12 bpp is palette driven */ fbi->dmadesc_palette->fdadr = fbi->dmadesc_fbhigh; diff -r afb03fdeafc4 -r d57753b57162 stage2/jzlcd.h --- a/stage2/jzlcd.h Mon Jan 25 18:01:52 2016 +0100 +++ b/stage2/jzlcd.h Mon Jan 25 18:04:21 2016 +0100 @@ -71,7 +71,6 @@ unsigned long screen; /* address of frame buffer */ unsigned long palette; /* address of palette memory */ - unsigned int palette_size; }; /* @@ -85,6 +84,11 @@ struct jz_fb_info jz_fb; } vidinfo_t; +/* Alignment/rounding macros. */ + +#define ALIGN(x,a) __ALIGN_MASK((x),(typeof(x))(a)-1) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) + /* General values for colour depths and framebuffer characteristics. */ #define LCD_MONOCHROME 0 diff -r afb03fdeafc4 -r d57753b57162 stage2/lcd.c --- a/stage2/lcd.c Mon Jan 25 18:01:52 2016 +0100 +++ b/stage2/lcd.c Mon Jan 25 18:04:21 2016 +0100 @@ -33,49 +33,89 @@ extern vidinfo_t panel_info; static unsigned long lcd_base; -unsigned long irq_counter = 0; -void test_pixel(unsigned short h, unsigned short v) +static unsigned int get_line_length() +{ + return ALIGN((panel_info.vl_col * NBITS(panel_info.vl_bpix)) / 8, sizeof(u32)); +} + +static u32 *get_pixel32(unsigned short h, unsigned short v) { - unsigned short v_max = panel_info.vl_row; - unsigned short h_max = panel_info.vl_col; - unsigned long *pix = (unsigned long *)lcd_base + v * h_max + h; + return (u32 *) (lcd_base + v * get_line_length()) + h; +} - /* NOTE: Code assumes 32 bits/pixel. */ -#ifdef NORMAL +static u16 *get_pixel16(unsigned short h, unsigned short v) +{ + return (u16 *) (lcd_base + v * get_line_length()) + h; +} + +static void test_pixel32(unsigned short h, unsigned short v) +{ + unsigned short v_max = panel_info.vl_row; + unsigned short h_max = panel_info.vl_col; + u32 *pix = get_pixel32(h, v); + *pix = ( (((255 * (h_max - h)) / (h_max - 1)) << 16) + ((((255 * h) / (h_max - 1) + (255 * (v_max - v)) / (v_max - 1)) / 2) << 8) + ((255 * v) / (v_max - 1)) ); -#elif HANDLER - unsigned short offset, bit; - bit = 31 - (32 * h / (h_max - 1)); - offset = v / 4; - *pix = ((*((unsigned long *) 0x80000200 + offset) & (1 << bit)) >> bit) ? 0xffffffff : 0; -#else - unsigned short bit; - volatile unsigned int cp0_register; - asm volatile( - "mfc0 %0, $12\n" - "nop" - : "=r"(cp0_register) +} + +static void test_pixel16_565(unsigned short h, unsigned short v) +{ + unsigned short v_max = panel_info.vl_row; + unsigned short h_max = panel_info.vl_col; + u16 *pix = get_pixel16(h, v); + + *pix = ( + (((31 * (h_max - h)) / (h_max - 1)) << 11) + + ((((63 * h) / (h_max - 1) + (63 * (v_max - v)) / (v_max - 1)) / 2) << 5) + + ((31 * v) / (v_max - 1)) ); - bit = 31 - (32 * h / (h_max - 1)); - *pix = (((cp0_register & (1 << bit)) >> bit) ? 0x007f0000 : 0x0000001f) * ((bit % 2) ? 2 : 1); - /* *pix = (((irq_counter & (1 << bit)) >> bit) ? 0x007f0000 : 0x0000001f) * ((bit % 2) ? 2 : 1); */ -#endif +} + +void test_pixel(unsigned short h, unsigned short v) +{ + switch (panel_info.vl_bpix) + { + case LCD_COLOR32: + test_pixel32(h, v); + break; + + default: + test_pixel16_565(h, v); + break; + } +} + +void clear_pixel32(unsigned short h, unsigned short v) +{ + u32 *pix = get_pixel32(h, v); + *pix = 0; +} + +void clear_pixel16(unsigned short h, unsigned short v) +{ + u16 *pix = get_pixel16(h, v); + *pix = 0; } void clear_pixel(unsigned short h, unsigned short v) { - unsigned short h_max = panel_info.vl_col; - unsigned long *pix = (unsigned long *)lcd_base + v * h_max + h; + switch (panel_info.vl_bpix) + { + case LCD_COLOR32: + clear_pixel32(h, v); + break; - *pix = 0; + default: + clear_pixel16(h, v); + break; + } } -void test_pattern(void *lcd_base) +void test_pattern() { unsigned short v_max = panel_info.vl_row; unsigned short h_max = panel_info.vl_col; diff -r afb03fdeafc4 -r d57753b57162 stage2/minipc_claa070vc01.c --- a/stage2/minipc_claa070vc01.c Mon Jan 25 18:01:52 2016 +0100 +++ b/stage2/minipc_claa070vc01.c Mon Jan 25 18:04:21 2016 +0100 @@ -2,7 +2,7 @@ * MiniPC screen details * * Copyright (C) 2005-2007, Ingenic Semiconductor Inc. - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -30,5 +30,5 @@ }; vidinfo_t panel_info = { - 800, 480, LCD_BPP, + 800, 480, LCD_COLOR32, }; diff -r afb03fdeafc4 -r d57753b57162 stage2/nanonote_gpm940b0.c --- a/stage2/nanonote_gpm940b0.c Mon Jan 25 18:01:52 2016 +0100 +++ b/stage2/nanonote_gpm940b0.c Mon Jan 25 18:04:21 2016 +0100 @@ -2,7 +2,7 @@ * Ben NanoNote screen details * * Copyright (C) Xiangfu Liu - * Copyright (C) 2015 Paul Boddie + * Copyright (C) 2015, 2016 Paul Boddie * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -30,5 +30,5 @@ }; vidinfo_t panel_info = { - 320, 240, LCD_BPP, + 320, 240, LCD_COLOR32, };