1 // SPDX-License-Identifier: GPL-2.0
3 #include <linux/crc32.h>
4 #include <drm/drm_gem_framebuffer_helper.h>
6 static uint32_t _vkms_get_crc(struct vkms_crc_data *crc_data)
8 struct drm_framebuffer *fb = &crc_data->fb;
9 struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
10 struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
13 unsigned int x = crc_data->src.x1 >> 16;
14 unsigned int y = crc_data->src.y1 >> 16;
15 unsigned int height = drm_rect_height(&crc_data->src) >> 16;
16 unsigned int width = drm_rect_width(&crc_data->src) >> 16;
17 unsigned int cpp = fb->format->cpp[0];
18 unsigned int src_offset;
19 unsigned int size_byte = width * cpp;
22 mutex_lock(&vkms_obj->pages_lock);
23 vaddr = vkms_obj->vaddr;
27 for (i = y; i < y + height; i++) {
28 src_offset = fb->offsets[0] + (i * fb->pitches[0]) + (x * cpp);
29 crc = crc32_le(crc, vaddr + src_offset, size_byte);
31 mutex_unlock(&vkms_obj->pages_lock);
36 void vkms_crc_work_handle(struct work_struct *work)
38 struct vkms_crtc_state *crtc_state = container_of(work,
39 struct vkms_crtc_state,
41 struct drm_crtc *crtc = crtc_state->base.crtc;
42 struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
43 struct vkms_device *vdev = container_of(out, struct vkms_device,
45 struct vkms_crc_data *primary_crc = NULL;
46 struct drm_plane *plane;
50 drm_for_each_plane(plane, &vdev->drm) {
51 struct vkms_plane_state *vplane_state;
52 struct vkms_crc_data *crc_data;
54 vplane_state = to_vkms_plane_state(plane->state);
55 crc_data = vplane_state->crc_data;
57 if (drm_framebuffer_read_refcount(&crc_data->fb) == 0)
60 if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
61 primary_crc = crc_data;
67 crc32 = _vkms_get_crc(primary_crc);
69 drm_crtc_add_crc_entry(crtc, true, crtc_state->n_frame, &crc32);
72 int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name,
75 struct vkms_output *out = drm_crtc_to_vkms_output(crtc);
80 if (src_name && strcmp(src_name, "auto") == 0)
87 /* make sure nothing is scheduled on crtc workq */
88 flush_workqueue(out->crc_workq);
90 spin_lock_irqsave(&out->lock, flags);
91 out->crc_enabled = enabled;
92 spin_unlock_irqrestore(&out->lock, flags);