Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

msm_ts.c for ZTE Racer with some changes by deadlink

By: a guest on Dec 4th, 2011  |  syntax: C  |  size: 16.36 KB  |  views: 196  |  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. #include <linux/delay.h>
  2. #include <linux/device.h>
  3. #include <linux/init.h>
  4. #include <linux/input.h>
  5. #include <linux/interrupt.h>
  6. #include <linux/io.h>
  7. #include <linux/module.h>
  8. #include <linux/platform_device.h>
  9. #include <linux/mfd/marimba-tsadc.h>
  10. #include <linux/pm.h>
  11.  
  12. #if defined(CONFIG_HAS_EARLYSUSPEND)
  13. #include <linux/earlysuspend.h>
  14. #endif
  15.  
  16. #include <mach/msm_ts.h>
  17. #include <linux/jiffies.h>  
  18.  
  19.  
  20. #define         TSSC_CTL                        0x100
  21. #define         TSSC_CTL_PENUP_IRQ      (1 << 12)
  22. #define         TSSC_CTL_DATA_FLAG      (1 << 11)
  23. #define         TSSC_CTL_DEBOUNCE_EN    (1 << 6)
  24. #define         TSSC_CTL_EN_AVERAGE     (1 << 5)
  25. #define         TSSC_CTL_MODE_MASTER    (3 << 3)
  26. #define         TSSC_CTL_SW_RESET       (1 << 2)
  27. #define         TSSC_CTL_ENABLE         (1 << 0)
  28. #define         TSSC_OPN                        0x104
  29. #define         TSSC_OPN_NOOP           0x00
  30. #define         TSSC_OPN_4WIRE_X        0x01
  31. #define         TSSC_OPN_4WIRE_Y        0x02
  32. #define         TSSC_OPN_4WIRE_Z1       0x03
  33. #define         TSSC_OPN_4WIRE_Z2       0x04
  34. #define         TSSC_SAMPLING_INT               0x108
  35. #define         TSSC_STATUS                     0x10c
  36. #define         TSSC_AVG_12                     0x110
  37. #define         TSSC_AVG_34                     0x114
  38. #define         TSSC_SAMPLE(op,samp)            ((0x118 + ((op & 0x3) * 0x20)) + ((samp & 0x7) * 0x4))
  39. #define         TSSC_TEST_1                     0x198
  40. #define         TSSC_TEST_1_EN_GATE_DEBOUNCE (1 << 2)
  41. #define         TSSC_TEST_2                     0x19c
  42. #define         TS_PENUP_TIMEOUT_MS 20
  43.  
  44. struct msm_ts {
  45.         struct msm_ts_platform_data     *pdata;
  46.         struct input_dev                *input_dev;
  47.         void __iomem                    *tssc_base;
  48.         uint32_t                        ts_down:1;
  49.         uint32_t                        zoomhack;
  50.         struct ts_virt_key              *vkey_down;
  51.  
  52.         unsigned int                    sample_irq;
  53.         unsigned int                    pen_up_irq;
  54.  
  55. #if defined(CONFIG_HAS_EARLYSUSPEND)
  56.         struct early_suspend            early_suspend;
  57. #endif
  58.         struct device                   *dev;
  59.         struct timer_list timer;
  60. };
  61.  
  62. static uint32_t msm_tsdebug;
  63. module_param_named(tsdebug, msm_tsdebug, uint, 0664);
  64.  
  65. // values from pointercal (stock 2.2.2)
  66. static int32_t msm_tscal_xscale = 17388;
  67. static int32_t msm_tscal_xoffset = -871728;
  68. static int32_t msm_tscal_yscale = 25403;
  69. static int32_t msm_tscal_yoffset = 45240;
  70. static int32_t msm_tscal_gesture_pressure = 1375; // optimized value
  71. static int32_t msm_tscal_gesture_blindspot = 30;
  72. static int32_t msm_tscal_pressure_limit = 200;
  73. static int32_t msm_haptic_feedback = 1;
  74. static int32_t msm_virtual_key_pressed = 0; // if virtual key pressed
  75. static int32_t msm_zoomhack_enabled = 1; // enable zoomhack
  76. static int32_t msm_tscal_min_jump = 30; // for dejitter
  77. static int32_t msm_tscal_max_jump = 70; // for variance
  78.  
  79. module_param_named(tscal_xscale, msm_tscal_xscale, int, 0664);
  80. module_param_named(tscal_xoffset, msm_tscal_xoffset, int, 0664);
  81. module_param_named(tscal_yscale, msm_tscal_yscale, int, 0664);
  82. module_param_named(tscal_yoffset, msm_tscal_yoffset, int, 0664);
  83. module_param_named(tscal_gesture_pressure, msm_tscal_gesture_pressure, int, 0664);
  84. module_param_named(tscal_gesture_blindspot, msm_tscal_gesture_blindspot, int, 0664);
  85. module_param_named(tscal_pressure_limit, msm_tscal_pressure_limit, int, 0664);
  86. module_param_named(virtual_key_pressed, msm_virtual_key_pressed, int, 0664);
  87. module_param_named(zoomhack_enabled, msm_zoomhack_enabled, int, 0664);
  88. module_param_named(haptic_feedback, msm_haptic_feedback, int, 0664);
  89.  
  90.  
  91. // for dejitter
  92. int last_x = 0;
  93. int last_y = 0;
  94. unsigned int last_z = 0;
  95. // for variance
  96. int noise = 0;
  97.  
  98.  
  99. #define tssc_readl(t, a)        (readl(((t)->tssc_base) + (a)))
  100. #define tssc_writel(t, v, a)    do {writel(v, ((t)->tssc_base) + (a));} while(0)
  101.  
  102.  
  103.  
  104. static int sqr (int x)
  105. {
  106.         return x * x;
  107. }
  108.  
  109. static void setup_next_sample(struct msm_ts *ts)
  110. {
  111.         uint32_t tmp;
  112.         tmp = ((7 << 7) | TSSC_CTL_DEBOUNCE_EN | TSSC_CTL_EN_AVERAGE |
  113.                TSSC_CTL_MODE_MASTER | TSSC_CTL_ENABLE);
  114.  
  115.         tssc_writel(ts, tmp, TSSC_CTL);
  116. }
  117.  
  118. #ifndef CONFIG_TOUCHSCREEN_VIRTUAL_KEYS
  119. static struct ts_virt_key *find_virt_key(struct msm_ts *ts,
  120.                                          struct msm_ts_virtual_keys *vkeys,
  121.                                          uint32_t val)
  122. {
  123.         int i;
  124.  
  125.         if (!vkeys)
  126.                 return NULL;
  127.  
  128.         for (i = 0; i < vkeys->num_keys; ++i)
  129.                 if ((val >= vkeys->keys[i].min) && (val <= vkeys->keys[i].max))
  130.                         return &vkeys->keys[i];
  131.         return NULL;
  132. }
  133. #endif
  134.  
  135.  
  136. static void ts_timer(unsigned long arg)
  137. {
  138.         struct msm_ts *ts = (struct msm_ts *)arg;
  139.         input_report_key(ts->input_dev, BTN_TOUCH, 0);
  140.         input_sync(ts->input_dev);
  141. }
  142.  
  143. static irqreturn_t msm_ts_irq(int irq, void *dev_id)
  144. {
  145.         struct msm_ts *ts = dev_id;
  146.         struct msm_ts_platform_data *pdata = ts->pdata;
  147.  
  148.         uint32_t tssc_avg12, tssc_avg34, tssc_status, tssc_ctl;
  149.         int x, y, z1, z2;
  150.         int was_down;
  151.         int down;
  152.         int z=0;
  153.         del_timer_sync(&ts->timer);
  154.         tssc_ctl = tssc_readl(ts, TSSC_CTL);
  155.         tssc_status = tssc_readl(ts, TSSC_STATUS);
  156.         tssc_avg12 = tssc_readl(ts, TSSC_AVG_12);
  157.         tssc_avg34 = tssc_readl(ts, TSSC_AVG_34);
  158.  
  159.         setup_next_sample(ts);
  160.  
  161.         x = tssc_avg12 & 0xffff;
  162.         y = tssc_avg12 >> 16;
  163.         z1 = tssc_avg34 & 0xffff;
  164.         z2 = tssc_avg34 >> 16;
  165.  
  166.         down = !(tssc_ctl & TSSC_CTL_PENUP_IRQ);
  167.         was_down = ts->ts_down;
  168.         ts->ts_down = down;
  169.  
  170.         /* no valid data */
  171.         if (down && !(tssc_ctl & TSSC_CTL_DATA_FLAG))
  172.                 return IRQ_HANDLED;
  173.  
  174.         if (msm_tsdebug & 2)
  175.                 printk("%s: down=%d, x=%d, y=%d, z1=%d, z2=%d, status %x\n",
  176.                        __func__, down, x, y, z1, z2, tssc_status);
  177.         if (down)
  178.         {
  179.                 z = ( ( z2 - z1 - 2)*x) / ( z1 + 2 );
  180.                 z = ( 2500 - z ) * 1000 / ( 2500 - 900 );
  181.                 if (z <= 0) z = 255;
  182.         }
  183.  
  184.         /* invert the inputs if necessary */
  185.         if (pdata->inv_x) x = pdata->inv_x - x;
  186.         if (pdata->inv_y) y = pdata->inv_y - y;
  187.         if (x < 0) x = 0;
  188.         if (y < 0) y = 0;
  189.         x = (x*msm_tscal_xscale + msm_tscal_xoffset + 32768)/65536;
  190.         y = (y*msm_tscal_yscale + msm_tscal_yoffset + 32768)/65536;
  191.  
  192.  
  193. #ifndef CONFIG_TOUCHSCREEN_VIRTUAL_KEYS
  194.         if (!was_down && down) {
  195.                 struct ts_virt_key *vkey = NULL;
  196.  
  197.                 if (pdata->vkeys_y && (y > pdata->virt_y_start))
  198.                         vkey = find_virt_key(ts, pdata->vkeys_y, x);
  199.                 if (!vkey && ts->pdata->vkeys_x && (x > pdata->virt_x_start))
  200.                         vkey = find_virt_key(ts, pdata->vkeys_x, y);
  201.  
  202.                 if (vkey) {
  203.                         WARN_ON(ts->vkey_down != NULL);
  204.                         if(msm_tsdebug)
  205.                                 printk("%s: virtual key down %d\n", __func__,
  206.                                        vkey->key);
  207.                         ts->vkey_down = vkey;
  208.                         input_report_key(ts->input_dev, vkey->key, 1);
  209.                         input_sync(ts->input_dev);
  210.             msm_virtual_key_pressed = 1;                      
  211.                         return IRQ_HANDLED;
  212.                 }
  213.         } else if (ts->vkey_down != NULL) {
  214.                 if (!down) {
  215.                         if(msm_tsdebug)
  216.                                 printk("%s: virtual key up %d\n", __func__,
  217.                                        ts->vkey_down->key);
  218.                         input_report_key(ts->input_dev, ts->vkey_down->key, 0);
  219.                         input_sync(ts->input_dev);
  220.             msm_virtual_key_pressed = 0;            
  221.                         ts->vkey_down = NULL;
  222.                 }
  223.                 return IRQ_HANDLED;
  224.         }
  225. #endif
  226.         // filtering
  227.         if (last_x != 0 && last_y != 0) {
  228.                 int dist = sqr (x - last_x) + sqr (y - last_y);
  229.  
  230.                 // variance
  231.                 if (noise > 1) {
  232.                         if (dist > msm_tscal_max_jump) {
  233.                                 // its fast moove
  234.                                 noise = 0;
  235.                         } else {
  236.                                 // its realy noise!
  237.                                 // nothing to do
  238.                         }
  239.                                
  240.                 } else if (x < 3 || dist > msm_tscal_max_jump) {
  241.                                 // maybe its noise
  242.                                 noise++;
  243.                                 // reset new position
  244.                                 x = last_x;
  245.                                 y = last_y;
  246.                                 z = last_z;
  247.                 }
  248.  
  249.                 // dejitter
  250.                 if (dist < msm_tscal_min_jump) {
  251.                         x = last_x;
  252.                         y = last_y;
  253.                         z = last_z;
  254.                 }
  255.                 if (noise != 2) {
  256.                         last_x = x;
  257.                         last_y = y;
  258.                         last_z = z;
  259.                 }
  260.         }
  261.         if (down) {
  262.                 if(z > (msm_tscal_gesture_pressure - msm_tscal_gesture_blindspot) && z < msm_tscal_gesture_pressure) {  // blind spot (1101-1199)
  263.                         down = 0;
  264.                         ts->zoomhack = 1;              
  265.                 } else if(z>=msm_tscal_gesture_pressure && msm_zoomhack_enabled == 1) { // Pinch zoom emulation & pinch rotation emulation if zoomhack enabled
  266.                         if(!ts->zoomhack) {                     // Flush real position to avoid jumpiness
  267.                                 down = 0;
  268.                                 ts->zoomhack = 1;
  269.                         }
  270.                         else {
  271.                                 int pinch_radius = (y+1)/2;                     // Base pinch radius on y position
  272.                                 int pinch_x = x - 120;                          // Get x offset
  273.  
  274.                                 int pinch_y = int_sqrt(pinch_radius*pinch_radius - pinch_x*pinch_x);    // Make sure pinch distance is the same even
  275.                                                                                                         // if we move x around. Pythagoras is our friend.
  276.                                 if(pinch_y>1000) pinch_y = 0;
  277.                
  278.                                 // Finger1
  279.                                 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 255);
  280.                                 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 5);
  281.                                 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, 120 + pinch_x);
  282.                                 input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, 175 - pinch_y);
  283.                                 input_mt_sync(ts->input_dev);
  284.                                 // Finger2
  285.                                 input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 255);
  286.                                 input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 5);
  287.                                 input_report_abs(ts->input_dev, ABS_MT_POSITION_X, 120 - pinch_x);
  288.                                                         input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, 175 + pinch_y);
  289.                                 input_mt_sync(ts->input_dev);
  290.                         }
  291.                 } else {
  292.                         if(ts->zoomhack) {      // Flush faked positions to avoid jumpiness
  293.                                 down = 0;
  294.                                 ts->zoomhack = 0;
  295.                         } else {
  296.                 // Filter
  297.                                 if (z > 400) {
  298.                                         input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, (z+1)/2);
  299.                                         input_report_abs(ts->input_dev, ABS_MT_WIDTH_MAJOR, 10);
  300.                                         input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
  301.                                         input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
  302.                                         input_mt_sync(ts->input_dev);
  303.                                 }
  304.                         }
  305.                 }
  306.         }
  307.         //if (NOISE_COUNT == 0) {
  308.                 input_report_key(ts->input_dev, BTN_TOUCH, down);
  309.                 input_sync(ts->input_dev);
  310.         //}
  311.  
  312.         if (30 == irq)mod_timer(&ts->timer,jiffies + msecs_to_jiffies(TS_PENUP_TIMEOUT_MS));
  313.         return IRQ_HANDLED;
  314. }
  315.  
  316. static int __devinit msm_ts_hw_init(struct msm_ts *ts)
  317. {
  318.         setup_next_sample(ts);
  319.  
  320.         return 0;
  321. }
  322.  
  323. #ifdef CONFIG_PM
  324. static int
  325. msm_ts_suspend(struct device *dev)
  326. {
  327.         struct msm_ts *ts =  dev_get_drvdata(dev);
  328.         uint32_t val;
  329.  
  330.         disable_irq(ts->sample_irq);
  331.         disable_irq(ts->pen_up_irq);
  332.         val = tssc_readl(ts, TSSC_CTL);
  333.         val &= ~TSSC_CTL_ENABLE;
  334.         tssc_writel(ts, val, TSSC_CTL);
  335.  
  336.         return 0;
  337. }
  338.  
  339. static int
  340. msm_ts_resume(struct device *dev)
  341. {
  342.         struct msm_ts *ts =  dev_get_drvdata(dev);
  343.  
  344.         msm_ts_hw_init(ts);
  345.  
  346.         enable_irq(ts->sample_irq);
  347.         enable_irq(ts->pen_up_irq);
  348.  
  349.         return 0;
  350. }
  351.  
  352. static struct dev_pm_ops msm_touchscreen_pm_ops = {
  353. #ifndef CONFIG_HAS_EARLYSUSPEND
  354.         .suspend        = msm_ts_suspend,
  355.         .resume         = msm_ts_resume,
  356. #endif
  357. };
  358. #endif
  359.  
  360. #ifdef CONFIG_HAS_EARLYSUSPEND
  361. static void msm_ts_early_suspend(struct early_suspend *h)
  362. {
  363.         struct msm_ts *ts = container_of(h, struct msm_ts, early_suspend);
  364.  
  365.         msm_ts_suspend(ts->dev);
  366. }
  367.  
  368. static void msm_ts_late_resume(struct early_suspend *h)
  369. {
  370.         struct msm_ts *ts = container_of(h, struct msm_ts, early_suspend);
  371.  
  372.         msm_ts_resume(ts->dev);
  373. }
  374. #endif
  375.  
  376. #if defined(CONFIG_TOUCHSCREEN_VIRTUAL_KEYS)
  377. #define virtualkeys virtualkeys.msm-touchscreen
  378. #if defined(CONFIG_MACH_MOONCAKE)
  379. static const char ts_keys_size[] = "0x01:102:0:320:80:50:0x01:139:80:320:80:50:0x01:158:160:320:80:50";
  380. #elif defined(CONFIG_MACH_V9)
  381. static const char ts_keys_size[] = "0x01:102:70:850:60:50:0x01:139:230:850:60:50:0x01:158:390:850:60:50";
  382. #endif
  383.  
  384. static ssize_t virtualkeys_show(struct device *dev,
  385.                 struct device_attribute *attr, char *buf)
  386. {
  387.         sprintf(buf,"%s\n",ts_keys_size);
  388.         printk("wly:%s\n",__FUNCTION__);
  389.     return strlen(ts_keys_size)+2;
  390. }
  391. static DEVICE_ATTR(virtualkeys, 0664, virtualkeys_show, NULL);
  392. extern struct kobject *android_touch_kobj;
  393. static struct kobject * virtual_key_kobj;
  394. static int ts_key_report_init(void)
  395. {
  396.         int ret;
  397.         virtual_key_kobj = kobject_get(android_touch_kobj);
  398.         if (virtual_key_kobj == NULL) {
  399.                 virtual_key_kobj = kobject_create_and_add("board_properties", NULL);
  400.                 if (virtual_key_kobj == NULL) {
  401.                         printk(KERN_ERR "%s: subsystem_register failed\n", __func__);
  402.                         ret = -ENOMEM;
  403.                         return ret;
  404.                 }
  405.         }
  406.         ret = sysfs_create_file(virtual_key_kobj, &dev_attr_virtualkeys.attr);
  407.         if (ret) {
  408.                 printk(KERN_ERR "%s: sysfs_create_file failed\n", __func__);
  409.                 return ret;
  410.         }
  411.  
  412.         return 0;
  413. }
  414. #endif
  415.  
  416. static int __devinit msm_ts_probe(struct platform_device *pdev)
  417. {
  418.         struct msm_ts_platform_data *pdata = pdev->dev.platform_data;
  419.         struct msm_ts *ts;
  420.         struct resource *tssc_res;
  421.         struct resource *irq1_res;
  422.         struct resource *irq2_res;
  423.         int err = 0;
  424. #ifndef CONFIG_TOUCHSCREEN_VIRTUAL_KEYS
  425.         int i;
  426. #endif
  427.         tssc_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tssc");
  428.         irq1_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tssc1");
  429.         irq2_res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "tssc2");
  430.  
  431.         if (!tssc_res || !irq1_res || !irq2_res) {
  432.                 pr_err("%s: required resources not defined\n", __func__);
  433.                 return -ENODEV;
  434.         }
  435.  
  436.         if (pdata == NULL) {
  437.                 pr_err("%s: missing platform_data\n", __func__);
  438.                 return -ENODEV;
  439.         }
  440.  
  441.         ts = kzalloc(sizeof(struct msm_ts), GFP_KERNEL);
  442.         if (ts == NULL) {
  443.                 pr_err("%s: No memory for struct msm_ts\n", __func__);
  444.                 return -ENOMEM;
  445.         }
  446.         ts->pdata = pdata;
  447.         ts->dev   = &pdev->dev;
  448.  
  449.         ts->sample_irq = irq1_res->start;
  450.         ts->pen_up_irq = irq2_res->start;
  451.  
  452.         ts->tssc_base = ioremap(tssc_res->start, resource_size(tssc_res));
  453.         if (ts->tssc_base == NULL) {
  454.                 pr_err("%s: Can't ioremap region (0x%08x - 0x%08x)\n", __func__,
  455.                        (uint32_t)tssc_res->start, (uint32_t)tssc_res->end);
  456.                 err = -ENOMEM;
  457.                 goto err_ioremap_tssc;
  458.         }
  459.  
  460.         ts->input_dev = input_allocate_device();
  461.         if (ts->input_dev == NULL) {
  462.                 pr_err("failed to allocate touchscreen input device\n");
  463.                 err = -ENOMEM;
  464.                 goto err_alloc_input_dev;
  465.         }
  466.         ts->input_dev->name = "msm-touchscreen";
  467.         ts->input_dev->dev.parent = &pdev->dev;
  468.  
  469.         input_set_drvdata(ts->input_dev, ts);
  470.  
  471.         input_set_capability(ts->input_dev, EV_KEY, BTN_TOUCH);
  472.         set_bit(EV_ABS, ts->input_dev->evbit);
  473.  
  474.         input_set_abs_params(ts->input_dev, ABS_MT_POSITION_X, pdata->min_x, pdata->max_x, 0, 0);
  475.         input_set_abs_params(ts->input_dev, ABS_MT_POSITION_Y, pdata->min_y, pdata->max_y, 0, 0);
  476.         input_set_abs_params(ts->input_dev, ABS_MT_TOUCH_MAJOR, pdata->min_press, pdata->max_press, 0, 0);
  477.         input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
  478.  
  479. #ifndef CONFIG_TOUCHSCREEN_VIRTUAL_KEYS
  480.         for (i = 0; pdata->vkeys_x && (i < pdata->vkeys_x->num_keys); ++i)
  481.                 input_set_capability(ts->input_dev, EV_KEY,
  482.                                      pdata->vkeys_x->keys[i].key);
  483.         for (i = 0; pdata->vkeys_y && (i < pdata->vkeys_y->num_keys); ++i)
  484.                 input_set_capability(ts->input_dev, EV_KEY,
  485.                                      pdata->vkeys_y->keys[i].key);
  486. #endif
  487.  
  488.         err = input_register_device(ts->input_dev);
  489.         if (err != 0) {
  490.                 pr_err("%s: failed to register input device\n", __func__);
  491.                 goto err_input_dev_reg;
  492.         }
  493.  
  494.         setup_timer(&ts->timer, ts_timer, (unsigned long)ts);
  495.         msm_ts_hw_init(ts);
  496.  
  497.         err = request_irq(ts->sample_irq, msm_ts_irq,
  498.                           (irq1_res->flags & ~IORESOURCE_IRQ) | IRQF_DISABLED,
  499.                           "msm_touchscreen", ts);
  500.         if (err != 0) {
  501.                 pr_err("%s: Cannot register irq1 (%d)\n", __func__, err);
  502.                 goto err_request_irq1;
  503.         }
  504.  
  505.         err = request_irq(ts->pen_up_irq, msm_ts_irq,
  506.                           (irq2_res->flags & ~IORESOURCE_IRQ) | IRQF_DISABLED,
  507.                           "msm_touchscreen", ts);
  508.         if (err != 0) {
  509.                 pr_err("%s: Cannot register irq2 (%d)\n", __func__, err);
  510.                 goto err_request_irq2;
  511.         }
  512.  
  513.         platform_set_drvdata(pdev, ts);
  514.  
  515. #ifdef CONFIG_HAS_EARLYSUSPEND
  516.         ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN +
  517.                                                 TSSC_SUSPEND_LEVEL;
  518.         ts->early_suspend.suspend = msm_ts_early_suspend;
  519.         ts->early_suspend.resume = msm_ts_late_resume;
  520.         register_early_suspend(&ts->early_suspend);
  521. #endif
  522.  
  523.         pr_info("%s: tssc_base=%p irq1=%d irq2=%d\n", __func__,
  524.                 ts->tssc_base, (int)ts->sample_irq, (int)ts->pen_up_irq);
  525.  
  526. #if defined(CONFIG_TOUCHSCREEN_VIRTUAL_KEYS)
  527.         ts_key_report_init();
  528. #endif
  529.         return 0;
  530.  
  531. err_request_irq2:
  532.         free_irq(ts->sample_irq, ts);
  533.  
  534. err_request_irq1:
  535.         /* disable the tssc */
  536.         tssc_writel(ts, TSSC_CTL_ENABLE, TSSC_CTL);
  537.  
  538. err_input_dev_reg:
  539.         input_set_drvdata(ts->input_dev, NULL);
  540.         input_free_device(ts->input_dev);
  541.  
  542. err_alloc_input_dev:
  543.         iounmap(ts->tssc_base);
  544.  
  545. err_ioremap_tssc:
  546.         kfree(ts);
  547.         return err;
  548. }
  549.  
  550. static struct platform_driver msm_touchscreen_driver = {
  551.         .driver = {
  552.                 .name = "msm_touchscreen",
  553.                 .owner = THIS_MODULE,
  554. #ifdef CONFIG_PM
  555.                 .pm = &msm_touchscreen_pm_ops,
  556. #endif
  557.         },
  558.         .probe          = msm_ts_probe,
  559. };
  560.  
  561. static int __init msm_ts_init(void)
  562. {
  563.         return platform_driver_register(&msm_touchscreen_driver);
  564. }
  565.  
  566. static void __exit msm_ts_exit(void)
  567. {
  568.         platform_driver_unregister(&msm_touchscreen_driver);
  569. }
  570.  
  571. module_init(msm_ts_init);
  572. module_exit(msm_ts_exit);
  573. MODULE_DESCRIPTION("Qualcomm MSM/QSD Touchscreen controller driver");
  574. MODULE_LICENSE("GPL");
  575. MODULE_ALIAS("platform:msm_touchscreen");
  576.  
  577.  
clone this paste RAW Paste Data