core.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. /*
  2. * linux/drivers/video/mmp/common.c
  3. * This driver is a common framework for Marvell Display Controller
  4. *
  5. * Copyright (C) 2012 Marvell Technology Group Ltd.
  6. * Authors: Zhou Zhu <zzhu3@marvell.com>
  7. *
  8. * This program is free software; you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation; either version 2 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but WITHOUT
  14. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  15. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  16. * more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along with
  19. * this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include <linux/slab.h>
  23. #include <linux/dma-mapping.h>
  24. #include <linux/export.h>
  25. #include <linux/module.h>
  26. #include <video/mmp_disp.h>
  27. static struct mmp_overlay *path_get_overlay(struct mmp_path *path,
  28. int overlay_id)
  29. {
  30. if (path && overlay_id < path->overlay_num)
  31. return &path->overlays[overlay_id];
  32. return NULL;
  33. }
  34. static int path_check_status(struct mmp_path *path)
  35. {
  36. int i;
  37. for (i = 0; i < path->overlay_num; i++)
  38. if (path->overlays[i].status)
  39. return 1;
  40. return 0;
  41. }
  42. /*
  43. * Get modelist write pointer of modelist.
  44. * It also returns modelist number
  45. * this function fetches modelist from phy/panel:
  46. * for HDMI/parallel or dsi to hdmi cases, get from phy
  47. * or get from panel
  48. */
  49. static int path_get_modelist(struct mmp_path *path,
  50. struct mmp_mode **modelist)
  51. {
  52. BUG_ON(!path || !modelist);
  53. if (path->panel && path->panel->get_modelist)
  54. return path->panel->get_modelist(path->panel, modelist);
  55. return 0;
  56. }
  57. /*
  58. * panel list is used to pair panel/path when path/panel registered
  59. * path list is used for both buffer driver and platdriver
  60. * plat driver do path register/unregister
  61. * panel driver do panel register/unregister
  62. * buffer driver get registered path
  63. */
  64. static LIST_HEAD(panel_list);
  65. static LIST_HEAD(path_list);
  66. static DEFINE_MUTEX(disp_lock);
  67. /*
  68. * mmp_register_panel - register panel to panel_list and connect to path
  69. * @p: panel to be registered
  70. *
  71. * this function provides interface for panel drivers to register panel
  72. * to panel_list and connect to path which matchs panel->plat_path_name.
  73. * no error returns when no matching path is found as path register after
  74. * panel register is permitted.
  75. */
  76. void mmp_register_panel(struct mmp_panel *panel)
  77. {
  78. struct mmp_path *path;
  79. mutex_lock(&disp_lock);
  80. /* add */
  81. list_add_tail(&panel->node, &panel_list);
  82. /* try to register to path */
  83. list_for_each_entry(path, &path_list, node) {
  84. if (!strcmp(panel->plat_path_name, path->name)) {
  85. dev_info(panel->dev, "connect to path %s\n",
  86. path->name);
  87. path->panel = panel;
  88. break;
  89. }
  90. }
  91. mutex_unlock(&disp_lock);
  92. }
  93. EXPORT_SYMBOL_GPL(mmp_register_panel);
  94. /*
  95. * mmp_unregister_panel - unregister panel from panel_list and disconnect
  96. * @p: panel to be unregistered
  97. *
  98. * this function provides interface for panel drivers to unregister panel
  99. * from panel_list and disconnect from path.
  100. */
  101. void mmp_unregister_panel(struct mmp_panel *panel)
  102. {
  103. struct mmp_path *path;
  104. mutex_lock(&disp_lock);
  105. list_del(&panel->node);
  106. list_for_each_entry(path, &path_list, node) {
  107. if (path->panel && path->panel == panel) {
  108. dev_info(panel->dev, "disconnect from path %s\n",
  109. path->name);
  110. path->panel = NULL;
  111. break;
  112. }
  113. }
  114. mutex_unlock(&disp_lock);
  115. }
  116. EXPORT_SYMBOL_GPL(mmp_unregister_panel);
  117. /*
  118. * mmp_get_path - get path by name
  119. * @p: path name
  120. *
  121. * this function checks path name in path_list and return matching path
  122. * return NULL if no matching path
  123. */
  124. struct mmp_path *mmp_get_path(const char *name)
  125. {
  126. struct mmp_path *path;
  127. int found = 0;
  128. mutex_lock(&disp_lock);
  129. list_for_each_entry(path, &path_list, node) {
  130. if (!strcmp(name, path->name)) {
  131. found = 1;
  132. break;
  133. }
  134. }
  135. mutex_unlock(&disp_lock);
  136. return found ? path : NULL;
  137. }
  138. EXPORT_SYMBOL_GPL(mmp_get_path);
  139. /*
  140. * mmp_register_path - init and register path by path_info
  141. * @p: path info provided by display controller
  142. *
  143. * this function init by path info and register path to path_list
  144. * this function also try to connect path with panel by name
  145. */
  146. struct mmp_path *mmp_register_path(struct mmp_path_info *info)
  147. {
  148. int i;
  149. size_t size;
  150. struct mmp_path *path = NULL;
  151. struct mmp_panel *panel;
  152. size = sizeof(struct mmp_path)
  153. + sizeof(struct mmp_overlay) * info->overlay_num;
  154. path = kzalloc(size, GFP_KERNEL);
  155. if (!path)
  156. return NULL;
  157. /* path set */
  158. mutex_init(&path->access_ok);
  159. path->dev = info->dev;
  160. path->id = info->id;
  161. path->name = info->name;
  162. path->output_type = info->output_type;
  163. path->overlay_num = info->overlay_num;
  164. path->plat_data = info->plat_data;
  165. path->ops.set_mode = info->set_mode;
  166. mutex_lock(&disp_lock);
  167. /* get panel */
  168. list_for_each_entry(panel, &panel_list, node) {
  169. if (!strcmp(info->name, panel->plat_path_name)) {
  170. dev_info(path->dev, "get panel %s\n", panel->name);
  171. path->panel = panel;
  172. break;
  173. }
  174. }
  175. dev_info(path->dev, "register %s, overlay_num %d\n",
  176. path->name, path->overlay_num);
  177. /* default op set: if already set by driver, never cover it */
  178. if (!path->ops.check_status)
  179. path->ops.check_status = path_check_status;
  180. if (!path->ops.get_overlay)
  181. path->ops.get_overlay = path_get_overlay;
  182. if (!path->ops.get_modelist)
  183. path->ops.get_modelist = path_get_modelist;
  184. /* step3: init overlays */
  185. for (i = 0; i < path->overlay_num; i++) {
  186. path->overlays[i].path = path;
  187. path->overlays[i].id = i;
  188. mutex_init(&path->overlays[i].access_ok);
  189. path->overlays[i].ops = info->overlay_ops;
  190. }
  191. /* add to pathlist */
  192. list_add_tail(&path->node, &path_list);
  193. mutex_unlock(&disp_lock);
  194. return path;
  195. }
  196. EXPORT_SYMBOL_GPL(mmp_register_path);
  197. /*
  198. * mmp_unregister_path - unregister and destroy path
  199. * @p: path to be destroyed.
  200. *
  201. * this function registers path and destroys it.
  202. */
  203. void mmp_unregister_path(struct mmp_path *path)
  204. {
  205. int i;
  206. if (!path)
  207. return;
  208. mutex_lock(&disp_lock);
  209. /* del from pathlist */
  210. list_del(&path->node);
  211. /* deinit overlays */
  212. for (i = 0; i < path->overlay_num; i++)
  213. mutex_destroy(&path->overlays[i].access_ok);
  214. mutex_destroy(&path->access_ok);
  215. kfree(path);
  216. mutex_unlock(&disp_lock);
  217. }
  218. EXPORT_SYMBOL_GPL(mmp_unregister_path);
  219. MODULE_AUTHOR("Zhou Zhu <zzhu3@marvell.com>");
  220. MODULE_DESCRIPTION("Marvell MMP display framework");
  221. MODULE_LICENSE("GPL");