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
通过 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)。
# 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 上。
# echo 1 > /sys/devices/omapdss/display0/update_mode
# cat /mnt/sdcard/umts_sholes.fb > /dev/graphics/fb0
这一节中提到的DSS.DISPC_GFX_BAj registers 就是要写 framebuffer SDRAM Address 的寄存器。
看下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)
//调用流程
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);
前世今生:
为什么又翻出了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
# 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
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_t fb_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 !
有疑问加站长微信联系(非本文作者)
本文来自:CSDN博客
感谢作者:chenqiang0721
查看原文:Milestone/umts_sholes/OMAP3430 DSS(Display Sub-System) Go-Through