malidp_planes.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /*
  2. * (C) COPYRIGHT 2016 ARM Limited. All rights reserved.
  3. * Author: Liviu Dudau <Liviu.Dudau@arm.com>
  4. *
  5. * This program is free software and is provided to you under the terms of the
  6. * GNU General Public License version 2 as published by the Free Software
  7. * Foundation, and any use by you of this program is subject to the terms
  8. * of such GNU licence.
  9. *
  10. * ARM Mali DP plane manipulation routines.
  11. */
  12. #include <drm/drmP.h>
  13. #include <drm/drm_atomic_helper.h>
  14. #include <drm/drm_fb_cma_helper.h>
  15. #include <drm/drm_gem_cma_helper.h>
  16. #include <drm/drm_plane_helper.h>
  17. #include "malidp_hw.h"
  18. #include "malidp_drv.h"
  19. /* Layer specific register offsets */
  20. #define MALIDP_LAYER_FORMAT 0x000
  21. #define MALIDP_LAYER_CONTROL 0x004
  22. #define LAYER_ENABLE (1 << 0)
  23. #define LAYER_ROT_OFFSET 8
  24. #define LAYER_H_FLIP (1 << 10)
  25. #define LAYER_V_FLIP (1 << 11)
  26. #define LAYER_ROT_MASK (0xf << 8)
  27. #define LAYER_COMP_MASK (0x3 << 12)
  28. #define LAYER_COMP_PIXEL (0x3 << 12)
  29. #define LAYER_COMP_PLANE (0x2 << 12)
  30. #define MALIDP_LAYER_COMPOSE 0x008
  31. #define MALIDP_LAYER_SIZE 0x00c
  32. #define LAYER_H_VAL(x) (((x) & 0x1fff) << 0)
  33. #define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
  34. #define MALIDP_LAYER_COMP_SIZE 0x010
  35. #define MALIDP_LAYER_OFFSET 0x014
  36. #define MALIDP_LAYER_STRIDE 0x018
  37. /*
  38. * This 4-entry look-up-table is used to determine the full 8-bit alpha value
  39. * for formats with 1- or 2-bit alpha channels.
  40. * We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
  41. * opacity for 2-bit formats.
  42. */
  43. #define MALIDP_ALPHA_LUT 0xffaa5500
  44. static void malidp_de_plane_destroy(struct drm_plane *plane)
  45. {
  46. struct malidp_plane *mp = to_malidp_plane(plane);
  47. if (mp->base.fb)
  48. drm_framebuffer_unreference(mp->base.fb);
  49. drm_plane_helper_disable(plane);
  50. drm_plane_cleanup(plane);
  51. devm_kfree(plane->dev->dev, mp);
  52. }
  53. static struct
  54. drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
  55. {
  56. struct malidp_plane_state *state, *m_state;
  57. if (!plane->state)
  58. return NULL;
  59. state = kmalloc(sizeof(*state), GFP_KERNEL);
  60. if (state) {
  61. m_state = to_malidp_plane_state(plane->state);
  62. __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
  63. state->rotmem_size = m_state->rotmem_size;
  64. state->format = m_state->format;
  65. state->n_planes = m_state->n_planes;
  66. }
  67. return &state->base;
  68. }
  69. static void malidp_destroy_plane_state(struct drm_plane *plane,
  70. struct drm_plane_state *state)
  71. {
  72. struct malidp_plane_state *m_state = to_malidp_plane_state(state);
  73. __drm_atomic_helper_plane_destroy_state(state);
  74. kfree(m_state);
  75. }
  76. static const struct drm_plane_funcs malidp_de_plane_funcs = {
  77. .update_plane = drm_atomic_helper_update_plane,
  78. .disable_plane = drm_atomic_helper_disable_plane,
  79. .set_property = drm_atomic_helper_plane_set_property,
  80. .destroy = malidp_de_plane_destroy,
  81. .reset = drm_atomic_helper_plane_reset,
  82. .atomic_duplicate_state = malidp_duplicate_plane_state,
  83. .atomic_destroy_state = malidp_destroy_plane_state,
  84. };
  85. static int malidp_de_plane_check(struct drm_plane *plane,
  86. struct drm_plane_state *state)
  87. {
  88. struct malidp_plane *mp = to_malidp_plane(plane);
  89. struct malidp_plane_state *ms = to_malidp_plane_state(state);
  90. struct drm_framebuffer *fb;
  91. int i;
  92. u32 src_w, src_h;
  93. if (!state->crtc || !state->fb)
  94. return 0;
  95. fb = state->fb;
  96. ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
  97. fb->format->format);
  98. if (ms->format == MALIDP_INVALID_FORMAT_ID)
  99. return -EINVAL;
  100. ms->n_planes = fb->format->num_planes;
  101. for (i = 0; i < ms->n_planes; i++) {
  102. if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) {
  103. DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
  104. fb->pitches[i], i);
  105. return -EINVAL;
  106. }
  107. }
  108. src_w = state->src_w >> 16;
  109. src_h = state->src_h >> 16;
  110. if ((state->crtc_w > mp->hwdev->max_line_size) ||
  111. (state->crtc_h > mp->hwdev->max_line_size) ||
  112. (state->crtc_w < mp->hwdev->min_line_size) ||
  113. (state->crtc_h < mp->hwdev->min_line_size) ||
  114. (state->crtc_w != src_w) || (state->crtc_h != src_h))
  115. return -EINVAL;
  116. /* packed RGB888 / BGR888 can't be rotated or flipped */
  117. if (state->rotation != DRM_ROTATE_0 &&
  118. (fb->format->format == DRM_FORMAT_RGB888 ||
  119. fb->format->format == DRM_FORMAT_BGR888))
  120. return -EINVAL;
  121. ms->rotmem_size = 0;
  122. if (state->rotation & MALIDP_ROTATED_MASK) {
  123. int val;
  124. val = mp->hwdev->rotmem_required(mp->hwdev, state->crtc_h,
  125. state->crtc_w,
  126. fb->format->format);
  127. if (val < 0)
  128. return val;
  129. ms->rotmem_size = val;
  130. }
  131. return 0;
  132. }
  133. static void malidp_de_plane_update(struct drm_plane *plane,
  134. struct drm_plane_state *old_state)
  135. {
  136. struct drm_gem_cma_object *obj;
  137. struct malidp_plane *mp;
  138. const struct malidp_hw_regmap *map;
  139. struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
  140. u16 ptr;
  141. u32 src_w, src_h, dest_w, dest_h, val;
  142. int i;
  143. mp = to_malidp_plane(plane);
  144. map = &mp->hwdev->map;
  145. /* convert src values from Q16 fixed point to integer */
  146. src_w = plane->state->src_w >> 16;
  147. src_h = plane->state->src_h >> 16;
  148. if (plane->state->rotation & MALIDP_ROTATED_MASK) {
  149. dest_w = plane->state->crtc_h;
  150. dest_h = plane->state->crtc_w;
  151. } else {
  152. dest_w = plane->state->crtc_w;
  153. dest_h = plane->state->crtc_h;
  154. }
  155. malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
  156. for (i = 0; i < ms->n_planes; i++) {
  157. /* calculate the offset for the layer's plane registers */
  158. ptr = mp->layer->ptr + (i << 4);
  159. obj = drm_fb_cma_get_gem_obj(plane->state->fb, i);
  160. malidp_hw_write(mp->hwdev, lower_32_bits(obj->paddr), ptr);
  161. malidp_hw_write(mp->hwdev, upper_32_bits(obj->paddr), ptr + 4);
  162. malidp_hw_write(mp->hwdev, plane->state->fb->pitches[i],
  163. mp->layer->base + MALIDP_LAYER_STRIDE);
  164. }
  165. malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
  166. mp->layer->base + MALIDP_LAYER_SIZE);
  167. malidp_hw_write(mp->hwdev, LAYER_H_VAL(dest_w) | LAYER_V_VAL(dest_h),
  168. mp->layer->base + MALIDP_LAYER_COMP_SIZE);
  169. malidp_hw_write(mp->hwdev, LAYER_H_VAL(plane->state->crtc_x) |
  170. LAYER_V_VAL(plane->state->crtc_y),
  171. mp->layer->base + MALIDP_LAYER_OFFSET);
  172. /* first clear the rotation bits */
  173. val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
  174. val &= ~LAYER_ROT_MASK;
  175. /* setup the rotation and axis flip bits */
  176. if (plane->state->rotation & DRM_ROTATE_MASK)
  177. val = ilog2(plane->state->rotation & DRM_ROTATE_MASK) << LAYER_ROT_OFFSET;
  178. if (plane->state->rotation & DRM_REFLECT_X)
  179. val |= LAYER_V_FLIP;
  180. if (plane->state->rotation & DRM_REFLECT_Y)
  181. val |= LAYER_H_FLIP;
  182. /*
  183. * always enable pixel alpha blending until we have a way to change
  184. * blend modes
  185. */
  186. val &= ~LAYER_COMP_MASK;
  187. val |= LAYER_COMP_PIXEL;
  188. /* set the 'enable layer' bit */
  189. val |= LAYER_ENABLE;
  190. malidp_hw_write(mp->hwdev, val,
  191. mp->layer->base + MALIDP_LAYER_CONTROL);
  192. }
  193. static void malidp_de_plane_disable(struct drm_plane *plane,
  194. struct drm_plane_state *state)
  195. {
  196. struct malidp_plane *mp = to_malidp_plane(plane);
  197. malidp_hw_clearbits(mp->hwdev, LAYER_ENABLE,
  198. mp->layer->base + MALIDP_LAYER_CONTROL);
  199. }
  200. static const struct drm_plane_helper_funcs malidp_de_plane_helper_funcs = {
  201. .atomic_check = malidp_de_plane_check,
  202. .atomic_update = malidp_de_plane_update,
  203. .atomic_disable = malidp_de_plane_disable,
  204. };
  205. int malidp_de_planes_init(struct drm_device *drm)
  206. {
  207. struct malidp_drm *malidp = drm->dev_private;
  208. const struct malidp_hw_regmap *map = &malidp->dev->map;
  209. struct malidp_plane *plane = NULL;
  210. enum drm_plane_type plane_type;
  211. unsigned long crtcs = 1 << drm->mode_config.num_crtc;
  212. unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 |
  213. DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y;
  214. u32 *formats;
  215. int ret, i, j, n;
  216. formats = kcalloc(map->n_input_formats, sizeof(*formats), GFP_KERNEL);
  217. if (!formats) {
  218. ret = -ENOMEM;
  219. goto cleanup;
  220. }
  221. for (i = 0; i < map->n_layers; i++) {
  222. u8 id = map->layers[i].id;
  223. plane = kzalloc(sizeof(*plane), GFP_KERNEL);
  224. if (!plane) {
  225. ret = -ENOMEM;
  226. goto cleanup;
  227. }
  228. /* build the list of DRM supported formats based on the map */
  229. for (n = 0, j = 0; j < map->n_input_formats; j++) {
  230. if ((map->input_formats[j].layer & id) == id)
  231. formats[n++] = map->input_formats[j].format;
  232. }
  233. plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
  234. DRM_PLANE_TYPE_OVERLAY;
  235. ret = drm_universal_plane_init(drm, &plane->base, crtcs,
  236. &malidp_de_plane_funcs, formats,
  237. n, plane_type, NULL);
  238. if (ret < 0)
  239. goto cleanup;
  240. drm_plane_helper_add(&plane->base,
  241. &malidp_de_plane_helper_funcs);
  242. plane->hwdev = malidp->dev;
  243. plane->layer = &map->layers[i];
  244. /* Skip the features which the SMART layer doesn't have */
  245. if (id == DE_SMART)
  246. continue;
  247. drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);
  248. malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
  249. plane->layer->base + MALIDP_LAYER_COMPOSE);
  250. }
  251. kfree(formats);
  252. return 0;
  253. cleanup:
  254. malidp_de_planes_destroy(drm);
  255. kfree(formats);
  256. return ret;
  257. }
  258. void malidp_de_planes_destroy(struct drm_device *drm)
  259. {
  260. struct drm_plane *p, *pt;
  261. list_for_each_entry_safe(p, pt, &drm->mode_config.plane_list, head) {
  262. drm_plane_cleanup(p);
  263. kfree(p);
  264. }
  265. }