Paul Kocialkowski's coding blog

Free software, programming and stuff

ALSA

Asus N56VB-S3055H laptop and Debian installation

Written by Paul Kocialkowski - 20 july 2013 - 4 comments

Asus N56VB-S3055H

Along with moving on to new studies (I'm done with High School), I got a brand new laptop: an Asus N56VB-S3055H. The hardware specs are really nice, with a quad-core i7-3630QM CPU, 6Gb RAM, 1Tb HDD. I was worried about the integrated nVidia card (GeForce GT 740M) at first, that I suspected to be a cause of problems on GNU/Linux. Thankfully, it does not bother me and the Intel Ivy-bridge card works just fine. I also had the great suprise of finding an ath9k WiFi card shipped with the laptop! You can find a complete hardware review at h-node: Asus N56VB-S3055H

Debian installation

I used to install every new machine with Trisquel GNU/Linux, however I don't really agree with the Linux-libre policy that is about blocking the firmwares load. Moreover, Debian recently made great efforts towards being a fully free distro. So basically, my Debian installation is fully free and the hardware doesn't require loaded non-free firmwares (which means I don't have to use the non-free Debian repo).

Setting up the BIOS

However the BIOS is non-free and it ships with Secure Mode enabled. The BIOS can be accessed by booting with the ESC key pressed and then selecting the option to access Setup. Make sure that you do not let it boot the preinstalled Windows 8 as there is no way to soft turn the computer off if you don't agree to the license terms.

In order to install GNU/Linux, make sure you disable the following options in the BIOS:

  • Intel Anti-theft technology
  • Fast Boot
  • Secure Boot Control

Then enable the following options:

  • Launch CCSM (you might want to disable PXE then)

UEFI boot with the Debian installer

With such options in the BIOS, you should be able to boot a GNU/Linux installation disc (and probably an USB install media too). However, be very careful: the BIOS only support UEFI boot from the HDD, so you have to install GRUB with UEFI support. In the debian-installer, I only had to create an UEFI partition (at the begining of the disk) and the installer did the rest. It also set the mountpoint to /boot/uefi. Keeping the Windows UEFI partition (make sure to format it though) would probably work too. As a matter of fact, I failed the installation the first time because I removed the partition (and the Debian installer warned me that it was a bad idea). So things aren't so bad in the end, since there is free software support for UEFI booting.

Setting up the touchpad correctly

The laptop has a synaptics touchpad which didn't work correctly at first: drag'n'drop was not at all possible and both click buttons triggered a left click. After some online research, I found one solution that is to use one-finger click for left click and two-finger click for right click. However, this was far from perfect since this is not the expected behavior and drag'n'drop was still impossible. Here is some documentation about how to set that up though: Left-, Right-, and Middle-click on Clickpad .

The real complete solution was adding some options to the synaptics Xorg input driver so that it handles soft buttons, clickpad and multi-touch.
It consists in creating /usr/share/X11/xorg.conf.d/75-synaptics.conf with the following contents:

Section "InputClass"
        Identifier "Default clickpad buttons"
        MatchDriver "synaptics"
        Option "SoftButtonAreas" "50% 0 82% 0 0 0 0 0"
	Option "ClickPad"         "true"
	Option "EmulateMidButtonTime" "0"
EndSection

Enabling the external subwoofer

Another feature that was missing was the external subwoofer. A couple of steps are required to enable it, described on the ArchWiki page for another Asus laptop: Asus N55SF Audio. However with strictly this, it still didn't work: I had to step up the Bass Speaker volume in alsamixer (make sure to select the Intel HDA card first) and obviously select the newly created 2.1 Output profile on the GNOME sound config app.

Tuning up GNOME

Since the main graphics chip is an Intel one, graphics acceleration worked out of the box on Debian, and I just ignore the nVidia card for now. That means I had the great pleasure of enjoying the use of GNOME-Shell for some time, but quickly went back to the traditional GNOME-Panel, that I find a lot more convenient for developing. Obviously, a lot of tuning up is needed to make the experience perfect.

Backlight, backlight…

I was very surprised with the way GNOME handles both the panel backlight and the keyboard backlight. Basically, these can be dynamically tuned with the media keys (Fn+Something combination keys), which works fine, but none of these changes are kept between sessions and reboots. That means I have to change these after every single login: that is so annying. So my solution was to create an init.d script that stores the backlight values at poweroff and to use a script launched at the GNOME session startup to bring back the previously stored values. It's a shame I have to do this, such basic support should come out of the box with software as popular as GNOME is.

Themes, icons, compositing

Collins desktop

Even though it has glitches, I always prefer enabling compositing in metacity so that stuff looks better (transparency, round angles, etc). Since GNOME switched to dconf, here is how I enabled compositing: using dconf-editor: org > gnome > metacity > compositing-manager.

As for the themes I use: Shiki-Colors-Metacity, which is packaged in Debian for window borders, Gnome-brave for icons (packaged as well) and Zukitwo-Sark for GTK+. For the latter, make sure to install its dependencies to avoid unexpected results:

sudo apt-get install gtk2-engines-murrine gtk2-engines-pixbuf

Galaxy S2 Replicant port status update

Written by Paul Kocialkowski - 04 february 2013 - 2 comments

Quite some time ago, I was given the opportunity to receive a crowd-funded Galaxy S2 phone. Even though I was very thankful for it, I couldn't really focus on it at first since I had to handle other things on various other devices I was working on. It left me somehow sad as I felt that it was my duty to add proper Replicant support for it. Today, I'm proud to announce that the biggest part of the work to support it is over.

The modem (XMM6260)

At first, we had to add support for the modem, an XMM 6260 modem with a custom Samsung firmware. The modem protocol is what we call Samsung IPC, the very same as the one used in the Nexus S or Galaxy S. Our lower-layer library to handle it is libsamsung-ipc, that is shared between Replicant and SHR. So We had to add support for XMM6260 in libsamsung-ipc, along with Galaxy S2-specific bits. Thoughtfully, we designed the upper layer, Samsung-RIL (that is specific to Replicant) to work with libsamsung-ipc regardless of the device it's running on. Nowadays, the modem support is complete and we have working calls, messages and data. Anyway, modem features support is up to Samsung-RIL, so it's not Galaxy S2-specific.

The Audio CODEC (Yamaha MC1N2)

After doing a break in Galaxy S2 development, I finally got back to it, and started the 4.0 Replicant version for the occasion. Since the audio module was non-free in CyanogenMod, it was one of the key components to add support for. (What good is a phone if you can't get any sound out of it?) So after digging a little in the kernel code, it turned out that the Audio CODEC had an ALSA interface driver. That means PCM In/Out interfaces as well as Mixer controls. Only problem was that I still couldn't get any sound out of it using the TinyALSA test utils. After doing a bit of research, I found out about the /dev/snd/hwC0D0 node, that was implementing hardware-specific controls (via ioctl). After adding debug prints to it and with the help of some CyanogenMod developers, I was able to reimplement it on my Yamaha-MC1N2-Audio library. The ALSA part was done with a 4.0 update (call it a complete rewrite) of my TinyALSA-Audio library. The combination of the two made it possible to have sound with Replicant (including during calls). It is even used by CyanogenMod since version 10.1!

The sensors (K3DH accelerometer)

With modem and audio support, the Galaxy S2 was made usable as a phone. Thanks to the free hwcomposer module, it's very fast too, so I decided to use it as a main phone for a time, and frankly quite enjoyed the ride. The sensors were also relying on a non-free library, the one called libakm: AKM is the compass manufacturer. Nonetheless, it includes the bits to properly handle the K3DH accelerometer chip too. The situation is quite similar to the Nexus S sensors, and I was able to figure out the accelerometer part back then (it was a KR3DH) and implemented it in the libakm_free library. Since it was quite easy for Nexus S (libakm was just a passthrough), I gave it a try on the Galaxy S2. After tracing the K3DH kernel driver, I figured that the values returned by libakm were just the result of linear functions applied to the data returned by the kernel. I renamed libakm_free to Samsung-Sensors and added support for the K3DH there.

The cameras (M5MO/S5K5BAFX)

Galaxy S2 Camera

Galaxy S2 support was then already pretty decent, and I was kind of proud of myself. Though, it take a look at the Galaxy S2 characteristics, you'll see that one of its key features is the 8MP camera it embeds. And sadly, there was no usable camera module around. Though, it appeared to have a V4L2 driver, which is pretty standard and easy to implement. However, I feared that I'd have to face the same situation as audio: standard interface but only usable with a non-trivial interface aside. Once again, I traced the kernel driver and started implementing, step by step. After a couple weeks of work (I wrote the implementation from scratch and obviously couldn't spend time on it everyday), it appeared that the original non-free camera module was doing a lot of unnecessary output/overlay operations. So I decided to cut out the crap and get to the essential, that is only using the capture V4L2 interface. This comes with some issues such as the inability to resize/crop the output buffer, but I think I found acceptable workarounds for that. In the end, my camera module turned out to work quite well and is now fully-featured (except EXIF that is currently broken, but it's such a pain in the ass that I don't really want to get into it and fix things). I pushed the code on the Galaxy S2 device tree as well as on my personal Exynos Camera git repo.

The future?

Now the Galaxy S2 is supported as well as the Nexus S in Replicant and the missing (and doable) parts left are mainly GPS and compass. The compass is an AKM8975 chip. Some code was released by AKM for this chipset and even though my first attempts to make it work failed, I guess there is a way to have it working properly. I didn't renew my attempts since this is quite a detail and there is probably more important things to work on at the moment. That's for instance the GPS: it's a GSD4t chip, the very same as the Galaxy Nexus. It needs a firmware upload and uses a SiRF-derived protocol that does not seem to be documented anywhere. I hope we'll be able to figure it out somehow: it would be very nice to have GPS support on these two devices!

Writing a fully-featured, clear and flexible ALSA libaudio for Gingerbread: TinyALSA-Audio

Written by Paul Kocialkowski - 01 august 2012 - 2 comments

As I am porting Replicant, our fully free Android derivate, to the new Goldelico GTA04, I had to deal with ALSA user-space integration in Gingerbread. So let's take a quick look about it:
On Gingebread (and previous versions), user-space audio is done via the libaudio library. The Android framework will basically interact with AudioFlinger that is the component in charge of loading that libaudio library and dealing with it (that's frameworks/base/services/audioflinger/AudioFlinger.cpp).
So libaudio is basically the place where PCM read/write and mixer stuff happens. As we started looking into the various existing ALSA libaudio, my fellow Replicant developer GNUtoo told me about TinyHAL, a clean and flexible audio module that does ALSA and routing from XML configuration files. Too bad, TinyHAL was designed for Ice Cream Sandwich, and the Audio API changed in ICS (basically, it is now a module, like the ones for gps, sensors, lights, etc). So I couldn't use it as-is, but there were various concepts I hoped I would be able to reuse, like the XML routing config or the use of the TinyALSA lib, that is very clean, simple to use and handles ioctl-level ALSA stuff.

In the end, I decided to write my own libaudio, using both TinyALSA and XML config files, that I called TinyALSA-Audio. Audio output and Mixer was quite straightforward and worked quickly. AudioFlinger basically opens the AudioStreamOut at 44100Hz, 2 chans, S16_LE format (signed 16bits, little endian), which works fine with the audio hardware, a TWL4030 Codec here, that didn't complain at all.

Next step was about audio input and recording. At first sight, I thought it would be as easy as audio output, that is just setting the controls, opening the device via TinyALSA, sending the config following what AudioFlinger asks and just read the data. So I basically wrote code that was that simple, but it failed while setting the config: cannot set hw params: Invalid argument was the error. As I didn't see what could possibly be wrong about the params, I decided to take a look at how tinycap, the capture utility that comes with TinyALSA handles things. It actually sets the params at 44100Hz, 2 chans, S16_LE, and recording works then. When I tried to force the params to what AudioFlinger asks, that is 8000Hz, 1 chan, S16_LE, I got the very same error as on my libaudio: cannot set hw params: Invalid argument.

So what was it all about? Does the CODEC only records at 44100Hz, 2 chans? I tried with zygote stopped, and then 8000Hz mono worked. I also checked in the kernel code: the TWL4030 CODEC is supposed to work at 8000Hz mono as well. So I deducted that when the output device is opened, the input device will only work at the same config (rate, chans). What a bummer! AudioFlinger asks for 8000Hz mono, not 44100hz stereo, though that's all I can get when output is opened (which is always the case when zygote is running).

Thanks to the AOSP, there are various others libaudio that I could use to learn things. First thing to know was if that "issue" was specific to TWL4030 or common to all ALSA CODECS. So I did the same test (with tinycap) on the Nexus S and Galaxy S, and the result was that both couldn't record at any other rate/chans that the ones set when opening output. Galaxy Nexus audio module confirmed that too. So what is the solution here? Obviously, it consists in finding a way to return 8000Hz mono data to AudioFlinger while reading 44100Hz stereo data: that's resampling.

Galaxy S and Nexus S libaudio all handled resampling by internal algorithms, which seemed a pain to use and adapt on my libaudio. The solution finally came from the Galaxy Nexus audio module. And I really want to send a big Thank-You to the people who wrote it. First of all, it uses the very same TinyALSA as my libaudio uses. Second thing is that it doesn't embed complicated algorithms for resampling but uses the new Android 4 framework for resampling, that wasn't so hard to understand. behind that engine is the libspeexresampler lib, that is part of speex code. So all I had to do was to backport that Android 4 resampling code, enable to build of libspeexresampler in gingerbread and make use of all that in my lib.

Though, wait a second, when reading AudioFlinger code, it all seemed to indicate that AudioFlinger embeds its own resampling engine, so that when the lbiaudio reports different parameters, it handles resampling to what it wants (mostly 8000hz mono). So I tried to make use of that, in vain. I couldn't figure out why it didn't work, it just didn't. I read the AudioFlinger code several times, made sure the resampler was enabled and all, but in the end, the produced audio was just garbage, so I just gave up on using AudioFlinfer's resampler. After all, if all the AOSP libaudio do not make use of it, there might be a reason. So the thing appears to be totally messed-up and nobody cares enough to fix it but rather implement resampling in the libaudio itself. Not a very good thing for me, I would have preferred to leave resampling to the upper layer, but anyway, I had Galaxy Nexus code that could be adapted to my lib. So that's basically what I did: backporting the Android 4 resampler code to my libaudio, making use of it and using ICS external/speex repo. In the end of this misadventure and with some fine tuning, it all worked.

That's pretty much the end of the story, now I have my TinyALSA-Audio lib that handles input/output routing via mixer audio output and audio input as well, to various rates. Here are some links: