ks0108.c 4.4 KB

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