summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVladislav Andresov <v.andresov@partner.samsung.com>2017-08-16 14:55:24 +0300
committerVasiliy Ulyanov <v.ulyanov@samsung.com>2017-08-25 14:23:55 +0300
commit7ef8aca66cdbcae9cd4f054d8c7ce3b828efe10c (patch)
treeda97ad913ffdc5bb01e9c10fa6d1a7e8f85da382
parent965e8ac50507da97f248da6327dc10b50def80dd (diff)
downloademulator-kernel-7ef8aca66cdbcae9cd4f054d8c7ce3b828efe10c.tar.gz
emulator-kernel-7ef8aca66cdbcae9cd4f054d8c7ce3b828efe10c.tar.bz2
emulator-kernel-7ef8aca66cdbcae9cd4f054d8c7ce3b828efe10c.zip
VIGS: Add DRM_IOCTL_SURFACE_CONVERT
This ioctl adds support of hardware surface convertion. Only y-invert operation has been implemented so far. Change-Id: Icf06dc84fd995eaa43c7990778d67e558c2c0274 Signed-off-by: Vladislav Andresov <v.andresov@partner.samsung.com> Signed-off-by: Vasiliy Ulyanov <v.ulyanov@samsung.com>
-rw-r--r--drivers/gpu/drm/vigs/vigs_driver.c2
-rw-r--r--drivers/gpu/drm/vigs/vigs_execbuffer.c39
-rw-r--r--drivers/gpu/drm/vigs/vigs_protocol.h25
-rw-r--r--drivers/gpu/drm/vigs/vigs_surface.c140
-rw-r--r--drivers/gpu/drm/vigs/vigs_surface.h4
-rw-r--r--include/drm/vigs_drm.h13
6 files changed, 222 insertions, 1 deletions
diff --git a/drivers/gpu/drm/vigs/vigs_driver.c b/drivers/gpu/drm/vigs/vigs_driver.c
index 24a8fc6bd8a6..f0211cc487a8 100644
--- a/drivers/gpu/drm/vigs/vigs_driver.c
+++ b/drivers/gpu/drm/vigs/vigs_driver.c
@@ -60,6 +60,8 @@ static struct drm_ioctl_desc vigs_drm_ioctls[] =
DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIGS_SURFACE_END_ACCESS, vigs_surface_end_access_ioctl,
DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
+ DRM_IOCTL_DEF_DRV(VIGS_SURFACE_CONVERT, vigs_surface_convert_ioctl,
+ DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIGS_CREATE_FENCE, vigs_fence_create_ioctl,
DRM_UNLOCKED | DRM_AUTH | DRM_RENDER_ALLOW),
DRM_IOCTL_DEF_DRV(VIGS_FENCE_WAIT, vigs_fence_wait_ioctl,
diff --git a/drivers/gpu/drm/vigs/vigs_execbuffer.c b/drivers/gpu/drm/vigs/vigs_execbuffer.c
index e619950387b8..d9c4c070f4f7 100644
--- a/drivers/gpu/drm/vigs/vigs_execbuffer.c
+++ b/drivers/gpu/drm/vigs/vigs_execbuffer.c
@@ -14,6 +14,7 @@ union vigs_request
struct vigsp_cmd_copy_request *copy;
struct vigsp_cmd_solid_fill_request *solid_fill;
struct vigsp_cmd_ga_copy_request *ga_copy;
+ struct vigsp_cmd_convert_request *convert;
void *data;
};
@@ -152,6 +153,9 @@ int vigs_execbuffer_validate_buffers(struct vigs_execbuffer *execbuffer,
case vigsp_cmd_ga_copy:
*num_buffers += 2;
break;
+ case vigsp_cmd_convert:
+ *num_buffers += 2;
+ break;
default:
break;
}
@@ -288,6 +292,36 @@ int vigs_execbuffer_validate_buffers(struct vigs_execbuffer *execbuffer,
++*num_buffers;
break;
+ case vigsp_cmd_convert:
+ ret = vigs_execbuffer_validate_buffer(vigs_dev,
+ &(*buffers)[*num_buffers],
+ list,
+ request.convert->src_id,
+ request_header->cmd,
+ 0,
+ request.data);
+
+ if (ret != 0) {
+ goto fail2;
+ }
+
+ ++*num_buffers;
+
+ ret = vigs_execbuffer_validate_buffer(vigs_dev,
+ &(*buffers)[*num_buffers],
+ list,
+ request.convert->dst_id,
+ request_header->cmd,
+ 1,
+ request.data);
+
+ if (ret != 0) {
+ goto fail2;
+ }
+
+ ++*num_buffers;
+
+ break;
default:
break;
}
@@ -385,6 +419,11 @@ void vigs_execbuffer_process_buffers(struct vigs_execbuffer *execbuffer,
}
}
break;
+ case vigsp_cmd_convert:
+ if (buffers[i].which && vigs_gem_in_vram(&sfc->gem)) {
+ sfc->is_gpu_dirty = true;
+ }
+ break;
default:
break;
}
diff --git a/drivers/gpu/drm/vigs/vigs_protocol.h b/drivers/gpu/drm/vigs/vigs_protocol.h
index 1115c9ae6694..c69d4c0f4327 100644
--- a/drivers/gpu/drm/vigs/vigs_protocol.h
+++ b/drivers/gpu/drm/vigs/vigs_protocol.h
@@ -52,7 +52,8 @@ typedef enum
vigsp_cmd_copy = 0x8,
vigsp_cmd_solid_fill = 0x9,
vigsp_cmd_set_plane = 0xA,
- vigsp_cmd_ga_copy = 0xB
+ vigsp_cmd_ga_copy = 0xB,
+ vigsp_cmd_convert = 0xC
/*
* @}
*/
@@ -375,6 +376,28 @@ struct vigsp_cmd_ga_copy_request
* @}
*/
+/*
+ * cmd_convert
+ *
+ * Convert surface 'src_id' to
+ * surface 'dst_id'.
+ *
+ * @{
+ */
+
+struct vigsp_cmd_convert_request
+{
+ vigsp_surface_id src_id;
+ vigsp_u32 src_format;
+ vigsp_surface_id dst_id;
+ vigsp_u32 dst_format;
+ vigsp_bool y_invert;
+};
+
+/*
+ * @}
+ */
+
#pragma pack()
#endif
diff --git a/drivers/gpu/drm/vigs/vigs_surface.c b/drivers/gpu/drm/vigs/vigs_surface.c
index b5ec2f4b85af..4eb91d80f3c3 100644
--- a/drivers/gpu/drm/vigs/vigs_surface.c
+++ b/drivers/gpu/drm/vigs/vigs_surface.c
@@ -2,6 +2,8 @@
#include "vigs_device.h"
#include "vigs_comm.h"
#include "vigs_mman.h"
+#include "vigs_execbuffer.h"
+#include "vigs_file.h"
#include <drm/vigs_drm.h>
/*
@@ -470,3 +472,141 @@ int vigs_surface_end_access_ioctl(struct drm_device *drm_dev,
&vigs_surface_end_access,
args);
}
+
+int vigs_surface_convert_ioctl(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv)
+{
+ struct vigs_device *vigs_dev = drm_dev->dev_private;
+ struct vigs_file *vigs_file = file_priv->driver_priv;
+ struct drm_vigs_surface_convert *args = data;
+ struct drm_gem_object *gem;
+ struct vigs_gem_object *vigs_gem;
+ struct vigs_surface *src_sfc = NULL, *dst_sfc = NULL;
+ struct vigsp_cmd_batch_header *batch_header;
+ struct vigsp_cmd_request_header *convert_request_header;
+ struct vigsp_cmd_convert_request *convert_request;
+ int ret;
+
+ /*
+ * Currently we support only y-invert operation. Format conversion still
+ * needs to be implemented.
+ */
+ if (args->src_format != args->dst_format) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* src_sfc */
+ gem = drm_gem_object_lookup(drm_dev, file_priv, args->src_handle);
+
+ if (gem == NULL) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ vigs_gem = gem_to_vigs_gem(gem);
+
+ if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+ drm_gem_object_unreference_unlocked(gem);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ src_sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+ /* dst_sfc */
+ gem = drm_gem_object_lookup(drm_dev, file_priv, args->dst_handle);
+
+ if (gem == NULL) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ vigs_gem = gem_to_vigs_gem(gem);
+
+ if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+ drm_gem_object_unreference_unlocked(gem);
+ ret = -ENOENT;
+ goto out;
+ }
+
+ dst_sfc = vigs_gem_to_vigs_surface(vigs_gem);
+
+ vigs_gem_reserve(&src_sfc->gem);
+
+ if (vigs_gem_in_vram(&src_sfc->gem) &&
+ vigs_surface_need_gpu_update(src_sfc)) {
+ vigs_comm_update_gpu(vigs_dev->comm,
+ src_sfc->id,
+ src_sfc->width,
+ src_sfc->height,
+ vigs_gem_offset(&src_sfc->gem));
+ src_sfc->is_gpu_dirty = false;
+ }
+
+ vigs_gem_unreserve(&src_sfc->gem);
+
+ mutex_lock(&vigs_file->mutex);
+
+ if (vigs_file->execbuffer == NULL) {
+ ret = vigs_execbuffer_create(vigs_dev,
+ 4096,
+ true,
+ &vigs_file->execbuffer);
+
+ if (ret != 0) {
+ DRM_ERROR("unable to create execbuffer\n");
+
+ goto out_unlock;
+ }
+
+ vigs_gem_reserve(&vigs_file->execbuffer->gem);
+
+ ret = vigs_gem_kmap(&vigs_file->execbuffer->gem);
+
+ vigs_gem_unreserve(&vigs_file->execbuffer->gem);
+
+ if (ret != 0) {
+ DRM_ERROR("unable to kmap execbuffer\n");
+
+ drm_gem_object_unreference_unlocked(&vigs_file->execbuffer->gem.base);
+ vigs_file->execbuffer = NULL;
+
+ goto out_unlock;
+ }
+ }
+
+ batch_header = vigs_file->execbuffer->gem.kptr;
+ convert_request_header = (struct vigsp_cmd_request_header *)(batch_header + 1);
+ convert_request = (struct vigsp_cmd_convert_request *)(convert_request_header + 1);
+
+ batch_header->fence_seq = 0;
+ batch_header->size = sizeof(*convert_request_header) +
+ sizeof(*convert_request);
+
+ convert_request_header->cmd = vigsp_cmd_convert;
+ convert_request_header->size = sizeof(*convert_request);
+
+ convert_request->src_id = src_sfc->id;
+ convert_request->src_format = args->src_format;
+ convert_request->dst_id = dst_sfc->id;
+ convert_request->dst_format = args->dst_format;
+ convert_request->y_invert = args->y_invert;
+
+ ret = vigs_comm_exec_checked(vigs_dev->comm, vigs_file->execbuffer);
+
+out_unlock:
+ mutex_unlock(&vigs_file->mutex);
+
+out:
+ if (src_sfc) {
+ drm_gem_object_unreference_unlocked(&src_sfc->gem.base);
+ }
+
+ if (dst_sfc) {
+ drm_gem_object_unreference_unlocked(&dst_sfc->gem.base);
+ }
+
+ return ret;
+}
diff --git a/drivers/gpu/drm/vigs/vigs_surface.h b/drivers/gpu/drm/vigs/vigs_surface.h
index 1d89e3b628c5..bd1707cef80e 100644
--- a/drivers/gpu/drm/vigs/vigs_surface.h
+++ b/drivers/gpu/drm/vigs/vigs_surface.h
@@ -121,6 +121,10 @@ int vigs_surface_end_access_ioctl(struct drm_device *drm_dev,
void *data,
struct drm_file *file_priv);
+int vigs_surface_convert_ioctl(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv);
+
/*
* @}
*/
diff --git a/include/drm/vigs_drm.h b/include/drm/vigs_drm.h
index 9ae82453429b..f418fef7c7cf 100644
--- a/include/drm/vigs_drm.h
+++ b/include/drm/vigs_drm.h
@@ -97,6 +97,15 @@ struct drm_vigs_surface_end_access
int sync;
};
+struct drm_vigs_surface_convert
+{
+ uint32_t src_handle;
+ uint32_t src_format;
+ uint32_t dst_handle;
+ uint32_t dst_format;
+ int y_invert;
+};
+
struct drm_vigs_create_fence
{
int send;
@@ -176,6 +185,8 @@ struct drm_vigs_dp_open_surface
#define DRM_VIGS_DP_CREATE_SURFACE 0x20
#define DRM_VIGS_DP_OPEN_SURFACE 0x21
+#define DRM_VIGS_SURFACE_CONVERT 0x22
+
#define DRM_IOCTL_VIGS_GET_PROTOCOL_VERSION DRM_IOR(DRM_COMMAND_BASE + \
DRM_VIGS_GET_PROTOCOL_VERSION, struct drm_vigs_get_protocol_version)
#define DRM_IOCTL_VIGS_CREATE_SURFACE DRM_IOWR(DRM_COMMAND_BASE + \
@@ -196,6 +207,8 @@ struct drm_vigs_dp_open_surface
DRM_VIGS_SURFACE_START_ACCESS, struct drm_vigs_surface_start_access)
#define DRM_IOCTL_VIGS_SURFACE_END_ACCESS DRM_IOW(DRM_COMMAND_BASE + \
DRM_VIGS_SURFACE_END_ACCESS, struct drm_vigs_surface_end_access)
+#define DRM_IOCTL_VIGS_SURFACE_CONVERT DRM_IOW(DRM_COMMAND_BASE + \
+ DRM_VIGS_SURFACE_CONVERT, struct drm_vigs_surface_convert)
#define DRM_IOCTL_VIGS_CREATE_FENCE DRM_IOWR(DRM_COMMAND_BASE + \
DRM_VIGS_CREATE_FENCE, struct drm_vigs_create_fence)
#define DRM_IOCTL_VIGS_FENCE_WAIT DRM_IOW(DRM_COMMAND_BASE + \