ks0108.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Filename: ks0108.c
  3. * Version: 0.1.0
  4. * Description: ks0108 LCD Controller driver
  5. * License: GPLv2
  6. * Depends: parport
  7. *
  8. * Author: Copyright (C) Miguel Ojeda Sandonis
  9. * Date: 2006-10-31
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with this program; if not, write to the Free Software
  22. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  23. *
  24. */
  25. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  26. #include <linux/init.h>
  27. #include <linux/module.h>
  28. #include <linux/kernel.h>
  29. #include <linux/delay.h>
  30. #include <linux/fs.h>
  31. #include <linux/io.h>
  32. #include <linux/parport.h>
  33. #include <linux/uaccess.h>
  34. #include <linux/ks0108.h>
  35. #define KS0108_NAME "ks0108"
  36. /*
  37. * Module Parameters
  38. */
  39. static unsigned int ks0108_port = CONFIG_KS0108_PORT;
  40. module_param(ks0108_port, uint, S_IRUGO);
  41. MODULE_PARM_DESC(ks0108_port, "Parallel port where the LCD is connected");
  42. static unsigned int ks0108_delay = CONFIG_KS0108_DELAY;
  43. module_param(ks0108_delay, uint, S_IRUGO);
  44. MODULE_PARM_DESC(ks0108_delay, "Delay between each control writing (microseconds)");
  45. /*
  46. * Device
  47. */
  48. static struct parport *ks0108_parport;
  49. static struct pardevice *ks0108_pardevice;
  50. /*
  51. * ks0108 Exported Commands (don't lock)
  52. *
  53. * You _should_ lock in the top driver: This functions _should not_
  54. * get race conditions in any way. Locking for each byte here would be
  55. * so slow and useless.
  56. *
  57. * There are not bit definitions because they are not flags,
  58. * just arbitrary combinations defined by the documentation for each
  59. * function in the ks0108 LCD controller. If you want to know what means
  60. * a specific combination, look at the function's name.
  61. *
  62. * The ks0108_writecontrol bits need to be reverted ^(0,1,3) because
  63. * the parallel port also revert them using a "not" logic gate.
  64. */
  65. #define bit(n) (((unsigned char)1)<<(n))
  66. void ks0108_writedata(unsigned char byte)
  67. {
  68. parport_write_data(ks0108_parport, byte);
  69. }
  70. void ks0108_writecontrol(unsigned char byte)
  71. {
  72. udelay(ks0108_delay);
  73. parport_write_control(ks0108_parport, byte ^ (bit(0) | bit(1) | bit(3)));
  74. }
  75. void ks0108_displaystate(unsigned char state)
  76. {
  77. ks0108_writedata((state ? bit(0) : 0) | bit(1) | bit(2) | bit(3) | bit(4) | bit(5));
  78. }
  79. void ks0108_startline(unsigned char startline)
  80. {
  81. ks0108_writedata(min_t(unsigned char, startline, 63) | bit(6) |
  82. bit(7));
  83. }
  84. void ks0108_address(unsigned char address)
  85. {
  86. ks0108_writedata(min_t(unsigned char, address, 63) | bit(6));
  87. }
  88. void ks0108_page(unsigned char page)
  89. {
  90. ks0108_writedata(min_t(unsigned char, page, 7) | bit(3) | bit(4) |
  91. bit(5) | bit(7));
  92. }
  93. EXPORT_SYMBOL_GPL(ks0108_writedata);
  94. EXPORT_SYMBOL_GPL(ks0108_writecontrol);
  95. EXPORT_SYMBOL_GPL(ks0108_displaystate);
  96. EXPORT_SYMBOL_GPL(ks0108_startline);
  97. EXPORT_SYMBOL_GPL(ks0108_address);
  98. EXPORT_SYMBOL_GPL(ks0108_page);
  99. /*
  100. * Is the module inited?
  101. */
  102. static unsigned char ks0108_inited;
  103. unsigned char ks0108_isinited(void)
  104. {
  105. return ks0108_inited;
  106. }
  107. EXPORT_SYMBOL_GPL(ks0108_isinited);
  108. static void ks0108_parport_attach(struct parport *port)
  109. {
  110. struct pardev_cb ks0108_cb;
  111. if (port->base != ks0108_port)
  112. return;
  113. memset(&ks0108_cb, 0, sizeof(ks0108_cb));
  114. ks0108_cb.flags = PARPORT_DEV_EXCL;
  115. ks0108_pardevice = parport_register_dev_model(port, KS0108_NAME,
  116. &ks0108_cb, 0);
  117. if (!ks0108_pardevice) {
  118. pr_err("ERROR: parport didn't register new device\n");
  119. return;
  120. }
  121. if (parport_claim(ks0108_pardevice)) {
  122. pr_err("could not claim access to parport %i. Aborting.\n",
  123. ks0108_port);
  124. goto err_unreg_device;
  125. }
  126. ks0108_parport = port;
  127. ks0108_inited = 1;
  128. return;
  129. err_unreg_device:
  130. parport_unregister_device(ks0108_pardevice);
  131. ks0108_pardevice = NULL;
  132. }
  133. static void ks0108_parport_detach(struct parport *port)
  134. {
  135. if (port->base != ks0108_port)
  136. return;
  137. if (!ks0108_pardevice) {
  138. pr_err("%s: already unregistered.\n", KS0108_NAME);
  139. return;
  140. }
  141. parport_release(ks0108_pardevice);
  142. parport_unregister_device(ks0108_pardevice);
  143. ks0108_pardevice = NULL;
  144. ks0108_parport = NULL;
  145. }
  146. /*
  147. * Module Init & Exit
  148. */
  149. static struct parport_driver ks0108_parport_driver = {
  150. .name = "ks0108",
  151. .match_port = ks0108_parport_attach,
  152. .detach = ks0108_parport_detach,
  153. .devmodel = true,
  154. };
  155. static int __init ks0108_init(void)
  156. {
  157. return parport_register_driver(&ks0108_parport_driver);
  158. }
  159. static void __exit ks0108_exit(void)
  160. {
  161. parport_unregister_driver(&ks0108_parport_driver);
  162. }
  163. module_init(ks0108_init);
  164. module_exit(ks0108_exit);
  165. MODULE_LICENSE("GPL v2");
  166. MODULE_AUTHOR("Miguel Ojeda Sandonis <miguel.ojeda.sandonis@gmail.com>");
  167. MODULE_DESCRIPTION("ks0108 LCD Controller driver");