drm_fb_dma_helper.c 5.6 KB

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