drm_fb_dma_helper.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * drm kms/fb dma helper functions
  4. *
  5. * Copyright (C) 2012 Analog Devices Inc.
  6. * Author: Lars-Peter Clausen <lars@metafoo.de>
  7. *
  8. * Based on udl_fbdev.c
  9. * Copyright (C) 2012 Red Hat
  10. */
  11. #include <drm/drm_damage_helper.h>
  12. #include <drm/drm_fb_dma_helper.h>
  13. #include <drm/drm_fourcc.h>
  14. #include <drm/drm_framebuffer.h>
  15. #include <drm/drm_gem_dma_helper.h>
  16. #include <drm/drm_gem_framebuffer_helper.h>
  17. #include <drm/drm_panic.h>
  18. #include <drm/drm_plane.h>
  19. #include <linux/dma-mapping.h>
  20. #include <linux/module.h>
  21. /**
  22. * DOC: framebuffer dma helper functions
  23. *
  24. * Provides helper functions for creating a DMA-contiguous framebuffer.
  25. *
  26. * Depending on the platform, the buffers may be physically non-contiguous and
  27. * mapped through an IOMMU or a similar mechanism, or allocated from
  28. * physically-contiguous memory (using, for instance, CMA or a pool of memory
  29. * reserved at early boot). This is handled behind the scenes by the DMA mapping
  30. * API.
  31. *
  32. * drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create
  33. * callback function to create a DMA-contiguous framebuffer.
  34. */
  35. /**
  36. * drm_fb_dma_get_gem_obj() - Get DMA GEM object for framebuffer
  37. * @fb: The framebuffer
  38. * @plane: Which plane
  39. *
  40. * Return the DMA GEM object for given framebuffer.
  41. *
  42. * This function will usually be called from the CRTC callback functions.
  43. */
  44. struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
  45. unsigned int plane)
  46. {
  47. struct drm_gem_object *gem;
  48. gem = drm_gem_fb_get_obj(fb, plane);
  49. if (!gem)
  50. return NULL;
  51. return to_drm_gem_dma_obj(gem);
  52. }
  53. EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj);
  54. /**
  55. * drm_fb_dma_get_gem_addr() - Get DMA (bus) address for framebuffer, for pixel
  56. * formats where values are grouped in blocks this will get you the beginning of
  57. * the block
  58. * @fb: The framebuffer
  59. * @state: Which state of drm plane
  60. * @plane: Which plane
  61. * Return the DMA GEM address for given framebuffer.
  62. *
  63. * This function will usually be called from the PLANE callback functions.
  64. */
  65. dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
  66. struct drm_plane_state *state,
  67. unsigned int plane)
  68. {
  69. struct drm_gem_dma_object *obj;
  70. dma_addr_t dma_addr;
  71. u8 h_div = 1, v_div = 1;
  72. u32 block_w = drm_format_info_block_width(fb->format, plane);
  73. u32 block_h = drm_format_info_block_height(fb->format, plane);
  74. u32 block_size = fb->format->char_per_block[plane];
  75. u32 sample_x;
  76. u32 sample_y;
  77. u32 block_start_y;
  78. u32 num_hblocks;
  79. obj = drm_fb_dma_get_gem_obj(fb, plane);
  80. if (!obj)
  81. return 0;
  82. dma_addr = obj->dma_addr + fb->offsets[plane];
  83. if (plane > 0) {
  84. h_div = fb->format->hsub;
  85. v_div = fb->format->vsub;
  86. }
  87. sample_x = (state->src_x >> 16) / h_div;
  88. sample_y = (state->src_y >> 16) / v_div;
  89. block_start_y = (sample_y / block_h) * block_h;
  90. num_hblocks = sample_x / block_w;
  91. dma_addr += fb->pitches[plane] * block_start_y;
  92. dma_addr += block_size * num_hblocks;
  93. return dma_addr;
  94. }
  95. EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr);
  96. /**
  97. * drm_fb_dma_sync_non_coherent - Sync GEM object to non-coherent backing
  98. * memory
  99. * @drm: DRM device
  100. * @old_state: Old plane state
  101. * @state: New plane state
  102. *
  103. * This function can be used by drivers that use damage clips and have
  104. * DMA GEM objects backed by non-coherent memory. Calling this function
  105. * in a plane's .atomic_update ensures that all the data in the backing
  106. * memory have been written to RAM.
  107. */
  108. void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
  109. struct drm_plane_state *old_state,
  110. struct drm_plane_state *state)
  111. {
  112. const struct drm_format_info *finfo = state->fb->format;
  113. struct drm_atomic_helper_damage_iter iter;
  114. const struct drm_gem_dma_object *dma_obj;
  115. unsigned int offset, i;
  116. struct drm_rect clip;
  117. dma_addr_t daddr;
  118. size_t nb_bytes;
  119. for (i = 0; i < finfo->num_planes; i++) {
  120. dma_obj = drm_fb_dma_get_gem_obj(state->fb, i);
  121. if (!dma_obj->map_noncoherent)
  122. continue;
  123. daddr = drm_fb_dma_get_gem_addr(state->fb, state, i);
  124. drm_atomic_helper_damage_iter_init(&iter, old_state, state);
  125. drm_atomic_for_each_plane_damage(&iter, &clip) {
  126. /* Ignore x1/x2 values, invalidate complete lines */
  127. offset = clip.y1 * state->fb->pitches[i];
  128. nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i];
  129. dma_sync_single_for_device(drm->dev, daddr + offset,
  130. nb_bytes, DMA_TO_DEVICE);
  131. }
  132. }
  133. }
  134. EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
  135. /**
  136. * drm_fb_dma_get_scanout_buffer - Provide a scanout buffer in case of panic
  137. * @plane: DRM primary plane
  138. * @sb: scanout buffer for the panic handler
  139. * Returns: 0 or negative error code
  140. *
  141. * Generic get_scanout_buffer() implementation, for drivers that uses the
  142. * drm_fb_dma_helper. It won't call vmap in the panic context, so the driver
  143. * should make sure the primary plane is vmapped, otherwise the panic screen
  144. * won't get displayed.
  145. */
  146. int drm_fb_dma_get_scanout_buffer(struct drm_plane *plane,
  147. struct drm_scanout_buffer *sb)
  148. {
  149. struct drm_gem_dma_object *dma_obj;
  150. struct drm_framebuffer *fb;
  151. if (!plane->state || !plane->state->fb)
  152. return -EINVAL;
  153. fb = plane->state->fb;
  154. /* Only support linear modifier */
  155. if (fb->modifier != DRM_FORMAT_MOD_LINEAR)
  156. return -ENODEV;
  157. dma_obj = drm_fb_dma_get_gem_obj(fb, 0);
  158. /* Buffer should be accessible from the CPU */
  159. if (dma_obj->base.import_attach)
  160. return -ENODEV;
  161. /* Buffer should be already mapped to CPU */
  162. if (!dma_obj->vaddr)
  163. return -ENODEV;
  164. iosys_map_set_vaddr(&sb->map[0], dma_obj->vaddr);
  165. sb->format = fb->format;
  166. sb->height = fb->height;
  167. sb->width = fb->width;
  168. sb->pitch[0] = fb->pitches[0];
  169. return 0;
  170. }
  171. EXPORT_SYMBOL(drm_fb_dma_get_scanout_buffer);