mdp-5-subdev.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336
  1. /* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. *
  12. */
  13. #include <linux/msm_mdp.h>
  14. #include <linux/slab.h>
  15. #include <mach/iommu_domains.h>
  16. #include <media/videobuf2-core.h>
  17. #include "enc-subdev.h"
  18. #include "mdp-subdev.h"
  19. #include "wfd-util.h"
  20. struct mdp_instance {
  21. struct fb_info *mdp;
  22. u32 height;
  23. u32 width;
  24. bool secure;
  25. };
  26. static int mdp_secure(struct v4l2_subdev *sd, void *arg);
  27. int mdp_init(struct v4l2_subdev *sd, u32 val)
  28. {
  29. return 0;
  30. }
  31. int mdp_open(struct v4l2_subdev *sd, void *arg)
  32. {
  33. struct mdp_instance *inst = kzalloc(sizeof(struct mdp_instance),
  34. GFP_KERNEL);
  35. struct mdp_msg_ops *mops = arg;
  36. int rc = 0;
  37. struct fb_info *fbi = NULL;
  38. if (!inst) {
  39. WFD_MSG_ERR("Out of memory\n");
  40. rc = -ENOMEM;
  41. goto mdp_open_fail;
  42. } else if (!mops) {
  43. WFD_MSG_ERR("Invalid arguments\n");
  44. rc = -EINVAL;
  45. goto mdp_open_fail;
  46. }
  47. fbi = msm_fb_get_writeback_fb();
  48. if (!fbi) {
  49. WFD_MSG_ERR("Failed to acquire mdp instance\n");
  50. rc = -ENODEV;
  51. goto mdp_open_fail;
  52. }
  53. msm_fb_writeback_init(fbi);
  54. inst->mdp = fbi;
  55. inst->secure = mops->secure;
  56. if (mops->secure) {
  57. rc = mdp_secure(sd, inst);
  58. if (rc) {
  59. WFD_MSG_ERR("Couldn't secure MDP\n");
  60. goto mdp_secure_fail;
  61. }
  62. }
  63. mops->cookie = inst;
  64. return 0;
  65. mdp_secure_fail:
  66. msm_fb_writeback_terminate(fbi);
  67. mdp_open_fail:
  68. kfree(inst);
  69. return rc;
  70. }
  71. int mdp_start(struct v4l2_subdev *sd, void *arg)
  72. {
  73. struct mdp_instance *inst = arg;
  74. int rc = 0;
  75. if (inst) {
  76. rc = msm_fb_writeback_start(inst->mdp);
  77. if (rc) {
  78. WFD_MSG_ERR("Failed to start MDP mode\n");
  79. goto exit;
  80. }
  81. }
  82. exit:
  83. return rc;
  84. }
  85. int mdp_stop(struct v4l2_subdev *sd, void *arg)
  86. {
  87. struct mdp_instance *inst = arg;
  88. int rc = 0;
  89. if (inst) {
  90. rc = msm_fb_writeback_stop(inst->mdp);
  91. if (rc) {
  92. WFD_MSG_ERR("Failed to stop writeback mode\n");
  93. return rc;
  94. }
  95. }
  96. return 0;
  97. }
  98. static int mdp_close(struct v4l2_subdev *sd, void *arg)
  99. {
  100. struct mdp_instance *inst = arg;
  101. if (inst) {
  102. if (inst->secure)
  103. msm_fb_writeback_set_secure(inst->mdp, false);
  104. msm_fb_writeback_terminate(inst->mdp);
  105. kfree(inst);
  106. }
  107. return 0;
  108. }
  109. static int mdp_q_buffer(struct v4l2_subdev *sd, void *arg)
  110. {
  111. int rc = 0;
  112. struct mdp_buf_info *binfo = arg;
  113. struct msmfb_data fbdata;
  114. struct mdp_instance *inst;
  115. if (!binfo || !binfo->inst || !binfo->cookie) {
  116. WFD_MSG_ERR("Invalid argument\n");
  117. return -EINVAL;
  118. }
  119. inst = binfo->inst;
  120. fbdata.offset = binfo->offset;
  121. fbdata.memory_id = binfo->fd;
  122. fbdata.iova = binfo->paddr;
  123. fbdata.id = 0;
  124. fbdata.flags = 0;
  125. fbdata.priv = (uint32_t)binfo->cookie;
  126. WFD_MSG_DBG("queue buffer to mdp with offset = %u, fd = %u, "\
  127. "priv = %p, iova = %p\n",
  128. fbdata.offset, fbdata.memory_id,
  129. (void *)fbdata.priv, (void *)fbdata.iova);
  130. rc = msm_fb_writeback_queue_buffer(inst->mdp, &fbdata);
  131. if (rc)
  132. WFD_MSG_ERR("Failed to queue buffer\n");
  133. return rc;
  134. }
  135. static int mdp_dq_buffer(struct v4l2_subdev *sd, void *arg)
  136. {
  137. int rc = 0;
  138. struct mdp_buf_info *obuf = arg;
  139. struct msmfb_data fbdata;
  140. struct mdp_instance *inst;
  141. if (!arg) {
  142. WFD_MSG_ERR("Invalid argument\n");
  143. return -EINVAL;
  144. }
  145. inst = obuf->inst;
  146. fbdata.flags = MSMFB_WRITEBACK_DEQUEUE_BLOCKING;
  147. rc = msm_fb_writeback_dequeue_buffer(inst->mdp, &fbdata);
  148. if (rc) {
  149. WFD_MSG_ERR("Failed to dequeue buffer\n");
  150. return rc;
  151. }
  152. WFD_MSG_DBG("dequeue buf from mdp with priv = %u\n",
  153. fbdata.priv);
  154. obuf->cookie = (void *)fbdata.priv;
  155. return rc;
  156. }
  157. static int mdp_set_prop(struct v4l2_subdev *sd, void *arg)
  158. {
  159. struct mdp_prop *prop = (struct mdp_prop *)arg;
  160. struct mdp_instance *inst = prop->inst;
  161. if (!prop || !inst) {
  162. WFD_MSG_ERR("Invalid arguments\n");
  163. return -EINVAL;
  164. }
  165. inst->height = prop->height;
  166. inst->width = prop->width;
  167. return 0;
  168. }
  169. static int mdp_mmap(struct v4l2_subdev *sd, void *arg)
  170. {
  171. int rc = 0, align = 0;
  172. struct mem_region_map *mmap = arg;
  173. struct mem_region *mregion;
  174. int domain = -1;
  175. struct mdp_instance *inst = NULL;
  176. if (!mmap || !mmap->mregion || !mmap->cookie) {
  177. WFD_MSG_ERR("Invalid argument\n");
  178. return -EINVAL;
  179. }
  180. inst = mmap->cookie;
  181. mregion = mmap->mregion;
  182. align = inst->secure ? SZ_1M : SZ_4K;
  183. if (mregion->size % align != 0) {
  184. WFD_MSG_ERR("Memregion not aligned to %d\n", align);
  185. return -EINVAL;
  186. }
  187. msm_fb_writeback_iommu_ref(inst->mdp, true);
  188. if (inst->secure) {
  189. rc = msm_ion_secure_buffer(mmap->ion_client,
  190. mregion->ion_handle, VIDEO_PIXEL, 0);
  191. if (rc) {
  192. WFD_MSG_ERR("Failed to secure input buffer\n");
  193. goto secure_fail;
  194. }
  195. }
  196. domain = msm_fb_get_iommu_domain(inst->mdp,
  197. inst->secure ? MDP_IOMMU_DOMAIN_CP :
  198. MDP_IOMMU_DOMAIN_NS);
  199. rc = ion_map_iommu(mmap->ion_client, mregion->ion_handle,
  200. domain, 0, align, 0,
  201. (unsigned long *)&mregion->paddr,
  202. (unsigned long *)&mregion->size,
  203. 0, 0);
  204. if (rc) {
  205. WFD_MSG_ERR("Failed to map into %ssecure domain: %d\n",
  206. !inst->secure ? "non" : "", rc);
  207. goto iommu_fail;
  208. }
  209. msm_fb_writeback_iommu_ref(inst->mdp, false);
  210. return 0;
  211. iommu_fail:
  212. if (inst->secure)
  213. msm_ion_unsecure_buffer(mmap->ion_client, mregion->ion_handle);
  214. secure_fail:
  215. msm_fb_writeback_iommu_ref(inst->mdp, false);
  216. return rc;
  217. }
  218. static int mdp_munmap(struct v4l2_subdev *sd, void *arg)
  219. {
  220. struct mem_region_map *mmap = arg;
  221. struct mem_region *mregion;
  222. int domain = -1;
  223. struct mdp_instance *inst = NULL;
  224. if (!mmap || !mmap->mregion || !mmap->cookie) {
  225. WFD_MSG_ERR("Invalid argument\n");
  226. return -EINVAL;
  227. }
  228. inst = mmap->cookie;
  229. mregion = mmap->mregion;
  230. msm_fb_writeback_iommu_ref(inst->mdp, true);
  231. domain = msm_fb_get_iommu_domain(inst->mdp,
  232. inst->secure ? MDP_IOMMU_DOMAIN_CP :
  233. MDP_IOMMU_DOMAIN_NS);
  234. ion_unmap_iommu(mmap->ion_client,
  235. mregion->ion_handle,
  236. domain, 0);
  237. if (inst->secure)
  238. msm_ion_unsecure_buffer(mmap->ion_client, mregion->ion_handle);
  239. msm_fb_writeback_iommu_ref(inst->mdp, false);
  240. return 0;
  241. }
  242. static int mdp_secure(struct v4l2_subdev *sd, void *arg)
  243. {
  244. struct mdp_instance *inst = NULL;
  245. int rc = 0;
  246. if (!arg) {
  247. WFD_MSG_ERR("Invalid argument\n");
  248. return -EINVAL;
  249. }
  250. inst = arg;
  251. rc = msm_fb_writeback_set_secure(inst->mdp, true);
  252. if (!rc)
  253. inst->secure = true;
  254. return rc;
  255. }
  256. long mdp_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
  257. {
  258. int rc = 0;
  259. if (!sd) {
  260. WFD_MSG_ERR("Invalid arguments\n");
  261. return -EINVAL;
  262. }
  263. switch (cmd) {
  264. case MDP_Q_BUFFER:
  265. rc = mdp_q_buffer(sd, arg);
  266. break;
  267. case MDP_DQ_BUFFER:
  268. rc = mdp_dq_buffer(sd, arg);
  269. break;
  270. case MDP_OPEN:
  271. rc = mdp_open(sd, arg);
  272. break;
  273. case MDP_START:
  274. rc = mdp_start(sd, arg);
  275. break;
  276. case MDP_STOP:
  277. rc = mdp_stop(sd, arg);
  278. break;
  279. case MDP_SET_PROP:
  280. rc = mdp_set_prop(sd, arg);
  281. break;
  282. case MDP_CLOSE:
  283. rc = mdp_close(sd, arg);
  284. break;
  285. case MDP_MMAP:
  286. rc = mdp_mmap(sd, arg);
  287. break;
  288. case MDP_MUNMAP:
  289. rc = mdp_munmap(sd, arg);
  290. break;
  291. default:
  292. WFD_MSG_ERR("IOCTL: %u not supported\n", cmd);
  293. rc = -EINVAL;
  294. break;
  295. }
  296. return rc;
  297. }