Monday, September 16, 2013

DWC USB interrupt spam in Rockchip SoCs

Some time ago, when looking for answers to some USB 1.1 problems on the RK chips, like:
- USB 1.1 to Ethernet dongle not working
- Repeated or missing key presses
I stumbled upon some Raspberry Pi forums complaining about the same things.

This is logical since both the Rasp. Pi SoC and the RK3066/3188 are using the same USB HW IP cores (from DesignWare, that is DWC).

One of the problems they were reporting was an excessive number of interrupts per second coming from the USB while the system was idle (I've confirmed it, even with just a USB 1.1 keyboard attached).

One way to check this is with the console command:
vmstat 1
Looking below label "in" will tell you how many interrupts are there per second. In my case, Linux3188 kernel ( http://github.com/Galland/Linux3188 ) on a RK3188 Cozyswan S400 (kindly donated by KSK Electrics) the result is some 10600 interrupts per second.

And a way to see who is interrupting is simply to type:
cat /proc/interrupts
In my case, the "dwc_otg_hcd:usb1, dwc_otg_pcd" is the root cause for some more than 8000 interrupts per second, just as it happens to RPi guys.

The problem seems to stem from the DWC driver, as explained here:
"the Synopsys driver relies on the start of frame interrupt for scheduling transfers if "descriptor DMA" is not implemented (which it isn't, on BCM2835).  8000 is one interrupt per microframe."
and propose the use of a FIQ (ARM fast interrupt handler) for USB IRQs to discard USB microframes that contain no data. More info here...

And the FIQ enabled code lies in this repo (see commits starting in April 2013 by Gordon Hollingworth): https://github.com/ghollingworth/linux/commits/rpi-3.6.y


Testing real screen resolution on RK Linux

Problem:


You think you have a 1080p screen resolution but when you draw a non-aliased one pixel width line and move the window around, it doesn't look one solid line anymore.

You're not on 1080p, but likely on a scaled 720p (even if Linux reports 1080p).


Test:


On a console type:

cat /sys/devices/platform/rk-fb/graphics/fb0/disp_info

for a working 1080p setup, the result should be something like:

win0:enabled
xvir:960
xact:1920
yact:1080
xdsp:1920
ydsp:1080
x_st:192
y_st:41
x_scale:1.0
y_scale:1.0
format:RGB565
win1:disabled
xvir:0
xdsp:320
ydsp:240
x_st:10
y_st:10
format:ARGB888

That is xact and yact (the virtual resolution seen by Linux) must be the same as xdsp and ydsp (the real resolution been sent to the screen), or else you have a scaled output (x_scale and y_scale not 1.0).

Solution:


If this is the case and you find that xdsp=1280 and ydsp=720, whereas you expected a 1080p display, the solution is in this commit:
https://github.com/Galland/3188-SRC-AP6210/commit/130c1ad6bb47f3b2401b6156f205dcb5882255c7


BTW, notice the 16 bits color: RGB565
I couldn't tell the difference with normal desktop usage, but it means half the memory operations (32 bits ARGB888 <-> 16 bits RGB565).

Wednesday, September 11, 2013

Root Rockchip sticks/tablets from Linux

Since with every new device it becomes a nightmare (at least for me, that I seldom use Windows) to find the right Windows drivers for ADB access... I noticed that the rooting procedure (TPSparky Vondroid) relies only on the adb command and... that is readily accessible from Linux.

Hence this little guide came up as I put together the necessary little bits and has been tested with a RK3066 based tablet (RK3188 devices should also be rootable with this method, confirmed with Minix Neo X7).


1st Set up Linux ADB access to the device


This step is entirely done from the Linux PC (Ubuntu in this case) where the RK device is connected (through the USB). 

Please note that if your RK device has several USB ports, there will be only one that can be connected to the PC, usually marked as OTG or Slave.


1) Download the lightweight adb tools:
sudo apt-get install android-tools-adb
or, if you don't have Ubuntu, proceed to download and install the whole Android SDK :S


2) Open/create the following text file to let your standard user connect to the RK device:
sudo gedit /etc/udev/rules.d/51-android.rules
and then add a new line with the following text:
SUBSYSTEM=="usb", ATTR{idVendor}=="2207", MODE="0666", GROUP="plugdev"
Of course make sure that your Linux user is part of group "plugdev" with the following terminal command:
groups user

3) Force a reload of the USB access rules to get the latest one on:
sudo udevadm control --reload-rules

4) Add RK devices USB Vendor ID to what adb may expect for your currently logged user:
echo "0x2207" >> ~/.android/adb_usb.ini


2nd Set up the RK device for ADB access


Unplug the RK device from the USB and go to its Settings page to follow this steps:

1) Go to Settings->Storage and click at the top right on the three dots

2) Select USB computer connection in the dropdown

3) Select "Mass Storage" check box and go back to Settings

4) Browse down in Settings and select Security

5) In Security Settings, select "Unknown sources"

6) Back in Settings, select Developer Options

7) In Developer Options, select "USB debugging"

8) Close settings, and any other open apps.

9) Using a known good USB cable, connect the RK device to the PC, you'll get "Connecting to USB" in the notifications area in Android, and a USB icon in the notification area. You Do Not want to select "Connect to Pc to Transfer Files", in the notification menu, just plug in the cable and let it be.

PS: If you don't get a connection you may have to go back into Settings and select USB, then click on "Connect to PC".

3rd Rooting the RK device from Linux


The following steps are just a COPY of those in "TPSparkyRoot.bat" with a minor fix for correct SuperSU installation.

These are to be done on the Linux PC:

1) Download the package with the needed su, SuperSU, busybox, and RootExplorer binaries

2) Extract the package into a folder, open a terminal and cd into that folder

3) Create a new text file (i.e. "gedit script.sh") and copy the following contents:

   echo "*---* VonDroid.com RK device Root Tool based on work by sunnydavid *---*"
   echo "--- Plug in your device, make sure debugging is enabled in Developer Options"
   echo "--- This script will now copy files over to your RK device"
   
   adb shell mv /data/local/tmp /data/local/tmp.bak
   adb shell ln -s /data /data/local/tmp
   adb reboot
   
   echo "--- Reboot 1/3 - Press Enter once the device has rebooted (if USB debugging doesn't appear in the Android bar you may have to click Settings->USB->Connect to PC)"
   read -p "or CTRL-C to exit"
   
   adb shell rm /data/local.prop > nul
   adb shell "echo \"ro.kernel.qemu=1\" > /data/local.prop"
   adb reboot
   
   echo "--- Reboot 2/3 - Press Enter once the device has rebooted (if USB debugging doesn't appear in the Android bar you may have to click Settings->USB->Connect to PC)"
   read -p "or CTRL-C to exit"
   
   adb shell id
   
   echo "--- If the ID shows as 0(root) then continue, otherwise CTRL+C to cancel and start over"
   read -p "CTRL-C to exit"
   
   adb remount
   adb push su /system/bin/su
   adb shell chown root.shell /system/bin/su
   adb shell chmod 6755 /system/bin/su
   adb push busybox /system/bin/busybox
   adb shell chown root.shell /system/bin/busybox
   adb shell chmod 0755 /system/bin/busybox
   
   echo "--- Installing SuperSU"
   
   adb push SuperSU.apk /system/app/SuperSU.apk
   adb shell chown root.root /system/app/SuperSU.apk
   adb shell chmod 0644 /system/app/SuperSU.apk
   adb push RootExplorer.apk /system/app/RootExplorer.apk
   adb shell chown root.root /system/app/RootExplorer.apk
   adb shell chmod 0644 /system/app/RootExplorer.apk
   
   echo "Completing Root ..."
   
   adb shell rm /data/local.prop
   adb shell rm /data/local/tmp
   adb shell mv /data/local/tmp.bak /data/local/tmp
   adb reboot
   
   echo "--- Reboot 3/3 - Your RK device should now be rooted!"


4) Make the script executable with: 
chmod +x script.sh


5) Restart the adb server by typing:
adb kill-server; adb start-server
6) And now when typing the following terminal command:
adb devices
you should see the connected device listed (my tablet for example is named 12345678...)


7) Execute the previously created script ( ./script.sh ) and follow the steps to the letter, including patiently waiting for the potential several-minutes-long pauses

PS: After every reboot you MUST check that in the Android status bar the "USB Debugging" message appears (so that there is adb connection with the PC), or else you'll have to go back into Settings and select USB, then click on "Connect to PC". Only then you can hit Enter in the script to let it go on.


That's it, your device should be rooted, all from within Linux!



DISCLAIMER: I've followed this instructions to root my own devices without any trouble. The rooting procedure itself is simply the very widely used TPSparky method. However I take no responsibility for any mishappenings that may arise from your trying it on your devices. That is entirely yours.


References:
http://forum.xda-developers.com/showthread.php?t=1526487
http://linux-rockchip.info/mw/index.php?title=ADB_shell_with_RK3066
http://forum.xda-developers.com/showthread.php?t=2127573