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

完成


返回上一頁