Search This Blog

Jun 22, 2011

Seiko touch panel works abnormal with DA9052 TSI driver

Customer's Android touch screen sometimes no response if draw stylus quickly

Customer use Seiko touch panel and i.MX53 quick start board.

Reproduce the issue with same environment

Got reworked i.MX53 QS board and Seiko WVGA resistance touch panel. Build LTIB 1105 for testing, select "evtest" package. Bootup board and login as root. Run "$evtest /dev/input/event1", we can see coordinate messages output when touching the panel.However, if draw stylus quickly, we will see coordinate messages stops even we move the stylus everywhere on panel. Until we pickup stylus from panel and draw again, we can see coordinate messages output again.

Root cause

After investigating, we found the problem comes from DA9052 TSI driver, one window filter function da9052_tsi_window_filter(), there is code which compare current (x,y) with previous (x,y) coordinate, if coordinate difference large than 50 pixels, diff_within_window() will return fail, and pre_raw_data will not update.
da9052_tsi_window_filter()
{
     static struct da9052_tsi_data prev_raw_data;
…
       ret = diff_within_window(&prev_raw_data, raw_data);
       if (!ret){
                prev_raw_data = (*raw_data);
…
}
For example If we draw stylus quickly from coordinate (100,100) to (600,100), the current (x,y) value now is(600,100), and previous (x,y) is (100,100). the ‘X’ coordinate diff will be (600-100=500), it will cause prev_raw_data not update, as static variable prev_raw_data->x is still 100. Even we keep pressing stylus in (600,100), in function
da9052_tsi_process_reg_data()
{
…
# if (ENABLE_WINDOW_FILTER)
    ret = da9052_tsi_window_filter(priv, &tmp_raw_data);
    if (ret != SUCCESS)
        continue;
#endif
    priv->early_data_flag = FALSE;

    if (down_interruptible(&priv->tsi_raw_fifo.lock)) {
        DA9052_DEBUG("%s: Failed to ", __FUNCTION__);
        DA9052_DEBUG("acquire RAW FIFO Lock!\n");
        up(&priv->tsi_reg_fifo.lock);
        return;
    }
    priv->tsi_raw_fifo.data[priv->tsi_raw_fifo.tail] = tmp_raw_data;
    incr_with_wrap_raw_fifo(priv->tsi_raw_fifo.tail);
    up(&priv->tsi_raw_fifo.lock);
…
}
From above code, we can see when da9052_tsi_window_filter() return failure, the priv->tsi_raw_fifo.data[priv->tsi_raw_fifo.tail] will not get value. So we can see the touch panel suck.

Solution

Two ways to solve the issue.
1. in “include/linux/mfd/da9052/tsi_cfg.h, the code changed like below.
-define ENABLE_WINDOW_FILTER                      1
   +define ENABLE_WINDOW_FILTER                      0
2. In "drivers/input/touchscreen/da9052_tsi_filter.c"
da9052_tsi_window_filter()
{
     static struct da9052_tsi_data prev_raw_data;
…
       ret = diff_within_window(&prev_raw_data, raw_data);
-       if (!ret){
+
                prev_raw_data = (*raw_data);
…
}

No comments: