Monday, August 23, 2010

Samsung work

1) Headset and send-end key driver.
The mobile runs on Qualcomm MSM7627. This is a having two ARM core, two DSP core. There is one ARM11 which is called as Application Processor(AP) on which linux runs. And there is ARM9 which is called Modem Processor(some times called Communication Processor CP) on which REX OS is running. Here CP is the master. Both communicates through Shared memory driver IPC. Whoever want to communicate will place the corresponding COMMAND and data and interrupt the other processor. Send end key is the the switch on the headset to send the key-press events to the application to for disconnecting the call or going to next track in music player. This is implemented as an input device. The driver mechanism is like this.
Headset detection is done on Modem. There is a IPC callback mechanism registered in RIL layer(on AP side) in application space for getting the status change of the headset. So once headset is inserted or remove, modem will pass this information through IPC. The callback in the mode side will write 1 or 0 for headset inserted and headset removed respectively to a sysfs entry(/sys/class/switch/h2w/headset) exported by the headset driver in the AP side. So once the headset is detected we will enable the send-end key interrupt which is done on the AP side. This is implemented on a gpio. Since due to noise created during the headset insertion, lot of spurious interrupts(send end key) where coming. So we enable the send-end key only after 100ms after the headset insertion. This is implemented by using delayed work-queue.

2) Firmware up-gradation on Touch screen.
The touch screen driver is from Melfas. The I2C is implemented using the i2c-gpio driver. This is a kernel driver which manipulates the gpio to implement the I2C protocol. We have to pass the gpios for sda and scl during the initialization of the driver.
some notes about this driver
=======================


This is a very simple bitbanging i2c bus driver utilizing the new
arch-neutral GPIO API. Useful for chips that don't have a built-in
i2c controller, additional i2c busses, or testing purposes.

To use, include something similar to the following in the
board-specific setup code:

#include

static struct i2c_gpio_platform_data i2c_gpio_data = {
.sda_pin = GPIO_PIN_FOO,
.scl_pin = GPIO_PIN_BAR,
};
static struct platform_device i2c_gpio_device = {
.name = "i2c-gpio",
.id = 0,
.dev = {
.platform_data = &i2c_gpio_data,
},
};

Register this platform_device, set up the i2c pins as GPIO if required and you're ready to go. This will use default values for udelay and timeout, and will work with GPIO hardware that does not support open drain mode, but allows changing the direction of the SDA i2c_gpio_device.id is the I2C adapter number i2c_gpio_platform_data has more members to define the pin is

struct i2c_gpio_platform_data {
unsigned int sda_pin;
unsigned int scl_pin;
/*signal toggle delay. SCL frequency is (500 / udelay) kHz*/
int udelay;
/*timeout: clock stretching timeout in jiffies. If the slave keeps
SCL low for longer than this, the transfer will time out.*/
int timeout;
unsigned int sda_is_open_drain:1;
unsigned int scl_is_open_drain:1;
unsigned int scl_is_output_only:1;
}
=============================

3) RamDump Issues
RamDump is a mechanism used by the samsung to catch the cause of any kernel crash and dump it in the RAM. Later they use one software to extract to the machine and can be analyzed. I will explain on RamDump here,
A kernel crash was happening like, freeing the VMA in interrupt context. The kernel back trace is showing starting from work_pending to a place where vumap().
In vunmap() function a BUG(in_interrupt()) is there. It is an assertion to tell that vma should not be freed in interrupt context.
Its takes some time to fix. But I feel little proud of myself after fixing that.
There was one call to lib/genalloc.c gen_pool_destroy(). In that function
write_unlock() is called without the write_lock(). This function basically decrements
and increments the preemt_count to disable the preemption. And everything was going wrong from here. So it was a kernel bug in 2.6.29 kernel.

4) changed msleep() to mdelay()
Not a good thing to do. But in this scenario it is the only solution. The scenario is when user press the , the device should wake up. But the lcd is taking around 900ms to wake up. I saw few msleep(), changed it to mdelay(). This got a reduction of 350ms The only problem is that, the processor will just spin and waist the processor cycles. But here when the device wakes up from sleep it wont be having other things to do. Moreover, mdelay() is not locking anything, it just uses its full time slot. Once its time-slot is over, scheduler will schedules it out.
Another option- One structure they are giving delay after each command. But most of the delay are zero. But in the kernel code they are using like this
msleep(table->wait).
I modified to
if(table->wait)
msleep(table->wait);
The reason is that even msleep(0) will take more than 10ms.