歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> S3C2410驅動分析之觸摸屏驅動

S3C2410驅動分析之觸摸屏驅動

日期:2017/3/1 10:24:34   编辑:Linux編程

內核版本: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