forked from ayufan-rock64/linux-kernel
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This patch implement the necessary functions to compute and add CRCs entries: - Implement the set_crc_source() callback. - Compute CRC using crc32 on the visible part of the framebuffer. - Use ordered workqueue per output to compute and add CRC at the end of a vblank. - Use appropriate synchronization methods since the CRC computation must be atomic wrt the generated vblank event for a given atomic update, by using spinlock across atomic_begin/atomic_flush to wrap the event handling code completely and match the flip event with the CRC. Since vkms_crc_work_handle() can sleep, spinlock can't be acquired while accessing vkms_output->primary_crc to compute CRC. To make sure the data is updated and released without conflict with the vkms_crc_work_handle(), the work_struct is flushed @crtc_destroy and the data is updated before scheduling the work handle again, as follow: * CRC data update: 1- store vkms_crc_data {fb, src} per plane_state 2- @plane_duplicate_state -> allocate vkms_crc_data 3- during atomic commit (@atomic_update) -> a) copy {fb, src} to plane_state->crc_data b) get reference to fb, 3- @plane_destroy_state -> a) if (fb refcount) remove reference to fb b) deallocate crc_data * Atomic Commit: 1- vkms_plane_atomic_check 2- vkms_prepare_fb -> vmap vkms_gem_obj->vaddr 3- atomic_begin -> hold crc spinlock 4- atomic_plane_update -> a) update vkms_output->primary_crc b) get reference to fb 5- atomic_flush -> a) send vblank event while holding event_lock b) release crc spinlock * hrtimer regular callback: 1- hold crc spinlock 2- drm_crtc_handle_vblank() 3- queue vkms_crc_work_handle 4- release crc spinlock * cleanup: 1- @cleanup_fb ->vunmap vkms_gem_obj->vaddr 2- @crtc_destroy -> flush work struct 3- @plane_destroy -> a) if (fb refcount) remove reference to fb b) deallocate crc_data Signed-off-by: Haneen Mohammed <[email protected]> [seanpaul fixed typo in vkms_crtc s/vblamk/vblank/] Signed-off-by: Sean Paul <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/b948327f48c3e70ab232b4a0848ee6d033b26484.1533171495.git.hamohammed.sa@gmail.com
- Loading branch information
1 parent
3e77c4d
commit 6c234fe
Showing
6 changed files
with
196 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o | ||
vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o vkms_crc.o | ||
|
||
obj-$(CONFIG_DRM_VKMS) += vkms.o |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
#include "vkms_drv.h" | ||
#include <linux/crc32.h> | ||
#include <drm/drm_gem_framebuffer_helper.h> | ||
|
||
static uint32_t _vkms_get_crc(struct vkms_crc_data *crc_data) | ||
{ | ||
struct drm_framebuffer *fb = &crc_data->fb; | ||
struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0); | ||
struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj); | ||
u32 crc = 0; | ||
int i = 0; | ||
unsigned int x = crc_data->src.x1 >> 16; | ||
unsigned int y = crc_data->src.y1 >> 16; | ||
unsigned int height = drm_rect_height(&crc_data->src) >> 16; | ||
unsigned int width = drm_rect_width(&crc_data->src) >> 16; | ||
unsigned int cpp = fb->format->cpp[0]; | ||
unsigned int src_offset; | ||
unsigned int size_byte = width * cpp; | ||
void *vaddr; | ||
|
||
mutex_lock(&vkms_obj->pages_lock); | ||
vaddr = vkms_obj->vaddr; | ||
if (WARN_ON(!vaddr)) | ||
return crc; | ||
|
||
for (i = y; i < y + height; i++) { | ||
src_offset = fb->offsets[0] + (i * fb->pitches[0]) + (x * cpp); | ||
crc = crc32_le(crc, vaddr + src_offset, size_byte); | ||
} | ||
mutex_unlock(&vkms_obj->pages_lock); | ||
|
||
return crc; | ||
} | ||
|
||
void vkms_crc_work_handle(struct work_struct *work) | ||
{ | ||
struct vkms_crtc_state *crtc_state = container_of(work, | ||
struct vkms_crtc_state, | ||
crc_work); | ||
struct drm_crtc *crtc = crtc_state->base.crtc; | ||
struct vkms_output *out = drm_crtc_to_vkms_output(crtc); | ||
struct vkms_device *vdev = container_of(out, struct vkms_device, | ||
output); | ||
struct vkms_crc_data *primary_crc = NULL; | ||
struct drm_plane *plane; | ||
|
||
u32 crc32 = 0; | ||
|
||
drm_for_each_plane(plane, &vdev->drm) { | ||
struct vkms_plane_state *vplane_state; | ||
struct vkms_crc_data *crc_data; | ||
|
||
vplane_state = to_vkms_plane_state(plane->state); | ||
crc_data = vplane_state->crc_data; | ||
|
||
if (drm_framebuffer_read_refcount(&crc_data->fb) == 0) | ||
continue; | ||
|
||
if (plane->type == DRM_PLANE_TYPE_PRIMARY) { | ||
primary_crc = crc_data; | ||
break; | ||
} | ||
} | ||
|
||
if (primary_crc) | ||
crc32 = _vkms_get_crc(primary_crc); | ||
|
||
drm_crtc_add_crc_entry(crtc, true, crtc_state->n_frame, &crc32); | ||
} | ||
|
||
int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name, | ||
size_t *values_cnt) | ||
{ | ||
struct vkms_output *out = drm_crtc_to_vkms_output(crtc); | ||
bool enabled = false; | ||
unsigned long flags; | ||
int ret = 0; | ||
|
||
if (src_name && strcmp(src_name, "auto") == 0) | ||
enabled = true; | ||
else if (src_name) | ||
ret = -EINVAL; | ||
|
||
*values_cnt = 1; | ||
|
||
/* make sure nothing is scheduled on crtc workq */ | ||
flush_workqueue(out->crc_workq); | ||
|
||
spin_lock_irqsave(&out->lock, flags); | ||
out->crc_enabled = enabled; | ||
spin_unlock_irqrestore(&out->lock, flags); | ||
|
||
return ret; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters