genodelabs / genode

Genode OS Framework
https://genode.org/
Other
1.07k stars 253 forks source link

arndale & framebuffer: FB-to-HDMI support #796

Closed m-stein closed 10 years ago

m-stein commented 11 years ago

Enable the use of the Arndale HDMI as output device behind the Genode framebuffer session.

m-stein commented 11 years ago

According to this there seems to be no Android version that supports HDMI on Arndale by now.

m-stein commented 11 years ago

Linaro Linux executes exynos_drm_init just fine, having all IPs enabled (FIMD, HDMI, VIDI, G2D), but it doesn't touch any other function in drivers/video/exynos/ and drivers/gpu/drm/exynos/.

nfeske commented 11 years ago

It is worthwhile to check the insignal forum (http://forum.insignal.co.kr/viewforum.php?f=10) for HDMI-related topics. For example:

Unfortunately, the search function of the forum does not seem to work well. So you'd need to go through the topics manually to find the interesting pieces.

m-stein commented 11 years ago

Thank you for the hint :-)

m-stein commented 11 years ago

I have an Android that puts a signal onto HDMI. Although the output is all black by now and the HDMI driver disconnects after a while with proc_dir_entry '479/hdmi' already registered, followed by a bactrace, and s5p-hdmi exynos5-hdmi: HDMI interrupt source is changed : external a MMIO-access trace might already provide enough information about HDMI initialization.

By now i can get Trace32 to log all commands that are executed by the CPU and list them afterwards. Unfortunately the so called Analyzer, wich is responsible for such tracing, is a bit of a swiss army knife wich is why i need more time to learn how to limit tracing to specific non-virtual MMIO ranges and maybe also how to export into a non-cryptic format.

m-stein commented 11 years ago

Real-time tracing feature of TRACE32 is of no use for MMIO tracing on Arndale. The according strategy would be to set breakpoints that are triggered by read/write access at a specific address range and configure them to execute appropriate tracing commands like traceon, traceoff or tracedata. Unfortunately for Arndale range-access triggered tracing-commands are not supported regardless of wether they're done on-chip, by software infusion or by debugging hardware. Thus i try to collect access information manually by using range-access triggered breakpoints that simply stop execution.

m-stein commented 11 years ago

HDMI MMIO is physically readable by the debugger only before the Linux kernel gets started and then again after Linux starts initializing HDMI. Trying to read from these adresses in the intervening time leads to a bus error.

m-stein commented 11 years ago

I've set-up physical read/write breaks for HDMI, Power Manager, and Clock Manager via break.set A:00:0x[start_base]0000--0x[end_base]ffff /ReadWrite /onchip but they get not triggered at all (while HDMI definitely gets initialized by Android).

m-stein commented 11 years ago

However, dumping HDMI MMIO physically while execution is paused before Linux starts and after HDMI has been initialized indicates that the address class and the addresses of the breakpoints are fine and that Android modifies the HDMI regs in harmony with the Arndale manual.

m-stein commented 11 years ago

I could not figure out how to prevail on Arndale breakpoint logic to stop on MMIO access. Thus i'll now try to marry an Android prebuilt by InSignal with a custom-built Linux kernel.

m-stein commented 11 years ago

Getting the Linux version and build parameters from the Arndale Android tutorial ends up in several not-so-simple shellscripts that shall keep building easy and flexible. Thus i prefer to build the whole thing and try to extract the ready-to-use Linux afterwards.

nfeske commented 11 years ago

Thanks for keeping the issue up to date. This way of documenting the steps is very much appreciated!

Maybe one day, we will find out how to gather proper MMIO traces via Trace32. ;-)

astarasikov commented 11 years ago

Instead of using the HW Debugger I suggest tracing MMIO in the linux kernel. I have two ideas

Sorry, I can not help you more. I was unable to order an Arndale, and got OMAP5432UEVM instead.

m-stein commented 11 years ago

@astarasikov: Thank you for your encouraging suggestions Alexander. My current plan is to use wrappers as you mentioned in your first idea. I've done it this way for Arndale AHCI also and it worked fine but if it fails i'll give the other ideas a try.

m-stein commented 11 years ago

It took some time to produce a Linux image with the Android repo because of some broken Make variables and some wrong decisions i've made while trying to fix the symptoms. Now i have an uncompressed Linux image as well as the boot args from prebuilt Android's /proc/cmdline. Unfortunately i have to pause work at this state for about 3 weeks. The next step will be to manually compose a uImage because the Android build tools don't do it, find out the initrd address of the eMMC Android, build a dtb via the Android build tools or find out the address of the eMMC dtb, boot Arndale, load custom Linux (and dtb) via TFTP, and boot via bootm [linux_addr] [initrd_addr] [dtb_addr].

astarasikov commented 11 years ago

On Jul 12, 2013 8:58 PM, "Martin Stein" notifications@github.com wrote:

It took some time to produce a Linux image with the Android repo because of some broken Make variables and some wrong decisions i've made while trying to fix the symptoms. Now i have an uncompressed Linux image, the boot args from prebuilt Android's /proc/cmdline. Unfortunately i have to pause work at this state for about 3 weeks. The next step would be to manually compose a uImage because the Android build tools don't do it, find out the initrd address of the eMMC Android, build a dtb via the Android build tools or find out the address of the eMMC dtb, boot Arndale in eMMC mode, load custom Linux (and dtb) via TFTP, and boot via boot [linux_addr] [initrd_addr] [dtb_addr].

I suggest that you edit the kernel config via the 'make menuconfig' option. you can unpack the initrd with cpio and the build the initramfs into the kernel image. To build dtb, do "make scripts/dts" or sth like that and use the dtc tool to compile a dts in arch/arm/boot. Then you can enable the config option and append the dtb to the zImage. This way you don't have to mess with addresses and can pack a minimal rootfs with ssh and bash to initrd.

— Reply to this email directly or view it on GitHub.

m-stein commented 11 years ago

@astarasikov: Thank you for the suggestion, i'll try that.

m-stein commented 11 years ago

I've updated android/linux sources, toolchain and external tools and found that kernel_make menuconfig/xconfig end up in lots of compile errors. Since i'm not interested in debugging them or using kernel_make config i'll continue without merging zImage, initrd, and dtb.

m-stein commented 11 years ago

To avoid kernel compile errors with the new sources one must replace

EXTRA_CFLAGS += -DUMP_SVN_REV=$(SVN_REV)
EXTRA_CFLAGS += -DUMP_SVN_REV_STRING=\"$(SVN_REV)\"

in ./kernel/drivers/gpu/vithar_rev0/ump/src/devicedrv/Makefile.common and ./kernel/drivers/gpu/vithar/ump/src/devicedrv/Makefile.common with

EXTRA_CFLAGS += -DUMP_SVN_REV=${MALI_RELEASE_NAME}
EXTRA_CFLAGS += -DUMP_SVN_REV_STRING=\"${MALI_RELEASE_NAME}\"

because without this replacement both vars may get set to "Unversioned directory" wich is not of the expected format.

m-stein commented 11 years ago

I'm now able to start Arndale Android with a custom Linux as follows:

# at host go to your Android working directory, customize Linux (./kernel/) and do:
kernel_make -j2
# insert SD card into host slot and mount it to '/media/sd/'
cp arch/arm/boot/zImage /media/sd/
umount /media/sd
# insert SD card into Arndale slot, start Arndale with eMMC bootmode, interrupt into uboot prompt and do:
fatload mmc 1:1 0x40008000 zImage
setenv bootargs 'console=ttySAC2,115200n8 vmalloc=512M androidboot.console=ttySAC2'
movi read rootfs 0 41000000 100000
bootm 40008000 41000000
m-stein commented 11 years ago

Android kernel config is a little inflexible - many thinning options lead to compile errors. I was able to deactivate the following features without also disturbing HDMI init:

m-stein commented 11 years ago

@nfeske: As you suggested, i've tried to deconfig further devices with pragmatic workarounds for the implied compile errors but since it ended in kernel panics or dead HDMI for all devices i've tried, i prefer to fall back to more restrictive tracing rules.

m-stein commented 11 years ago

I'm now able to selectively print MMIO tracing of HDMI controller, Display controller, and Graphic Mixers as well as CMU, PMU, GPIO and PIC till and while LCD gets a valid signal from Android.

m-stein commented 11 years ago

I've classified nearly all MMIO regions wether they are interesting, maybe later interesting, or not interesting for the HDMI project. For the interesting regions i've also enriched tracing info and picked out single "bad" addresses that solely bloat the trace, such as interrupt acknowledgment (blacklist).

m-stein commented 11 years ago

I've tried to switch to another boot procedure that uses SD bootmode. This way it would have been possible to use TFTP instead of transferring the zImage via SD card wich is slow and scuffs card HW. The uboot cmds would have been:

usb start; dhcp
setenv serverip x.x.x.x
tftp 0x40008000 /var/lib/tftpboot/zImage
mmc dev 2
mmc read 0x41000000 0x2427 0x800
setenv bootargs 'console=ttySAC2,115200n8 vmalloc=512M androidboot.console=ttySAC2'
bootm 0x40008000 0x41000000

The problem is, that the bootm of our SD uboot doesn't support zImage format in contrast to the bootm of the eMMC uboot. Thus i tried to do kernel_make uImage and tftp 0x40008000 /var/lib/tftpboot/uImage but then the boot attempt stucks after:

## Booting kernel from Legacy Image at 40008000 ...
   Image Name:   Linux-3.0.31-gfe3dd84
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    3553256 Bytes = 3.4 MiB
   Load Address: 40008000
   Entry Point:  40008000
   Verifying Checksum ... OK
## Loading init Ramdisk from Legacy Image at 41000000 ...
   Image Name:   Android Ramdisk Image
   Image Type:   ARM Linux RAMDisk Image (uncompressed)
   Data Size:    167601 Bytes = 163.7 KiB
   Load Address: 40800000
   Entry Point:  40800000
   Verifying Checksum ... OK
   XIP Kernel Image ... OK
Starting kernel ...

I assumed that this comes from a broken uImage creation in Androids kernel_make since Android doesn't need the uImage. Thus i manually created uImage from vmlinux but since Androids vmlinux has load/entry address 0xc0008000 (in contrast to Androids zImage with 0x40008000) and Arndale then throws a prefetch abort at 0xc0008004 (the address doesn't exist physically at Arndale), i assume that with non-Android Linux (our normal Arndale Linux has also 0xc0008000) the MMU gets configured appropriately before jumping to 0xc0008000. This lead to the idea that Linux startup code should be position independent and i tried mkimage -A arm -O linux -T kernel -C gzip -a 0x40008000 -e 0x40008000 -d vmlinux.bin uImage to preempt the vmlinux settings. Unfortunately boot attempt now stucked again after Starting kernel ... (using tftp 0x50000000 /var/lib/tftpboot/uImage and bootm 0x50000000 0x41000000 to avoid gunzip overlap error)

Long story short, i have to fall back to the eMMC bootmode solution to continue tracing.

m-stein commented 11 years ago

I've created a framebuffer server basement and a simple run test for Arndale HDMI. I've also ported the (as far as i can estimate by now) HDMI-related parts of Linux's initial CMU/PMU configuration and tested it.

m-stein commented 11 years ago

I've ported the initial I2C communication with the HDMI PHY controller. I was able to reuse the class I2c_master from the Exynos5 AHCI driver, wich should thus be moved to an own header in os/include/drivers/i2c/. Thereby i found incoherence between the tracing output and the Linux sources that lead me to a bug in my tracing patches. Thus i had to check my preliminary work against the new tracing output.

m-stein commented 11 years ago

There is MMIO that is accessed by Linux through functions whose definitions i can't find in the sources or through objectdumps. Some of them are related to the Gscaler so i hope they're not relevant for HDMI since i've no idea how to find the physical locations of these regions.

m-stein commented 11 years ago

Unfortunately the I2C driver in Linux changed between my Android Linux version (older) and the Linux version that was used for AHCI tracing (newer). In the AHCI Linux HDMI PHY I2C is treated as quirk since it may hang up during operation. So since i must assume that my AHCI tracing differs from a quirked operating sequence i decide to follow the Android version. Btw. also the config that Android uses for HDMI PHY isn't one of the options the spec defines (spec simply provides static configs for several pixel clock ratios).

m-stein commented 11 years ago

I've modified I2C transmit to act as in the Android Linux version and extended the driver by I2C receive since Linux also reads HDMI PHY config.

For any reason the HDMI PHY controller doesn't give a feedback - neither via IRQ session, ACK bit or IRQ_PENDING bit. I'll try to get information from both, the newer and the older Linux driver how this might be fixed.

m-stein commented 11 years ago

The status quo of this issue gets pushed to https://github.com/m-stein/genode/tree/issue796. I'll not tag the commits at this branch as long as the branch history isn't suitable for genodelabs/master (this would cause ref-message chaos on rebasing).

m-stein commented 11 years ago

Now i receive feedback via I2C from the HDMI PHY controller. I'd missed to set a crucial CMU bit because the tracing filters were to restrictive.

m-stein commented 11 years ago

The first HDMI PHY config via I2C and the following CMU/PMU config until first TV MIXER config succeed. Next step is to configure TV MIXER and HDMI CTRL.

m-stein commented 11 years ago

Initial TV MIXER config is done.

m-stein commented 11 years ago

I'm a little clueless: I have an MMIO region that is accessible from within core but throws an asynchronous external data abort when accessed from within the framebuffer driver. The raw pagetable entries for core and FB driver differ only in the mapping size (FB driver uses a small page and core uses a section). All other mapping attrributes are the same.

m-stein commented 11 years ago

Indeed, the access in core failed too after some repetitions and the access in FB drive succeeded sporadically. The trick can be found in platform driver: As long as clocks and/or power lines of the Arndale display controller (Touchscreen) are disabled the distinct video mixer in turn acts broken. In this case, access to video mixer MMIO may read/write bogus values or cause asynchronous external aborts.

m-stein commented 11 years ago

A first phase of HDMI CTRL config (SW reset HDMI CORE and HDMI PHY), a second phase of HDMI PHY config via I2C (now fully configured for 27.027 MHz pixel clock), and a second phase of TV MIXER config (more detailed e.g. input-channel specific configs) are ported and tested.

m-stein commented 11 years ago

Instead of receiving the HDMI HPD-plug interrupt after HDMI init, the driver receives an HDMI HPD-unplug interrupt although the HDMI monitor is plugged in. No further interrupt is received when unplugging and plugging in again the HDMI monitor at runtime.

m-stein commented 11 years ago

Ignoring the IRQ problem by now, the HDMI-core config has been ported, leaving only the config of the HDMI timing-generator.

m-stein commented 11 years ago

HDMI timing-generator config is ported and tested.

m-stein commented 11 years ago

As printk in delay functions is a bad idea in Linux i first modify CMU/PMU-config in Genode in a way that is not done at once at the beginning but distributed over the whole HDMI config as in Linux. If this does not solve the IRQ problem i'll fiddle with the CMU/PMU-config timing.

m-stein commented 11 years ago

The HDMI-init trace is not complete: The trace ends in the mid of a function and then continuously shows the video-mixer IRQ handler. First intention was that the IRQ handler suppresses HDMI init because of higher priority but when thwarting IRQ handler via 5 sec delay (before it requests a lock) HDMI init still discontinues.

m-stein commented 11 years ago

LCD gets a signal from Genode now (Power LED lights green).

m-stein commented 11 years ago

We're now at the same state as Linux. Since Linux doesn't init any of the two graphic inputs at the video mixer in a way that they can be used, there is only GSCALER video input left (which we don't want to use). So Genode doesn't put a picture on screen even with a buffer installed at a graphic input subsequently. Although we're not looking for a GSCALER solution it would be nice to have an Android with HDMI output other than signal LED. Unfortunately, upgrading Android sources and rebuilding kernel has not fixed this problem, so i'll now go through HDMI related components and try to understand and modify ported Linux config with the help of Arndale spec and Genodes OMAP-HDMI driver.

m-stein commented 11 years ago

Genode driver is now able to get an HPD-plugged IRQ for HDMI but in contrast to Android it is received only when HDMI connector gets plugged in and not if it is already plugged in.

m-stein commented 11 years ago

Androids pad-control config is ported and HPD-plugged IRQ for HDMI is now received even if HDMI is already plugged in. When connector gets plugged in after start-up the driver awakes sometimes with both, plugged and unplugged IRQ triggered. This might be due to an unstable phase while connecting and could be avoided later via the HPD-state filter feature in HDMI CONTROL, which isn't used by Android.

m-stein commented 11 years ago

I was not able to persuade eMMC Android with self-built Linux to ignore the fact that no touchscreen is available and output HDMI picture anyhow. There's another option: Although Insignal Exynos5 forum is obviously abandoned in the meantime, older posts suggest that self-building complete Android from latest sources could enable HDMI output. So i'll try this first and then try self-made HDMI config.

m-stein commented 11 years ago

Have built Android (with proprietaries vendor_samsung_slsi_exynos5250_jb_20130419_6610f80 and vendor_insignal_arndale_jb_20130119_5bfcd73) + Kernel + uBoot (with Linaro arm-2009q3). Now trying to create SD card to boot from.

m-stein commented 11 years ago

Creating SD card with latest mksdboot from Androids env-setup as mentioned in the wiki failed. Then tried an old version of mksdboot (throws no errors in contrast to latest version) but COM port is still silent.

m-stein commented 11 years ago

Created SD card successfully:

# at Arndale eMMC mode read uboot env from eMMC
mmc read 0 0x41000000 1031 32
md.b 0x41000000 0x4000

# copy hex dump to host file env.hex, at host convert to ASCII
cd <Android_repo>
cat env.hex | perl -ne 's/([0-9a-f]{2})/print chr hex $1/gie' > env.txt

# modify device/samsung/arndale/conf/vold.fstab
-dev_mount sdcard0 /storage/sdcard0 1 /devices/platform/dw_mmc.0/mmc_host/mmc0
-dev_mount sdcard1 /storage/sdcard1 auto /devices/platform/dw_mmc.2/mmc_host/mmc1 /devices/platform/dw_mmc.2/mmc_host/mmc2
-dev_mount usb /storage/usb1 auto /devices/platform/s5p-ehci
-dev_mount usb /storage/usb2 auto /devices/platform/exynos-xhci
+dev_mount sdcard0 /storage/sdcard0 1 /devices/platform/dw_mmc.2/mmc_host/mmc1
+dev_mount sdcard1 /storage/sdcard1 auto /devices/platform/dw_mmc.0/mmc_host/mmc0 +/devices/platform/dw_mmc.1/mmc_host/mmc2
+dev_mount usb /storage/usb1 auto /devices/platform/s5p-ehci
+dev_mount usb /storage/usb2 auto /devices/platform/exynos-xhci

# modify device/samsung/arndale/conf/fstab.arndale
-/dev/block/mmcblk0p2    /system             ext4      ro                                                    wait
-/dev/block/mmcblk0p4    /cache              ext4      noatime,nosuid,nodev,nomblk_io_submit,errors=panic    wait
-/dev/block/mmcblk0p3    /data               ext4      noatime,nosuid,nodev,nomblk_io_submit,noauto_da_alloc,errors=panic wait
+/dev/block/mmcblk1p2    /system             ext4      ro                                                    wait
+/dev/block/mmcblk1p4    /cache              ext4      noatime,nosuid,nodev,nomblk_io_submit,errors=panic    wait
+/dev/block/mmcblk1p3    /data               ext4      noatime,nosuid,nodev,nomblk_io_submit,noauto_da_alloc,errors=panic wait

# modify device/samsung/arndale/conf/init.arndale.rc
-service setup_fs /system/bin/setup_fs \
-            /dev/block/mmcblk0p3 \
-            /dev/block/mmcblk0p4
+service setup_fs /system/bin/setup_fs \
+            /dev/block/mmcblk1p3 \
+            /dev/block/mmcblk1p4

# modify system/core/rootdir/etc/mountd.conf
-    block_device    /dev/block/mmcblk0
+    block_device    /dev/block/mmcblk1

# re-build Android
source arndale_envsetup.sh
make -j2

# create SD-partitions
sudo fdisk /dev/mmcblk0
    o
    n p 1 3109568 7815167
    n p 2 62464 1078207
    n p 3 1078208 2093887
    n p 4 2093888 3109567
    t 1 c
    w

# format SD partitions
sudo mkfs.msdos -F 32 /dev/mmcblk0p1 -n SD1
sudo mkfs.ext4 -L SD2 /dev/mmcblk0p2
sudo mkfs.ext4 -L SD3 /dev/mmcblk0p3
sudo mkfs.ext4 -L SD4 /dev/mmcblk0p4

# flash boot region to SD
sudo dd if=vendor/insignal/arndale/exynos5250/exynos5250.bl1.bin of=/dev/mmcblk0 bs=512 seek=1
sudo dd if=u-boot/bl2.bin of=/dev/mmcblk0 bs=512 seek=31
sudo dd if=u-boot/u-boot.bin of=/dev/mmcblk0 bs=512 seek=63
sudo dd if=vendor/insignal/arndale/exynos5250/exynos5250.tzsw.bin of=/dev/mmcblk0 bs=512 seek=719
sudo dd if=env.txt of=/dev/mmcblk0 bs=512 seek=1031
sudo dd if=kernel/arch/arm/boot/zImage of=/dev/mmcblk0 bs=512 seek=1063
sudo dd if=out/target/product/arndale/ramdisk.img.ub of=/dev/mmcblk0 bs=512 seek=9255

# mount /dev/mmcblk0p2 to media/SD2, download make_ext4fs & simg2img from
# http://web.djodjo.org/?a=download:android:tools:x86_linux:ext4tools

# fill system partition
sudo mkdir /media/system
simg2img out/target/product/arndale/system.img system.raw
sudo mount -t ext4 -o loop system.raw /media/system
sudo cp -r /media/system/* /media/SD2/
umount /media/SD2