vigs_fence.o \
vigs_fenceman.o \
vigs_file.o \
- vigs_plane.o
+ vigs_plane.o \
+ vigs_dp.o
obj-$(CONFIG_DRM_VIGS) += vigs_drm.o
int vigs_comm_set_plane(struct vigs_comm *comm,
u32 plane,
- vigsp_surface_id sfc_id,
+ u32 width,
+ u32 height,
+ vigsp_plane_format format,
+ vigsp_surface_id surfaces[4],
unsigned int src_x,
unsigned int src_y,
unsigned int src_w,
int ret;
struct vigsp_cmd_set_plane_request *request;
- DRM_DEBUG_DRIVER("plane = %u, sfc_id = %u, src_x = %u, src_y = %u, src_w = %u, src_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, z_pos = %d\n",
- plane, sfc_id, src_x, src_y, src_w, src_h,
+ DRM_DEBUG_DRIVER("plane = %u, src_x = %u, src_y = %u, src_w = %u, src_h = %u, dst_x = %d, dst_y = %d, dst_w = %u, dst_h = %u, z_pos = %d\n",
+ plane, src_x, src_y, src_w, src_h,
dst_x, dst_y, dst_w, dst_h, z_pos);
mutex_lock(&comm->mutex);
if (ret == 0) {
request->plane = plane;
- request->sfc_id = sfc_id;
+ request->width = width;
+ request->height = height;
+ request->format = format;
+ memcpy(request->surfaces, surfaces, sizeof(request->surfaces));
request->src_rect.pos.x = src_x;
request->src_rect.pos.y = src_y;
request->src_rect.size.w = src_w;
int vigs_comm_set_plane(struct vigs_comm *comm,
u32 plane,
- vigsp_surface_id sfc_id,
+ u32 width,
+ u32 height,
+ vigsp_plane_format format,
+ vigsp_surface_id surfaces[4],
unsigned int src_x,
unsigned int src_y,
unsigned int src_w,
vigs_fb = fb_to_vigs_fb(crtc->fb);
- if (vigs_fb->fb_sfc->scanout) {
+ if (vigs_fb->surfaces[0]->scanout) {
retry:
ret = vigs_framebuffer_pin(vigs_fb);
goto retry;
}
- vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
+ vigs_gem_reserve(&vigs_fb->surfaces[0]->gem);
ret = vigs_comm_set_root_surface(vigs_dev->comm,
- vigs_fb->fb_sfc->id,
+ vigs_fb->surfaces[0]->id,
1,
- vigs_gem_offset(&vigs_fb->fb_sfc->gem));
+ vigs_gem_offset(&vigs_fb->surfaces[0]->gem));
- vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
+ vigs_gem_unreserve(&vigs_fb->surfaces[0]->gem);
if (ret != 0) {
vigs_framebuffer_unpin(vigs_fb);
}
} else {
ret = vigs_comm_set_root_surface(vigs_dev->comm,
- vigs_fb->fb_sfc->id,
+ vigs_fb->surfaces[0]->id,
0,
0);
}
}
- if (vigs_old_fb && vigs_old_fb->fb_sfc->scanout) {
+ if (vigs_old_fb && vigs_old_fb->surfaces[0]->scanout) {
vigs_framebuffer_unpin(vigs_old_fb);
}
vigs_comm_set_root_surface(vigs_dev->comm, 0, 0, 0);
- if (vigs_fb->fb_sfc->scanout) {
+ if (vigs_fb->surfaces[0]->scanout) {
vigs_framebuffer_unpin(vigs_fb);
}
}
#include "vigs_fbdev.h"
#include "vigs_execbuffer.h"
#include "vigs_surface.h"
+#include "vigs_dp.h"
#include <drm/vigs_drm.h>
static void vigs_device_mman_vram_to_gpu(void *user_data,
goto fail4;
}
- ret = vigs_comm_create(vigs_dev, &vigs_dev->comm);
+ ret = vigs_dp_create(vigs_dev, &vigs_dev->dp);
if (ret != 0) {
goto fail5;
}
+ ret = vigs_comm_create(vigs_dev, &vigs_dev->comm);
+
+ if (ret != 0) {
+ goto fail6;
+ }
+
spin_lock_init(&vigs_dev->irq_lock);
drm_mode_config_init(vigs_dev->drm_dev);
ret = vigs_crtc_init(vigs_dev);
if (ret != 0) {
- goto fail6;
+ goto fail7;
}
ret = vigs_output_init(vigs_dev);
if (ret != 0) {
- goto fail6;
+ goto fail7;
}
for (i = 0; i < VIGS_MAX_PLANES; ++i) {
ret = vigs_plane_init(vigs_dev, i);
if (ret != 0) {
- goto fail6;
+ goto fail7;
}
}
ret = drm_vblank_init(drm_dev, 1);
if (ret != 0) {
- goto fail6;
+ goto fail7;
}
/*
ret = drm_irq_install(drm_dev);
if (ret != 0) {
- goto fail7;
+ goto fail8;
}
ret = vigs_fbdev_create(vigs_dev, &vigs_dev->fbdev);
if (ret != 0) {
- goto fail8;
+ goto fail9;
}
return 0;
-fail8:
+fail9:
drm_irq_uninstall(drm_dev);
-fail7:
+fail8:
drm_vblank_cleanup(drm_dev);
-fail6:
+fail7:
drm_mode_config_cleanup(vigs_dev->drm_dev);
vigs_comm_destroy(vigs_dev->comm);
+fail6:
+ vigs_dp_destroy(vigs_dev->dp);
fail5:
vigs_fenceman_destroy(vigs_dev->fenceman);
fail4:
drm_vblank_cleanup(vigs_dev->drm_dev);
drm_mode_config_cleanup(vigs_dev->drm_dev);
vigs_comm_destroy(vigs_dev->comm);
+ vigs_dp_destroy(vigs_dev->dp);
vigs_fenceman_destroy(vigs_dev->fenceman);
ttm_object_device_release(&vigs_dev->obj_dev);
vigs_mman_destroy(vigs_dev->mman);
struct vigs_mman;
struct vigs_fenceman;
+struct vigs_dp;
struct vigs_comm;
struct vigs_fbdev;
struct vigs_surface;
struct vigs_fenceman *fenceman;
+ struct vigs_dp *dp;
+
struct vigs_comm *comm;
struct vigs_fbdev *fbdev;
--- /dev/null
+#include "vigs_dp.h"
+#include "vigs_surface.h"
+#include "vigs_device.h"
+
+int vigs_dp_create(struct vigs_device *vigs_dev,
+ struct vigs_dp **dp)
+{
+ int ret = 0;
+
+ DRM_DEBUG_DRIVER("enter\n");
+
+ *dp = kzalloc(sizeof(**dp), GFP_KERNEL);
+
+ if (!*dp) {
+ ret = -ENOMEM;
+ goto fail1;
+ }
+
+ return 0;
+
+fail1:
+ *dp = NULL;
+
+ return ret;
+}
+
+void vigs_dp_destroy(struct vigs_dp *dp)
+{
+ DRM_DEBUG_DRIVER("enter\n");
+
+ kfree(dp);
+}
+
+void vigs_dp_remove_surface(struct vigs_dp *dp, struct vigs_surface *sfc)
+{
+ int i, j;
+
+ for (i = 0; i < VIGS_MAX_PLANES; ++i) {
+ for (j = 0; j < DRM_VIGS_NUM_DP_FB_BUF; ++j) {
+ if (dp->planes[i].fb_bufs[j].y == sfc) {
+ dp->planes[i].fb_bufs[j].y = NULL;
+ }
+ if (dp->planes[i].fb_bufs[j].c == sfc) {
+ dp->planes[i].fb_bufs[j].c = NULL;
+ }
+ }
+ }
+}
+
+int vigs_dp_surface_create_ioctl(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv)
+{
+ struct vigs_device *vigs_dev = drm_dev->dev_private;
+ struct vigs_dp *dp = vigs_dev->dp;
+ struct drm_vigs_dp_create_surface *args = data;
+ struct vigs_surface *sfc = NULL;
+ bool busy;
+ uint32_t handle;
+ int ret;
+
+ if (args->dp_plane >= VIGS_MAX_PLANES) {
+ DRM_ERROR("bad DP plane = %u\n", args->dp_plane);
+ return -ENOMEM;
+ }
+
+ if (args->dp_fb_buf >= DRM_VIGS_NUM_DP_FB_BUF) {
+ DRM_ERROR("bad DP fb buf = %u\n", args->dp_fb_buf);
+ return -ENOMEM;
+ }
+
+ mutex_lock(&vigs_dev->drm_dev->struct_mutex);
+
+ switch (args->dp_mem_flag) {
+ case DRM_VIGS_DP_FB_Y:
+ busy = dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].y != NULL;
+ break;
+ case DRM_VIGS_DP_FB_C:
+ busy = dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].c != NULL;
+ break;
+ default:
+ mutex_unlock(&vigs_dev->drm_dev->struct_mutex);
+ DRM_ERROR("bad DP mem flag = %u\n", args->dp_mem_flag);
+ return -ENOMEM;
+ }
+
+ mutex_unlock(&vigs_dev->drm_dev->struct_mutex);
+
+ if (busy) {
+ DRM_INFO("DP mem %u:%u:%u is busy\n", args->dp_plane,
+ args->dp_fb_buf,
+ args->dp_mem_flag);
+ return -ENOMEM;
+ }
+
+ ret = vigs_surface_create(vigs_dev,
+ args->width,
+ args->height,
+ args->stride,
+ args->format,
+ false,
+ &sfc);
+
+ if (ret != 0) {
+ return ret;
+ }
+
+ /*
+ * Check busy again since DP mem might
+ * gotten busy while we were creating our surface.
+ * If it's not busy then occupy it.
+ */
+
+ mutex_lock(&vigs_dev->drm_dev->struct_mutex);
+
+ switch (args->dp_mem_flag) {
+ case DRM_VIGS_DP_FB_Y:
+ if (dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].y) {
+ busy = true;
+ } else {
+ dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].y = sfc;
+ }
+ break;
+ case DRM_VIGS_DP_FB_C:
+ if (dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].c) {
+ busy = true;
+ } else {
+ dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].c = sfc;
+ }
+ break;
+ default:
+ drm_gem_object_unreference(&sfc->gem.base);
+ mutex_unlock(&vigs_dev->drm_dev->struct_mutex);
+ BUG();
+ return -ENOMEM;
+ }
+
+ mutex_unlock(&vigs_dev->drm_dev->struct_mutex);
+
+ if (busy) {
+ drm_gem_object_unreference_unlocked(&sfc->gem.base);
+
+ DRM_INFO("DP mem %u:%u:%u is busy\n", args->dp_plane,
+ args->dp_fb_buf,
+ args->dp_mem_flag);
+ return -ENOMEM;
+ }
+
+ ret = drm_gem_handle_create(file_priv,
+ &sfc->gem.base,
+ &handle);
+
+ if (ret == 0) {
+ args->handle = handle;
+ args->size = vigs_gem_size(&sfc->gem);
+ args->id = sfc->id;
+ } else {
+ /*
+ * Don't bother setting DP mem slot to NULL here, DRM
+ * will do this for us once the GEM is freed.
+ */
+ }
+
+ drm_gem_object_unreference_unlocked(&sfc->gem.base);
+
+ return ret;
+}
+
+int vigs_dp_surface_open_ioctl(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv)
+{
+ struct vigs_device *vigs_dev = drm_dev->dev_private;
+ struct vigs_dp *dp = vigs_dev->dp;
+ struct drm_vigs_dp_open_surface *args = data;
+ struct vigs_surface *sfc = NULL;
+ uint32_t handle;
+ int ret;
+
+ if (args->dp_plane >= VIGS_MAX_PLANES) {
+ DRM_ERROR("bad DP plane = %u\n", args->dp_plane);
+ return -ENOMEM;
+ }
+
+ if (args->dp_fb_buf >= DRM_VIGS_NUM_DP_FB_BUF) {
+ DRM_ERROR("bad DP fb buf = %u\n", args->dp_fb_buf);
+ return -ENOMEM;
+ }
+
+ mutex_lock(&vigs_dev->drm_dev->struct_mutex);
+
+ switch (args->dp_mem_flag) {
+ case DRM_VIGS_DP_FB_Y:
+ sfc = dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].y;
+ break;
+ case DRM_VIGS_DP_FB_C:
+ sfc = dp->planes[args->dp_plane].fb_bufs[args->dp_fb_buf].c;
+ break;
+ default:
+ mutex_unlock(&vigs_dev->drm_dev->struct_mutex);
+ DRM_ERROR("bad DP mem flag = %u\n", args->dp_mem_flag);
+ return -ENOMEM;
+ }
+
+ if (sfc) {
+ drm_gem_object_reference(&sfc->gem.base);
+ } else {
+ mutex_unlock(&vigs_dev->drm_dev->struct_mutex);
+ DRM_INFO("DP mem %u:%u:%u is empty\n", args->dp_plane,
+ args->dp_fb_buf,
+ args->dp_mem_flag);
+ return -ENOMEM;
+ }
+
+ mutex_unlock(&vigs_dev->drm_dev->struct_mutex);
+
+ ret = drm_gem_handle_create(file_priv,
+ &sfc->gem.base,
+ &handle);
+
+ if (ret == 0) {
+ args->handle = handle;
+ }
+
+ drm_gem_object_unreference_unlocked(&sfc->gem.base);
+
+ return ret;
+}
--- /dev/null
+#ifndef _VIGS_DP_H_
+#define _VIGS_DP_H_
+
+#include "drmP.h"
+#include "vigs_protocol.h"
+#include <drm/vigs_drm.h>
+
+struct vigs_device;
+struct vigs_surface;
+
+struct vigs_dp_fb_buf
+{
+ /*
+ * These are weak pointers, no reference is kept
+ * for them. When surface is destroyed they're
+ * automatically reset to NULL. Must be
+ * accessed only with drm_device::struct_mutex held.
+ * @{
+ */
+
+ struct vigs_surface *y;
+ struct vigs_surface *c;
+
+ /*
+ * @}
+ */
+};
+
+struct vigs_dp_plane
+{
+ struct vigs_dp_fb_buf fb_bufs[DRM_VIGS_NUM_DP_FB_BUF];
+};
+
+struct vigs_dp
+{
+ struct vigs_dp_plane planes[VIGS_MAX_PLANES];
+};
+
+int vigs_dp_create(struct vigs_device *vigs_dev,
+ struct vigs_dp **dp);
+
+void vigs_dp_destroy(struct vigs_dp *dp);
+
+/*
+ * Must be called with drm_device::struct_mutex held.
+ * @{
+ */
+
+void vigs_dp_remove_surface(struct vigs_dp *dp, struct vigs_surface *sfc);
+
+/*
+ * @}
+ */
+
+/*
+ * IOCTLs
+ * @{
+ */
+
+int vigs_dp_surface_create_ioctl(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv);
+
+int vigs_dp_surface_open_ioctl(struct drm_device *drm_dev,
+ void *data,
+ struct drm_file *file_priv);
+
+/*
+ * @}
+ */
+
+#endif
#include "vigs_file.h"
#include "vigs_plane.h"
#include "vigs_mman.h"
+#include "vigs_dp.h"
#include <drm/drmP.h>
#include <linux/module.h>
#include <drm/vigs_drm.h>
DRM_IOCTL_DEF_DRV(VIGS_FENCE_UNREF, vigs_fence_unref_ioctl,
DRM_UNLOCKED | DRM_AUTH),
DRM_IOCTL_DEF_DRV(VIGS_PLANE_SET_ZPOS, vigs_plane_set_zpos_ioctl,
- DRM_UNLOCKED | DRM_AUTH)
+ DRM_UNLOCKED | DRM_AUTH),
+
+ DRM_IOCTL_DEF_DRV(VIGS_DP_CREATE_SURFACE, vigs_dp_surface_create_ioctl,
+ DRM_UNLOCKED | DRM_AUTH),
+ DRM_IOCTL_DEF_DRV(VIGS_DP_OPEN_SURFACE, vigs_dp_surface_open_ioctl,
+ DRM_UNLOCKED | DRM_AUTH)
};
static const struct file_operations vigs_drm_driver_fops =
struct vigsp_cmd_update_gpu_request *update_gpu;
struct vigsp_cmd_copy_request *copy;
struct vigsp_cmd_solid_fill_request *solid_fill;
+ struct vigsp_cmd_ga_copy_request *ga_copy;
void *data;
};
case vigsp_cmd_solid_fill:
*num_buffers += 1;
break;
+ case vigsp_cmd_ga_copy:
+ *num_buffers += 2;
+ break;
default:
break;
}
++*num_buffers;
+ break;
+ case vigsp_cmd_ga_copy:
+ ret = vigs_execbuffer_validate_buffer(vigs_dev,
+ &(*buffers)[*num_buffers],
+ list,
+ request.ga_copy->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.ga_copy->dst_id,
+ request_header->cmd,
+ 1,
+ request.data);
+
+ if (ret != 0) {
+ goto fail2;
+ }
+
+ ++*num_buffers;
+
break;
default:
break;
void vigs_execbuffer_process_buffers(struct vigs_execbuffer *execbuffer,
struct vigs_validate_buffer *buffers,
- int num_buffers)
+ int num_buffers,
+ bool *sync)
{
union vigs_request request;
struct vigs_gem_object *gem;
sfc->is_gpu_dirty = true;
}
break;
+ case vigsp_cmd_ga_copy:
+ if (buffers[i].which && vigs_gem_in_vram(&sfc->gem)) {
+ sfc->is_gpu_dirty = true;
+ } else if (buffers[i].which == 0) {
+ if (vigs_gem_in_vram(&sfc->gem)) {
+ request.ga_copy->src_scanout = true;
+ request.ga_copy->src_offset = vigs_gem_offset(&sfc->gem);
+ *sync = true;
+ } else {
+ request.ga_copy->src_scanout = false;
+ request.ga_copy->src_offset = 0;
+ }
+ }
+ break;
default:
break;
}
goto out3;
}
- vigs_execbuffer_process_buffers(execbuffer, buffers, num_buffers);
+ vigs_execbuffer_process_buffers(execbuffer, buffers, num_buffers, &sync);
vigs_execbuffer_fence(execbuffer, fence);
void vigs_execbuffer_process_buffers(struct vigs_execbuffer *execbuffer,
struct vigs_validate_buffer *buffers,
- int num_buffers);
+ int num_buffers,
+ bool *sync);
void vigs_execbuffer_fence(struct vigs_execbuffer *execbuffer,
struct vigs_fence *fence);
#include "drm_crtc_helper.h"
#include <drm/vigs_drm.h>
-static struct drm_framebuffer *vigs_fb_create(struct drm_device *drm_dev,
- struct drm_file *file_priv,
- struct drm_mode_fb_cmd2 *mode_cmd)
-{
- struct vigs_device *vigs_dev = drm_dev->dev_private;
- struct drm_gem_object *gem;
- struct vigs_gem_object *vigs_gem;
- struct vigs_surface *vigs_sfc;
- struct vigs_framebuffer *vigs_fb;
- int ret;
-
- DRM_DEBUG_KMS("enter\n");
-
- gem = drm_gem_object_lookup(drm_dev, file_priv, mode_cmd->handles[0]);
-
- if (!gem) {
- DRM_ERROR("GEM lookup failed, handle = %u\n", mode_cmd->handles[0]);
- return ERR_PTR(-ENOENT);
- }
-
- vigs_gem = gem_to_vigs_gem(gem);
-
- if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
- DRM_ERROR("GEM is not a surface, handle = %u\n", mode_cmd->handles[0]);
- drm_gem_object_unreference_unlocked(gem);
- return ERR_PTR(-ENOENT);
- }
-
- vigs_sfc = vigs_gem_to_vigs_surface(vigs_gem);
-
- ret = vigs_framebuffer_create(vigs_dev,
- mode_cmd,
- vigs_sfc,
- &vigs_fb);
-
- drm_gem_object_unreference_unlocked(gem);
-
- if (ret != 0) {
- DRM_ERROR("unable to create the framebuffer: %d\n", ret);
- return ERR_PTR(ret);
- }
-
- return &vigs_fb->base;
-}
-
-static void vigs_output_poll_changed(struct drm_device *drm_dev)
-{
- struct vigs_device *vigs_dev = drm_dev->dev_private;
-
- DRM_DEBUG_KMS("enter\n");
-
- if (vigs_dev->fbdev) {
- vigs_fbdev_output_poll_changed(vigs_dev->fbdev);
- }
-}
-
static void vigs_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct vigs_framebuffer *vigs_fb = fb_to_vigs_fb(fb);
+ int i;
DRM_DEBUG_KMS("enter\n");
drm_framebuffer_cleanup(fb);
/*
- * And we can finally free the GEM.
+ * And we can finally free the GEMs.
*/
- drm_gem_object_unreference_unlocked(&vigs_fb->fb_sfc->gem.base);
+ for (i = 0; i < 4; ++i) {
+ if (vigs_fb->surfaces[i]) {
+ drm_gem_object_unreference_unlocked(&vigs_fb->surfaces[i]->gem.base);
+ }
+ }
kfree(vigs_fb);
}
+static int vigs_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+ struct vigs_framebuffer *vigs_fb = fb_to_vigs_fb(fb);
+
+ DRM_DEBUG_KMS("enter\n");
+
+ return drm_gem_handle_create(file_priv, &vigs_fb->surfaces[0]->gem.base, handle);
+}
+
static int vigs_framebuffer_dirty(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned flags, unsigned color,
return 0;
}
-static int vigs_framebuffer_create_handle(struct drm_framebuffer *fb,
- struct drm_file *file_priv,
- unsigned int *handle)
+static struct drm_framebuffer_funcs vigs_framebuffer_funcs =
{
- struct vigs_framebuffer *vigs_fb = fb_to_vigs_fb(fb);
+ .destroy = vigs_framebuffer_destroy,
+ .create_handle = vigs_framebuffer_create_handle,
+ .dirty = vigs_framebuffer_dirty,
+};
+
+static struct drm_framebuffer *vigs_fb_create(struct drm_device *drm_dev,
+ struct drm_file *file_priv,
+ struct drm_mode_fb_cmd2 *mode_cmd)
+{
+ struct vigs_device *vigs_dev = drm_dev->dev_private;
+ struct vigs_surface *surfaces[4];
+ int ret, i;
+ int num_planes = drm_format_num_planes(mode_cmd->pixel_format);
+ struct vigs_framebuffer *vigs_fb;
+
+ DRM_DEBUG_KMS("enter\n");
+
+ for (i = 0; i < num_planes; ++i) {
+ struct drm_gem_object *gem;
+ struct vigs_gem_object *vigs_gem;
+
+ gem = drm_gem_object_lookup(drm_dev, file_priv, mode_cmd->handles[i]);
+
+ if (!gem) {
+ DRM_ERROR("GEM lookup failed, handle = %u\n", mode_cmd->handles[i]);
+ ret = -ENOENT;
+ goto fail;
+ }
+
+ vigs_gem = gem_to_vigs_gem(gem);
+
+ if (vigs_gem->type != VIGS_GEM_TYPE_SURFACE) {
+ DRM_ERROR("GEM is not a surface, handle = %u\n", mode_cmd->handles[i]);
+ drm_gem_object_unreference_unlocked(gem);
+ ret = -ENOENT;
+ goto fail;
+ }
+
+ surfaces[i] = vigs_gem_to_vigs_surface(vigs_gem);
+ }
+
+ vigs_fb = kzalloc(sizeof(*vigs_fb), GFP_KERNEL);
+
+ if (!vigs_fb) {
+ ret = -ENOMEM;
+ goto fail;
+ }
+
+ vigs_fb->comm = vigs_dev->comm;
+
+ for (i = 0; i < num_planes; ++i) {
+ vigs_fb->surfaces[i] = surfaces[i];
+ }
+
+ ret = drm_framebuffer_init(vigs_dev->drm_dev,
+ &vigs_fb->base,
+ &vigs_framebuffer_funcs);
+
+ if (ret != 0) {
+ DRM_ERROR("unable to create the framebuffer: %d\n", ret);
+ kfree(vigs_fb);
+ goto fail;
+ }
+
+ drm_helper_mode_fill_fb_struct(&vigs_fb->base, mode_cmd);
+
+ return &vigs_fb->base;
+
+fail:
+ for (i--; i >= 0; i--) {
+ drm_gem_object_unreference_unlocked(&surfaces[i]->gem.base);
+ }
+
+ return ERR_PTR(ret);
+}
+
+static void vigs_output_poll_changed(struct drm_device *drm_dev)
+{
+ struct vigs_device *vigs_dev = drm_dev->dev_private;
DRM_DEBUG_KMS("enter\n");
- return drm_gem_handle_create(file_priv, &vigs_fb->fb_sfc->gem.base, handle);
+ if (vigs_dev->fbdev) {
+ vigs_fbdev_output_poll_changed(vigs_dev->fbdev);
+ }
}
static struct drm_mode_config_funcs vigs_mode_config_funcs =
.output_poll_changed = vigs_output_poll_changed
};
-static struct drm_framebuffer_funcs vigs_framebuffer_funcs =
-{
- .destroy = vigs_framebuffer_destroy,
- .create_handle = vigs_framebuffer_create_handle,
- .dirty = vigs_framebuffer_dirty,
-};
-
void vigs_framebuffer_config_init(struct vigs_device *vigs_dev)
{
DRM_DEBUG_KMS("enter\n");
}
(*vigs_fb)->comm = vigs_dev->comm;
- (*vigs_fb)->fb_sfc = fb_sfc;
+ (*vigs_fb)->surfaces[0] = fb_sfc;
ret = drm_framebuffer_init(vigs_dev->drm_dev,
&(*vigs_fb)->base,
{
int ret;
- vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
+ vigs_gem_reserve(&vigs_fb->surfaces[0]->gem);
- ret = vigs_gem_pin(&vigs_fb->fb_sfc->gem);
+ ret = vigs_gem_pin(&vigs_fb->surfaces[0]->gem);
- vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
+ vigs_gem_unreserve(&vigs_fb->surfaces[0]->gem);
return ret;
}
void vigs_framebuffer_unpin(struct vigs_framebuffer *vigs_fb)
{
- vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
+ vigs_gem_reserve(&vigs_fb->surfaces[0]->gem);
- vigs_gem_unpin(&vigs_fb->fb_sfc->gem);
+ vigs_gem_unpin(&vigs_fb->surfaces[0]->gem);
- vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
+ vigs_gem_unreserve(&vigs_fb->surfaces[0]->gem);
}
*/
struct vigs_comm *comm;
- struct vigs_surface *fb_sfc;
+ struct vigs_surface *surfaces[4];
};
static inline struct vigs_framebuffer *fb_to_vigs_fb(struct drm_framebuffer *fb)
#include "vigs_device.h"
#include "vigs_mman.h"
#include "vigs_surface.h"
+#include "vigs_dp.h"
#include <drm/vigs_drm.h>
#include <ttm/ttm_placement.h>
{
struct vigs_gem_object *vigs_gem = gem_to_vigs_gem(gem);
+ if (vigs_gem->type == VIGS_GEM_TYPE_SURFACE) {
+ struct vigs_device *vigs_dev = gem->dev->dev_private;
+
+ vigs_dp_remove_surface(vigs_dev->dp,
+ vigs_gem_to_vigs_surface(vigs_gem));
+ }
+
vigs_gem_reserve(vigs_gem);
vigs_gem_kunmap(vigs_gem);
{
DRM_FORMAT_XRGB8888,
DRM_FORMAT_ARGB8888,
+ DRM_FORMAT_NV21,
+ fourcc_code('N', 'V', '4', '2'),
+ DRM_FORMAT_NV61
};
static int vigs_plane_update(struct drm_plane *plane,
struct vigs_plane *vigs_plane = plane_to_vigs_plane(plane);
struct vigs_device *vigs_dev = plane->dev->dev_private;
struct vigs_framebuffer *vigs_fb = fb_to_vigs_fb(fb);
- int ret;
+ int ret, i;
uint32_t src_x_whole = src_x >> 16;
uint32_t src_y_whole = src_y >> 16;
uint32_t src_w_whole = src_w >> 16;
uint32_t src_h_whole = src_h >> 16;
+ vigsp_surface_id surface_ids[4] = { 0, 0, 0, 0 };
+ vigsp_plane_format format;
DRM_DEBUG_KMS("enter: crtc_x = %d, crtc_y = %d, crtc_w = %u, crtc_h = %u, src_x = %u, src_y = %u, src_w = %u, src_h = %u\n",
crtc_x, crtc_y, crtc_w, crtc_h, src_x, src_y, src_w, src_h);
- if (vigs_fb->fb_sfc->scanout) {
- vigs_gem_reserve(&vigs_fb->fb_sfc->gem);
+ if (vigs_fb->surfaces[0]->scanout) {
+ vigs_gem_reserve(&vigs_fb->surfaces[0]->gem);
- if (vigs_gem_in_vram(&vigs_fb->fb_sfc->gem) &&
- vigs_surface_need_gpu_update(vigs_fb->fb_sfc)) {
+ if (vigs_gem_in_vram(&vigs_fb->surfaces[0]->gem) &&
+ vigs_surface_need_gpu_update(vigs_fb->surfaces[0])) {
vigs_comm_update_gpu(vigs_dev->comm,
- vigs_fb->fb_sfc->id,
- vigs_fb->fb_sfc->width,
- vigs_fb->fb_sfc->height,
- vigs_gem_offset(&vigs_fb->fb_sfc->gem));
+ vigs_fb->surfaces[0]->id,
+ vigs_fb->surfaces[0]->width,
+ vigs_fb->surfaces[0]->height,
+ vigs_gem_offset(&vigs_fb->surfaces[0]->gem));
+ }
+
+ vigs_gem_unreserve(&vigs_fb->surfaces[0]->gem);
+ }
+
+ for (i = 0; i < 4; ++i) {
+ if (vigs_fb->surfaces[i]) {
+ surface_ids[i] = vigs_fb->surfaces[i]->id;
}
+ }
- vigs_gem_unreserve(&vigs_fb->fb_sfc->gem);
+ switch (fb->pixel_format) {
+ case DRM_FORMAT_XRGB8888:
+ format = vigsp_plane_bgrx8888;
+ break;
+ case DRM_FORMAT_ARGB8888:
+ format = vigsp_plane_bgra8888;
+ break;
+ case DRM_FORMAT_NV21:
+ format = vigsp_plane_nv21;
+ break;
+ case fourcc_code('N', 'V', '4', '2'):
+ format = vigsp_plane_nv42;
+ break;
+ case DRM_FORMAT_NV61:
+ format = vigsp_plane_nv61;
+ break;
+ default:
+ BUG();
+ format = vigsp_plane_bgrx8888;
+ break;
}
ret = vigs_comm_set_plane(vigs_dev->comm,
vigs_plane->index,
- vigs_fb->fb_sfc->id,
+ fb->width,
+ fb->height,
+ format,
+ surface_ids,
src_x_whole,
src_y_whole,
src_w_whole,
struct vigs_plane *vigs_plane = plane_to_vigs_plane(plane);
struct vigs_device *vigs_dev = plane->dev->dev_private;
int ret;
+ vigsp_surface_id surface_ids[4] = { 0, 0, 0, 0 };
DRM_DEBUG_KMS("enter\n");
0,
0,
0,
+ surface_ids,
+ 0,
+ 0,
0,
0,
0,
/*
* Bump this whenever protocol changes.
*/
-#define VIGS_PROTOCOL_VERSION 17
+#define VIGS_PROTOCOL_VERSION 18
#define VIGS_MAX_PLANES 2
vigsp_cmd_copy = 0x8,
vigsp_cmd_solid_fill = 0x9,
vigsp_cmd_set_plane = 0xA,
+ vigsp_cmd_ga_copy = 0xB
/*
* @}
*/
vigsp_surface_bgra8888 = 0x1,
} vigsp_surface_format;
+typedef enum
+{
+ vigsp_plane_bgrx8888 = 0x0,
+ vigsp_plane_bgra8888 = 0x1,
+ vigsp_plane_nv21 = 0x2,
+ vigsp_plane_nv42 = 0x3,
+ vigsp_plane_nv61 = 0x4
+} vigsp_plane_format;
+
#pragma pack(1)
struct vigsp_point
/*
* cmd_set_plane
*
- * Assigns surface 'sfc_id' to plane identified by 'plane'.
+ * Assigns surfaces 'surfaces' to plane identified by 'plane'.
*
- * Pass 0 as sfc_id in order to disable the plane.
+ * Pass 0 as surfaces[0] in order to disable the plane.
*
* @{
*/
struct vigsp_cmd_set_plane_request
{
vigsp_u32 plane;
- vigsp_surface_id sfc_id;
+ vigsp_u32 width;
+ vigsp_u32 height;
+ vigsp_plane_format format;
+ vigsp_surface_id surfaces[4];
struct vigsp_rect src_rect;
vigsp_s32 dst_x;
vigsp_s32 dst_y;
vigsp_s32 z_pos;
};
+/*
+ * @}
+ */
+
+/*
+ * cmd_ga_copy
+ *
+ * Copies part of surface 'src_id' to
+ * surface 'dst_id' given surface
+ * sizes.
+ *
+ * @{
+ */
+
+struct vigsp_cmd_ga_copy_request
+{
+ vigsp_surface_id src_id;
+ vigsp_bool src_scanout;
+ vigsp_offset src_offset;
+ vigsp_u32 src_stride;
+ vigsp_surface_id dst_id;
+ vigsp_u32 dst_stride;
+ struct vigsp_copy entry;
+};
+
/*
* @}
*/
/*
* Bump this whenever driver interface changes.
*/
-#define DRM_VIGS_DRIVER_VERSION 12
+#define DRM_VIGS_DRIVER_VERSION 13
/*
* Surface access flags.
#define DRM_VIGS_SAF_WRITE 2
#define DRM_VIGS_SAF_MASK 3
+/*
+ * Number of DP framebuffers.
+ */
+#define DRM_VIGS_NUM_DP_FB_BUF 4
+
+/*
+ * DP memory types.
+ */
+#define DRM_VIGS_DP_FB_Y 2
+#define DRM_VIGS_DP_FB_C 3
+
struct drm_vigs_get_protocol_version
{
uint32_t version;
int zpos;
};
+struct drm_vigs_dp_create_surface
+{
+ uint32_t dp_plane;
+ uint32_t dp_fb_buf;
+ uint32_t dp_mem_flag;
+ uint32_t width;
+ uint32_t height;
+ uint32_t stride;
+ uint32_t format;
+ uint32_t handle;
+ uint32_t size;
+ uint32_t id;
+};
+
+struct drm_vigs_dp_open_surface
+{
+ uint32_t dp_plane;
+ uint32_t dp_fb_buf;
+ uint32_t dp_mem_flag;
+ uint32_t handle;
+};
+
#define DRM_VIGS_GET_PROTOCOL_VERSION 0x00
#define DRM_VIGS_CREATE_SURFACE 0x01
#define DRM_VIGS_CREATE_EXECBUFFER 0x02
#define DRM_VIGS_FENCE_UNREF 0x0D
#define DRM_VIGS_PLANE_SET_ZPOS 0x0E
+#define DRM_VIGS_DP_CREATE_SURFACE 0x20
+#define DRM_VIGS_DP_OPEN_SURFACE 0x21
+
#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 + \
#define DRM_IOCTL_VIGS_PLANE_SET_ZPOS DRM_IOW(DRM_COMMAND_BASE + \
DRM_VIGS_PLANE_SET_ZPOS, struct drm_vigs_plane_set_zpos)
+#define DRM_IOCTL_VIGS_DP_CREATE_SURFACE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_VIGS_DP_CREATE_SURFACE, struct drm_vigs_dp_create_surface)
+#define DRM_IOCTL_VIGS_DP_OPEN_SURFACE DRM_IOWR(DRM_COMMAND_BASE + \
+ DRM_VIGS_DP_OPEN_SURFACE, struct drm_vigs_dp_open_surface)
+
#endif