mtk_drm_fb.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. /*
  2. * Copyright (c) 2015 MediaTek Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <drm/drmP.h>
  14. #include <drm/drm_crtc_helper.h>
  15. #include <drm/drm_fb_helper.h>
  16. #include <drm/drm_gem.h>
  17. #include <linux/dma-buf.h>
  18. #include <linux/reservation.h>
  19. #include "mtk_drm_drv.h"
  20. #include "mtk_drm_fb.h"
  21. #include "mtk_drm_gem.h"
  22. /*
  23. * mtk specific framebuffer structure.
  24. *
  25. * @fb: drm framebuffer object.
  26. * @gem_obj: array of gem objects.
  27. */
  28. struct mtk_drm_fb {
  29. struct drm_framebuffer base;
  30. /* For now we only support a single plane */
  31. struct drm_gem_object *gem_obj;
  32. };
  33. #define to_mtk_fb(x) container_of(x, struct mtk_drm_fb, base)
  34. struct drm_gem_object *mtk_fb_get_gem_obj(struct drm_framebuffer *fb)
  35. {
  36. struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
  37. return mtk_fb->gem_obj;
  38. }
  39. size_t mtk_fb_get_size(struct drm_framebuffer *fb)
  40. {
  41. struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
  42. struct mtk_drm_gem_obj *mtk_gem = NULL;
  43. if (!mtk_fb->gem_obj)
  44. return 0;
  45. mtk_gem = to_mtk_gem_obj(mtk_fb->gem_obj);
  46. if (!mtk_gem)
  47. return 0;
  48. return mtk_gem->size;
  49. }
  50. dma_addr_t mtk_fb_get_dma(struct drm_framebuffer *fb)
  51. {
  52. struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
  53. struct mtk_drm_gem_obj *mtk_gem = NULL;
  54. if (!mtk_fb->gem_obj)
  55. return 0;
  56. mtk_gem = to_mtk_gem_obj(mtk_fb->gem_obj);
  57. if (!mtk_gem)
  58. return 0;
  59. return mtk_gem->dma_addr;
  60. }
  61. bool mtk_drm_fb_is_secure(struct drm_framebuffer *fb)
  62. {
  63. struct drm_gem_object *gem = NULL;
  64. struct mtk_drm_gem_obj *mtk_gem = NULL;
  65. if (!fb)
  66. return false;
  67. gem = mtk_fb_get_gem_obj(fb);
  68. if (!gem)
  69. return false;
  70. mtk_gem = to_mtk_gem_obj(gem);
  71. return mtk_gem->sec;
  72. }
  73. static int mtk_drm_fb_create_handle(struct drm_framebuffer *fb,
  74. struct drm_file *file_priv,
  75. unsigned int *handle)
  76. {
  77. struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
  78. return drm_gem_handle_create(file_priv, mtk_fb->gem_obj, handle);
  79. }
  80. static void mtk_drm_fb_destroy(struct drm_framebuffer *fb)
  81. {
  82. struct mtk_drm_fb *mtk_fb = to_mtk_fb(fb);
  83. drm_framebuffer_cleanup(fb);
  84. drm_gem_object_unreference_unlocked(mtk_fb->gem_obj);
  85. kfree(mtk_fb);
  86. }
  87. static const struct drm_framebuffer_funcs mtk_drm_fb_funcs = {
  88. .create_handle = mtk_drm_fb_create_handle,
  89. .destroy = mtk_drm_fb_destroy,
  90. };
  91. static struct mtk_drm_fb *
  92. mtk_drm_framebuffer_init(struct drm_device *dev,
  93. const struct drm_mode_fb_cmd2 *mode,
  94. struct drm_gem_object *obj)
  95. {
  96. struct mtk_drm_fb *mtk_fb;
  97. int ret;
  98. mtk_fb = kzalloc(sizeof(*mtk_fb), GFP_KERNEL);
  99. if (!mtk_fb)
  100. return ERR_PTR(-ENOMEM);
  101. drm_helper_mode_fill_fb_struct(dev, &mtk_fb->base, mode);
  102. mtk_fb->gem_obj = obj;
  103. ret = drm_framebuffer_init(dev, &mtk_fb->base, &mtk_drm_fb_funcs);
  104. if (ret) {
  105. DRM_ERROR("failed to initialize framebuffer\n");
  106. kfree(mtk_fb);
  107. return ERR_PTR(ret);
  108. }
  109. return mtk_fb;
  110. }
  111. struct drm_framebuffer *
  112. mtk_drm_framebuffer_create(struct drm_device *dev,
  113. const struct drm_mode_fb_cmd2 *mode,
  114. struct drm_gem_object *obj)
  115. {
  116. struct mtk_drm_fb *mtk_fb;
  117. mtk_fb = mtk_drm_framebuffer_init(dev, mode, obj);
  118. if (IS_ERR(mtk_fb))
  119. return ERR_CAST(mtk_fb);
  120. return &mtk_fb->base;
  121. }
  122. /*
  123. * Wait for any exclusive fence in fb's gem object's reservation object.
  124. *
  125. * Returns -ERESTARTSYS if interrupted, else 0.
  126. */
  127. int mtk_fb_wait(struct drm_framebuffer *fb)
  128. {
  129. struct drm_gem_object *gem;
  130. struct reservation_object *resv;
  131. long ret;
  132. if (!fb)
  133. return 0;
  134. gem = mtk_fb_get_gem_obj(fb);
  135. if (!gem || !gem->dma_buf || !gem->dma_buf->resv)
  136. return 0;
  137. resv = gem->dma_buf->resv;
  138. ret = reservation_object_wait_timeout_rcu(resv, false, true,
  139. MAX_SCHEDULE_TIMEOUT);
  140. /* MAX_SCHEDULE_TIMEOUT on success, -ERESTARTSYS if interrupted */
  141. if (ret < 0) {
  142. DDPAEE("%s:%d, invalid ret:%ld\n",
  143. __func__, __LINE__,
  144. ret);
  145. return ret;
  146. }
  147. return 0;
  148. }
  149. struct drm_framebuffer *
  150. mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file,
  151. const struct drm_mode_fb_cmd2 *cmd)
  152. {
  153. struct mtk_drm_fb *mtk_fb = NULL;
  154. struct drm_gem_object *gem = NULL;
  155. struct mtk_drm_gem_obj *mtk_gem = NULL;
  156. unsigned int width = cmd->width;
  157. unsigned int height = cmd->height;
  158. unsigned int size, bpp;
  159. int ret;
  160. if (cmd->pixel_format == DRM_FORMAT_C8)
  161. goto fb_init;
  162. gem = drm_gem_object_lookup(file, cmd->handles[0]);
  163. if (!gem)
  164. return ERR_PTR(-ENOENT);
  165. bpp = drm_format_plane_cpp(cmd->pixel_format, 0);
  166. size = (height - 1) * cmd->pitches[0] + width * bpp;
  167. size += cmd->offsets[0];
  168. mtk_gem = to_mtk_gem_obj(gem);
  169. if (gem->size < size && !mtk_gem->sec) {
  170. DRM_ERROR("%s:%d, size:(%ld,%d), sec:%d\n",
  171. __func__, __LINE__,
  172. gem->size, size,
  173. mtk_gem->sec);
  174. DRM_ERROR("w:%d, h:%d, bpp:(%d,%d), pitch:%d, offset:%d\n",
  175. width, height,
  176. cmd->pixel_format, bpp,
  177. cmd->pitches[0],
  178. cmd->offsets[0]);
  179. ret = -EINVAL;
  180. goto unreference;
  181. }
  182. fb_init:
  183. mtk_fb = mtk_drm_framebuffer_init(dev, cmd, gem);
  184. if (IS_ERR(mtk_fb)) {
  185. ret = PTR_ERR(mtk_fb);
  186. goto unreference;
  187. }
  188. return &mtk_fb->base;
  189. unreference:
  190. drm_gem_object_unreference_unlocked(gem);
  191. return ERR_PTR(ret);
  192. }