0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #include <drm/drm_damage_helper.h>
0013 #include <drm/drm_fb_cma_helper.h>
0014 #include <drm/drm_fourcc.h>
0015 #include <drm/drm_framebuffer.h>
0016 #include <drm/drm_gem_cma_helper.h>
0017 #include <drm/drm_gem_framebuffer_helper.h>
0018 #include <drm/drm_plane.h>
0019 #include <linux/dma-mapping.h>
0020 #include <linux/module.h>
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
0042 unsigned int plane)
0043 {
0044 struct drm_gem_object *gem;
0045
0046 gem = drm_gem_fb_get_obj(fb, plane);
0047 if (!gem)
0048 return NULL;
0049
0050 return to_drm_gem_cma_obj(gem);
0051 }
0052 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065 dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
0066 struct drm_plane_state *state,
0067 unsigned int plane)
0068 {
0069 struct drm_gem_cma_object *obj;
0070 dma_addr_t paddr;
0071 u8 h_div = 1, v_div = 1;
0072 u32 block_w = drm_format_info_block_width(fb->format, plane);
0073 u32 block_h = drm_format_info_block_height(fb->format, plane);
0074 u32 block_size = fb->format->char_per_block[plane];
0075 u32 sample_x;
0076 u32 sample_y;
0077 u32 block_start_y;
0078 u32 num_hblocks;
0079
0080 obj = drm_fb_cma_get_gem_obj(fb, plane);
0081 if (!obj)
0082 return 0;
0083
0084 paddr = obj->paddr + fb->offsets[plane];
0085
0086 if (plane > 0) {
0087 h_div = fb->format->hsub;
0088 v_div = fb->format->vsub;
0089 }
0090
0091 sample_x = (state->src_x >> 16) / h_div;
0092 sample_y = (state->src_y >> 16) / v_div;
0093 block_start_y = (sample_y / block_h) * block_h;
0094 num_hblocks = sample_x / block_w;
0095
0096 paddr += fb->pitches[plane] * block_start_y;
0097 paddr += block_size * num_hblocks;
0098
0099 return paddr;
0100 }
0101 EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 void drm_fb_cma_sync_non_coherent(struct drm_device *drm,
0116 struct drm_plane_state *old_state,
0117 struct drm_plane_state *state)
0118 {
0119 const struct drm_format_info *finfo = state->fb->format;
0120 struct drm_atomic_helper_damage_iter iter;
0121 const struct drm_gem_cma_object *cma_obj;
0122 unsigned int offset, i;
0123 struct drm_rect clip;
0124 dma_addr_t daddr;
0125 size_t nb_bytes;
0126
0127 for (i = 0; i < finfo->num_planes; i++) {
0128 cma_obj = drm_fb_cma_get_gem_obj(state->fb, i);
0129 if (!cma_obj->map_noncoherent)
0130 continue;
0131
0132 daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
0133 drm_atomic_helper_damage_iter_init(&iter, old_state, state);
0134
0135 drm_atomic_for_each_plane_damage(&iter, &clip) {
0136
0137 offset = clip.y1 * state->fb->pitches[i];
0138
0139 nb_bytes = (clip.y2 - clip.y1) * state->fb->pitches[i];
0140 dma_sync_single_for_device(drm->dev, daddr + offset,
0141 nb_bytes, DMA_TO_DEVICE);
0142 }
0143 }
0144 }
0145 EXPORT_SYMBOL_GPL(drm_fb_cma_sync_non_coherent);