TI-Android-GingerBread-2.3.4-DevKit-2.1 PortingGuides

From Texas Instruments Wiki
Jump to: navigation, search

TIBanner.png


Contents

About this manual


Power Management

Introduction

Android supports its own Power Management (on top of the standard Linux Power Management) designed with the premise that the CPU shouldn't consume power if no applications or services require power.

Android requires that applications and services request CPU resources with "wake locks" through the Android application framework and native Linux libraries. If there are no active wake locks, Android will shut down the CPU.

Features Overview

Below are the features supported in TI-Android-GingerBread-2.3.4-DevKit-2.1

AM37X, OMAP35X

  • Change of LCD backlights based on Wake Locks and Screen Timeouts (DIM,OFF)
  • LCD back light brightness control from Settings Application
  • Suspending the device to Memory.The device can be suspended in two ways.
    • Pressing the POWER key on the keypad
    • Allowing the system go to suspend after a screen timeout
  • Prevent Suspend based on Wake Locks
  • System Resume on Key Press
  • System Resume on Alarm
  • CPU Dynamic Voltage and Frequency Scaling (ondemand, performance, powersave and userspace governors)
  • CPU Idle States
  • Enabling system for hitting retention during idle
  • Enabling system for hitting OFF
  • Smart Reflex

AM35X

  • Suspending the device to Memory.The device can be suspended in two ways.
    • Pressing the POWER key on the keypad
    • Allowing the system go to suspend after a screen timeout
  • Prevent Suspend based on Wake Locks
  • System Resume on Key Press
  • Android Early Suspend Feature for frame buffer driver

Limitations

  • In beagle and am35x platforms there is no keypad connected to the wake up domain. So wake up is not possible by pressing keys. As a workaround, you can wake up am35x platform like below
    • Press ENTER on Serial Port console and then press any key on the keypad to wake up the device.
  • If the usb device connected to the USB EHCI port when suspending the device, it might not work properly after resume. So Disconnect any usb device connected to USB EHCI port when suspending the device and connect it after resume.
  • In Suspend, If USB OTG cable is connected, it makes Powerdomain (core_pwrdm) not entering to sleep State
  • Inserting and Removing USB OTG cable continuously after suspend-resume makes system hang sometimes

Android PM Sub-System Overview

Pm block.JPG

Driver Configuration

Suspend Resume

-*- Power Management support
│ │[*] Power Management Debug Support
│ │[ ] Extra PM attributes in sysfs for low-level debugging/testing
│ │[ ] Verbose Power Management debugging
│ │[*] Suspend to RAM and standby
│ │[ ] Test suspend/resume and wakealarm during bootup
│ │[*] Wake lock
│ │[*] Wake lock stats
│ │[*] Userspace wake locks
│ │[*] Early suspend
│ │User-space screen access (Sysfs interface) --->
│ │< > Advanced Power Management Emulation
│ │-*- Run-time PM core functionality
│ │-*- Operating Performance Point (OPP) Layer library 

Linux Suspend Resume Code is located at kernel/power

Android power management patches for wakelock feature and earlysuspend are present in wakelock.c and earlysuspend.c

Generic Device/Bus suspend resume code located at drivers/base/power/

Device/Bus level suspend resume code in .suspend and .resume callbacks for each device driver or bus driver

Low level Suspend Resume Code in arch/arm/mach-omap2/pm34xx.c

CPU Idle

CPU Power Management --->
│ │ [*] CPU idle PM support


The default CPU Idle governor is menu governor and the code is located at drivers/cpuidle

Platform dependant cpu idle code which sets number of states, power domain status for each state is located at arch/arm/mach-omap2/cpuidle34xx.c

This code sets "exit_latency", "target_residency" and "idle state entering function"( platform dependant parameters used by the generic cpuidle driver to decide on state transition)

as well.

The function to for entering to idle state (omap_sram_idle) is defined at arch/arm/mach-omap2/pm34xx.c

CPU DVFS

CPU Power Management --->
│ │ [*] CPU Frequency scaling
│ │ [ ] Enable CPUfreq debugging
│ │ <*> CPU frequency translation statistics
│ │ [*] CPU frequency translation statistics details
│ │ Default CPUFreq governor (performance) --->
│ │ -*- 'performance' governor
│ │ <*> 'powersave' governor
│ │ <*> 'userspace' governor for userspace frequency scaling
│ │ <*> 'ondemand' cpufreq policy governor
│ │ < > 'interactive' cpufreq policy governor
│ │ < > 'conservative' cpufreq governor 


There are different generic CPU frequency governors like performance, powersave, userspace, ondemand etc to control transitions among various OPPs(Operating Points).

The code is located at drivers/cpufreq.

The definitions for various OPPs are defined at arch/arm/mach-omap2/opp3xxx_data.c

Smart Reflex

System Type ---> [*] TI OMAP Common Features ---> [*] SmartReflex support

System Type ---> [*] TI OMAP Common Features ---> [*] Class 3 mode of Smartreflex Implementation

Class 3 implementation of Smart Reflex employs continuous voltage calibration. The code changes are at arch/arm/mach-omap2/smartreflex-class3.c and arch/arm/mach-omap2/smartreflex.c

Android PM HAL Configuration

Android Power Manager Service

Android Power Manager controls the following features

  • Change of LCD backlights based on Wake Locks and Screen Timeouts (DIM,OFF)
  • LCD back light brightness control from Settings Application
  • Suspending the device to Memory.The device can be suspended in two ways.
  • Pressing the POWER key on the keypad
  • Allowing the system go to suspend after a screen timeout
  • Prevent Suspend based on Wake Locks
  • System Resume on Key Press

Android Power Management service defined at frameworks/base/services/java/com/android/server/PowerManagerService.java changes the states of the android device based on the user events and the screen timeouts. The same service provides wakelock feature for the android applications.

Android HAL for Power and Lights

hardware/libhardware_legacy/power/power.c defines the interfaces for wake locks and power states of the device.

hardware/ti/omap3/liblights/omap3evm/lights.c defines the interfaces for the sysfs path of lcd backlight.

Device Initialization

device/ti/omap3evm/init.rc

device/ti/am3517evm/init.rc

device/ti/beagleboard/init.rc

Power Management Sequence

Android Layer

Android Power management framework has the following responsibilities

  • The framework provides applications access to WAKELOCK, STATES, BACKLIGHT features of android kernel, thus
    • Applications can hold different wakelocks to keep the CPU on, partially on like that.
    • Android Settings application can control screen brightness
    • Android Key Press can put the system into suspend mode
  • The framework controls the various android power states based on timeouts and user activity
    • Refer to the below state diagrams which relates time and user events to various power states.

Time out behavior when we have set Stay Awake option is true

Time out behavior when we have set Stay Awake option is false

Time out behavior when we have set Stay Awake option is true

Time out behavior when we have set Stay Awake option is true

POWER Button behavior when we have set Stay Awake option is false

POWER Button behavior when we have set Stay Awake option is false

POWER Button behavior when we have Stay Awake option is true

POWER Button behavior when we have set Stay Awake option is false
The entry "setprop hw.nopm false" enables suspend and resume features.

These files are parsed by the android init program. So all the initial power management settings are done in init.rc

How to enable suspend/wake up feature for Keypad keys

How to designate a POWER key

Power key is the key which can suspend the Android system. In the Keypad mapping file you can designated one key as POWER key.

For example for omap3evm keypad mapping file, TWL4030_Keypad.kl(located at system/usr/keylayout ) key 105 is designated at POWER key.

How to designate keys as WAKE keys

Any key in the physical keypad can wake up the Android system. In the Keypad mapping file you can designated any key as WAKE key.

For example for omap3evm keypad mapping file, TWL4030_Keypad.kl(located at system/usr/keylayout ) some keys are designated as WAKE keys.

Some keys are designated as WAKE_DROPPED. Those keys can also wake up the system but the correspondinf Android functionality is not passed to the upper layers.

How to enable Touch Wake up/Resume

By default, Android does not support wake up from touch. See this link to understand the touch event flow in Android. After Android EventHub system receive events from kernel input layer, Touch events and Key events separated and passed to different upper layers. For touch events to wake Android and to bring the locked screen, the following method can be used.

  1. While touch event is being processed, Check if the screen is off.
  2. If the screen is off, Let Android WindowManager know that a wake event has occured.
  3. For this pass a fake key event intercept call form the input manager

The below patch in frameworks/base achieves this

--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -914,7 +914,15 @@ void NativeInputManager::interceptGenericBeforeQueueing(nsecs_t when, uint32_t&
 #if DEBUG_INPUT_DISPATCHER_POLICY
     LOGD("interceptGenericBeforeQueueing - when=%lld, policyFlags=0x%x", when, policyFlags);
 #endif
-
+    if (isScreenOn() == false) {
+          int32_t flags=0x8;
+          int32_t deviceId =0x0;
+          int32_t action =0x0;
+          int32_t keyCode =0x52;
+          int32_t scanCode =0x19;
+          uint32_t dpolicyFlags = 0x2000002;
+          interceptKeyBeforeQueueing(nsecs_t (when), deviceId, action, flags, keyCode, scanCode, dpolicyFlags);
+    }
     // Policy:
     // - Ignore untrusted events and pass them along.
     // - No special filtering for injected events required at this time.

How to change the Brighness Control Interface

The LCD _FILE global variable in hardware/ti/omap3/liblights/omap3evm/lights.c defines the interfaces for the sysfs path of lcd backlight.

For example LCD_FILE is specified as "/sys/class/backlight/sharp-ls/brightness" for omap3evm.

Android tries write values of range 0-255 to this interface. Need to modify the function set_light_backlight in hardware/ti/omap3/liblights/omap3evm/lights.c to calibrate this android values to the values expected by the lcd backlight driver interface.

Power Management Framework in Kernel

Suspend-Resume Feature

Suspend Resume Sequence

The normal Linux Suspend sequance is initiated by writing a value "mem" to "/sys/power/state" interface. This will be going to enter_state() in kernel/power/main.c.The detailed flow of the things are explained at http://kerneltrap.org/node/14004.

But in Android things are little bit different. Android Power manager service will write the value "mem" to "/sys/power/state" when the suspend sequence is initiated by the user or the screen timeout. In android patched kernel, it will be going to request_suspend_state() in kernel/power/earlysuspend.c. It calls the early suspend routines of all the drivers registered with the Android early suspend feature and checks whether any wakelocks preventing suspending are held. Once all the wakelocks are unlocked, the enter_state function in kernel/power/main.c is called. Then it follows the normal linux suspend sequence. In resume After normal linux resume sequence is completed, the late resume routines of all the drivers registered with the Android early suspend feature.

How to enable wake up capability to a device driver

There are two requirements for a device to be wake up capable.

  • The wake up event from the device should trigger any of the pins (GPIO bank 0 or any other configured wake up source) connected to the wake up domain of the cpu.
  • he device must be configured stay partially awake in suspended state in order to trigger the wake up event.

When the system enters a low power state, each device's driver is asked to suspend the device by putting it into state compatible with the target system state. The wakeup-enabled devices will usually stay partly functional in order to wake the system.

This capability of a device is initialized by bus or device driver code using device_init_wakeup(dev,can_wakeup). This is also controlled through one of the sysfs entry "/sys/devices/.../power/wakeup". The "can_wakeup" flag just records whether the device (and its driver) can physically support wakeup events. When that flag is clear, the sysfs "wakeup" file is empty, and "device_may_wakeup()" returns false.

Usually a wake up capable device will invoke device_init_wakeup(dev,pdata->wakeup) during its .probe routine with the pdata is being its device specific data. While .remove routine the device invoke device_init_wakeup(dev,0).

The device's .suspend function will contain the call to enable_irq_wake for the particular irq line and the .resume function will contain a call to disable_irq_line. So device can be partially functional in suspended state.

EXAMPLE: matrix keypad driver

matrix keypad is a simple gpio based keypad

Let's see platform-dependent keypad data of this driver

struct matrix_keypad_platform_data {
       .......................
       bool            wakeup;
}; 

It has a field wakeup controls whether the device should be set up as wakeup source.

This field can be set us "true" in the board initialization file of the device.

Now lets explore the ".probe" and ".remove" functions of the driver

static int __devinit matrix_keypad_probe(struct platform_device *pdev) {

       const struct matrix_keypad_platform_data *pdata;
       ................................
       pdata = pdev->dev.platform_data;
       ................................
       device_init_wakeup(&pdev->dev, pdata->wakeup);

} 
static int __devexit matrix_keypad_remove(struct platform_device *pdev)
     struct matrix_keypad *keypad = platform_get_drvdata(pdev);
    const struct matrix_keypad_platform_data *pdata = keypad->pdata;
    int i;
    device_init_wakeup(&pdev->dev, 0);
    .................................
}

Also in the suspend routine of the driver, enable_irq_wake is called for the irq lines corresponding to the gpio keys

static int matrix_keypad_suspend(struct device *dev)
{
        struct platform_device *pdev = to_platform_device(dev);
        .................................
        if (device_may_wakeup(&pdev->dev))
                for (i = 0; i < pdata->num_row_gpios; i++)
                        enable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));

        return 0;
}
static int matrix_keypad_resume(struct device *dev)

{


       struct platform_device *pdev = to_platform_device(dev);
      .................................
      if (device_may_wakeup(&pdev->dev))
              for (i = 0; i < pdata->num_row_gpios; i++)
                      disable_irq_wake(gpio_to_irq(pdata->row_gpios[i]));
      .................................


}


Power Consumption Details of Suspend Resume.

By default in suspend all power domains enter to RETENTION mode. Upon resume, you can check the powerdomain state statistics to check whether all states hit the desired state, cf. 'Debug info'

# cat /debug/pm_debug/count

In addition, if any powerdomains did not hit the desired state, you will see a message on the console.
If the OFF mode is enabled all the power domains will hit the OFF mode in suspend.You can enable the off mode via

# echo 1 > /debug/pm_debug/enable_off_mode

Once again, after a suspend use the powerdomain transition stats to check that transitions to off-mode are happening

# cat /debug/pm_debug/count

Notes : Core domain cannot enter into OFF mode if the board ES revision is less than 1.2

CPU Idle Features

There are seven power states introduced by CPU Idle. See the the MPU, CORE states and latencies/thresholds.

Two parameters exit_latency and target_residency are the two platform dependant parameters used by the generic cpuidle driver to decide on state transition. The exit_latency is sleep + wake latency. The target_residency is threshold from the below table. You can change these parameters from /arch/arm/mach-omap2/cpuidle34xx.c

Power States
CORE STATE
MPU STATE
sleep latency
wake_latency
threshold
C0
Active
WFI
2
2
5
C1
Inactive
WFI
10
10
30
C2
Inactive
CSWR
50
50
300
C3
Inactive
OFF
1500
1800
4000
C4
RET
RET
2500
7500
12000
C5
RET
OFF
3000
8500
15000
C6
OFF
OFF
10000
30000
300000

But MPU and CORE Domains will be transitioned to RETENTION or OFF mode depending on the sleep while idle and enable off mode settings.

ie to enable all the C states you need to set the sleep while idle and enable off mode.

Enabling system for hitting retention during idle

To enable powerdomain transitions to off mode

# echo 1 > /debug/pm_debug/sleep_while_idle

Also need to wait for any inactivity timers to expire

# echo 5 > /sys/devices/platform/omap/omap_uart.0/sleep_timeout
# echo 5 > /sys/devices/platform/omap/omap_uart.1/sleep_timeout
# echo 5 > /sys/devices/platform/omap/omap_uart.2/sleep_timeout
Enabling system for hitting OFF

To enable powerdomain transitions to off mode

# echo 1 > /debug/pm_debug/enable_off_mode

The usage and time count for these different states can be checked via

#cat /sys/devices/system/cpu/cpu0/cpuidle/state*/time
#cat /sys/devices/system/cpu/cpu0/cpuidle/state*/usage

Impact on Power Consumption on Android system

CPU Idle features are hidden from Android power management. Still cpu idle framework controls the overall power behavior by moving the MPU, CORE power domains.

Here is a list of peripherals controlled by MPU, CORE and PER domains.
MPU
MPU core
ICECrusher CS
MPU async bridge (master)
CORE
GPMC
USB TLL
GPTIMER[10, 11]
HDQ/1-Wire
HS USB
I2C[1, 2, 3]
ICR
IVA2.2 async bridge 1 (slave)
IVA2.2 async bridge 2 (master)
IVA2.2 WUGEN
MAILBOXES
McBSP[1, 5]
McSPI[1, 2, 3, 4]
MMC/SD/SDIO[1, 2, 3]
MPU async bridge (slave)
MPU INTC
OCM_RAM
OCM_ROM
SCM
SDRC
SMS
L3 interconnect
UART[1, 2]
SDMA
Temperature sensor (x2)]
L4-Core interconnect

DVFS - CPU Freq framework

Introduction to DVFS

The CPU can operate on different Operating Points(OPP) depending on the performance(CPU Frequency) required

Each OPP is characterized by:

  • CPU frequency
  • Voltage required by the CPU.

Here is the OPP Table for DM3730

OPP
Frequency
MPU Voltage
L3 Voltage
DSP Voltage
OPP50
300MHz
1.012500
1000000
1.012500
OPP100
600MHz
1.200000
1.200000
1.200000
OPP-Turbo
800MHz
1.325000
1.200000
1.325000
OPP-SB
1GHz
1.375000
1.200000
1.375000

Refer to the device specific TRM for OPP definitions.

The DVFS has been implemented using the cpufreq framework.

CPU Freq framework

The cpufreq framework consists of:

  • A set of governors that decides the target OPP of the system
  • A driver that actually transitions the system to the target OPPs specified by the governor.

There are four different governors controls the target OPPs of the system, ie ondemand, performance, powersave, userspace

Enabling ondemand frequency governor

The ondemand governor enables DVFS(frequency/OPP) transitions based on CPU load.

echo ondemand > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 
Enabling performance frequency governor

The performance governor keeps the CPU always at the highest frequency.

echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 
Enabling powersave frequency governor

The powersave governor keeps the CPU always at the lowest frequency.

echo powersave > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 
Enabling userspace frequency governor

Once this governor is enabled, DVFS( frequency) transitions will be manually triggered by a userspace application by using the CPUfreq sysfs interface

echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 
See all the available operating points
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 
Application can select any of the available frequency from the above
echo <Desired Frequancy> > /sys/devices/system/cpu/cpu0/cpufreq/ scaling_setspeed 

You can check the transitions and statistics at /sys/devices/system/cpu/cpu0/cpufreq/stats

Impact of Power Consumption on Android system

DVFS features are hidden from Android power management. Still DVFS framework controls the overall power consumption by varying the operating voltage.

P = V2 / R

Where V is the operating voltage for a given operating point(OPP). 


Smart Reflex

The variations in the silicon manufacturing processes are responsible for the difference in performance and/or power consumption of the device. Adaptive Voltage Scaling- AVS, implemented with SmartReflex(TM) technology, tends to narrow this difference.

Dedicated SmartReflex hardware implements a feedback loop - without processor intervention - which optimizes the voltage levels to account for differences in the manufacturing process, temperature and silicon degradation.

To enable smart reflex

# echo 1 > /debug/voltage/vdd_core/smartreflex/autocomp
# echo 1 > /debug/voltage/vdd_mpu/smartreflex/autocomp

To disable smart reflex

# echo 0 > /debug/voltage/vdd_core/smartreflex/autocomp
# echo 0 > /debug/voltage/vdd_mpu/smartreflex/autocomp

Impact on Power Consuption on Android System

This feature is hardware controlled after initialization. Initialization is done from the kernel. Android Power management is completely unaware of smart reflex.

Power consumption is reduced since the operating voltage is lowered for each operating point in which the device is operating in.

To minimize the power consumption in runtime

The maximum power reduction in runtime is achieved when “enable_off_mode”, “sleep_while_idle”and “smart reflex” options are enabled and dvfs option is set to “power save”.


To minimize the power consumption in suspend

The maximum power reduction in suspend is achieved when “enable_off_mode”, “sleep_while_idle”and “smart reflex” options are enabled and UART console timeouts are set.

Please check the power consumption analysis at http://processors.wiki.ti.com/index.php/Android_Benchmarks_DevKit2.3.4v2.1#Power_Management



WLan

Introduction

This section of guide provides a step by step explanation of what's involved in adding a new WiFi driver and making WiFi work in a custom Android build like Rowboat.

Features Overview

  • WLAN (802.11 b/g/n)
  • Core IP pre-tested against WiFi specifications.
  • Currently only station mode is supported.


Android WLAN Sub-System Overview

WLAN Stack.jpg

Android uses a modified wpa_supplicant (external/wpa_supplicant_6) daemon for wifi support which is controlled through a socket by hardware/libhardware_legacy/wifi/wifi.c (WiFiHW) that gets controlled from Android UI through android.net.wifi package from frameworks/base/wifi/java/android/net/wifi and it's corresponding JNI implementation in frameworks/base/core/jni/android_net_wifi_Wifi.cpp Higher level network management is done in frameworks/base/core/java/android/net.

Driver Configuration

In this Devkit release we are using WL12XX Compat wireless SDK. The drivers and firmwares of WL12XX Compat release are at hardware/ti/wlan/WL1271_compat

  • Make sure the following options are not enabled in the Kernel:
   CONFIG_CFG80211
   CONFIG_LIB80211
   CONFIG_MAC80211

Else corresponding Wireless Compat driver modules will not build.

  • On the other hand following Config options should be enabled in Kernel:
   CONFIG_WIRELESS_EXT=y
   CONFIG_WEXT_CORE=y
   CONFIG_WEXT_PROC=y
   CONFIG_WEXT_PRIV=y
  • On AM37 WL1271 SDIO is connected to MMC2 bus. Its relevant initialization and pin-muxing is done at arch/arm/mach-omap2/board-omap3evm.c under CONFIG_WL12XX_PLATFORM_DATA macro. Do take care of this initialization and pin-muxing if using any other MMC bus e.g. MMC3.

Android WiFi HAL Configuration

  • Enable building of wpa_supplicant in your BoardConfig.mk

This is by simply adding following options in BoardConfig.mk:

   BOARD_WPA_SUPPLICANT_DRIVER := WEXT
   WPA_SUPPLICANT_VERSION      := VER_0_6_X
   WIFI_DRIVER_MODULE_PATH     := "/system/etc/wifi/wl12xx_sdio.ko"
   WIFI_DRIVER_MODULE_ARG      := ""
   WIFI_DRIVER_MODULE_NAME     := "wl12xx_sdio"
   WIFI_DRIVER_FW_STA_PATH     := "/system/etc/firmware/ti-connectivity/wl1271-fw-2.bin"

This will set WPA_BUILD_SUPPLICANT to true in external/wpa_supplicant_6/Android.mk enabling building of driver_wext.c. At run time wl12xx_sdio will get loaded from WIFI_DRIVER_MODULE_PATH. We don't need any external WIFI_FIRMWARE_LOADER because our driver module wl12xx_sdio is capable of loading the firmware from WIFI_DRIVER_FW_STA_PATH

  • Android uses SIOCSIWPRIV ioctl to send commands to modify driver behaviour and receive information like signal strength, mac address of the AP, link speed etc. This ioctl is usually not implemented. A quick workaround was to emulate this ioctl functionality in WPA_supplicant itself. Here is the corresponding patch Added emulation of Android private ioctls for generic WiFi drivers
  • Next we need to provide a proper wpa_supplicant.conf for our device. That we will keep in /data/misc/wifi.
  • Set the correct permissions and paths created from init.rc
   # give system access to wpa_supplicant.conf for backup and restore
   mkdir /system/etc/wifi 0770 system wifi
   chmod 0770 /system/etc/wifi
   chmod 0660 /system/etc/wifi/wpa_supplicant.conf
   chown system wifi /system/etc/wifi/wpa_supplicant.conf
   mkdir /data/misc/wifi 0770 system wifi
   mkdir /data/misc/wifi/sockets 0770 system wifi
   chmod 0770 /data/misc/wifi
   chmod 0660 /data/misc/wifi/wpa_supplicant.conf
   chown system wifi /data/misc/wifi
   chown system wifi /data/misc/wifi/wpa_supplicant.conf

Important We use System user(uid: 1000) to initiate wpa_supplicant service that way are able to enable WiFi over Android NFS rootfs. Here is the detailed discussion on that WiFi does not work when booting from an NFS file system

  • Start wpa_supplicant and dhcpcd_wlan0 from init.rc.
   # wpa_supplicant and dhcp daemon
   service wpa_supplicant /system/bin/wpa_supplicant -Dwext -iwlan0 -c/data/misc/wifi/wpa_supplicant.conf -dd
       socket wpa_wlan0 dgram 660 system wifi
       group system wifi inet
       disabled
   #service dhcpcd_${iface} /system/bin/dhcpcd -o domain_name_servers -ABKL ${iface}
   service dhcpcd_wlan0 /system/bin/dhcpcd  -ABKL wlan0
       disabled
       oneshot


Bluetooth

Introduction

This section describes how to enable Bluetooth support on Android for wl1271 chipset.

Features Overview

  • Bluetooth 2.1
  • OPP, A2DP, AVRCP, HSP/HFP profiles are supported.


Android BT Sub-System Overview

BT Stack.jpg


Enable Bluetooth with the following setting in BoardConfig.mk:

   # Bluetooth
   BOARD_HAVE_BLUETOOTH := true

This enables bluez external/bluez HAL layer, which is used to connect with Android Frameworks (frameworks/base/core/jni/android_bluetooth_*.cpp, frameworks/base/core/java/android/bluetooth/*.java and SystemServer via DBUS .

Driver Configuration

  • WL1271 BT UART initialization and power on/off is implemented at drivers/tty/tty_io.c
  • The following kernel configs are enabled for Bluetooth support:
CONFIG_BT=y
CONFIG_BT_L2CAP=y
CONFIG_BT_RFCOMM=y
CONFIG_BT_RFCOMM_TTY=y
CONFIG_BT_BNEP=y
CONFIG_BT_BNEP_MC_FILTER=y
CONFIG_BT_BNEP_PROTO_FILTER=y
CONFIG_BT_HIDP=y
CONFIG_BT_HCIUART=y
CONFIG_BT_HCIUART_H4=y
CONFIG_BT_HCIUART_BCSP=y
CONFIG_BT_HCIUART_LL=y
CONFIG_BT_WL1271=y
  • The following kernel configs are enabled for Bluetooth AVRCP support:
CONFIG_INPUT_MISC=y
CONFIG_INPUT_UINPUT=y
  • The following kernel configs are enabled for Bluetooth Audio (SCO-over-PCM) support:
CONFIG_BT_SCO=y
CONFIG_SND_SOC_WL1271BT=y

Android BT HAL Configuration

  • Set the correct permissions and paths created from init.rc
   #Owners, Modes for Bluetooth
   #console changed to ttyO* from ttyS* since 2.6.37 kernel.
   chmod 0660 /dev/ttyO1
   chown bluetooth bluetooth /dev/ttyO1
   chmod 0660 sys/class/rfkill/rfkill0/state
   chown bluetooth bluetooth /sys/class/rfkill/rfkill0/state
   write /sys/class/rfkill/rfkill0/state 0
  • The following services are registered in init.rc for Bluetooth operation:
  • dbus-daemon: (deal connections between hcid and system server)
   service dbus /system/bin/dbus-daemon --system --nofork
   socket dbus stream 660 bluetooth bluetooth
   user bluetooth
   group bluetooth net_bt_admin
  • bluetoothd: create hcid (Bluetooth Host Controller Interface Daemon) service, but disabled at first
   service bluetoothd /system/bin/bluetoothd -n
   socket bluetooth stream 660 bluetooth bluetooth
   socket dbus_bluetooth stream 660 bluetooth bluetooth
   group bluetooth net_bt_admin misc
   disabled
  • hciattach - Project external/bluetooth/bluez is patched to enable TI-WL1271 chipset specific hciattach tool. This service attaches the BT UART HCI interface to the bluetooth stack at 3000000 baud rate. It is also responsible for loading the BT firmware on WL1271.

Note:

   Starting 2.6.37 kernel, UART driver is changed to use ttyO* instead of ttyS* 
   service hciattach /system/bin/hciattach -n /dev/ttyO1 texas 3000000
   user root
   group bluetooth net_bt_admin misc
   disabled
   oneshot
  • btpwr - Bluedroid system/bluetooth/bluedroid is used by Android UI to enable/disable Bluetooth. It uses the linux kernel rfkill infrastructure for this. The current kernel supplied with TI Android DevKit does not support rfkill, hence bluedroid is modified to use the wl1271bt_enable app provided with the Wireless Compat release. The wl1271bt_enable app is registered as a service named btpwr in init.rc. This service runs the wl1271bt_enable app to power-on/power-off the BT module in WL1271. wl1271bt_enable uses the ioctls exposed by the kernel at drivers/tty/tty_io.c.
   # rfkill is not supported, use this instead
   service btpwr /wl1271bt_enable /dev/ttyO1
   disabled
   oneshot
  • opush - BT Object Push Profile
   service opush /system/bin/sdptool add --channel=12 OPUSH
   user bluetooth
   group bluetooth net_bt_admin
   disabled
   oneshot

Audio

Introduction

Audio module is available inside PMIC IC TPS65950 (in OMAP35xEVM, AM37xEVM, BEAGLE, BEAGLE-XM) and AIC23 (in AM3517EVM), contains audio analog inputs and outputs. It is connected to the main processor through the TDM / I2S interface and used to transmit and receive audio data. The TPS65950 / AIC23 audio codec is connected via Multi-Channel Buffered Serial Port (McBSP) interface, a communication peripheral, to the main processor.


McBSP provides a full-duplex direct serial interface between the main processor (AM/DM37x, OMAP35x and AM3517) and other devices in the system such as the TPS65950 / AIC23 codec. It provides a direct interface to industry standard codecs, analog interface chips (AICs) and other serially connected A/D and D/A devices:

  • Inter-IC Sound (I2S) compliant devices
  • Pulse Code Modulation (PCM) devices
  • Time Division Multiplexed (TDM) bus devices.


The TPS65950 / AIC23 audio module is controlled by internal registers that can be accessed by the high speed I2C control interface.

This user manual section defines and describes the user level and platform level interfaces of the ALSA SoC Audio driver.


Features Overview

The features supported by ALSA SoC Audio driver are:

  • Supports AIC23 audio codec (on AM3517 only) and TPS65950 audio codec (on AM/DM37x,OMAP35x only) in ALSA SoC framework.
  • Multiple sample rates support (8KHz, 16KHz, 22.05KHz, 32KHz, 44.1KHz, 48KHz, 64KHz, 88.2KHz and 96KHz - AM3517; 8 KHz, 11.025 KHz, 12 KHz, 16 KHz, 22.05 KHz, 24 KHz, 32 KHz, 44.1 KHz and 48 KHz - AM/DM37x,OMAP35x) for both capture and playback.
  • Supports audio in stereo mode.
  • Supports simultaneous playback and record (full-duplex mode).
  • Start, stop, pause and resume feature.
  • Supports mixer interface for audio codecs.
  • Supports MMAP mode for both playback and capture.
  • McBSP is configured as slave and TPS65950 / AIC23 Codec is configured as master.


Important
Please note that enabling any line-in inputs necessitates connecting an audio playback source's output ; connecting a (non-preamplified) microphone input (like the one from a head-set jack) might not work.


Android Audio Sub-System Overview

Audio Stack.jpg


  • To use ALSA framework as HAL we need to build Rowboat with following options in BoardConfig.mk:
BOARD_USES_ALSA_AUDIO := true
BUILD_WITH_ALSA_UTILS := true
  • Generic ALSA as AudioFlinger Interface(libaudio.so) is implemented at hardware/alsa_sound.
  • Audio device specific settings and controls(alsa.omap3.so) are implemented at hardware/ti/omap3/modules/alsa.
  • ALSA library(libasound.so) is implemented at external/alsa-libs.
  • ALSA core utils(alsa_aplay, alsa_amixer) are implemented at external/alsa-utils.


Driver Configuration

To enable/disable audio support, start the Linux Kernel Configuration tool:

$ make ARCH=arm menuconfig
  • Select Device Drivers from the main menu.
    ...
    ...
    Power management options --->
    [*] Networking support --->
    '''Device Drivers --->'''
    File systems --->
    Kernel hacking --->
    ...
    ...

  • Select Sound card support as shown here:
    ...
    ...
    Multimedia devices --->
    Graphics support --->
'''<*> Sound card support --->'''
[*] HID Devices --->
[*] USB support --->
    ...
    ...

  • Select Advanced Linux Sound Architecture as shown here:


--- Sound card support
'''<*> Advanced Linux Sound Architecture --->'''
< > Open Sound System (DEPRECATED) --->


  • Select ALSA for SoC audio support as shown here:


    ...
    ...
[*] ARM sound devices  --->
[*] SPI sound devices  --->
[*] USB sound devices  --->
'''<*> ALSA for SoC audio support --->'''


  • For AM/DM37x,OMAP35x, select SoC Audio support for OMAP3EVM board as shown here:
--- ALSA for SoC audio support
<*> SoC Audio for the Texas Instruments OMAP chips
'''<*> SoC Audio support for OMAP3EVM board'''
< > Build all ASoC CODEC drivers


  • For AM3517, select SoC Audio support for OMAP3517 / AM3517 EVM as shown here:
--- ALSA for SoC audio support
<*> SoC Audio for the Texas Instruments OMAP chips
'''<*> SoC Audio support for OMAP3517 / AM3517 EVM'''
< > Build all ASoC CODEC drivers


  • Make sure that McBSP support is enabled. To check the same, select System Type from the main menu.
    ...
    ...
[*] Enable loadable module support --->
[*] Enable the block layer --->
    '''System Type --->'''
    Bus support --->
    Kernel Features --->
    ...
    ...


  • Select TI OMAP Common Features as shown here:
    [*] MMU-based Paged Memory Management Support
    ARM system type (TI OMAP) --->
    '''TI OMAP Common Features --->'''
    TI OMAP2/3/4 Specific Features  --->
    *** Processor Type ***
-*- Support ARM V6K processor extensions 
    ...
    ...


  • McBSP support should be selected:
    ...
    ...
[ ] Multiplexing debug output
[*] Warn about pins the bootloader didn't set up
-*- McBSP support
< > Mailbox framework support
< > Export OMAP IOMMU internals in DebugFS
    System timer (Use 32KHz timer) --->
    ...
    ...



Android Audio HAL Configuration

Before diving into Android ALSA hardware layer, we have to verify whether ALSA driver is properly working or not. We will use ALSA utilities(alsa_aplay, alsa_arecord, and alsa_amixer) which got build along with Rowboat and is a part of external/alsa-utils package.

  • alsa_amixer is used to set ALSA controls & settings.
  • alsa_arecord and alsa_aplay are used for record and playback purpose respectively.


By default alsa_arecord doesn't exist. It is a soft link to alsa_aplay. So to create the link run the following command from Android prompt.

# ln -s /system/bin/alsa_aplay /system/bin/alsa_arecord


Important (for AM/DM37x,OMAP35x ONLY)

  • Audio capture channels AUXL and AUXR are by default disabled for AM37x,OMAP35x ASoC driver. To enable run the following 'alsa_amixer' commands:
# alsa_amixer cset name='Analog Left AUXL Capture Switch' 1
# alsa_amixer cset name='Analog Right AUXR Capture Switch' 1
  • Audio playback (on Headset channel) is muted by default and capture is set to capture at MAX volume. Run the following 'alsa_amixer' commands to fix the volume settings:
# alsa_amixer set 'Headset' 3
# alsa_amixer set 'Analog' 0
  • Software loopback command to test capture-playback. Following command will record in "CD" format and play the recorded data.
# alsa_arecord -f cd | alsa_aplay

The --help option provides a comprehensive list of command-line options for ALSA utilities.

The above procedure should get your Audio Capture and Playback working from command line. If it is then we are all set to make the corresponding changes in Android HAL layer and that will be all.

Hardware specific ALSA configurations will go here to hardware/ti/omap3/modules/alsa/alsa_module.cpp file.

Select and configure hardware devices

  • List down all the Audio devices available on target/AM37x.
# alsa_aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: omap3evm [omap3evm], device 0: TWL4030 twl4030-0 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 0: omap3evm [omap3evm], device 1: WL1271 BT PCM wl1271bt-1 []
  Subdevices: 1/1
  Subdevice #0: subdevice #0
  • We got that default out device is hw 0:0 whereas BT SCO device is hw 0:1
  • Define: deviceName() to return correct out device on query. See the implementation for details.
  • In alsa_handle_t _defaults[] goes the ALSA handle settings:
.....
    {
        module      : 0,
        devices     : OMAP3_OUT_SCO,
        curDev      : 0,
        curMode     : 0,
        handle      : 0,
        format      : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT
        channels    : 2,
        sampleRate  : DEFAULT_SAMPLE_RATE, // should ideally be 8000
        latency     : 200000, // Desired Delay in usec
        bufferSize  : DEFAULT_SAMPLE_RATE / 5, // Desired Number of samples
                mmap            :0,
        modPrivate  : (void *)&setScoControls,
    },
    {
        module      : 0,
        devices     : OMAP3_OUT_DEFAULT,
        curDev      : 0,
        curMode     : 0,
        handle      : 0,
        format      : SND_PCM_FORMAT_S16_LE, // AudioSystem::PCM_16_BIT
        channels    : 2,
        sampleRate  : DEFAULT_SAMPLE_RATE,
        latency     : 200000, // Desired Delay in usec
        bufferSize  : DEFAULT_SAMPLE_RATE / 11, // Desired Number of samples
                mmap            :0,
        modPrivate  : (void *)&setDefaultControls,
    },
.....
  • In setDefaultControls() we set the ALSA controls. It is similar to setting the ALSA Switch and Volume controls what we did using the alsa_amixer command for AM37/OMAP35 above. You can see the exact one-to-one mapping of those commands here.
  • How to set controls for default out device:
.....
void setDefaultControls(uint32_t devices, int mode)
{
LOGV("%s", __FUNCTION__);
    ALSAControl control("hw:00");

    /* check whether the devices is input or not */
    /* for output devices */
    if (devices & 0x0000FFFF){
        if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
            control.set("HeadsetR Mixer AudioR1", 1); // on
            control.set("HeadsetL Mixer AudioL1", 1); // on
            control.set("Headset Playback Volume", 1); //Headset Volume
        } else {
            control.set("HeadsetR Mixer AudioR1", (unsigned int)0); // off
            control.set("HeadsetL Mixer AudioL1", (unsigned int)0); // off
        }
    }

    /* for input devices */
    if (devices >> 16) {
        if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
            control.set("Analog Left AUXL Capture Switch", 1); //on
            control.set("Analog Right AUXR Capture Switch", 1); //on
            control.set("Analog Capture Volume", (unsigned int)0); //Capture volume '0' to capture less noice
        } else {
            control.set("Analog Left AUXL Capture Switch", (unsigned int)0); //off
            control.set("Analog Right AUXR Capture Switch", (unsigned int)0); //off
        }
    }
}
.....


Important
Please note that enabling any line-in inputs necessitates connecting an audio playback source's output ; connecting a (non-preamplified) microphone input (like the one from a head-set jack) might not work.

Important (for AM3517 ONLY)
By default Line is enabled. Connect an audio player source to Line In Codec 1 jack on the application board and a headset or speaker source to the Line-Out Codec 1 jack.

Camera

Introduction

This porting guide briefs about porting camera module to Gingerbread with respect to camera sensor mt9v113 for Beagle board and mt9t111 for AM37x.

Features Overview

  • Still image capture
  • Capture in YUV format from the sensor at VGA resolution
  • Standard V4L2 ioctls
  • Buffer accessing mechanism through userpointer and memory mapping

Android Camera Sub-System Overview

Android's camera application connects with android HAL through camera binding interface. HAL inturn connects physical camera sensor and provides control & data interface between application and camera sensor. The block diagram below shows the camera sub-system in android
Camera stack.jpg


Adding Camera Module to Linux Kernel

  • Write/Get camera driver. (mt9v113.c / mt9111.c)
  • Put driver files at <Kernel>/drivers/media/video. Good to have header files at <Kernel>/include/media
  • Open & Edit <Kernel>drivers/media/video/Makefile

$vim <Kernel>/drivers/media/video/Makefile Add driver file to get compiled. e.x. obj-$(CONFIG_VIDEO_MT9V113) += mt9v113.o obj-$(CONFIG_VIDEO_MT9T111) += mt9t111.o

  • Open & Edit <Kernel>/drivers/media/video/Kconfig

$vim <Kernel>/drivers/media/video/Kconfig Add config entry for the driver. e.x. config VIDEO_MT9V113

tristate "Aptina MT9V113 VGA CMOS IMAGE SENSOR"
depends on VIDEO_V4L2 && I2C
---help---
This is a Video4Linux2 sensor-level driver for the Aptina MT9V113
image sensor.
To compile this driver as a module, choose M here: the
module will be called mt9v113.

config VIDEO_MT9T111

tristate "Aptina MT9T111 VGA CMOS IMAGE SENSOR"
depends on VIDEO_V4L2 && I2C
---help---
This is a Video4Linux2 sensor-level driver for the Aptina MT9T111
image sensor.
To compile this driver as a module, choose M here.

  • Add board specific changes for camera sensor to the board file
  • For the reference refer file - '<Kernel>/arch/arm/mach-omap2/board-omap3beagle-camera.c'

Driver Configuration

$cd <Kernel> $make CROSS_COMPILE=arm-eabi- ARCH=arm menuconfig

  • Go to device drivers -> multimedia support -> video capture adapters -> encoders/decoders and other helper chips, select added camera driver

(Select MT9V113 camera sensor for Beagleboard-xm and MT9T111 for AM37x)

  • Camera sensor driver source is located at kernel/drivers/media/video/mt9v113.c for MT9V113 for Beagleboard-xm and kernel/drivers/media/video/mt9t111.c for AM37x
General setup  --->                                                                   
[*] Enable loadable module support  --->                                       
[*] Enable the block layer  ---> 
    System Type  --->  
[*] FIQ Mode Serial Debugger                                                           
    Bus support  --->                                                       
    Kernel Features  --->                                                      
    Boot options  --->                                                         
    CPU Power Management  --->                                                 
    Floating point emulation  --->                                             
    Userspace binary formats  --->                                             
    Power management options  --->                                             
[*] Networking support  --->                                                
    Device Drivers  --->                                                      
    File systems  --->                      
    Kernel Hacking --->
    Security options --->
-*- Cryptographic API --->
    Library routines --->

    *** Multimedia core support ***                                                       
[*]   Media Controller API (EXPERIMENTAL)
[*]   Video For Linux                                                                       
[*]     Enable Video For Linux API 1 (DEPRECATED)
[*]     V4L2 sub-device userspace API (EXPERIMENTAL)                                      
< >   DVB for Linux                                                                         
    *** Multimedia drivers ***                                                            
[ ]   Load and attach frontend and tuner driver modules as needed                           
[ ]   Customize analog and hybrid tuner modules to build  --->                              
[*]   Video capture adapters  --->                 
[ ]   Memory -to -memory multemedia devices --->                                      
[*]   Radio Adapters  --->                                                                  
[ ]   DAB adapters               

[ ]   Enable advanced debug functionality
[ ]   Enable old-style fixed minor ranges for video devices
[ ]   Autoselect pertinent encoders/decoders and other helper chips
      Encoders/decoders and other helper chips  --->
< >   VPSS system module driver
< >   VPFE Video Capture Driver
<*>   OMAP2/OMAP3 V4L2-Display Driver 
< >   CPiA2 Video For Linux
< >   SR030PC30 VGA camera support
<*>   OMAP 3 camera support (EXPERIMENTAL)
[*]     OMAP 3 camera debug messages
< >   SOC camera support 
[*]   V4L USB devices --->


< > OmniVision OV7670 sensor support
<*> Micron mt9v011 sensor support
<*> Aptina MT9V113 VGA CMOS IMAGE SENSOR
<*> Aptina MT9T111 VGA CMOS IMAGE SENSOR
< > TCM825x camera sensor support
< > Philips SAA7110 vdieo decoder 


Android Camera HAL Configuration

  • Camera HAL source is located at android_source/hardware/ti/omap3/camera/ and the shared library libcamera.so is created out of this.
  • The HAL is implemented based on CameraHardwareInterface.h in framework/base/include/camera/CameraHardwareInterface.h
  • HAL communicates with hardware through V4L2 framework and media controller framework in the linux kernel

Refer GingerBread source.

  • Following section briefs about important interface which needs to be defined under camera HAL.


/* constructor */ CameraHardware::CameraHardware()

: mParameters(),
mPreviewHeap(0),
mRawHeap(0),
mCamera(0),
mPreviewFrameSize(0),
mNotifyCb(0),
mDataCb(0),
mDataCbTimestamp(0),
mCallbackCookie(0),
mMsgEnabled(0),
previewStopped(true)

{

/* create camera, open camera sensor(video device), open subdevice and set up format pads, open media device, enumerate all the entities, set-up media link, close the media device */
/* init default paramets
e.x.
CameraParameters p;
p.setPreviewSize(320, 240);
p.set(CameraParameters::KEY_JPEG_QUALITY, 100);
p.setPreviewFormat(CameraParameters::PIXEL_FORMAT_YUV422SP);
*/
initDefaultParameters();

} /* destructor */ CameraHardware::~CameraHardware() {

/* close device and delete instance created */

}

sp<IMemoryHeap> CameraHardware::getPreviewHeap() const {

/* return preview frame pointer */
return mPreviewHeap;

}


void CameraHardware::setCallbacks(notify_callback notify_cb,

data_callback data_cb,
data_callback_timestamp data_cb_timestamp,
void* user)

{

/* store callback to local pointers, need to callback at the time of preview/image capture 
e.x.
mNotifyCb = notify_cb;
mDataCb = data_cb;
mDataCbTimestamp = data_cb_timestamp;
mCallbackCookie = user;*/

}

void CameraHardware::enableMsgType(int32_t msgType) {

/* set local message flag. Application will give this notification to perform certain action while previewing.
ex.start video, image caputure etc. */ 
mMsgEnabled |= msgType;

}

void CameraHardware::disableMsgType(int32_t msgType) {

mMsgEnabled &= ~msgType;

}

bool CameraHardware::msgTypeEnabled(int32_t msgType) {

/* return message value - presently enable at HAL 
return (mMsgEnabled & msgType); */

} /* start preview */ status_t CameraHardware::startPreview() {

/* configure device and start preview thread */
/* in preview thread call 
- check message type
- fill preview frame pointer with valid preview data
- call data callback with data
*/ 

}

void CameraHardware::stopPreview() {

/* stop preview */

}

status_t CameraHardware::startRecording() {

/* configure device & start record thread */
/* record thread
- check message type
- if message type contains - CAMERA_MSG_VIDEO_FRAME then call 'mDataCbTimestamp' with video frame captured
*/ 

}

void CameraHardware::stopRecording() {

/* stop recording */

}

status_t CameraHardware::takePicture() {

/* 
- configure camera device
- take a current frame
- check message type
- call callback
*/
}

status_t CameraHardware::setParameters(const CameraParameters& params) {

/* 
- configure device as per parameters
*/

}

CameraParameters CameraHardware::getParameters() const {

/*
- return current value of parameter set
*/

}

  • Create and configure android.mk file

LOCAL_PATH:= $(call my-dir)

  1. libcamera

include $(CLEAR_VARS) LOCAL_SRC_FILES:= \

source1.cpp \
source2.cpp ...

LOCAL_MODULE:= libcamera LOCAL_SHARED_LIBRARIES:= \

libcutils \
libui \
libutils \
libbinder \
libjpeg \
libcamera_client \
libsurfaceflinger_client

LOCAL_C_INCLUDES += \

external/jpeg

include $(BUILD_SHARED_LIBRARY) include $(all-subdir-makefiles)

  • Compile android system or one can also compile individal subsystem by

Go to module directory $cd /projects/rowboat-android/hardware/ti/omap3/camera $source <ANDROID_ROOT>/build/envsetup.sh $mm TARGET_PRODUCT= <TARGET PRODUCT NAME> e.g.$ mm TARGET_PRODUCT=beagleboard copy libcamera.so to out/target/product/<boardname>/system/lib


Note: - To enable camera on android the corresponding BoardConfig.mk file should have USES_CAMERA_STUB commented otherwise camera stub will be used.


Display

Introduction

This section of the porting guide describes the display system with respect to AM35x, AM37x and Beagle board. Display Sub-System hardware integrates one graphics pipeline, two video pipelines, and two overlay managers (one for digital and one for analog interface). Digital interface is used for LCD and DVI output and analog interface is used for TV out.

Sharp LS037V7DW01 LCD Panel and Sharp LQ043T1DG01 LCD Panel are used on boards OMAP3EVM and AM35x respectively. Porting explanation for Sharp LS037V7DW01 LCD Panel is given in this section

Features Overview

  • Supports LCD display interface at VGA resolution (480*640)
  • Supports TV display interface at NTSC/PAL resolutions (both S-Video out and Composite out is supported)
  • Supports DVI digital interface (mode selection via boot argument).
  • Supports rotation - 0, 90, 180 and 270 degrees on LCD and TV output
  • Supports overlay

Android Display Subsystem Overview

The block diagram below shows the display subsystem in GingerBread android. Android display system is based on a Client/Server Architecture.
Server side: Surface Flinger is a service coded in C++

  • Manages access to display subsystem
  • Seamlessly composites 2D and 3D graphic layers from multiple applications

Client side: Applications can draw on surfaces using two paths:

  • Use widgets/View/Canvas provided by the JAVA APIs and managed by C++ external Skia library
  • Access OpenGL through JNI to directly create 3D surfaces

Surface Flinger Provides system-wide surface “composer”, handling all surface rendering to frame buffer device. Uses OPENGL and hardware accelerator for composing surfaces. Surfaces passed as buffers via binder IPC calls.

Display_system_overview.jpg

























Driver Configuration

V4L2 Driver

  • Select "Device Drivers" from the main menu.
    ...
    ...
    Power management options  --->
[*] Networking support  --->
    Device Drivers  --->
    File systems  --->
    Kernel hacking  --->
    ...
    ...
  • Select "Multimedia support" from the menu.
    ...
    ...
    Multifunction device drivers  --->
[*] Voltage and Current Regulator Support  --->
<*> Multimedia support  --->
    Graphics support  --->
<*> Sound card support  --->
    ...
    ...
  • Select "Video For Linux" from the menu.
    ...
    ...
    *** Multimedia core support ***
<*>   Video For Linux
[*]     Enable Video For Linux API 1 (DEPRECATED)
< >   DVB for Linux
    ...
    ...
  • Select "Video capture adapters" from the same menu. Press <ENTER> to enter the corresponding sub-menu.
    ...
    ...
[ ]   Customize analog and hybrid tuner modules to build  --->
[*]   Video capture adapters  --->
[ ]   Memory-to-memory multimedia devices  --->
    ...
    ...
  • Select "OMAP2/OMAP3 V4L2-DSS drivers" from the menu.
    ...
    ...
-*-   VPSS System module driver
<*>   VPFE Video Capture Driver
<*>     DM6446 CCDC HW module
<*>   OMAP2/OMAP3 V4L2-Display driver
< >   CPiA2 Video For Linux
    ...
    ...

Frame Buffer Driver

  • Select "Device Drivers" from the main menu.
    ...
    ...
    Power management options  --->
[*] Networking support  --->
    Device Drivers  --->
    File systems  --->
    Kernel hacking  --->
    ...
    ...
  • Select "Graphics support" from the menu.
    ...
    ...
[*] Voltage and Current Regulator Support  --->
<*> Multimedia support  --->
    Graphics support  --->
<*> Sound card support  --->
[*] HID Devices  --->
    ...
    ...
  • Select "Support for frame buffer devices" from the menu.
    ...
    ...
<M> Lowlevel video output switch controls
<*> Support for frame buffer devices  --->
< > Virtual Frame Buffer support (ONLY FOR TESTING!)
    ...
    ...
  • Select "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" from the same menu.
    ...
    ...
[ ] Check bootloader initialization
-*- OMAP2/3 Display Subsystem support (EXPERIMENTAL)  --->
[*] Backlight & LCD device support  --->
    ...
    ...
  • Configure default VRAM size to the required/expected size of buffer, the default is 4MB.

Go inside option "OMAP2/3 Display Subsystem support"

    ...
    ...
--- OMAP2/3 Display Subsystem support (EXPERIMENTAL)
(4)   VRAM size (MB)
[*]   Debug support
    ...
    ...
  • Select "DPI support" from the menu.
    ...
    ...
[ ]   Debug support
[*]   DPI support
[ ]   RFBI support
    ...
    ...

TV Output Support

  • Select "Device Drivers" from the main menu.
    ...
    ...
    Power management options  --->
[*] Networking support  --->
    Device Drivers  --->
    File systems  --->
    Kernel hacking  --->
    ...
    ...
  • Select "Graphics support" from the menu.
    ...
    ...
[*] Voltage and Current Regulator Support  --->
<*> Multimedia support  --->
    Graphics support  --->
<*> Sound card support  --->
[*] HID Devices  --->
    ...
    ...
  • Select "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" from the same menu.
    ...
    ...
[ ] Check bootloader initialization
-*- OMAP2/3 Display Subsystem support (EXPERIMENTAL)  --->
[*] Backlight & LCD device support  --->
    ...
    ...
  • Select "VENC support" from the menu.
    ...
    ...
[ ]   Debug support
[ ]   RFBI support
[*]   VENC support
      OMAP2_VENC_OUT_TYPE (Use S-Video output interface)  --->
[ ]   SDI support
    ...
    ...

Note: Confirm OMAP2_VENC_OUT_TYPE is set to "Use S-Video output interface"

LCD Driver Support

  • Select "Device Drivers" from the main menu.
    ...
    ...
    Power management options  --->
[*] Networking support  --->
    Device Drivers  --->
    File systems  --->
    Kernel hacking  --->
    ...
    ...
  • Select "Graphics support" from the menu.
    ...
    ...
[*] Voltage and Current Regulator Support  --->
<*> Multimedia support  --->
    Graphics support  --->
<*> Sound card support  --->
[*] HID Devices  --->
    ...
    ...
  • Select "OMAP2/3 Display Subsystem support (EXPERIMENTAL)" from the same menu.
    ...
    ...
[ ] Check bootloader initialization
-*- OMAP2/3 Display Subsystem support (EXPERIMENTAL)  --->
[*] Backlight & LCD device support  --->
    ...
    ...
  • Select "OMAP2/3 Display Device Drivers" from the next sub-menu:
    ...
    ...
(1)   Minimum FCK/PCK ratio (for scaling)
<*>   OMAP2/3 frame buffer support (EXPERIMENTAL)  --->
      OMAP2/3 Display Device Drivers  --->
    ...
    ...
  • Select "Sharp LS037V7DW01 LCD Panel" from the next sub-menu:
    ...
    ...
<*> Generic Panel
<*> Sharp LS037V7DW01 LCD Panel
< > Sharp LQ043T1DG01 LCD Panel
    ...
    ...

Modification in Board File and LCD driver

  • LCD interface related pin mux state and set as per requirement. It may required to check default pin muxing setup in u-boot as well.
  • Implement display_lcd_init(), display_lcd_enable() and display_lcd_disable() and link to display driver. Where DSS module will use it in runtime. e.g. @arch/arm/mach-omap2/board-omap3evm.c
 static struct omap_dss_device omap3_evm_lcd_device = {
	.name			= "lcd",
	.driver_name		= "sharp_ls_panel",
	.type			= OMAP_DISPLAY_TYPE_DPI,
	.phy.dpi.data_lines	= 18,
	.platform_enable	= omap3_evm_enable_lcd,
	.platform_disable	= omap3_evm_disable_lcd,
	.set_backlight		= omap3evm_set_bl_intensity,
 }; 
  • LCD timing need to set as per datasheet information. e.g. @drivers/video/omap2/displays/panel-*.c
 static struct omap_video_timings sharp_ls_timings = {
	.x_res = 480,
	.y_res = 640,

	.pixel_clock	= 19200,

	.hsw		= 2,
	.hfp		= 1,
	.hbp		= 28,

	.vsw		= 1,
	.vfp		= 1,
	.vbp		= 1,
 }; 

Note: Colorbar testing of LCD can be done at u-boot level by configuring the set of registers manually.

MMC

Introduction

TI AM37x/AM3517 has an multimedia card high-speed/secure data/secure digital I/O (MMC/SD/SDIO) host controller, which provides an interface between microprocessor and either MMC, SD memory cards, or SDIO cards. The current version of the user guide talks about the MMC/SD controller. The MMC driver is implemented on top of host controller as a HS-MMC controller driver and supports MMC, SD, SD High Speed and SDHC cards. The salient features of the aforementioned HS-MMC host controller are:

  • Full compliance with MMC/SD command/response sets as defined in the Specification.
  • Supports 1-bit or 4-bit transfer mode specifications for SD and SDIO cards
  • Supports 1-bit, 4-bit, or 8-bit transfer mode specifications for MMC cards
  • Built-in 1024-byte buffer for read or write
  • 32-bit-wide access bus to maximize bus throughput
  • Single interrupt line for multiple interrupt source events
  • Two slave DMA channels (1 for TX, 1 for RX)
  • Designed for low power and Programmable clock generation


Features Overview

The MMC/SD/SDIO driver supports following features

  • The driver is built in-kernel (part of vmlinux).
  • MMC cards including High Speed cards.
  • SD cards including SD High Speed and SDHC cards
  • Uses block bounce buffer to aggregate scattered blocks


Driver Configuration

The default kernel configuration enables support for MMC/SD(built-in to kernel). The selection of MMC/SD/SDIO driver can be modified as follows:

  • start Linux Kernel Configuration tool.
$ make menuconfig  ARCH=arm
  • Select Device Drivers from the main menu.
...
...
Kernel Features  --->
Boot options  --->
CPU Power Management  --->
Floating point emulation  --->
Userspace binary formats  --->
Power management options  --->
[*] Networking support  --->
Device Drivers  --->
...
...
  • Select MMC/SD/SDIO card support from the menu.
...
...
[*] USB support  --->
<*> MMC/SD/SDIO card support  --->
< > Sony MemoryStick card support (EXPERIMENTAL)  --->
...
...
  • Select OMAP HS MMC driver
...
[ ] MMC debugging
[ ] Assume MMC/SD cards are non-removable (DANGEROUS) 
     *** MMC/SD/SDIO Card Drivers ***
<*> MMC block device driver
[*]  Use bounce buffer for simple hosts
...
<*>   TI OMAP High Speed Multimedia Card Interface support 
...


Android MMC HAL or Vold Configuration

Android system uses vold as the mount daemon, which detects, mounts and monitors the status of sdcard. The mount daemon needs a configuration file to tell it what the sdcard device is. Since Android 2.2 (froyo), it ships with a new implementation of vold (aka vold2). The configuration is changed to /etc/vold.fstab and its format is also changed. See system/core/rootdir/etc/vold.fstab in the Android source tree for the detailed explanations of the format.

However, a fixed vold.fstab can only support block device with fixed name.

# cat /etc/vold.fstab
dev_mount sdcard /mnt/sdcard 3 /devices/platform/mmci-omap-hs.0/mmc_host/mmc0

Depending on the MMC interface this value can change. Best way is to probe sysfs directories to find the fixed name.

# ls /sys/devices/platform/mmci-omap-hs.X/mmc_host/mmcY


Touchscreen

Introduction

The touch controller is ADS7846 with SPI interface (in OMAP35xEVM and AM37xEVM) and TSC2004 with I2C interface (in AM3517EVM). Both are resistive touch screen controllers.

Features Overview

The features supported by Touchscreen in Android are:

  • Single touch input
  • Single click
  • Single long click
  • Uni-direction motion touch

Driver Configuration

Add touchscreen driver support

  • Start the Linux Kernel Configuration tool:
    $ make ARCH=arm menuconfig
  • Select Device Drivers from the main menu.
    ...
    Power management options --->
    [*] Networking support --->
    Device Drivers --->
    File systems --->
    Kernel hacking --->
    ...
  • Select Input device support form the next menu:
    ...
    [ ] ISDN support  --->
    < > Telephony support  --->
    Input device support  --->
    Character devices  --->
    -*- I2C support  --->
    ...
  • Select Touchscreens from the next menu:
    ...
    [ ]   Joysticks/Gamepads  --->
    [ ]   Tablets  --->
    [*]   Touchscreens  --->
    [*]   Miscellaneous devices  --->
    Hardware I/O ports  --->
    ...
  • Select ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens from the next menu:
    ...
--- Touchscreens
<*>   ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens
< >   AD7877 based touchscreens
< >   Analog Devices AD7879-1/AD7889-1 touchscreen interface
    ...
  • Select SPI support from the Device Driver menu:
    ...
    Character devices  --->
    -*- I2C support  --->
    [*] SPI support  --->
        PPS support  --->
    -*- GPIO Support  --->
    ...
  • Select McSPI driver for OMAP24xx/OMAP34xx from the next menu.
   .... 
    < >   GPIO-based bitbanging SPI Master
    <*>   McSPI driver for OMAP24xx/OMAP34xx
    < >   Xilinx SPI controller common module
    ...
  • Add the touch controller configuration values in board file (e.g. board-omap3evm.c).
static struct ads7846_platform_data ads7846_config = {
        .x_max                  = 0x0fff,
        .y_max                  = 0x0fff,
        .x_plate_ohms           = 180,
        .pressure_max           = 255,
        .debounce_max           = 10,
        .debounce_tol           = 3,
        .debounce_rep           = 1,
        .get_pendown_state      = ads7846_get_pendown_state,
        .keep_vref_on           = 1,
        .settle_delay_usecs     = 150,
        .wakeup                 = true,
};

Test touch driver using getevent

  • Once Touchscreen and SPI driver is up through board file (e.g. board-omap3evm.c) configuration.
  • Test with AndroidFS as events are coming while touching the LCD display. Run on command prompt:
    # getevent
    add device 1: /dev/input/event1
      name:     "ADS7846 Touchscreen"
    
    /dev/input/event1: 0001 014a 00000001
    /dev/input/event1: 0003 0000 0000089e
    /dev/input/event1: 0003 0001 000005fe
    /dev/input/event1: 0003 0018 0000004f
    /dev/input/event1: 0000 0000 00000000
    
  • It confirms that touch inputs and irq based event generation is working fine.

Touch Calibration

  • Touch inputs (x, y, pressure) need to calibrate based on touch controller used.
  • To define the touch input boundaries, the following macros are used in driver (e.g. drivers/input/touchscreen/ads7846.c)
    • OMAP3EVM_XMIN -- Minimum raw x input possible
    • OMAP3EVM_XMAX -- Maximum raw x input possible
    • OMAP3EVM_YMIN -- Minimux raw y input possible
    • OMAP3EVM_YMAX -- Maximum raw y input possible
  • add the log to get print of x, y and pressure values as raw and absolute both in function ads7846_report_state():
		printk("raw input x=%d y%d pressure=%d \n", x, y, Rt);
#ifdef CONFIG_MACH_OMAP3EVM
                x = pdata->x_max -
                        ((pdata->x_max * (x - OMAP3EVM_XMIN)) / (OMAP3EVM_XMAX- OMAP3EVM_XMIN));
                y = pdata->y_max -
                        ((pdata->y_max * (y - OMAP3EVM_YMIN)) / (OMAP3EVM_YMAX - OMAP3EVM_YMIN));
#endif
		printk("abs input x=%d y%d pressure=%d \n", x, y, Rt);
  • Get the debug log for x, y and pressure at following points on the touchscreen
    • Left Top Most Point
    • Right Top Most Point
    • Left Bottom Down Point
    • Right Bottom Down Point
  • Update the macros based on observation of above input points
    • set OMAP3EVM_XMIN value as "minimum x input possible value from the reading of left top most touch"
    • set OMAP3EVM_XMAX value as "maximum x input possible value from the reading of right top most touch"
    • set OMAP3EVM_YMIN value as "minimux y input possible value from the reading of left top most touch"
    • set OMAP3EVM_YMAX value as "maximum y input possible value from the reading of left bottom down touch"

Note: Above four macros need to be fine tune to get the correct absolute value of x and y.

  • For example in ads7846.c:
#ifdef CONFIG_MACH_OMAP3EVM
#define OMAP3EVM_XMIN           0x136
#define OMAP3EVM_XMAX           0xe84
#define OMAP3EVM_YMIN           0x0d9
#define OMAP3EVM_YMAX           0xec6
#endif

Note: sometimes calculation method return negative values. Then method needs some modification to get positive calculated touch inputs.

Test Touch Calibration in Android

  • Run android on the board.
  • select "Menu" -> "Dev Tools" -> "Pointer Location" utility
  • Touch and draw on the screen and observe that the expected points are getting marked on the lcd screen.
  • if drawing on lcd is not proper then driver needs to be fine tune the above mentioned macros.

Improve Touch Screen Sensitivity

Observations on the touch screen with touch controller ADS7846 shows that some of the gentle touches are not passed to the kernel input layer.

The following patch passes these ignored touch events to the input layer with a medium pressure value.

--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -814,14 +814,20 @@ static void ads7846_report_state(struct ads7846 *ts)
                else
                        Rt = 0;
                dev_vdbg(&ts->spi->dev, "x/y: %d/%d, PD %d\n", x, y, Rt);
-       } else if (likely(x && z1)) {
+       } else if (likely(x)) {
                /* compute touch pressure resistance using equation #2 */
                Rt = z2;
                Rt -= z1;
                Rt *= x;
                Rt *= ts->x_plate_ohms;
-               Rt /= z1;
-               Rt = (Rt + 2047) >> 12;
+               if(z1 != 0) {
+                       Rt /= z1;
+                       Rt = (Rt + 2047) >> 12;
+               }
+               else {
+                       Rt = ts->pressure_max / 2;
+                       packet->tc.ignore = false;
+               }
        } else {
                Rt = 0;
        }

NOTE: The above patch is experimental and should be used with caution.

Keypad

Introduction

The matrix keypad controller is TWL4030 with I2C interface (in OMAP35xEVM, AM37xEVM, BEAGLE, BEAGLE-XM) and IO expanded keypad controller is TCA6416 with I2C interface (in AM3517EVM). Here porting explanation for matrix keypad controller.

Features Overview

  • 8x8 matrix key layout support
  • single click input

Driver Configuration

Add keypad driver support

  • start the Linux Kernel Configuration tool:
    $ make ARCH=arm menuconfig
  • Select Device Drivers from the main menu.
    ...
    Power management options --->
    [*] Networking support --->
    Device Drivers --->
    File systems --->
    Kernel hacking --->
    ...
  • Select Input device support form the next menu:
    ...
    [ ] ISDN support  --->
    < > Telephony support  --->
    Input device support  --->
    Character devices  --->
    -*- I2C support  --->
    ...
  • Select Keyboards from the next menu:
    ...
    < >   Reset key
          *** Input Device Drivers ***
    [*]   Keyboards  --->
    [ ]   Mice  --->
    [ ]   Joysticks/Gamepads  --->
....
  • Select TI TWL4030/TWL5030/TPS659x0 keypad support from the next menu:
    ....
    < >   Sun Type 4 and Type 5 keyboard
    <*>   TI TWL4030/TWL5030/TPS659x0 keypad support
    < >   XT keyboard
....

Test keypad driver using getevent

  • Once matrix keypad and I2C driver is up through board file (e.g. board-omap3evm.c) configuration.
  • Test with AndroidFS as events are coming while pressing the keys. Run on command prompt:
    # getevent
    add device 0: /dev/input/event0
      name:     "TWL4030 Keypad"
    
    /dev/input/event0: 0001 001c 00000001
    /dev/input/event0: 0000 0000 00000000
    /dev/input/event0: 0001 001c 00000000
    /dev/input/event0: 0000 0000 00000000
    
  • It confirms that keypad inputs and irq based event generation is working fine.

Android Keypad Configuration

  • The <matrix keypad driver name>.kl (e.g. TWL4030_Keypad.kl) should be present in root directory of AndroidFS.
  • Check and confirm the key mappings are same as expected.


NAND

Introduction

This section of porting guide will describe the NAND layout present on EVMs and how to integrate Fastboot functionality in u-boot. Micron Nand part (OMAP35x and AM3517) and Hynix Nand part (AM37x) are supported.

NAND Layout

The NAND on the EVM has been configured in the following manner.

 +------------+-->0x00000000-> X-loader start
 |            |
 |            |-->0x0007FFFF-> X-loader end  
 |            |-->0x00080000-> U-Boot start
 |            |
 |            |-->0x001BFFFF-> U-Boot end  
 |            |-->0x001C0000-> ENV start
 |            |
 |            |
 |            |-->0x0027FFFF-> ENV end
 |            |-->0x00280000-> Linux Kernel start
 |            |
 |            |
 |            |
 |            |
 |            |-->0x0077FFFF-> Linux Kernel end
 |            |-->0x00780000-> Filesystem start
 |            |
 |            |
 |            |
 |            |
 |            |
 |            |
 |            |
 |            |
 +------------+-->0x20000000-> Filesystem end


Features Overview


Driver Configuration

  • Start the Kernel configuration tool to enable/disable NAND and UBIFS support:
$ make menuconfig ARCH=arm
  • Enable NAND support from the main menu. Select Device Drivers -> MTD support -> NAND support.
-> Device Drivers
   -> Memory Technology Device (MTD) support (MTD [=y])
      -> NAND Device Support (MTD_NAND [=y])     
  • Enable UBI support. Select Device Drivers -> MTD support -> Enable UBI.
-> Device Drivers
   -> Memory Technology Device (MTD) support (MTD [=y])
      -> Enable UBI - Unsorted block images (MTD_UBI [=y])
  • Enable UBIFS support. Select Filesystems -> Misc filesystems -> UBIFS support.
-> File systems
   -> Miscellaneous filesystems (MISC_FILESYSTEMS [=y])
      -> UBIFS file system support (UBIFS_FS [=y])


Fastboot

Fastboot flashing utility is for updating the different software components of Android. Here is a guide to reflash the xloader, u-boot, kernel and root-filesystem (UBIFS image). This guide assume that Rowboat has been compiled before trying out these instructions.

Establishing Fastboot connectivity

  • Connect serial port to host PC via null modem cable.
  • Serial port settings: 115200 8N1, No flow control.
  • Apply power to the board.
  • Press any key in serial port utility during boot and get U-boot command prompt.
  • Run "fastboot" on u-boot command prompt (u-boot will echo "fastboot initialized").
  • Connect USB cable between USB OTG port of the board and host PC.

Setup on linux host

  • On command prompt, run
   $ export ANDROID_ROOT=<rowboat top level directory>
   $ cd $ANDROID_ROOT/out/host/linux-x86/bin
   $ sudo ./fastboot devices

if a device number is echoed, fastboot is working.

Setup on Windows host

   %SingleBootLoaderInterface% = USB_Install, USB\VID_0451
  • Proceed installing, with the difference that device to be selected is "Android Bootloader Interface" instead of "Android ADB Interface".

Supported Fastboot commands

   $ export ANDROID_ROOT=<rowboat_top_level_build_directory>
   $ cd $ANDROID_ROOT/out/host/linux-x86/bin
  • List connected devices
   $ sudo ./fastboot devices
  • Update images.
   $ sudo ./fastboot flash image_name <image_path>
  • Erasing images or partition.
   $ sudo ./fastboot erase <partition name> (eg. xloader)
  • Display fastboot variable
   $ sudo ./fastboot getvar <variable>
  • Exit fastboot mode in uboot
   $ sudo ./fastboot continue

Important

  • AM3517evm u-boot doesn't support Full Speed USB mode(USB 1.1) and it expects HOST machine USB port to be High Speed USB (USB 2.0).

Fastboot Porting guide

Fastboot implementation have a generic board independent function driver (cmd_fastboot.c), which will communicate with USB gadget driver, in the present case USB gadget stack is handled by MUSB driver. In the board dependent files, configurations like the available partition name, offset, size, method of nand write etc are defined.

In the Config file:

  • Enable CONFIG_FASTBOOT
  • Enable CONFIG_MUSB_UDC, disable CONFIG_MUSB_HCD (assumption: gadget driver used is MUSB)
  • Enable CONFIG_CMD_FASTBOOT
  • Define CONFIG_FASTBOOT_TRANSFER_BUFFER (location to which fastboot data has to be downloaded)
  • Define CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE (maximum fastboot data that can be downloaded, make sure it does not overlap bootloader memory)
  • Define FASTBOOT_NAND_BLOCK_SIZE
  • Define FASTBOOT_NAND_OOB_SIZE
  • Define FASTBOOT_PRODUCT_NAME, make sure that string is same as value of TARGET_PRODUCT used for compiling Android
  • Define USB_BCD_VERSION to 0x0200, if HS USB support is required

In the Board file:

  • Add header file - fastboot.h
  • Define "struct fastboot_ptentry" array with entries equal to the number of partitions required
  • Each entry to have name - this is the variable used for flashing, erasing.
  • Each entry to provide NAND start address & length
  • Each entry to specify flags, options as follows,
  • FASTBOOT_PTENTRY_FLAGS_WRITE_HW_ECC - flash the partition using HW ECC
  • FASTBOOT_PTENTRY_FLAGS_HW_ECC_LAYOUT_1 - Sets the NANDECC to use Kernel/FS layout for writing
  • FASTBOOT_PTENTRY_FLAGS_HW_ECC_LAYOUT_2 - Sets the NANDECC to use X-loader/U-boot layout for writing
  • FASTBOOT_PTENTRY_FLAGS_WRITE_SW_ECC - flash the partition using SW ECC
  • FASTBOOT_PTENTRY_FLAGS_WRITE_I - Use write.i for NAND write
  • FASTBOOT_PTENTRY_FLAGS_WRITE_JFFS2 - Use write.jffs2 for NAND write
  • FASTBOOT_PTENTRY_FLAGS_WRITE_ENV - Add this flag to indicate to fastboot driver the partition for storing environmental variable
  • FASTBOOT_PTENTRY_FLAGS_REPEAT_4 - Use this to indicate that partition will be written 4 times
  • Additional flags can be defined to write till 15 times, last 4 bits are reserved for repeat value, Define required value & OR the value in flag
  • Invoke fastboot API, ' fastboot_flash_add_ptn' for each partition so as to inform about the partition details to fastboot driver.

Notes

  • Existing USB gadget supported only FS, this was modified so that HS USB can be handled. Changes were done in USB header files, MUSB files.
  • AM35X was having problems due to the wrapper over MUSB IP. Fix in MUSB UDC; read TI EP interrupt register instead of MUSB register.
  • A fix with respect to the index for EP array has also been done.
  • MUSB EP setup has been modified to be more in line with the USB TRM.
  • Portions of the code that has been ported from OmapZoom is included within the macro FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING.


Sensors

Introduction

This section of guide provides a step by step explanation of what's involved in adding/porting sensors in a custom Android build like Rowboat.

Accelerometer

Android sensor sub system overview

AndroidSensor.jpg

Above diagram shows the android subsystem overview.

  • Application Framework
    • Sensor Applications use the Sensor application framework to get the sensor data. It communicates with C++ layer through sensor Java native interface (JNI)
  • Sensor Libraries
    • Sensor middle layer mainly consists of Sensor Manager, Sensor service and Sensor hardware abstraction layer.
  • Input Subsystem
    • This is a generic Linux framework for all input devices like keyboard, mouse, touchscreen and defines a standard set of events. It interfaces to user space through /sys/class/input interface.
  • Evdev
    • Evdev provides a generic way for input device events to be accessible under /dev/input/eventX .
  • LIS331DLH Accelerometer Driver
    • This driver communicates with LIS331DLH accelerometer chip via GPIO and I2C bus. GPIO line is used for generating interrupts while I2C bus for accessing and configuring accelerometer registers.

Driver porting

On AM37x Flashboard Accelerometer(LIS331DLH) is connected to I2C 1 bus. Its relevant initialization and pin-muxing is done at <kernel>/arch/arm/mach-omap2/board-omap3evm.c file.

Modify LIS331DLH data structure

Modify the following structure to change the axes directions (negate_x, negate_y, negate_x) and axis mapping (axis_map_x, axis_map_y, axis_map_z). This can be used to calibrate the sensor.

  struct lis331dlh_platform_data lis331dlh_omap3evm_data = {
       .min_interval = 1,
       .poll_interval = 200,
       .g_range = LIS331DLH_G_8G,
       .axis_map_x = 0,
       .axis_map_y = 1,
       .axis_map_z = 2,
       .negate_x = 0,
       .negate_y = 0,
       .negate_z = 0,
  };

Add I2C board info structure

On Flashboard accelerometer is connected to I2C 1. If your sensor is interfaced on different I2C bus then please do the following changes to your board file.

  static struct i2c_board_info __initdata omap3evm_i2c_x_boardinfo[] = {
     {
             I2C_BOARD_INFO("lis331dlh", 0x18),
             .platform_data = &lis331dlh_omap3evm_data,
     },
  };

Where 0x18 is the lis331dlh chip address. Please change this address corresponding to your chip address.

Register i2c bus

Register I2C bus with the i2c sub-system.

  static int __init omap3_evm_i2c_init(void)
  {
       .
       .
       omap_register_i2c_bus(x, 100, omap3evm_i2c_x_boardinfo, ARRAY_SIZE(omap3evm_i2c_x_boardinfo));
       .
       .
       return 0;
  }
    
  Note: where x is i2c bus number.

Interrupt line modification

on Flash board accelerometer interrupt line is connected to GPIO 42.Please change the following if your accelerometer interrupt line is connected to different GPIO.

Pin mux change in board configuration file

Add following line to omap36x_board_mux structure to arch/arm/mach-omap2/board-omap3evm.c file.

  static struct omap_board_mux omap36x_board_mux[] __initdata = {
  {
      .
      .
      //Ex: Pin mux for GPIO 42.
      OMAP3_MUX(GPMC_A9, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP), 
  }
    
  Note: Please change OMAP3_MUX arguments as per your GPIO No.
LIS331DLH driver file modification

LIS331DLH accelerometer driver is located at <kernel>/driver/misc/lis331dlh.c file. Change the following macro for your interrupt gpio number.

  #define LIS331DLH_INT2_GPIO     GPIO_NO

Test Accelerometer driver

Enable Accelerometer sensor.

  #cat 1 > /sys/bus/i2c/drivers/lis331dlh/1-0018/enable
   
  Note: Please ckeck appropriate sysfs path as per your driver

Use getevent command to see accelerometer events

  #getevent
     add device 2: /dev/input/event2
     name:     "Acceleromter"
     /dev/input/event2: 0001 014a 00000001
     /dev/input/event2: 0003 0000 0000089e
     /dev/input/event2: 0003 0001 000005fe

Android hardware abstraction layer

Sensor hardware abstraction layer (HAL) is located in <android source>/hardware/ti/omap3/libsensors directory.

Adding new sensor support in android HAL Ex: Accelerometer

Implement a sensor class

Accelerometer sensor class in implemented in AccelSensor.h and AccelSensor.cpp file.

  class AccelSensor : public SensorBase {
       int mEnabled;
       .
       .
       int setInitialState();
       
   public:
      
       AccelSensor();
       virtual ~AccelSensor();
       virtual int readEvents(sensors_event_t* data, int count);
       virtual bool hasPendingEvents() const;
       virtual int setDelay(int32_t handle, int64_t ns);
       virtual int enable(int32_t handle, int enabled);
   };
Add new sensor support

Add new sensor support in sensors.cpp file.

  • Add new sensor to sSensorList Structure
  /* The SENSORS Module */
  static const struct sensor_t sSensorList[] = {
  .
  .
  { "VTI 3 axis accelerometer",
    "VTI",
    1, SENSORS_ACCELERATION_HANDLE,
    SENSOR_TYPE_ACCELEROMETER, RANGE_A, RESOLUTION_A, 0.23f, 20000, { } },
  };
  • Create object of new sensor
  sensors_poll_context_t::sensors_poll_context_t()
  {
       .
       .
       mSensors[accel] = new AccelSensor();
       mPollFds[accel].fd = mSensors[accel]->getFd();
       mPollFds[accel].events = POLLIN;
       mPollFds[accel].revents = 0;
       .
       .
       int wakeFds[2];
       int result = pipe(wakeFds);
       LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
       fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
       fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
       mWritePipeFd = wakeFds[1];
               
       mPollFds[wake].fd = wakeFds[0];
       mPollFds[wake].events = POLLIN;
       mPollFds[wake].revents = 0;
            
 }


  • Update sensors_poll_context_t structure and add new sensor case to handleToDriver function.
  struct sensors_poll_context_t {
      struct sensors_poll_device_t device; // must be first
      .
      .
  private:
      enum {
           accel           = 0,
           light           = 1,
           proximity       = 2,
           press_temp      = 3,
           numSensorDrivers,
           numFds,
      };
     
    
   int handleToDriver(int handle) const {
           switch (handle) {
                    case ID_A:
                           return accel;
                       .
                       .
       }
           return -EINVAL;
   }

Calibration methods

Axis device.png

The sensor coordinate-system is defined relative to the screen of the device in its default orientation.The X axis is horizontal and points to the right, the Y axis is vertical and points up and the Z axis points towards the outside of the front face of the screen. Co-ordinates behind the screen have negative Z values.

The sensor calibration involves

  • Changing axes directions and swapping axes as per device default orientation.
  • Zero calibration

Changing axes directions and swapping axes

A sensor in a steady state on a horizontal surface should measure 0 g in X axis and 0 g in Y axis whereas the Z axis will measure 1 g(9.8).

  • Identifying whether to swap axes:
    • Run a standard sensor application which displays the sensor readings and monitor sensor readings.
    • Point a x-axis towards ground and check whether x-axis reading is getting changed. If some other axis (let's say y-axis) reading is getting changed then you need to swap axes (i.e. treat sensor y-axis as x-axis in software).
    • Similarly record point other axes towards ground and swap if required.
  • Identifying whether to change axes directions

The axes direction can be verified by pointing the axis of interest towards the ground, noting the output value, rotating the sensor by 180 degrees (pointing to the sky) and noting the output value again. By doing so, ±1 g acceleration is applied to the sensor.

    • Run a standard sensor application which displays the sensor readings and monitor sensor readings.
    • Point +x axis towards ground, you should get +g. If you are getting -g then change the direction of the axis.
    • Similarly point other axes towards ground and change direction if required.

This calibration method can be achieved by modifying the driver or android hardware abstraction layer.

Driver Modification

Accelerometer platform data structure is as follows.

  struct lis331dlh_platform_data lis331dlh_omap3evm_data = {
      .min_interval = 1,
      .poll_interval = 200,
      .g_range = LIS331DLH_G_8G,
      .axis_map_x = 0,
      .axis_map_y = 1,
      .axis_map_z = 2,
      .negate_x = 0,
      .negate_y = 0,
      .negate_z = 0,
  }; 

axis_map_x, axis_map_y, axis_map_z can be used to swap x, y and z axes. If axis_map_x is 0 then it will be mapped to x-axis in android, if it is 1 then it will be mapped to y axis in Android and so on.

To change the axes direction we can set negate_x, negate_y and negate_z value to 1. If negate_x, negate_y and negate_z values are set to 1 then driver will negate accelerometer axes readings before passing to user space (Android).

Android HAL modification

This type of calibration can be achieved in Android HAL as well by modifying readEvents() function in <android source>/hardware/ti/omap3/libsensors/AccelSensor.cpp file.

  int AccelSensor::readEvents(sensors_event_t* data, int count)
  {
      .
      .
      while (count && mInputReader.readEvent(&event)) {
          int type = event->type;
          if (type == EV_ABS) {
              float value = event->value;
              if (event->code == EVENT_TYPE_ACCEL_Y) {
                  mPendingEvent.data[1] =  -(value * CONVERT_A_Y);
              } else if (event->code == EVENT_TYPE_ACCEL_X) {
                  mPendingEvent.data[0] = -(value * CONVERT_A_X);
              } else if (event->code == EVENT_TYPE_ACCEL_Z) {
                  mPendingEvent.data[2] = -(value * CONVERT_A_Z);
              }
     .
     .
     .
  }

data[index]: index can be changed to swap axes and value can be negated to change the axis direction.

Accelerometer zero calibration

When the device rests on a level surface, X and Y should measure around 0 g where as Z axis should measure 1 g (9.8). The accelerometer can be zero calibrated i.e. adjusted so that the acceleration reads zero at the current acceleration of the device.

Procedure for zero calibration:

  • Run a standard sensor application and monitor readings.
  • Take the accelerometer x,y readings when device is in steady state on a horizontal surface.
  • Ideally x, y readings should be zero. if it is not the case then save x, y readings in dx and dy variables.
  • Substact dx and dy from data[0], data[1] values for zero calibration.
  • For z-axis calibration, place the device in a steady state perpendicular to the surface.
  • Ideally z-axis reading should be zero. If you are not getting zero reading, save z axis reading in dz variable substact dz from data[2].

Lets say you are geting x=1.3 and y=1.7 when device is in steady state on a horizontal surface and z=1.4 when device is in a steady state perpendicular to the surface. Modify the readEvents() function in <android source>/hardware/ti/omap3/libsensors/AccelSensor.cpp file as below.

  int AccelSensor::readEvents(sensors_event_t* data, int count)
  { 
      float dx=1.3, dy=1.7, dz=1.4;
      .
      .
      while (count && mInputReader.readEvent(&event)) {
          int type = event->type;
          if (type == EV_ABS) {
              float value = event->value;
              if (event->code == EVENT_TYPE_ACCEL_Y) {
                  mPendingEvent.data[1] =  -(value * CONVERT_A_Y) - dy;
              } else if (event->code == EVENT_TYPE_ACCEL_X) {
                  mPendingEvent.data[0] = -(value * CONVERT_A_X) - dx;
              } else if (event->code == EVENT_TYPE_ACCEL_Z) {
                  mPendingEvent.data[2] = -(value * CONVERT_A_Z) - dz;
              }
     .
     .
     .
  }


Zero calibration can be achieved in application layer as well.Following links show examples for achieving zero calibration at application level.

http://www.intuitor.com/student/Android%20Phone%20Site/StephanAccelerometerAndroid.php

http://stuffthathappens.com/blog/2009/03/15/android-accelerometer/

Important files

  • Sensor Manager Application Layer: <android source>/frameworks/base/core/java/android/hardware folder
  • Sensor JNI layer: <android source>/frameworks/base/core/jni/android_hardware_SensorManager.cpp file
  • Sensor Manager Library: <android source>/frameworks/base/libs/gui folder
  • Sensor Service: <android source>/frameworks/base/services/sensorservice folder
  • Sensor HAL: <android source>/hardware/ti/omap3/libsensors folder
  • Accelerometer Sensor driver: <kernel>/drivers/input/misc/lis331dlh.c file

Mass storage

Introduction

The Android system uses vold as the mount daemon which detects, mounts and monitors the status of external storage.This mount daemon needs a configuration file(vold.fstab) to determine the mount device and location where it should be mounted.
Vold reads /etc/vold.fstab configuration file and mounts the device specified in the file. The basic format of the vold.fstab is

  dev_mount <label> <mount_point> <part> <sysfs_path1...> 
  
  where
  label - Label for the volume
  mount_point - Where the volume will be mounted
  part - Partition # (1 based), or 'auto' for first usable partition.
  <sysfs_path> - List of sysfs paths to source devices

sysfs_path is the full or partial path where kernel exports the udev information about the device currently pluged into system.
See system/core/rootdir/etc/vold.fstab in the Android source tree for the detailed explanations of the format.

Beagleboard example

In case of Beagleboard-XM, Kernel populates udev entries in any one of the following paths based on the port to which external storage device is connected.

  /sys/devices/platform/ehci-omap.0/usb1/1-2/1-2.2/
  /sys/devices/platform/ehci-omap.0/usb1/1-2/1-2.3/
  /sys/devices/platform/ehci-omap.0/usb1/1-2/1-2.4/
  /sys/devices/platform/ehci-omap.0/usb1/1-2/1-2.5/

To detect connected usb mass storage device and mount/unmount it automatically when pluged/unpluged, follow below mentioned procedure.

1. Modify vold.fstab file as per following patch

   diff --git a/vold.fstab b/vold.fstab
   index fc83907..2ace73f 100644
   --- a/vold.fstab
   +++ b/vold.fstab
   @@ -1,2 +1,6 @@
   dev_mount sdcard /mnt/sdcard auto /devices/platform/mmci-omap-hs.0/mmc_host/mmc0
   +dev_mount usb /mnt/usb2 auto /devices/platform/ehci-omap.0/usb1/1-2/1-2.2/
   +dev_mount usb /mnt/usb3 auto /devices/platform/ehci-omap.0/usb1/1-2/1-2.3/
   +dev_mount usb /mnt/usb4 auto /devices/platform/ehci-omap.0/usb1/1-2/1-2.4/
   +dev_mount usb /mnt/usb5 auto /devices/platform/ehci-omap.0/usb1/1-2/1-2.5/

2. Modify init.rc file as per following patch

diff --git a/init.rc b/init.rc
index 4585248..b1a38f2 100644
--- a/init.rc
+++ b/init.rc
@@ -23,6 +23,10 @@ loglevel 3
 # create mountpoints
     mkdir /mnt 0775 root system
     mkdir /mnt/sdcard 0000 system system
+    mkdir /mnt/usb2 0000 system system
+    mkdir /mnt/usb3 0000 system system
+    mkdir /mnt/usb4 0000 system system
+    mkdir /mnt/usb5 0000 system system
 
 # Create cgroup mount point for cpu accounting
     mkdir /acct
@@ -31,6 +35,10 @@ loglevel 3
 
 # Backwards Compat - XXX: Going away in G*
     symlink /mnt/sdcard /sdcard
+    symlink /mnt/usb2 /usb2
+    symlink /mnt/usb3 /usb3
+    symlink /mnt/usb4 /usb4
+    symlink /mnt/usb5 /usb5
 
     mkdir /system
     mkdir /data 0771 system system

Test Mass storage in Android

Connect USB mass storage device to board and check whether it is mounted properly.

  • Use mount command to see the list of mount points. Here is the sample output of mount command.
# mount

rootfs / rootfs rw 0 0
172.24.132.204:/home/workdir/TI_Android_GingerBread_2_3_Sources/out/target/product/beagleboard/android_rootfs / nfs rw,relatime,vers=3,rsize=262144,0
tmpfs /dev tmpfs rw,relatime,mode=755 0 0
devpts /dev/pts devpts rw,relatime,mode=600 0 0
proc /proc proc rw,relatime 0 0
sysfs /sys sysfs rw,relatime 0 0
tmpfs /mnt/asec tmpfs rw,relatime,mode=755,gid=1000 0 0
/dev/block/mmcblk0p3 /part-3 vfat rw,relatime,fmask=0000,dmask=0000,allow_utime=0022,codepage=cp437,iocharset=iso8859-1,shortname=mixed,errors=remount-ro 00
/dev/block/vold/179:3 /mnt/sdcard vfat rw,nosuid,nodev,noexec,relatime,fmask=0000,dmask=0000,allow_utime=0022,codepage=cp437,iocharset=iso8859-1,shortname=0
/dev/block/vold/179:3 /mnt/secure/asec vfat rw,nosuid,nodev,noexec,relatime,fmask=0000,dmask=0000,allow_utime=0022,codepage=cp437,iocharset=iso8859-1,short0
tmpfs /mnt/sdcard/.android_secure tmpfs ro,relatime,size=0k,mode=000 0 0
/dev/block/vold/8:17 /mnt/usb4 vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iochars0
/dev/block/vold/8:17 /mnt/secure/asec vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,0
tmpfs /mnt/usb4/.android_secure tmpfs ro,relatime,size=0k,mode=000 0 0
/dev/block/vold/8:1 /mnt/usb2 vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,iocharse0
/dev/block/vold/8:1 /mnt/secure/asec vfat rw,dirsync,nosuid,nodev,noexec,relatime,uid=1000,gid=1015,fmask=0702,dmask=0702,allow_utime=0020,codepage=cp437,i0
tmpfs /mnt/usb2/.android_secure tmpfs ro,relatime,size=0k,mode=000 0 0
  • Run file manager application and see whether usb2, usb3, usb4 and usb5 directories are populated with appropriate files and directories.

AndroidFileManager.png

Versioning

This is Release DevKit-V2.1 The release is available from http://software-dl.ti.com/dsps/dsps_public_sw/sdo_tii/TI_Android_DevKit/TI_Android_GingerBread_2_3_4_DevKit_2_1/index_FDS.html
The release notes is available at http://processors.wiki.ti.com/index.php/TI-Android-GingerBread-2.3.4-DevKit-2.1_ReleaseNotes

Technical Support and Product Updates

For further information or to report any problems, contact http://e2e.ti.com/android or http://support.ti.com.
For community support join http://groups.google.com/group/rowboat
For IRC #rowboat on irc.freenode.net