Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Jul 28th, 2013  |  syntax: None  |  size: 15.08 KB  |  views: 32  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /***************************************************************************
  2.  *             __________               __   ___.
  3.  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
  4.  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
  5.  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
  6.  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
  7.  *                     \/            \/     \/    \/            \/
  8.  * $Id$
  9.  *
  10.  * Copyright (C) 2011 by Amaury Pouly
  11.  *
  12.  * This program is free software; you can redistribute it and/or
  13.  * modify it under the terms of the GNU General Public License
  14.  * as published by the Free Software Foundation; either version 2
  15.  * of the License, or (at your option) any later version.
  16.  *
  17.  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
  18.  * KIND, either express or implied.
  19.  *
  20.  ****************************************************************************/
  21. #include "button-target.h"
  22. #include "system.h"
  23. #include "system-target.h"
  24. #include "pinctrl-imx233.h"
  25. #include "generic_i2c.h"
  26. #include "synaptics-rmi.h"
  27. #include "lcd.h"
  28. #include "string.h"
  29. #include "usb.h"
  30. #include "power-imx233.h"
  31.  
  32. #ifndef BOOTLOADER
  33.  
  34. bool button_debug_screen(void)
  35. {
  36.     char product_id[RMI_PRODUCT_ID_LEN];
  37.     rmi_read(RMI_PRODUCT_ID, RMI_PRODUCT_ID_LEN, product_id);
  38.     int x_max = rmi_read_single(RMI_2D_SENSOR_XMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_XMAX_LSB(0));
  39.     int y_max = rmi_read_single(RMI_2D_SENSOR_YMAX_MSB(0)) << 8 | rmi_read_single(RMI_2D_SENSOR_YMAX_LSB(0));
  40.     int func_presence = rmi_read_single(RMI_FUNCTION_PRESENCE(RMI_2D_TOUCHPAD_FUNCTION));
  41.     int sensor_prop = rmi_read_single(RMI_2D_SENSOR_PROP2(0));
  42.     int sensor_resol = rmi_read_single(RMI_2D_SENSOR_RESOLUTION(0));
  43.     int min_dist = rmi_read_single(RMI_2D_MIN_DIST);
  44.     int gesture_settings = rmi_read_single(RMI_2D_GESTURE_SETTINGS);
  45.     int sensibility_counter = 0;
  46.     union
  47.     {
  48.         unsigned char data;
  49.         signed char value;
  50.     }sensitivity;
  51.     rmi_read(RMI_2D_SENSITIVITY_ADJ, 1, &sensitivity.data);
  52.  
  53.     /* Device to screen */
  54.     int zone_w = LCD_WIDTH;
  55.     int zone_h = (zone_w * y_max + x_max - 1) / x_max;
  56.     int zone_x = 0;
  57.     int zone_y = LCD_HEIGHT - zone_h;
  58.     #define DX2SX(x) (((x) * zone_w ) / x_max)
  59.     #define DY2SY(y) (zone_h - ((y) * zone_h ) / y_max)
  60.     struct viewport report_vp;
  61.     memset(&report_vp, 0, sizeof(report_vp));
  62.     report_vp.x = zone_x;
  63.     report_vp.y = zone_y;
  64.     report_vp.width = zone_w;
  65.     report_vp.height = zone_h;
  66.     struct viewport gesture_vp;
  67.     memset(&gesture_vp, 0, sizeof(gesture_vp));
  68.     gesture_vp.x = LCD_WIDTH / 2;
  69.     gesture_vp.y = zone_y - 80;
  70.     gesture_vp.width = LCD_WIDTH / 2;
  71.     gesture_vp.height = 80;
  72.    
  73.     while(1)
  74.     {
  75.         lcd_set_viewport(NULL);
  76.         lcd_clear_display();
  77.         int btns = button_read_device();
  78.         lcd_putsf(0, 0, "button bitmap: %x", btns);
  79.         lcd_putsf(0, 1, "RMI: id=%s p=%x s=%x", product_id, func_presence, sensor_prop);
  80.         lcd_putsf(0, 2, "xmax=%d ymax=%d res=%d", x_max, y_max, sensor_resol);
  81.         lcd_putsf(0, 3, "attn=%d ctl=%x int=%x",
  82.             imx233_pinctrl_get_gpio(0, 27) ? 0 : 1,
  83.             rmi_read_single(RMI_DEVICE_CONTROL),
  84.             rmi_read_single(RMI_INTERRUPT_REQUEST));
  85.         lcd_putsf(0, 4, "sensi: %d min_dist: %d", (int)sensitivity.value, min_dist);
  86.         lcd_putsf(0, 5, "gesture: %x", gesture_settings);
  87.  
  88.         union
  89.         {
  90.             unsigned char data[10];
  91.             struct
  92.             {
  93.                 struct rmi_2d_absolute_data_t absolute;
  94.                 struct rmi_2d_relative_data_t relative;
  95.                 struct rmi_2d_gesture_data_t gesture;
  96.             }s;
  97.         }u;
  98.         int absolute_x = u.s.absolute.x_msb << 8 | u.s.absolute.x_lsb;
  99.         int absolute_y = u.s.absolute.y_msb << 8 | u.s.absolute.y_lsb;
  100.         int nr_fingers = u.s.absolute.misc & 7;
  101.         bool gesture = (u.s.absolute.misc & 8) == 8;
  102.         int palm_width = u.s.absolute.misc >> 4;
  103.         rmi_read(RMI_DATA_REGISTER(0), 10, u.data);
  104.         lcd_putsf(0, 6, "abs: %d %d %d", absolute_x, absolute_y, (int)u.s.absolute.z);
  105.         lcd_putsf(0, 7, "rel: %d %d", (int)u.s.relative.x, (int)u.s.relative.y);
  106.         lcd_putsf(0, 8, "gesture: %x %x", u.s.gesture.misc, u.s.gesture.flick);
  107.         lcd_putsf(0, 9, "misc: w=%d g=%d f=%d", palm_width, gesture, nr_fingers);
  108.  
  109.         lcd_set_viewport(&report_vp);
  110.         lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0, 0), LCD_BLACK);
  111.         lcd_drawrect(0, 0, zone_w, zone_h);
  112.         if(nr_fingers == 1)
  113.         {
  114.             lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0, 0, 0xff), LCD_BLACK);
  115.             lcd_drawline(DX2SX(absolute_x) - u.s.relative.x,
  116.                 DY2SY(absolute_y) + u.s.relative.y,
  117.                 DX2SX(absolute_x), DY2SY(absolute_y));
  118.             lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0, 0xff, 0), LCD_BLACK);
  119.             lcd_fillrect(DX2SX(absolute_x) - 1, DY2SY(absolute_y) - 1, 3, 3);
  120.         }
  121.         lcd_set_viewport(&gesture_vp);
  122.         lcd_set_drawinfo(DRMODE_SOLID, LCD_RGBPACK(0xff, 0xff, 0), LCD_BLACK);
  123.         if(u.s.gesture.misc & RMI_2D_GEST_MISC_CONFIRMED)
  124.         {
  125.             switch(u.s.gesture.misc & RMI_2D_GEST_MISC_TAP_CODE_BM)
  126.             {
  127.                 case RMI_2D_GEST_MISC_NO_TAP: break;
  128.                 case RMI_2D_GEST_MISC_SINGLE_TAP:
  129.                     lcd_putsf(0, 0, "TAP!");
  130.                     break;
  131.                 case RMI_2D_GEST_MISC_DOUBLE_TAP:
  132.                     lcd_putsf(0, 0, "DOUBLE TAP!");
  133.                     break;
  134.                 case RMI_2D_GEST_MISC_TAP_AND_HOLD:
  135.                     lcd_putsf(0, 0, "TAP & HOLD!");
  136.                     break;
  137.                 default: break;
  138.             }
  139.            
  140.             if(u.s.gesture.misc & RMI_2D_GEST_MISC_FLICK)
  141.             {
  142.                 lcd_putsf(0, 1, "FLICK!");
  143.                 int flick_x = u.s.gesture.flick & RMI_2D_GEST_FLICK_X_BM;
  144.                 int flick_y = (u.s.gesture.flick & RMI_2D_GEST_FLICK_Y_BM) >> RMI_2D_GEST_FLICK_Y_BP;
  145.                 #define SIGN4EXT(a) \
  146.                     if(a & 8) a = -((a ^ 0xf) + 1);
  147.                 SIGN4EXT(flick_x);
  148.                 SIGN4EXT(flick_y);
  149.                
  150.                 int center_x = (LCD_WIDTH * 2) / 3;
  151.                 int center_y = 40;
  152.                 lcd_drawline(center_x, center_y, center_x + flick_x * 5, center_y - flick_y * 5);
  153.             }
  154.         }
  155.         lcd_update();
  156.        
  157.         if(btns & BUTTON_POWER)
  158.             break;
  159.         if(btns & BUTTON_VOL_DOWN || btns & BUTTON_VOL_UP)
  160.         {
  161.             if(btns & BUTTON_VOL_UP)
  162.                 sensibility_counter++;
  163.             if(btns & BUTTON_VOL_DOWN)
  164.                 sensibility_counter--;
  165.             if((sensibility_counter == -15) || (sensibility_counter == 15))
  166.             {
  167.                 sensitivity.value += (sensibility_counter / 15);
  168.                 sensibility_counter = 0;
  169.             }
  170.             rmi_write(RMI_2D_SENSITIVITY_ADJ, 1, &sensitivity.data);
  171.         }
  172.        
  173.         yield();
  174.     }
  175.  
  176.     return true;
  177. }
  178.  
  179. struct button_area_t
  180. {
  181.     /* define a rectangle region */
  182.     int lx, ly;
  183.     int rx, ry;
  184.     int button;
  185. };
  186.  
  187. static struct button_area_t button_areas[] =
  188. {
  189.     {1003, 658, 2006, 1316, BUTTON_SELECT},
  190.     {0, 658, 1003, 1316, BUTTON_LEFT},
  191.     {2006, 658, 3009, 1316, BUTTON_RIGHT},
  192.     {1003, 0 , 2006, 658, BUTTON_DOWN},
  193.     {1003, 1316, 2006, 1974, BUTTON_UP},
  194.     {2006, 1316, 3009, 1974, BUTTON_PLAYPAUSE},
  195.     {0, 1316, 1003, 1974, BUTTON_BACK},
  196.     {0, 0 , 1003, 658, BUTTON_BOTTOMLEFT},
  197.     {2006, 0 , 3009, 658, BUTTON_BOTTOMRIGHT},
  198.     {0, 0, 0, 0, 0},
  199. };
  200.  
  201. #define RMI_INTERRUPT       1
  202. #define RMI_SET_SENSITIVITY 2
  203. #define RMI_SET_SLEEP_MODE  3
  204. /* timeout before lowering touchpad power from lack of activity */
  205. #define ACTIVITY_TMO (60 * HZ)
  206.  
  207. static int touchpad_btns = 0;
  208. static long rmi_stack [DEFAULT_STACK_SIZE/sizeof(long)];
  209. static const char rmi_thread_name[] = "rmi";
  210. static struct event_queue rmi_queue;
  211. static unsigned last_activity = 0;
  212.  
  213. static int find_button(int x, int y)
  214. {
  215.     struct button_area_t *area = button_areas;
  216.     for(; area->button != 0; area++)
  217.     {
  218.         if(area->lx <= x && x <= area->rx &&
  219.                 area->ly <= y && y <= area->ry)
  220.             return area->button;
  221.     }
  222.     return 0;
  223. }
  224.  
  225. static int touchpad_read_device(void)
  226. {
  227.     return touchpad_btns;
  228. }
  229.  
  230. static void rmi_attn_cb(int bank, int pin, intptr_t user)
  231. {
  232.     (void) bank;
  233.     (void) pin;
  234.     (void) user;
  235.     /* the callback will not be fired until interrupt is enabled back so
  236.      * the queue will not overflow or contain multiple RMI_INTERRUPT events */
  237.     queue_post(&rmi_queue, RMI_INTERRUPT, 0);
  238. }
  239.  
  240. void touchpad_enable(bool en)
  241. {
  242.     queue_post(&rmi_queue, RMI_SET_SLEEP_MODE, en ? RMI_SLEEP_MODE_LOW_POWER : RMI_SLEEP_MODE_SENSOR_SLEEP);
  243. }
  244.  
  245. static void rmi_thread(void)
  246. {
  247.     struct queue_event ev;
  248.    
  249.     while(1)
  250.     {
  251.         queue_wait_w_tmo(&rmi_queue, &ev, HZ);
  252.         /* handle usb connect and ignore all messages except rmi interrupts */
  253.         switch(ev.id)
  254.         {
  255.             case SYS_USB_CONNECTED:
  256.                 usb_acknowledge(SYS_USB_CONNECTED_ACK);
  257.                 break;
  258.             case RMI_SET_SENSITIVITY:
  259.                 /* handle negative values as well ! */
  260.                 rmi_write_single(RMI_2D_SENSITIVITY_ADJ, (unsigned char)(int8_t)ev.data);
  261.                 break;
  262.             case RMI_SET_SLEEP_MODE:
  263.                 /* reset activity */
  264.                 last_activity = current_tick;
  265.                 rmi_set_sleep_mode(ev.data);
  266.                 break;
  267.             case RMI_INTERRUPT:
  268.                 do_interrupt();
  269.                 break;
  270.             default:
  271.                  /* activity timeout */
  272.                 if(TIME_AFTER(current_tick, last_activity + ACTIVITY_TMO))
  273.                 {
  274.                     rmi_set_sleep_mode(RMI_SLEEP_MODE_VERY_LOW_POWER);
  275.                     rmi_set_report_rate(RMI_REPORT_RATE_LOW);
  276.                 }
  277.                 break;
  278.         }
  279.     }
  280. }
  281.  
  282.  
  283.  
  284. void button_init_device(void)
  285. {
  286.     /* Synaptics TouchPad information:
  287.      * - product id: 1533
  288.      * - nr function: 1 (0x10 = 2D touchpad)
  289.      * 2D Touchpad information (function 0x10)
  290.      * - nr data sources: 3
  291.      * - standard layout
  292.      * - extra data registers: 7
  293.      * - nr sensors: 1
  294.      * 2D Touchpad Sensor #0 information:
  295.      * - has relative data: yes
  296.      * - has palm detect: yes
  297.      * - has multi finger: yes
  298.      * - has enhanced gesture: yes
  299.      * - has scroller: no
  300.      * - has 2D scrollers: no
  301.      * - Maximum X: 3009
  302.      * - Maxumum Y: 1974
  303.      * - Resolution: 82
  304.      *
  305.      * ATTENTION line: B0P27 asserted low
  306.      *
  307.      * The B0P26 line seems to be related to the touchpad
  308.      */
  309.      
  310.     /* touchpad power */
  311.     imx233_pinctrl_acquire(0, 26, "touchpad power");
  312.     imx233_pinctrl_set_function(0, 26, PINCTRL_FUNCTION_GPIO);
  313.     imx233_pinctrl_enable_gpio(0, 26, false);
  314.     imx233_pinctrl_set_drive(0, 26, PINCTRL_DRIVE_8mA);
  315.    
  316.     rmi_init(0x40);
  317.  
  318.     char product_id[RMI_PRODUCT_ID_LEN];
  319.     rmi_read(RMI_PRODUCT_ID, RMI_PRODUCT_ID_LEN, product_id);
  320.     /* The OF adjust the sensitivity based on product_id[1] compared to 2.
  321.      * Since it doesn't to work great, just hardcode the sensitivity to
  322.      * some reasonable value for now. */
  323.     rmi_write_single(RMI_2D_SENSITIVITY_ADJ, 13);
  324.    
  325.     rmi_write_single(RMI_2D_GESTURE_SETTINGS,
  326.         RMI_2D_GESTURE_PRESS_TIME_300MS |
  327.         RMI_2D_GESTURE_FLICK_DIST_4MM << RMI_2D_GESTURE_FLICK_DIST_BP |
  328.         RMI_2D_GESTURE_FLICK_TIME_700MS << RMI_2D_GESTURE_FLICK_TIME_BP);
  329.  
  330.     queue_init(&rmi_queue, true);
  331.     create_thread(rmi_thread, rmi_stack, sizeof(rmi_stack), 0,
  332.             rmi_thread_name IF_PRIO(, PRIORITY_USER_INTERFACE) IF_COP(, CPU));
  333.     /* low power mode seems to be enough for normal use */
  334.     rmi_set_sleep_mode(RMI_SLEEP_MODE_LOW_POWER);
  335.     /* enable interrupt */
  336.     imx233_pinctrl_acquire(0, 27, "touchpad int");
  337.     imx233_pinctrl_set_function(0, 27, PINCTRL_FUNCTION_GPIO);
  338.     imx233_pinctrl_enable_gpio(0, 27, false);
  339.     imx233_pinctrl_setup_irq(0, 27, true, true, false, &rmi_attn_cb, 0);
  340.     /* Volume down */
  341.     imx233_pinctrl_acquire(1, 30, "volume down");
  342.     imx233_pinctrl_set_function(1, 30, PINCTRL_FUNCTION_GPIO);
  343.     imx233_pinctrl_enable_gpio(1, 30, false);
  344. }
  345.  
  346. #else
  347.  
  348. void button_init_device(void)
  349. {
  350.     /* Volume down */
  351.     imx233_pinctrl_acquire(1, 30, "volume down");
  352.     imx233_pinctrl_set_function(1, 30, PINCTRL_FUNCTION_GPIO);
  353.     imx233_pinctrl_enable_gpio(1, 30, false);
  354. }
  355.  
  356. int touchpad_read_device(void)
  357. {
  358.     return 0;
  359. }
  360.  
  361. #endif
  362.  
  363. int button_read_device(void)
  364. {
  365.     int res = 0;
  366.     if(!imx233_pinctrl_get_gpio(1, 30))
  367.         res |= BUTTON_VOL_DOWN;
  368.     /* The imx233 uses the voltage on the PSWITCH pin to detect power up/down
  369.      * events as well as recovery mode. Since the power button is the power button
  370.      * and the volume up button is recovery, it is not possible to know whether
  371.      * power button is down when volume up is down (except if there is another
  372.      * method but volume up and power don't seem to be wired to GPIO pins).
  373.      * As a probable consequence of that, it has been reported that pressing
  374.      * volume up sometimes return BUTTON_POWER instead of BUTTON_VOL_UP. The
  375.      * following volume_power_lock prevent BUTTON_POWER to happen if volume up
  376.      * has been send since a very short time. */
  377.     static int volume_power_lock = 0;
  378.     if(volume_power_lock > 0)
  379.         volume_power_lock--;
  380.     switch(BF_RD(POWER_STS, PSWITCH))
  381.     {
  382.         case 1:
  383.             if(volume_power_lock == 0)
  384.                 res |= BUTTON_POWER;
  385.             break;
  386.         case 3:
  387.             res |= BUTTON_VOL_UP;
  388.             volume_power_lock = 5;
  389.             break;
  390.         default:
  391.             break;
  392.     }
  393.     return res | touchpad_read_device();
  394. }
  395.  
  396. static void do_interrupt(void)
  397. {
  398.     /* rmi_set_sleep_mode() and rmi_set_report_rate() are not doing anything if the value
  399.        they are given is already the one setted */
  400.     rmi_set_sleep_mode(RMI_SLEEP_MODE_LOW_POWER);
  401.     rmi_set_report_rate(RMI_REPORT_RATE_NORMAL);
  402.     last_activity = current_tick;
  403.     /* clear interrupt */
  404.     rmi_read_single(RMI_INTERRUPT_REQUEST);
  405.     /* read data */
  406.     union
  407.     {
  408.         unsigned char data[10];
  409.         struct
  410.         {
  411.             struct rmi_2d_absolute_data_t absolute;
  412.             struct rmi_2d_relative_data_t relative;
  413.             struct rmi_2d_gesture_data_t gesture;
  414.         }s;
  415.     }u;
  416.     rmi_read(RMI_DATA_REGISTER(0), 10, u.data);
  417.     int absolute_x = u.s.absolute.x_msb << 8 | u.s.absolute.x_lsb;
  418.     int absolute_y = u.s.absolute.y_msb << 8 | u.s.absolute.y_lsb;
  419.     int nr_fingers = u.s.absolute.misc & 7;
  420.    
  421.    
  422.     if(nr_fingers == 1)
  423.         touchpad_btns = find_button(absolute_x, absolute_y);
  424.     else
  425.         touchpad_btns = 0;
  426.    
  427.     /* enable interrupt */
  428.     imx233_pinctrl_setup_irq(0, 27, true, true, false, &rmi_attn_cb, 0);
  429. }
clone this paste RAW Paste Data