Miyoo
移植XBoot
移植的部份就只有顯示屏的程式碼,過程如下所示:
--- src/arch/arm32/mach-f1c100s/driver/fb-f1c100s_orig.c 2018-12-30 22:22:53.370788418 +0800 +++ src/arch/arm32/mach-f1c100s/driver/fb-f1c100s.c 2018-12-31 19:45:36.824995967 +0800 @@ -30,6 +30,7 @@ #include <led/led.h> #include <framebuffer/framebuffer.h> #include <f1c100s-gpio.h> +#include <f1c100s/reg-gpio.h> #include <f1c100s/reg-tcon.h> #include <f1c100s/reg-defe.h> #include <f1c100s/reg-debe.h> @@ -39,6 +40,7 @@ virtual_addr_t virtdefe; virtual_addr_t virtdebe; virtual_addr_t virttcon; + virtual_addr_t virtgpio; char * clkdefe; char * clkdebe; @@ -53,6 +55,7 @@ int bits_per_pixel; int bytes_per_pixel; int index; + int lcdc_use_gpio; void * vram[2]; struct { @@ -73,6 +76,46 @@ int brightness; }; +static void sunxi_lcdc_output(struct fb_f1c100s_pdata_t * pdat, uint32_t is_data, uint32_t val) +{ + uint32_t ret; + + if (pdat->lcdc_use_gpio){ + ret = (val & 0x00ff) << 1; + ret|= (val & 0xff00) << 2; + ret|= is_data ? 0x80000 : 0; + ret|= 0x100000; + write32(pdat->virtgpio + PD_DATA, ret); + ret|= 0x40000; + write32(pdat->virtgpio + PD_DATA, ret); + } + else { + ret = read32(pdat->virttcon + TCON0_CPU_IF_REG); + if (is_data) { + ret|= 0x2000000; + } + else { + ret&= 0xfdffffff; + } + write32(pdat->virttcon + TCON0_CPU_IF_REG, ret); + while(read32(pdat->virttcon + TCON0_CPU_IF_REG) & 0xc0000){ + ndelay(1); + } + write32(pdat->virttcon + TCON0_CPU_WR_REG, ((val & 0xfc00) << 8) | ((val & 0x0300) << 6) | ((val & 0x00e0) << 5) | ((val & 0x001f) << 3)); + //write32(pdat->virttcon + TCON0_CPU_WR_REG, val); + } +} + +static void r61520_lcd_cmd(struct fb_f1c100s_pdata_t * pdat, uint32_t val) +{ + sunxi_lcdc_output(pdat, 0, val); +} + +static void r61520_lcd_dat(struct fb_f1c100s_pdata_t * pdat, uint32_t val) +{ + sunxi_lcdc_output(pdat, 1, val); +} + static inline void f1c100s_debe_set_mode(struct fb_f1c100s_pdata_t * pdat) { struct f1c100s_debe_reg_t * debe = (struct f1c100s_debe_reg_t *)(pdat->virtdebe); @@ -147,7 +190,7 @@ write32((virtual_addr_t)&tcon->ctrl, val); val = (pdat->timing.v_front_porch + pdat->timing.v_back_porch + pdat->timing.v_sync_len); - write32((virtual_addr_t)&tcon->tcon0_ctrl, (1 << 31) | ((val & 0x1f) << 4)); + write32((virtual_addr_t)&tcon->tcon0_ctrl, (1 << 31) | ((val & 0x1f) << 4) | (1 << 24)); // 8080 interface val = clk_get_rate(pdat->clktcon) / pdat->timing.pixel_clock_hz; write32((virtual_addr_t)&tcon->tcon0_dclk, (0xf << 28) | (val << 0)); write32((virtual_addr_t)&tcon->tcon0_timing_active, ((pdat->width - 1) << 16) | ((pdat->height - 1) << 0)); @@ -161,7 +204,7 @@ write32((virtual_addr_t)&tcon->tcon0_timing_sync, ((pdat->timing.h_sync_len - 1) << 16) | ((pdat->timing.v_sync_len - 1) << 0)); write32((virtual_addr_t)&tcon->tcon0_hv_intf, 0); - write32((virtual_addr_t)&tcon->tcon0_cpu_intf, 0); + write32((virtual_addr_t)&tcon->tcon0_cpu_intf, 0xe4000000); // 8080 mode if(pdat->bits_per_pixel == 18 || pdat->bits_per_pixel == 16) { @@ -268,9 +311,236 @@ memcpy(pdat->vram[pdat->index], render->pixels, render->pixlen); dma_cache_sync(pdat->vram[pdat->index], render->pixlen, DMA_TO_DEVICE); f1c100s_debe_set_address(pdat, pdat->vram[pdat->index]); + + { + uint32_t x, y; + uint32_t val, *p = render->pixels; + + r61520_lcd_cmd(pdat, 0x2c); + for(y=0; y<240; y++){ + for(x=0; x<320; x++){ + val = *p++; + r61520_lcd_dat(pdat, ((val & 0xf80000) >> 8) | ((val & 0x00fc00) >> 5) | ((val & 0xf8) >> 3)); + } + } + } } } +static void sunxi_lcdc_gpio_config(struct fb_f1c100s_pdata_t * pdat, uint32_t use_gpio) +{ + uint32_t ret; + + pdat->lcdc_use_gpio = use_gpio; + if(pdat->lcdc_use_gpio){ + write32(pdat->virtgpio + PD_CFG0, 0x11111117); // 0x11111117 + write32(pdat->virtgpio + PD_CFG1, 0x11111171); // 0x11111171 + write32(pdat->virtgpio + PD_CFG2, 0x00111111); // 0x00111111, CS/RD/RS/WR + write32(pdat->virtgpio + PD_DATA, 0xffffffff); + } + else { + write32(pdat->virtgpio + PD_CFG0, 0x22222227); // 0x22222221 + write32(pdat->virtgpio + PD_CFG1, 0x22222272); // 0x22222212 + write32(pdat->virtgpio + PD_CFG2, 0x00222222); // 0x00222222, CS/RD/RS/WR + } + ret = read32(pdat->virtgpio + PE_CFG0); + ret&= 0xf0ffffff; + ret|= 0x01000000; + write32(pdat->virtgpio + PE_CFG0, ret); + + ret = read32(pdat->virtgpio + PE_CFG1); + ret&= 0xffff0fff; + ret|= 0x00001000; + write32(pdat->virtgpio + PE_CFG1, ret); +} + +static void r61520_lcd_init(struct fb_f1c100s_pdata_t * pdat) +{ + uint32_t ret; + + ret = read32(pdat->virtgpio + PE_DATA); + ret|= 0x0040; + write32(pdat->virtgpio + PE_DATA, ret); + + ret = read32(pdat->virtgpio + PE_DATA); + ret&= ~0x0800; + write32(pdat->virtgpio + PE_DATA, ret); + mdelay(150); + ret|= 0x0800; + write32(pdat->virtgpio + PE_DATA, ret); + mdelay(50); + + r61520_lcd_cmd(pdat, 0xb0); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0xb1); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0xb3); + r61520_lcd_dat(pdat, 0x02); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0xb4); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0xc0); + r61520_lcd_dat(pdat, 0x07); + r61520_lcd_dat(pdat, 0x4f); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x01); + r61520_lcd_dat(pdat, 0x33); + + r61520_lcd_cmd(pdat, 0xc1); + r61520_lcd_dat(pdat, 0x01); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x1a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x08); + + r61520_lcd_cmd(pdat, 0xc3); + r61520_lcd_dat(pdat, 0x01); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x1a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x08); + + r61520_lcd_cmd(pdat, 0xc4); + r61520_lcd_dat(pdat, 0x11); + r61520_lcd_dat(pdat, 0x01); + r61520_lcd_dat(pdat, 0x43); + r61520_lcd_dat(pdat, 0x01); + + r61520_lcd_cmd(pdat, 0xc8); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x8a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x09); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x10); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x23); + r61520_lcd_dat(pdat, 0x10); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x60); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x10); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0xc9); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x8a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x09); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x10); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x23); + r61520_lcd_dat(pdat, 0x10); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x09); + r61520_lcd_dat(pdat, 0x88); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x23); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0xca); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x8a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x09); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x10); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x23); + r61520_lcd_dat(pdat, 0x10); + r61520_lcd_dat(pdat, 0x05); + r61520_lcd_dat(pdat, 0x09); + r61520_lcd_dat(pdat, 0x88); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x08); + r61520_lcd_dat(pdat, 0x0a); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x23); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0xd0); + r61520_lcd_dat(pdat, 0x07); + r61520_lcd_dat(pdat, 0xc6); + r61520_lcd_dat(pdat, 0xdc); + + r61520_lcd_cmd(pdat, 0xd1); + r61520_lcd_dat(pdat, 0x54); + r61520_lcd_dat(pdat, 0x0d); + r61520_lcd_dat(pdat, 0x02); + + r61520_lcd_cmd(pdat, 0xd2); + r61520_lcd_dat(pdat, 0x63); + r61520_lcd_dat(pdat, 0x24); + + r61520_lcd_cmd(pdat, 0xd4); + r61520_lcd_dat(pdat, 0x63); + r61520_lcd_dat(pdat, 0x24); + + r61520_lcd_cmd(pdat, 0xd8); + r61520_lcd_dat(pdat, 0x07); + r61520_lcd_dat(pdat, 0x07); + + r61520_lcd_cmd(pdat, 0xe0); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0x13); + + r61520_lcd_cmd(pdat, 0x20); + + r61520_lcd_cmd(pdat, 0x35); + r61520_lcd_dat(pdat, 0x00); + + r61520_lcd_cmd(pdat, 0x44); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x30); + + r61520_lcd_cmd(pdat, 0x36); + r61520_lcd_dat(pdat, 0xe0); + + r61520_lcd_cmd(pdat, 0x3a); + r61520_lcd_dat(pdat, 0x55); + + r61520_lcd_cmd(pdat, 0x2a); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x01); + r61520_lcd_dat(pdat, 0x3f); + + r61520_lcd_cmd(pdat, 0x2b); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0x00); + r61520_lcd_dat(pdat, 0xef); + + r61520_lcd_cmd(pdat, 0x11); + r61520_lcd_cmd(pdat, 0x29); + r61520_lcd_cmd(pdat, 0x2c); +} + static struct device_t * fb_f1c100s_probe(struct driver_t * drv, struct dtnode_t * n) { struct fb_f1c100s_pdata_t * pdat; @@ -298,23 +568,24 @@ pdat->virtdefe = phys_to_virt(F1C100S_DEFE_BASE); pdat->virtdebe = phys_to_virt(F1C100S_DEBE_BASE); pdat->virttcon = phys_to_virt(F1C100S_TCON_BASE); + pdat->virtgpio = phys_to_virt(F1C100S_GPIO_BASE); pdat->clkdefe = strdup(clkdefe); pdat->clkdebe = strdup(clkdebe); pdat->clktcon = strdup(clktcon); pdat->rstdefe = dt_read_int(n, "reset-defe", -1); pdat->rstdebe = dt_read_int(n, "reset-debe", -1); pdat->rsttcon = dt_read_int(n, "reset-tcon", -1); - pdat->width = dt_read_int(n, "width", 800); - pdat->height = dt_read_int(n, "height", 400); + pdat->width = dt_read_int(n, "width", 320); + pdat->height = dt_read_int(n, "height", 240); pdat->pwidth = dt_read_int(n, "physical-width", 216); pdat->pheight = dt_read_int(n, "physical-height", 135); - pdat->bits_per_pixel = dt_read_int(n, "bits-per-pixel", 18); - pdat->bytes_per_pixel = dt_read_int(n, "bytes-per-pixel", 4); + pdat->bits_per_pixel = dt_read_int(n, "bits-per-pixel", 16); + pdat->bytes_per_pixel = dt_read_int(n, "bytes-per-pixel", 2); pdat->index = 0; pdat->vram[0] = dma_alloc_noncoherent(pdat->width * pdat->height * pdat->bytes_per_pixel); pdat->vram[1] = dma_alloc_noncoherent(pdat->width * pdat->height * pdat->bytes_per_pixel); - pdat->timing.pixel_clock_hz = dt_read_long(n, "clock-frequency", 33000000); + pdat->timing.pixel_clock_hz = dt_read_long(n, "clock-frequency", 8000000); pdat->timing.h_front_porch = dt_read_int(n, "hfront-porch", 40); pdat->timing.h_back_porch = dt_read_int(n, "hback-porch", 87); pdat->timing.h_sync_len = dt_read_int(n, "hsync-len", 1); @@ -371,6 +642,8 @@ } dev->driver = drv; + sunxi_lcdc_gpio_config(pdat, 1); + r61520_lcd_init(pdat); return dev; } --- src/arch/arm32/mach-f1c100s/include/f1c100s/reg-gpio_orig.h +++ src/arch/arm32/mach-f1c100s/include/f1c100s/reg-gpio.h @@ -1,55 +0,0 @@ +/* + * Copyright (C) 2018 Steward Fu <steward.fu@gmail.com> + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option)any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef __REG_GPIO_H__ +#define __REG_GPIO_H__ + +#define F1C100S_GPIO_BASE 0x01c20800 + +#define PD_CFG0 ((3*0x24)+0x00) //Port n Configure Register 0 (n=0~5) +#define PD_CFG1 ((3*0x24)+0x04) //Port n Configure Register 1 (n=0~5) +#define PD_CFG2 ((3*0x24)+0x08) //Port n Configure Register 2 (n=0~5) +#define PD_CFG3 ((3*0x24)+0x0C) //Port n Configure Register 3 (n=0~5) +#define PD_DATA ((3*0x24)+0x10) //Port n Data Register (n=0~5) +#define PD_DRV0 ((3*0x24)+0x14) //Port n Multi-Driving Register 0 (n=0~5) +#define PD_DRV1 ((3*0x24)+0x18) //Port n Multi-Driving Register 1 (n=0~5) +#define PD_PUL0 ((3*0x24)+0x1C) //Port n Pull Register 0 (n=0~5) +#define PD_PUL1 ((3*0x24)+0x20) //Port n Pull Register 1 (n=0~5) + +#define PD_INT_CFG0 (0x200+(n*0x20)+0x0) //PIO Interrupt Configure Register 0 (n=0~2) +#define PD_INT_CFG1 (0x200+(n*0x20)+0x4) //PIO Interrupt Configure Register 1 (n=0~2) +#define PD_INT_CFG2 (0x200+(n*0x20)+0x8) //PIO Interrupt Configure Register 2 (n=0~2) +#define PD_INT_CFG3 (0x200+(n*0x20)+0xC) //PIO Interrupt Configure Register 3 (n=0~2) +#define PD_INT_CTRL (0x200+(n*0x20)+0x10) //PIO Interrupt Control Register (n=0~2) +#define PD_INT_STA (0x200+(n*0x20)+0x14) //PIO Interrupt Status Register (n=0~2) +#define PD_INT_DEB (0x200+(n*0x20)+0x18) //PIO Interrupt Debounce Register (n=0~2) + +#define PE_CFG0 ((3*0x24)+0x00) //Port n Configure Register 0 (n=0~5) +#define PE_CFG1 ((3*0x24)+0x04) //Port n Configure Register 1 (n=0~5) +#define PE_CFG2 ((3*0x24)+0x08) //Port n Configure Register 2 (n=0~5) +#define PE_CFG3 ((3*0x24)+0x0C) //Port n Configure Register 3 (n=0~5) +#define PE_DATA ((3*0x24)+0x10) //Port n Data Register (n=0~5) +#define PE_DRV0 ((3*0x24)+0x14) //Port n Multi-Driving Register 0 (n=0~5) +#define PE_DRV1 ((3*0x24)+0x18) //Port n Multi-Driving Register 1 (n=0~5) +#define PE_PUL0 ((3*0x24)+0x1C) //Port n Pull Register 0 (n=0~5) +#define PE_PUL1 ((3*0x24)+0x20) //Port n Pull Register 1 (n=0~5) + +#define SDR_PAD_DRV 0x2C0 //SDRAM Pad Multi-Driving Register +#define SDR_PAD_PUL 0x2C4 //SDRAM Pad Pull Register + +#endif --- src/arch/arm32/mach-f1c100s/include/f1c100s/reg-tcon_orig.h +++ src/arch/arm32/mach-f1c100s/include/f1c100s/reg-tcon.h +#define F1C100S_TCON_BASE (0x01c0c000) +#define TCON0_CPU_IF_REG 0x060 //TCON0 CPU Interface Control Register +#define TCON0_CPU_WR_REG 0x064 //TCON0 CPU Mode Write Register
完成