exynos_mipi_dsi.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright (C) 2012 Samsung Electronics
  3. *
  4. * Author: InKi Dae <inki.dae@samsung.com>
  5. * Author: Donghwa Lee <dh09.lee@samsung.com>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License as
  9. * published by the Free Software Foundation; either version 2 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  20. * MA 02111-1307 USA
  21. */
  22. #include <common.h>
  23. #include <malloc.h>
  24. #include <linux/err.h>
  25. #include <asm/arch/dsim.h>
  26. #include <asm/arch/mipi_dsim.h>
  27. #include <asm/arch/power.h>
  28. #include <asm/arch/cpu.h>
  29. #include <asm/arch/clk.h>
  30. #include "exynos_mipi_dsi_lowlevel.h"
  31. #include "exynos_mipi_dsi_common.h"
  32. #define master_to_driver(a) (a->dsim_lcd_drv)
  33. #define master_to_device(a) (a->dsim_lcd_dev)
  34. static struct exynos_platform_mipi_dsim *dsim_pd;
  35. struct mipi_dsim_ddi {
  36. int bus_id;
  37. struct list_head list;
  38. struct mipi_dsim_lcd_device *dsim_lcd_dev;
  39. struct mipi_dsim_lcd_driver *dsim_lcd_drv;
  40. };
  41. static LIST_HEAD(dsim_ddi_list);
  42. static LIST_HEAD(dsim_lcd_dev_list);
  43. int exynos_mipi_dsi_register_lcd_device(struct mipi_dsim_lcd_device *lcd_dev)
  44. {
  45. struct mipi_dsim_ddi *dsim_ddi;
  46. if (!lcd_dev) {
  47. debug("mipi_dsim_lcd_device is NULL.\n");
  48. return -EFAULT;
  49. }
  50. if (!lcd_dev->name) {
  51. debug("dsim_lcd_device name is NULL.\n");
  52. return -EFAULT;
  53. }
  54. dsim_ddi = kzalloc(sizeof(struct mipi_dsim_ddi), GFP_KERNEL);
  55. if (!dsim_ddi) {
  56. debug("failed to allocate dsim_ddi object.\n");
  57. return -EFAULT;
  58. }
  59. dsim_ddi->dsim_lcd_dev = lcd_dev;
  60. list_add_tail(&dsim_ddi->list, &dsim_ddi_list);
  61. return 0;
  62. }
  63. struct mipi_dsim_ddi
  64. *exynos_mipi_dsi_find_lcd_device(struct mipi_dsim_lcd_driver *lcd_drv)
  65. {
  66. struct mipi_dsim_ddi *dsim_ddi;
  67. struct mipi_dsim_lcd_device *lcd_dev;
  68. list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
  69. lcd_dev = dsim_ddi->dsim_lcd_dev;
  70. if (!lcd_dev)
  71. continue;
  72. if (lcd_drv->id >= 0) {
  73. if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0 &&
  74. lcd_drv->id == lcd_dev->id) {
  75. /**
  76. * bus_id would be used to identify
  77. * connected bus.
  78. */
  79. dsim_ddi->bus_id = lcd_dev->bus_id;
  80. return dsim_ddi;
  81. }
  82. } else {
  83. if ((strcmp(lcd_drv->name, lcd_dev->name)) == 0) {
  84. /**
  85. * bus_id would be used to identify
  86. * connected bus.
  87. */
  88. dsim_ddi->bus_id = lcd_dev->bus_id;
  89. return dsim_ddi;
  90. }
  91. }
  92. kfree(dsim_ddi);
  93. list_del(&dsim_ddi_list);
  94. }
  95. return NULL;
  96. }
  97. int exynos_mipi_dsi_register_lcd_driver(struct mipi_dsim_lcd_driver *lcd_drv)
  98. {
  99. struct mipi_dsim_ddi *dsim_ddi;
  100. if (!lcd_drv) {
  101. debug("mipi_dsim_lcd_driver is NULL.\n");
  102. return -EFAULT;
  103. }
  104. if (!lcd_drv->name) {
  105. debug("dsim_lcd_driver name is NULL.\n");
  106. return -EFAULT;
  107. }
  108. dsim_ddi = exynos_mipi_dsi_find_lcd_device(lcd_drv);
  109. if (!dsim_ddi) {
  110. debug("mipi_dsim_ddi object not found.\n");
  111. return -EFAULT;
  112. }
  113. dsim_ddi->dsim_lcd_drv = lcd_drv;
  114. debug("registered panel driver(%s) to mipi-dsi driver.\n",
  115. lcd_drv->name);
  116. return 0;
  117. }
  118. struct mipi_dsim_ddi
  119. *exynos_mipi_dsi_bind_lcd_ddi(struct mipi_dsim_device *dsim,
  120. const char *name)
  121. {
  122. struct mipi_dsim_ddi *dsim_ddi;
  123. struct mipi_dsim_lcd_driver *lcd_drv;
  124. struct mipi_dsim_lcd_device *lcd_dev;
  125. list_for_each_entry(dsim_ddi, &dsim_ddi_list, list) {
  126. lcd_drv = dsim_ddi->dsim_lcd_drv;
  127. lcd_dev = dsim_ddi->dsim_lcd_dev;
  128. if (!lcd_drv || !lcd_dev)
  129. continue;
  130. debug("lcd_drv->id = %d, lcd_dev->id = %d\n",
  131. lcd_drv->id, lcd_dev->id);
  132. if ((strcmp(lcd_drv->name, name) == 0)) {
  133. lcd_dev->master = dsim;
  134. dsim->dsim_lcd_dev = lcd_dev;
  135. dsim->dsim_lcd_drv = lcd_drv;
  136. return dsim_ddi;
  137. }
  138. }
  139. return NULL;
  140. }
  141. /* define MIPI-DSI Master operations. */
  142. static struct mipi_dsim_master_ops master_ops = {
  143. .cmd_write = exynos_mipi_dsi_wr_data,
  144. .get_dsim_frame_done = exynos_mipi_dsi_get_frame_done_status,
  145. .clear_dsim_frame_done = exynos_mipi_dsi_clear_frame_done,
  146. };
  147. int exynos_mipi_dsi_init(void)
  148. {
  149. struct mipi_dsim_device *dsim;
  150. struct mipi_dsim_config *dsim_config;
  151. struct mipi_dsim_ddi *dsim_ddi;
  152. dsim = kzalloc(sizeof(struct mipi_dsim_device), GFP_KERNEL);
  153. if (!dsim) {
  154. debug("failed to allocate dsim object.\n");
  155. return -EFAULT;
  156. }
  157. /* get mipi_dsim_config. */
  158. dsim_config = dsim_pd->dsim_config;
  159. if (dsim_config == NULL) {
  160. debug("failed to get dsim config data.\n");
  161. return -EFAULT;
  162. }
  163. dsim->pd = dsim_pd;
  164. dsim->dsim_config = dsim_config;
  165. dsim->master_ops = &master_ops;
  166. /* bind lcd ddi matched with panel name. */
  167. dsim_ddi = exynos_mipi_dsi_bind_lcd_ddi(dsim, dsim_pd->lcd_panel_name);
  168. if (!dsim_ddi) {
  169. debug("mipi_dsim_ddi object not found.\n");
  170. return -ENOSYS;
  171. }
  172. if (dsim_pd->lcd_power)
  173. dsim_pd->lcd_power();
  174. if (dsim_pd->mipi_power)
  175. dsim_pd->mipi_power();
  176. /* phy_enable(unsigned int dev_index, unsigned int enable) */
  177. if (dsim_pd->phy_enable)
  178. dsim_pd->phy_enable(0, 1);
  179. set_mipi_clk();
  180. exynos_mipi_dsi_init_dsim(dsim);
  181. exynos_mipi_dsi_init_link(dsim);
  182. exynos_mipi_dsi_set_hs_enable(dsim);
  183. /* set display timing. */
  184. exynos_mipi_dsi_set_display_mode(dsim, dsim->dsim_config);
  185. /* initialize mipi-dsi client(lcd panel). */
  186. if (dsim_ddi->dsim_lcd_drv && dsim_ddi->dsim_lcd_drv->mipi_panel_init) {
  187. dsim_ddi->dsim_lcd_drv->mipi_panel_init(dsim);
  188. dsim_ddi->dsim_lcd_drv->mipi_display_on(dsim);
  189. }
  190. debug("mipi-dsi driver(%s mode) has been probed.\n",
  191. (dsim_config->e_interface == DSIM_COMMAND) ?
  192. "CPU" : "RGB");
  193. return 0;
  194. }
  195. void exynos_set_dsim_platform_data(struct exynos_platform_mipi_dsim *pd)
  196. {
  197. if (pd == NULL) {
  198. debug("pd is NULL\n");
  199. return;
  200. }
  201. dsim_pd = pd;
  202. }