這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
Milestone/umts_sholes/OMAP3430 DSS(Display Sub-System) Go-Through
前世今生:
為什麼又翻出了10年入手的Milestone,費時費力sync 了github 上的代碼,編譯umts_sholes 工程?
一個關於通過讀寫 fb0裝置節點讀寫LCD屏的問題,現在高通的解決方案MSM8974/MSM8x26通過讀寫fb0 裝置節點都
不能完成讀寫LCD屏操作。
完全弄清楚這個問題首先需要理解Tiny6410/Milestone 是如何通過讀寫fb0 裝置節點完成讀寫LCD 屏的。
印象中 CM7 umts_sholes 採用 2ndboot 啟動核心的ROM就是通過寫 /dev/graphics/fb0 這個裝置節點將2ndboot 的image 刷到LCD 上的。
因此,研究了一下 OMAP3430 DSS。廢話不多說,用代碼 TRM 說明問題。
/home/CORPUSERS/xxxx/projects/umts_sholes/out/target/product/umts_sholes/system/bin/sh_hijack.sh
#!/system/bin/sh echo 32 > /sys/devices/platform/omapfb/graphics/fb0/bits_per_pixel echo 1 > /sys/devices/omapdss/display0/update_mode /system/bin/busybox_static gunzip -c /etc/2ndboot/2ndboot.fb.gz > /dev/graphics/fb0 /system/bin/busybox_static insmod /etc/2ndboot/hbootmod.ko > /cache/2ndboot.log 2>&1 /system/bin/busybox_static mknod /dev/hbootctrl c 245 0 >> /cache/2ndboot.log 2>&1 echo 255 > /sys/class/leds/green/brightness /system/bin/hbootuser /etc/2ndboot/hboot.cfg >> /cache/2ndboot.log 2>&1 /system/bin/busybox_static sleep 10
通過 Omap3430-trm.pdf (http://www.droid-developers.org/images/0/0b/Omap3430-trm.pdf),可以看到 OMAP3430 DSS主要的module: Display Controller Module(DISPC), Display Serial Interface(DSI),Serial Display Interface(SDI CONFIG_OMAP2_DSS_SDI
沒有開啟,因此umts_sholes 並沒有使用SDI,使用的是DSI)。
The Big Picture
Milestone 通過fb0 裝置節點刷LCD 的方法:
# cat /dev/graphics/fb0 > /mnt/sdcard/umts_sholes.fb
//強制刷 LCD 之前需要將 update_mode 設定為1, auto update 模式,預設情況下update mode 是Manual update mode。
Manual update mode 下需要設定 dirty 才能真正寫到 LCD 上。
enum omapfb_update_mode {OMAPFB_UPDATE_DISABLED = 0,OMAPFB_AUTO_UPDATE,OMAPFB_MANUAL_UPDATE};
static int dsi_update_thread(void *data){struct omap_dss_device *device;u16 x, y, w, h;u8 num_timeouts = 0;u8 num_success = 0;while (1) {bool sched;wait_event_interruptible(dsi.waitqueue,dsi.update_mode == OMAP_DSS_UPDATE_AUTO ||(dsi.update_mode == OMAP_DSS_UPDATE_MANUAL && dsi.update_region.dirty == true) ||kthread_should_stop());if (kthread_should_stop())break;
# echo 1 > /sys/devices/omapdss/display0/update_mode
# cat /mnt/sdcard/umts_sholes.fb > /dev/graphics/fb0
讀寫 /dev/graphics/fb0 字元裝置節點對應執行的驅動file_operations fb_fops 位於fbmem.c,
static const struct file_operations fb_fops = {.owner =THIS_MODULE,.read =fb_read,.write =fb_write,.unlocked_ioctl = fb_ioctl,#ifdef CONFIG_COMPAT.compat_ioctl = fb_compat_ioctl,#endif.mmap =fb_mmap,.open =fb_open,.release =fb_release,#ifdef HAVE_ARCH_FB_UNMAPPED_AREA.get_unmapped_area = get_fb_unmapped_area,#endif#ifdef CONFIG_FB_DEFERRED_IO.fsync =fb_deferred_io_fsync,#endif};
static ssize_tfb_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos){//這個函數指標是 NULL.if (info->fbops->fb_write)return info->fbops->fb_write(info, buf, count, ppos);//真正完成寫 LCD 的有效代碼是這一段//info->screen_base 儲存的是 framebuffer SDRAM 中的Virtual Address,//這塊記憶體位址 在DSS driver 中會配到DISPC Display Controller 的一個寄存器中,// Dispc 負責將 SDRAM 中的這段記憶體資料搬運通過資料線發給 LCD.dst = (u32 __iomem *) (info->screen_base + p);while (count) {c = (count > PAGE_SIZE) ? PAGE_SIZE : count;src = buffer;if (copy_from_user(src, buf, c)) {err = -EFAULT;break;}for (i = c >> 2; i--; )fb_writel(*src++, dst++);if (c & 3) {u8 *src8 = (u8 *) src;u8 __iomem *dst8 = (u8 __iomem *) dst;for (i = c & 3; i--; )fb_writeb(*src8++, dst8++);dst = (u32 __iomem *) dst8;}*ppos += c;buf += c;cnt += c;count -= c;}
Omap3430-trm.pdf <Display Subsystem Basic Programming Model>
這一節中提到的DSS.DISPC_GFX_BAj registers 就是要寫 framebuffer SDRAM Address 的寄存器。
15.5.3.2 Graphics Layer Configuration
15.5.3.2.1 Graphics DMA Registers
15.5.3.3 Video Layer Configuration
15.5.3.3.1 Video DMA Registers
看下Driver 的結構
~/projects/umts_sholes/kernel/drivers/video/omap2$ tree
.
├── displays
│ ├── Kconfig
│ ├── Makefile
│ ├── omap-panel.c
│ ├── panel-mapphone.c
├── dss
│ ├── core.c
│ ├── dispc.c
│ ├── display.c
│ ├── dpi.c
│ ├── dsi.c
│ ├── dss.c
│ ├── dss.h
│ ├── Kconfig
│ ├── Makefile
│ ├── manager.c
│ ├── overlay.c
│ ├── rfbi.c
│ └── venc.c
├── Kconfig
├── Makefile
├── misc
│ ├── dispsw.c
│ ├── dispsw-mr.c
│ ├── dispsw-mr.h
│ ├── dispsw-rotate.c
│ ├── dispsw-rotate.h
│ ├── Kconfig
│ └── Makefile
├── omapfb
│ ├── Kconfig
│ ├── Makefile
│ ├── omapfb.h
│ ├── omapfb-ioctl.c
│ ├── omapfb-main.c
│ └── omapfb-sysfs.c
├── vram.c
└── vrfb.c
4 directories, 41 files
~/projects/umts_sholes/kernel/drivers/video/omap2$ grep -nr "DISPC_GFX" .
./dss/dispc.c:75:#define DISPC_GFX_BA0 DISPC_REG(0x0080)
./dss/dispc.c:76:#define DISPC_GFX_BA1 DISPC_REG(0x0084)
./dss/dispc.c:77:#define DISPC_GFX_POSITION DISPC_REG(0x0088)
./dss/dispc.c:78:#define DISPC_GFX_SIZE DISPC_REG(0x008C)
./dss/dispc.c:79:#define DISPC_GFX_ATTRIBUTES DISPC_REG(0x00A0)
./dss/dispc.c:80:#define DISPC_GFX_FIFO_THRESHOLD DISPC_REG(0x00A4)
./dss/dispc.c:81:#define DISPC_GFX_FIFO_SIZE_STATUSDISPC_REG(0x00A8)
./dss/dispc.c:82:#define DISPC_GFX_ROW_INC DISPC_REG(0x00AC)
./dss/dispc.c:83:#define DISPC_GFX_PIXEL_INC DISPC_REG(0x00B0)
./dss/dispc.c:84:#define DISPC_GFX_WINDOW_SKIP DISPC_REG(0x00B4)
./dss/dispc.c:85:#define DISPC_GFX_TABLE_BA DISPC_REG(0x00B8)
./dss/dispc.c:95:#define DISPC_GFX_PRELOAD DISPC_REG(0x022C)
static void _dispc_set_plane_ba0(enum omap_plane plane, u32 paddr){const struct dispc_reg ba0_reg[] = { DISPC_GFX_BA0,DISPC_VID_BA0(0),DISPC_VID_BA0(1) };dispc_write_reg(ba0_reg[plane], paddr);//paddr 就是framebuffer SDRAM中對應的物理地址}
//調用流程
dsi_update_thread
-> dss_setup_partial_planes
-> configure_dispc(void)
-> configure_overlay
-> _dispc_setup_plane
-> _dispc_set_plane_ba0(plane, paddr + offset0);
-> _dispc_set_plane_ba1(plane, paddr + offset1);
關於 sync/build umts_sholes 原始碼,請參考以下文章:
http://blog.csdn.net/fervor_heart/article/details/10060557
That's All ! Thanks !