歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

S3C2410驅動分析之觸摸屏驅動

內核版本:2.6.36

源碼路徑:drivers/input/touchscreen/s3c2410_ts.c

在Linux-2.6.36中,S3C2410對應的觸摸屏驅動程序是drivers/input/touchscreen/s3c2410_ts.c,本文對這個文件進行分析,詳細介紹相關知識點。S3C2410的觸摸屏驅動和ADC驅動緊密聯系在一起,在讀本文之前,請大家先看我的這篇《S3C2410驅動分析之ADC通用驅動》http://www.linuxidc.com/Linux/2012-04/58701.htm。
首先我們看模塊初始化函數:
  1. 436static int __init s3c2410ts_init(void)  
  2. 437{  
  3. 438    return platform_driver_register(&s3c_ts_driver);  
  4. 439}  
該驅動程序是以platform driver的方式注冊的,這裡注冊的platform_driver是s3c_ts_driver,其定義如下:
  1. 423static struct platform_driver s3c_ts_driver = {  
  2. 424    .driver         = {  
  3. 425        .name   = "samsung-ts",  
  4. 426        .owner  = THIS_MODULE,  
  5. 427#ifdef CONFIG_PM  
  6. 428        .pm = &s3c_ts_pmops,  
  7. 429#endif  
  8. 430    },  
  9. 431    .id_table   = s3cts_driver_ids,  
  10. 432    .probe      = s3c2410ts_probe,  
  11. 433    .remove     = __devexit_p(s3c2410ts_remove),  
  12. 434};  
這裡需要關注的是platform_driver結構的id_table和probe兩個成員。s3cts_driver_ids定義如下:
  1. 415static struct platform_device_id s3cts_driver_ids[] = {  
  2. 416    { "s3c2410-ts", 0 },  
  3. 417    { "s3c2440-ts", 0 },  
  4. 418    { "s3c64xx-ts", FEAT_PEN_IRQ },  
  5. 419    { }  
  6. 420};  
421MODULE_DEVICE_TABLE(platform, s3cts_driver_ids);
probe成員函數s3c2410ts_probe當模塊被加載時就會執行,其代碼如下:
  1. 234/** 
  2. 235 * s3c2410ts_probe - device core probe entry point 
  3. 236 * @pdev: The device we are being bound to. 
  4. 237 * 
  5. 238 * Initialise, find and allocate any resources we need to run and then 
  6. 239 * register with the ADC and input systems. 
  7. 240 */  
  8. 241static int __devinit s3c2410ts_probe(struct platform_device *pdev)  
  9. 242{  
  10. 243    struct s3c2410_ts_mach_info *info;  
  11. 244    struct device *dev = &pdev->dev;  
  12. 245    struct input_dev *input_dev;  
  13. 246    struct resource *res;  
  14. 247    int ret = -EINVAL;  
  15. 248  
  16. 249    /* Initialise input stuff */  
  17. 250    memset(&ts, 0, sizeof(struct s3c2410ts));  
  18. 251  
  19. 252    ts.dev = dev;  
  20. 253  
  21. 254    info = pdev->dev.platform_data;  
  22. 255    if (!info) {  
  23. 256        dev_err(dev, "no platform data, cannot attach\n");  
  24. 257        return -EINVAL;  
  25. 258    }  
  26. 259  
  27. 260    dev_dbg(dev, "initialising touchscreen\n");  
  28. 261  
  29. 262    ts.clock = clk_get(dev, "adc");  
  30. 263    if (IS_ERR(ts.clock)) {  
  31. 264        dev_err(dev, "cannot get adc clock source\n");  
  32. 265        return -ENOENT;  
  33. 266    }  
  34. 267  
  35. 268    clk_enable(ts.clock);  
  36. 269    dev_dbg(dev, "got and enabled clocks\n");  
  37. 270  
  38. 271    ts.irq_tc = ret = platform_get_irq(pdev, 0);  
  39. 272    if (ret < 0) {  
  40. 273        dev_err(dev, "no resource for interrupt\n");  
  41. 274        goto err_clk;  
  42. 275    }  
  43. 276  
  44. 277    res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  
  45. 278    if (!res) {  
  46. 279        dev_err(dev, "no resource for registers\n");  
  47. 280        ret = -ENOENT;  
  48. 281        goto err_clk;  
  49. 282    }  
  50. 283  
  51. 284    ts.io = ioremap(res->start, resource_size(res));  
  52. 285    if (ts.io == NULL) {  
  53. 286        dev_err(dev, "cannot map registers\n");  
  54. 287        ret = -ENOMEM;  
  55. 288        goto err_clk;  
  56. 289    }  
  57. 290  
  58. 291    /* inititalise the gpio */  
  59. 292    if (info->cfg_gpio)  
  60. 293        info->cfg_gpio(to_platform_device(ts.dev));  
  61. 294  
  62. 295    ts.client = s3c_adc_register(pdev, s3c24xx_ts_select,  
  63. 296                     s3c24xx_ts_conversion, 1);  
  64. 297    if (IS_ERR(ts.client)) {  
  65. 298        dev_err(dev, "failed to register adc client\n");  
  66. 299        ret = PTR_ERR(ts.client);  
  67. 300        goto err_iomap;  
  68. 301    }  
  69. 302  
  70. 303    /* Initialise registers */  
  71. 304    if ((info->delay & 0xffff) > 0)  
  72. 305        writel(info->delay & 0xffff, ts.io + S3C2410_ADCDLY);  
  73. 306  
  74. 307    writel(WAIT4INT | INT_DOWN, ts.io + S3C2410_ADCTSC);  
  75. 308  
  76. 309    input_dev = input_allocate_device();  
  77. 310    if (!input_dev) {  
  78. 311        dev_err(dev, "Unable to allocate the input device !!\n");  
  79. 312        ret = -ENOMEM;  
  80. 313        goto err_iomap;  
  81. 314    }  
  82. 315  
  83. 316    ts.input = input_dev;  
  84. 317    ts.input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);  
  85. 318    ts.input->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);  
  86. 319    input_set_abs_params(ts.input, ABS_X, 0, 0x3FF, 0, 0);  
  87. 320    input_set_abs_params(ts.input, ABS_Y, 0, 0x3FF, 0, 0);  
  88. 321  
  89. 322    ts.input->name = "S3C24XX TouchScreen";  
  90. 323    ts.input->id.bustype = BUS_HOST;  
  91. 324    ts.input->id.vendor = 0xDEAD;  
  92. 325    ts.input->id.product = 0xBEEF;  
  93. 326    ts.input->id.version = 0x0102;  
  94. 327  
  95. 328    ts.shift = info->oversampling_shift;  
  96. 329    ts.features = platform_get_device_id(pdev)->driver_data;  
  97. 330  
  98. 331    ret = request_irq(ts.irq_tc, stylus_irq, IRQF_DISABLED,  
  99. 332              "s3c2410_ts_pen", ts.input);  
  100. 333    if (ret) {  
  101. 334        dev_err(dev, "cannot get TC interrupt\n");  
  102. 335        goto err_inputdev;  
  103. 336    }  
  104. 337  
  105. 338    dev_info(dev, "driver attached, registering input device\n");  
  106. 339  
  107. 340    /* All went ok, so register to the input system */  
  108. 341    ret = input_register_device(ts.input);  
  109. 342    if (ret < 0) {  
  110. 343        dev_err(dev, "failed to register input device\n");  
  111. 344        ret = -EIO;  
  112. 345        goto err_tcirq;  
  113. 346    }  
  114. 347  
  115. 348    return 0;  
  116. 349  
  117. 350 err_tcirq:  
  118. 351    free_irq(ts.irq_tc, ts.input);  
  119. 352 err_inputdev:  
  120. 353    input_unregister_device(ts.input);  
  121. 354 err_iomap:  
  122. 355    iounmap(ts.io);  
  123. 356 err_clk:  
  124. 357    del_timer_sync(&touch_timer);  
  125. 358    clk_put(ts.clock);  
  126. 359    return ret;  
  127. 360}  
243行,定義s3c2410_ts_mach_info結構體變量info,該結構體定義在arch/arm/plat-samsung/include/plat/ts.h文件中:
  1. 13struct s3c2410_ts_mach_info {  
  2. 14       int             delay;  
  3. 15       int             presc;  
  4. 16       int             oversampling_shift;  
  5. 17    void    (*cfg_gpio)(struct platform_device *dev);  
  6. 18};  
delay保存ADC的延遲時間。
presc保存ADC的預分頻系數。
oversampling_shift保存采樣次數log2值。
cfg_gpio函數用於設置gpio。
250行,將ts清0,ts是s3c2410ts結構體類型變量,其定義如下:
  1. 62/** 
  2. 63 * struct s3c2410ts - driver touchscreen state. 
  3. 64 * @client: The ADC client we registered with the core driver. 
  4. 65 * @dev: The device we are bound to. 
  5. 66 * @input: The input device we registered with the input subsystem. 
  6. 67 * @clock: The clock for the adc. 
  7. 68 * @io: Pointer to the IO base. 
  8. 69 * @xp: The accumulated X position data. 
  9. 70 * @yp: The accumulated Y position data. 
  10. 71 * @irq_tc: The interrupt number for pen up/down interrupt 
  11. 72 * @count: The number of samples collected. 
  12. 73 * @shift: The log2 of the maximum count to read in one go. 
  13. 74 * @features: The features supported by the TSADC MOdule. 
  14. 75 */  
  15. 76struct s3c2410ts {  
  16. 77    struct s3c_adc_client *client;  
  17. 78    struct device *dev;  
  18. 79    struct input_dev *input;  
  19. 80    struct clk *clock;  
  20. 81    void __iomem *io;  
  21. 82    unsigned long xp;  
  22. 83    unsigned long yp;  
  23. 84    int irq_tc;  
  24. 85    int count;  
  25. 86    int shift;  
  26. 87    int features;  
  27. 88};  
  28. 89  
  29. 90static struct s3c2410ts ts;  
s3c2410ts結構體的各個成員的含義在注冊中已經說的很清楚,這裡不再解釋。
Copyright © Linux教程網 All Rights Reserved