vs_plane.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright (C) 2020 VeriSilicon Holdings Co., Ltd.
  4. */
  5. #include <drm/drm_atomic.h>
  6. #include <drm/drm_atomic_helper.h>
  7. #include <drm/drm_plane_helper.h>
  8. #include <drm/drm_fb_cma_helper.h>
  9. #include <drm/drm_gem_cma_helper.h>
  10. #include <drm/vs_drm.h>
  11. #include "vs_type.h"
  12. #include "vs_crtc.h"
  13. #include "vs_plane.h"
  14. #include "vs_gem.h"
  15. #include "vs_fb.h"
  16. void vs_plane_destory(struct drm_plane *plane)
  17. {
  18. struct vs_plane *vs_plane = to_vs_plane(plane);
  19. drm_plane_cleanup(plane);
  20. kfree(vs_plane);
  21. }
  22. static void vs_plane_reset(struct drm_plane *plane)
  23. {
  24. struct vs_plane_state *state;
  25. struct vs_plane *vs_plane = to_vs_plane(plane);
  26. if (plane->state) {
  27. __drm_atomic_helper_plane_destroy_state(plane->state);
  28. state = to_vs_plane_state(plane->state);
  29. kfree(state);
  30. plane->state = NULL;
  31. }
  32. state = kzalloc(sizeof(*state), GFP_KERNEL);
  33. if (state == NULL)
  34. return;
  35. __drm_atomic_helper_plane_reset(plane, &state->base);
  36. state->degamma = VS_DEGAMMA_DISABLE;
  37. state->degamma_changed = false;
  38. state->base.zpos = vs_plane->id;
  39. memset(&state->status, 0, sizeof(state->status));
  40. }
  41. static void _vs_plane_duplicate_blob(struct vs_plane_state *state,
  42. struct vs_plane_state *ori_state)
  43. {
  44. state->watermark = ori_state->watermark;
  45. state->color_mgmt = ori_state->color_mgmt;
  46. state->roi = ori_state->roi;
  47. if(state->watermark)
  48. drm_property_blob_get(state->watermark);
  49. if (state->color_mgmt)
  50. drm_property_blob_get(state->color_mgmt);
  51. if (state->roi)
  52. drm_property_blob_get(state->roi);
  53. }
  54. static int
  55. _vs_plane_set_property_blob_from_id(struct drm_device *dev,
  56. struct drm_property_blob **blob,
  57. uint64_t blob_id,
  58. size_t expected_size)
  59. {
  60. struct drm_property_blob *new_blob = NULL;
  61. if (blob_id) {
  62. new_blob = drm_property_lookup_blob(dev, blob_id);
  63. if (new_blob == NULL)
  64. return -EINVAL;
  65. if (new_blob->length != expected_size) {
  66. drm_property_blob_put(new_blob);
  67. return -EINVAL;
  68. }
  69. }
  70. drm_property_replace_blob(blob, new_blob);
  71. drm_property_blob_put(new_blob);
  72. return 0;
  73. }
  74. static struct drm_plane_state *
  75. vs_plane_atomic_duplicate_state(struct drm_plane *plane)
  76. {
  77. struct vs_plane_state *ori_state;
  78. struct vs_plane_state *state;
  79. if (WARN_ON(!plane->state))
  80. return NULL;
  81. ori_state = to_vs_plane_state(plane->state);
  82. state = kzalloc(sizeof(*state), GFP_KERNEL);
  83. if (!state)
  84. return NULL;
  85. __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
  86. state->degamma = ori_state->degamma;
  87. state->degamma_changed = ori_state->degamma_changed;
  88. _vs_plane_duplicate_blob(state, ori_state);
  89. memcpy(&state->status, &ori_state->status, sizeof(ori_state->status));
  90. return &state->base;
  91. }
  92. static void vs_plane_atomic_destroy_state(struct drm_plane *plane,
  93. struct drm_plane_state *state)
  94. {
  95. struct vs_plane_state *vs_plane_state = to_vs_plane_state(state);
  96. __drm_atomic_helper_plane_destroy_state(state);
  97. drm_property_blob_put(vs_plane_state->watermark);
  98. drm_property_blob_put(vs_plane_state->color_mgmt);
  99. drm_property_blob_put(vs_plane_state->roi);
  100. kfree(vs_plane_state);
  101. }
  102. static int vs_plane_atomic_set_property(struct drm_plane *plane,
  103. struct drm_plane_state *state,
  104. struct drm_property *property,
  105. uint64_t val)
  106. {
  107. struct drm_device *dev = plane->dev;
  108. struct vs_plane *vs_plane = to_vs_plane(plane);
  109. struct vs_plane_state *vs_plane_state = to_vs_plane_state(state);
  110. int ret = 0;
  111. if (property == vs_plane->degamma_mode) {
  112. if (vs_plane_state->degamma != val) {
  113. vs_plane_state->degamma = val;
  114. vs_plane_state->degamma_changed = true;
  115. } else {
  116. vs_plane_state->degamma_changed = false;
  117. }
  118. } else if (property == vs_plane->watermark_prop) {
  119. ret = _vs_plane_set_property_blob_from_id(dev,
  120. &vs_plane_state->watermark,
  121. val, sizeof(struct drm_vs_watermark));
  122. return ret;
  123. } else if (property == vs_plane->color_mgmt_prop) {
  124. ret = _vs_plane_set_property_blob_from_id(dev,
  125. &vs_plane_state->color_mgmt,
  126. val, sizeof(struct drm_vs_color_mgmt));
  127. return ret;
  128. } else if (property == vs_plane->roi_prop) {
  129. ret = _vs_plane_set_property_blob_from_id(dev,
  130. &vs_plane_state->roi,
  131. val, sizeof(struct drm_vs_roi));
  132. return ret;
  133. } else {
  134. return -EINVAL;
  135. }
  136. return 0;
  137. }
  138. static int vs_plane_atomic_get_property(struct drm_plane *plane,
  139. const struct drm_plane_state *state,
  140. struct drm_property *property,
  141. uint64_t *val)
  142. {
  143. struct vs_plane *vs_plane = to_vs_plane(plane);
  144. const struct vs_plane_state *vs_plane_state =
  145. container_of(state, const struct vs_plane_state, base);
  146. if (property == vs_plane->degamma_mode)
  147. *val = vs_plane_state->degamma;
  148. else if (property == vs_plane->watermark_prop)
  149. *val = (vs_plane_state->watermark) ?
  150. vs_plane_state->watermark->base.id : 0;
  151. else if (property == vs_plane->color_mgmt_prop)
  152. *val = (vs_plane_state->color_mgmt) ?
  153. vs_plane_state->color_mgmt->base.id : 0;
  154. else if (property == vs_plane->roi_prop)
  155. *val = (vs_plane_state->roi) ?
  156. vs_plane_state->roi->base.id : 0;
  157. else
  158. return -EINVAL;
  159. return 0;
  160. }
  161. const struct drm_plane_funcs vs_plane_funcs = {
  162. .update_plane = drm_atomic_helper_update_plane,
  163. .disable_plane = drm_atomic_helper_disable_plane,
  164. .destroy = vs_plane_destory,
  165. .reset = vs_plane_reset,
  166. .atomic_duplicate_state = vs_plane_atomic_duplicate_state,
  167. .atomic_destroy_state = vs_plane_atomic_destroy_state,
  168. .atomic_set_property = vs_plane_atomic_set_property,
  169. .atomic_get_property = vs_plane_atomic_get_property,
  170. };
  171. static unsigned char vs_get_plane_number(struct drm_framebuffer *fb)
  172. {
  173. const struct drm_format_info *info;
  174. if (!fb)
  175. return 0;
  176. info = drm_format_info(fb->format->format);
  177. if (!info || info->num_planes > MAX_NUM_PLANES)
  178. return 0;
  179. return info->num_planes;
  180. }
  181. static int vs_plane_atomic_check(struct drm_plane *plane,
  182. struct drm_plane_state *state)
  183. {
  184. struct vs_plane *vs_plane = to_vs_plane(plane);
  185. struct drm_framebuffer *fb = state->fb;
  186. struct drm_crtc *crtc = state->crtc;
  187. struct vs_crtc *vs_crtc = to_vs_crtc(crtc);
  188. if (!crtc || !fb)
  189. return 0;
  190. return vs_plane->funcs->check(vs_crtc->dev, vs_plane, state);
  191. }
  192. static void vs_plane_atomic_update(struct drm_plane *plane,
  193. struct drm_plane_state *old_state)
  194. {
  195. unsigned char i, num_planes;
  196. struct drm_framebuffer *fb;
  197. struct vs_plane *vs_plane = to_vs_plane(plane);
  198. struct drm_plane_state *state = plane->state;
  199. struct vs_crtc *vs_crtc = to_vs_crtc(state->crtc);
  200. struct vs_plane_state *plane_state = to_vs_plane_state(state);
  201. struct drm_format_name_buf *name = &plane_state->status.format_name;
  202. if (!state->fb || !state->crtc)
  203. return;
  204. fb = state->fb;
  205. num_planes = vs_get_plane_number(fb);
  206. for (i = 0; i < num_planes; i++) {
  207. struct vs_gem_object *vs_obj;
  208. vs_obj = vs_fb_get_gem_obj(fb, i);
  209. vs_plane->dma_addr[i] = vs_obj->iova + fb->offsets[i];
  210. }
  211. plane_state->status.src = drm_plane_state_src(state);
  212. plane_state->status.dest = drm_plane_state_dest(state);
  213. drm_get_format_name(fb->format->format, name);
  214. vs_plane->funcs->update(vs_crtc->dev, vs_plane);
  215. }
  216. static void vs_plane_atomic_disable(struct drm_plane *plane,
  217. struct drm_plane_state *old_state)
  218. {
  219. struct vs_plane *vs_plane = to_vs_plane(plane);
  220. struct vs_crtc *vs_crtc = to_vs_crtc(old_state->crtc);
  221. vs_plane->funcs->disable(vs_crtc->dev, vs_plane, old_state);
  222. }
  223. const struct drm_plane_helper_funcs vs_plane_helper_funcs = {
  224. .atomic_check = vs_plane_atomic_check,
  225. .atomic_update = vs_plane_atomic_update,
  226. .atomic_disable = vs_plane_atomic_disable,
  227. };
  228. static const struct drm_prop_enum_list vs_degamma_mode_enum_list[] = {
  229. { VS_DEGAMMA_DISABLE, "disabled" },
  230. { VS_DEGAMMA_BT709, "preset degamma for BT709" },
  231. { VS_DEGAMMA_BT2020, "preset degamma for BT2020" },
  232. };
  233. struct vs_plane *vs_plane_create(struct drm_device *drm_dev,
  234. struct vs_plane_info *info,
  235. unsigned int layer_num,
  236. unsigned int possible_crtcs)
  237. {
  238. struct vs_plane *plane;
  239. int ret;
  240. if (!info)
  241. return NULL;
  242. plane = kzalloc(sizeof(struct vs_plane), GFP_KERNEL);
  243. if (!plane)
  244. return NULL;
  245. ret = drm_universal_plane_init(drm_dev, &plane->base, possible_crtcs,
  246. &vs_plane_funcs, info->formats,
  247. info->num_formats, info->modifiers, info->type,
  248. info->name ? info->name : NULL);
  249. if (ret)
  250. goto err_free_plane;
  251. drm_plane_helper_add(&plane->base, &vs_plane_helper_funcs);
  252. /* Set up the plane properties */
  253. if (info->degamma_size) {
  254. plane->degamma_mode = drm_property_create_enum(drm_dev, 0,
  255. "DEGAMMA_MODE",
  256. vs_degamma_mode_enum_list,
  257. ARRAY_SIZE(vs_degamma_mode_enum_list));
  258. if (!plane->degamma_mode)
  259. goto error_cleanup_plane;
  260. drm_object_attach_property(&plane->base.base,
  261. plane->degamma_mode,
  262. VS_DEGAMMA_DISABLE);
  263. }
  264. if (info->rotation) {
  265. ret = drm_plane_create_rotation_property(&plane->base,
  266. DRM_MODE_ROTATE_0,
  267. info->rotation);
  268. if (ret)
  269. goto error_cleanup_plane;
  270. }
  271. if (info->blend_mode) {
  272. ret = drm_plane_create_blend_mode_property(&plane->base,
  273. info->blend_mode);
  274. if (ret)
  275. goto error_cleanup_plane;
  276. ret = drm_plane_create_alpha_property(&plane->base);
  277. if (ret)
  278. goto error_cleanup_plane;
  279. }
  280. if (info->color_encoding) {
  281. ret = drm_plane_create_color_properties(&plane->base,
  282. info->color_encoding,
  283. BIT(DRM_COLOR_YCBCR_LIMITED_RANGE),
  284. DRM_COLOR_YCBCR_BT709,
  285. DRM_COLOR_YCBCR_LIMITED_RANGE);
  286. if (ret)
  287. goto error_cleanup_plane;
  288. }
  289. if (info->zpos != 255) {
  290. ret = drm_plane_create_zpos_property(&plane->base, info->zpos, 0, layer_num - 1);
  291. if (ret)
  292. goto error_cleanup_plane;
  293. }
  294. #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
  295. else {
  296. ret = drm_plane_create_zpos_immutable_property(&plane->base,
  297. info->zpos);
  298. if (ret)
  299. goto error_cleanup_plane;
  300. }
  301. #endif
  302. if (info->watermark) {
  303. plane->watermark_prop = drm_property_create(drm_dev, DRM_MODE_PROP_BLOB,
  304. "WATERMARK", 0);
  305. if (!plane->watermark_prop)
  306. goto error_cleanup_plane;
  307. drm_object_attach_property(&plane->base.base, plane->watermark_prop, 0);
  308. }
  309. if (info->color_mgmt) {
  310. plane->color_mgmt_prop = drm_property_create(drm_dev, DRM_MODE_PROP_BLOB,
  311. "COLOR_CONFIG", 0);
  312. if (!plane->color_mgmt_prop)
  313. goto error_cleanup_plane;
  314. drm_object_attach_property(&plane->base.base, plane->color_mgmt_prop, 0);
  315. }
  316. if (info->roi) {
  317. plane->roi_prop = drm_property_create(drm_dev, DRM_MODE_PROP_BLOB,
  318. "ROI", 0);
  319. if (!plane->roi_prop)
  320. goto error_cleanup_plane;
  321. drm_object_attach_property(&plane->base.base, plane->roi_prop, 0);
  322. }
  323. return plane;
  324. error_cleanup_plane:
  325. drm_plane_cleanup(&plane->base);
  326. err_free_plane:
  327. kfree(plane);
  328. return NULL;
  329. }