From 610c0c2b2813c36dc16838bbdbba4c29f8680dde Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2018 07:32:05 +0100 Subject: virtio-gpu: add VIRTIO_GPU_F_EDID feature The feature allows the guest request an EDID blob (describing monitor capabilities) for a given scanout (aka virtual monitor connector). It brings a new command message, which has just a scanout field (beside the standard virtio-gpu header) and a response message which carries the EDID data. Signed-off-by: Gerd Hoffmann Reviewed-by: Dave Airlie Link: http://patchwork.freedesktop.org/patch/msgid/20181030063206.19528-2-kraxel@redhat.com --- include/uapi/linux/virtio_gpu.h | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h index f43c3c6171ff..8e88eba1fa7a 100644 --- a/include/uapi/linux/virtio_gpu.h +++ b/include/uapi/linux/virtio_gpu.h @@ -41,6 +41,7 @@ #include #define VIRTIO_GPU_F_VIRGL 0 +#define VIRTIO_GPU_F_EDID 1 enum virtio_gpu_ctrl_type { VIRTIO_GPU_UNDEFINED = 0, @@ -56,6 +57,7 @@ enum virtio_gpu_ctrl_type { VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING, VIRTIO_GPU_CMD_GET_CAPSET_INFO, VIRTIO_GPU_CMD_GET_CAPSET, + VIRTIO_GPU_CMD_GET_EDID, /* 3d commands */ VIRTIO_GPU_CMD_CTX_CREATE = 0x0200, @@ -76,6 +78,7 @@ enum virtio_gpu_ctrl_type { VIRTIO_GPU_RESP_OK_DISPLAY_INFO, VIRTIO_GPU_RESP_OK_CAPSET_INFO, VIRTIO_GPU_RESP_OK_CAPSET, + VIRTIO_GPU_RESP_OK_EDID, /* error responses */ VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, @@ -291,6 +294,21 @@ struct virtio_gpu_resp_capset { __u8 capset_data[]; }; +/* VIRTIO_GPU_CMD_GET_EDID */ +struct virtio_gpu_cmd_get_edid { + struct virtio_gpu_ctrl_hdr hdr; + __le32 scanout; + __le32 padding; +}; + +/* VIRTIO_GPU_RESP_OK_EDID */ +struct virtio_gpu_resp_edid { + struct virtio_gpu_ctrl_hdr hdr; + __le32 size; + __le32 padding; + __u8 edid[1024]; +}; + #define VIRTIO_GPU_EVENT_DISPLAY (1 << 0) struct virtio_gpu_config { -- cgit v1.2.3-58-ga151 From b4b01b4995fb15b55a2d067eb405917f5ab32709 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 30 Oct 2018 07:32:06 +0100 Subject: drm/virtio: add edid support linux guest driver implementation of the VIRTIO_GPU_F_EDID feature. Signed-off-by: Gerd Hoffmann Acked-by: Daniel Vetter Link: http://patchwork.freedesktop.org/patch/msgid/20181030063206.19528-3-kraxel@redhat.com --- drivers/gpu/drm/virtio/virtgpu_display.c | 12 ++++++ drivers/gpu/drm/virtio/virtgpu_drv.c | 1 + drivers/gpu/drm/virtio/virtgpu_drv.h | 3 ++ drivers/gpu/drm/virtio/virtgpu_kms.c | 8 ++++ drivers/gpu/drm/virtio/virtgpu_vq.c | 67 ++++++++++++++++++++++++++++++++ 5 files changed, 91 insertions(+) diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index 8f8fed471e34..b5580b11a063 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -169,6 +169,12 @@ static int virtio_gpu_conn_get_modes(struct drm_connector *connector) struct drm_display_mode *mode = NULL; int count, width, height; + if (output->edid) { + count = drm_add_edid_modes(connector, output->edid); + if (count) + return count; + } + width = le32_to_cpu(output->info.r.width); height = le32_to_cpu(output->info.r.height); count = drm_add_modes_noedid(connector, XRES_MAX, YRES_MAX); @@ -287,6 +293,8 @@ static int vgdev_output_init(struct virtio_gpu_device *vgdev, int index) drm_connector_init(dev, connector, &virtio_gpu_connector_funcs, DRM_MODE_CONNECTOR_VIRTUAL); drm_connector_helper_add(connector, &virtio_gpu_conn_helper_funcs); + if (vgdev->has_edid) + drm_connector_attach_edid_property(connector); drm_encoder_init(dev, encoder, &virtio_gpu_enc_funcs, DRM_MODE_ENCODER_VIRTUAL, NULL); @@ -378,6 +386,10 @@ int virtio_gpu_modeset_init(struct virtio_gpu_device *vgdev) void virtio_gpu_modeset_fini(struct virtio_gpu_device *vgdev) { + int i; + + for (i = 0 ; i < vgdev->num_scanouts; ++i) + kfree(vgdev->outputs[i].edid); virtio_gpu_fbdev_fini(vgdev); drm_mode_config_cleanup(vgdev->ddev); } diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index d9287c144fe5..f7f32a885af7 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -80,6 +80,7 @@ static unsigned int features[] = { */ VIRTIO_GPU_F_VIRGL, #endif + VIRTIO_GPU_F_EDID, }; static struct virtio_driver virtio_gpu_driver = { .feature_table = features, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 4632bd7e1972..7bec6e36886b 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -115,6 +115,7 @@ struct virtio_gpu_output { struct drm_encoder enc; struct virtio_gpu_display_one info; struct virtio_gpu_update_cursor cursor; + struct edid *edid; int cur_x; int cur_y; bool enabled; @@ -204,6 +205,7 @@ struct virtio_gpu_device { struct ida ctx_id_ida; bool has_virgl_3d; + bool has_edid; struct work_struct config_changed_work; @@ -294,6 +296,7 @@ int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx); int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, int idx, int version, struct virtio_gpu_drv_cap_cache **cache_p); +int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev); void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, uint32_t nlen, const char *name); void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev, diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 691b842d5f3a..3af6181c05a8 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -44,6 +44,8 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work) virtio_cread(vgdev->vdev, struct virtio_gpu_config, events_read, &events_read); if (events_read & VIRTIO_GPU_EVENT_DISPLAY) { + if (vgdev->has_edid) + virtio_gpu_cmd_get_edids(vgdev); virtio_gpu_cmd_get_display_info(vgdev); drm_helper_hpd_irq_event(vgdev->ddev); events_clear |= VIRTIO_GPU_EVENT_DISPLAY; @@ -156,6 +158,10 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) #else DRM_INFO("virgl 3d acceleration not supported by guest\n"); #endif + if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_F_EDID)) { + vgdev->has_edid = true; + DRM_INFO("EDID support available.\n"); + } ret = virtio_find_vqs(vgdev->vdev, 2, vqs, callbacks, names, NULL); if (ret) { @@ -201,6 +207,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags) if (num_capsets) virtio_gpu_get_capsets(vgdev, num_capsets); + if (vgdev->has_edid) + virtio_gpu_cmd_get_edids(vgdev); virtio_gpu_cmd_get_display_info(vgdev); wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending, 5 * HZ); diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 93f2c3a51ee8..2c6764f08f18 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -584,6 +584,45 @@ static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev, wake_up(&vgdev->resp_wq); } +static int virtio_get_edid_block(void *data, u8 *buf, + unsigned int block, size_t len) +{ + struct virtio_gpu_resp_edid *resp = data; + size_t start = block * EDID_LENGTH; + + if (start + len > le32_to_cpu(resp->size)) + return -1; + memcpy(buf, resp->edid + start, len); + return 0; +} + +static void virtio_gpu_cmd_get_edid_cb(struct virtio_gpu_device *vgdev, + struct virtio_gpu_vbuffer *vbuf) +{ + struct virtio_gpu_cmd_get_edid *cmd = + (struct virtio_gpu_cmd_get_edid *)vbuf->buf; + struct virtio_gpu_resp_edid *resp = + (struct virtio_gpu_resp_edid *)vbuf->resp_buf; + uint32_t scanout = le32_to_cpu(cmd->scanout); + struct virtio_gpu_output *output; + struct edid *new_edid, *old_edid; + + if (scanout >= vgdev->num_scanouts) + return; + output = vgdev->outputs + scanout; + + new_edid = drm_do_get_edid(&output->conn, virtio_get_edid_block, resp); + + spin_lock(&vgdev->display_info_lock); + old_edid = output->edid; + output->edid = new_edid; + drm_connector_update_edid_property(&output->conn, output->edid); + spin_unlock(&vgdev->display_info_lock); + + kfree(old_edid); + wake_up(&vgdev->resp_wq); +} + int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev) { struct virtio_gpu_ctrl_hdr *cmd_p; @@ -686,6 +725,34 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, return 0; } +int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev) +{ + struct virtio_gpu_cmd_get_edid *cmd_p; + struct virtio_gpu_vbuffer *vbuf; + void *resp_buf; + int scanout; + + if (WARN_ON(!vgdev->has_edid)) + return -EINVAL; + + for (scanout = 0; scanout < vgdev->num_scanouts; scanout++) { + resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_edid), + GFP_KERNEL); + if (!resp_buf) + return -ENOMEM; + + cmd_p = virtio_gpu_alloc_cmd_resp + (vgdev, &virtio_gpu_cmd_get_edid_cb, &vbuf, + sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_edid), + resp_buf); + cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_EDID); + cmd_p->scanout = cpu_to_le32(scanout); + virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); + } + + return 0; +} + void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id, uint32_t nlen, const char *name) { -- cgit v1.2.3-58-ga151 From 42843dc2d536afb5bb1b318b48f3f22b485f0dec Mon Sep 17 00:00:00 2001 From: Koen Kooi Date: Mon, 19 Nov 2018 11:02:39 +0100 Subject: drm/meson: Add implicit fencing support for primary and overlay planes Suggested by Qiang Yu to fix tearing artefacts in the Kodi GUI. Suggested-by: Qiang Yu Signed-off-by: Koen Kooi Acked-by: Neil Armstrong [narmstrong: added Suggested-by tag] Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/1542621759-26413-1-git-send-email-koen@dominion.thruhere.net --- drivers/gpu/drm/meson/meson_overlay.c | 2 ++ drivers/gpu/drm/meson/meson_plane.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index 9aebc5e4b418..691a9fd16b36 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "meson_overlay.h" @@ -532,6 +533,7 @@ static const struct drm_plane_helper_funcs meson_overlay_helper_funcs = { .atomic_check = meson_overlay_atomic_check, .atomic_disable = meson_overlay_atomic_disable, .atomic_update = meson_overlay_atomic_update, + .prepare_fb = drm_gem_fb_prepare_fb, }; static const struct drm_plane_funcs meson_overlay_funcs = { diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 12a47b4f65a5..8ee2cf9e47cd 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include "meson_plane.h" @@ -322,6 +323,7 @@ static const struct drm_plane_helper_funcs meson_plane_helper_funcs = { .atomic_check = meson_plane_atomic_check, .atomic_disable = meson_plane_atomic_disable, .atomic_update = meson_plane_atomic_update, + .prepare_fb = drm_gem_fb_prepare_fb, }; static const struct drm_plane_funcs meson_plane_funcs = { -- cgit v1.2.3-58-ga151 From c6fdea6e1a1942bd1ab2abaa16c34f23a25226b9 Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Wed, 21 Nov 2018 22:35:10 +0100 Subject: drm: Merge drm_info.c into drm_debugfs.c Ever since commit cb6458f97b53d7f73043206c18014b3ca63ac345 Author: Daniel Vetter Date: Thu Aug 8 15:41:34 2013 +0200 drm: remove procfs code, take 2 Having the code shared between procfs and debugfs in the separate drm_info.c file stopped making sense. Merge them. Noticed because Lyude asked some questions on irc about why we even have drm_info_node and I remember this old story. Cc: Lyude Paul Reviewed-by: Lyude Paul Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181121213510.31260-1-daniel.vetter@ffwll.ch --- drivers/gpu/drm/Makefile | 2 +- drivers/gpu/drm/drm_debugfs.c | 89 ++++++++++++++++++++++++++ drivers/gpu/drm/drm_info.c | 137 ----------------------------------------- drivers/gpu/drm/drm_internal.h | 5 -- 4 files changed, 90 insertions(+), 143 deletions(-) delete mode 100644 drivers/gpu/drm/drm_info.c diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 576ba985e138..7c88f12096c5 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -10,7 +10,7 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \ drm_scatter.o drm_pci.o \ drm_sysfs.o drm_hashtab.o drm_mm.o \ drm_crtc.o drm_fourcc.o drm_modes.o drm_edid.o \ - drm_info.o drm_encoder_slave.o \ + drm_encoder_slave.o \ drm_trace_points.o drm_global.o drm_prime.o \ drm_rect.o drm_vma_manager.o drm_flip_work.o \ drm_modeset_lock.o drm_atomic.o drm_bridge.o \ diff --git a/drivers/gpu/drm/drm_debugfs.c b/drivers/gpu/drm/drm_debugfs.c index 373bd4c2b698..f8468eae0503 100644 --- a/drivers/gpu/drm/drm_debugfs.c +++ b/drivers/gpu/drm/drm_debugfs.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include "drm_internal.h" @@ -43,6 +45,93 @@ * Initialization, etc. **************************************************/ +static int drm_name_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_minor *minor = node->minor; + struct drm_device *dev = minor->dev; + struct drm_master *master; + + mutex_lock(&dev->master_mutex); + master = dev->master; + seq_printf(m, "%s", dev->driver->name); + if (dev->dev) + seq_printf(m, " dev=%s", dev_name(dev->dev)); + if (master && master->unique) + seq_printf(m, " master=%s", master->unique); + if (dev->unique) + seq_printf(m, " unique=%s", dev->unique); + seq_printf(m, "\n"); + mutex_unlock(&dev->master_mutex); + + return 0; +} + +static int drm_clients_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + struct drm_file *priv; + kuid_t uid; + + seq_printf(m, + "%20s %5s %3s master a %5s %10s\n", + "command", + "pid", + "dev", + "uid", + "magic"); + + /* dev->filelist is sorted youngest first, but we want to present + * oldest first (i.e. kernel, servers, clients), so walk backwardss. + */ + mutex_lock(&dev->filelist_mutex); + list_for_each_entry_reverse(priv, &dev->filelist, lhead) { + struct task_struct *task; + + rcu_read_lock(); /* locks pid_task()->comm */ + task = pid_task(priv->pid, PIDTYPE_PID); + uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; + seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n", + task ? task->comm : "", + pid_vnr(priv->pid), + priv->minor->index, + drm_is_current_master(priv) ? 'y' : 'n', + priv->authenticated ? 'y' : 'n', + from_kuid_munged(seq_user_ns(m), uid), + priv->magic); + rcu_read_unlock(); + } + mutex_unlock(&dev->filelist_mutex); + return 0; +} + +static int drm_gem_one_name_info(int id, void *ptr, void *data) +{ + struct drm_gem_object *obj = ptr; + struct seq_file *m = data; + + seq_printf(m, "%6d %8zd %7d %8d\n", + obj->name, obj->size, + obj->handle_count, + kref_read(&obj->refcount)); + return 0; +} + +static int drm_gem_name_info(struct seq_file *m, void *data) +{ + struct drm_info_node *node = (struct drm_info_node *) m->private; + struct drm_device *dev = node->minor->dev; + + seq_printf(m, " name size handles refcount\n"); + + mutex_lock(&dev->object_name_lock); + idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); + mutex_unlock(&dev->object_name_lock); + + return 0; +} + static const struct drm_info_list drm_debugfs_list[] = { {"name", drm_name_info, 0}, {"clients", drm_clients_info, 0}, diff --git a/drivers/gpu/drm/drm_info.c b/drivers/gpu/drm/drm_info.c deleted file mode 100644 index 6b68e9088436..000000000000 --- a/drivers/gpu/drm/drm_info.c +++ /dev/null @@ -1,137 +0,0 @@ -/** - * \file drm_info.c - * DRM info file implementations - * - * \author Ben Gamari - */ - -/* - * Created: Sun Dec 21 13:09:50 2008 by bgamari@gmail.com - * - * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California. - * Copyright 2008 Ben Gamari - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include - -#include "drm_internal.h" -#include "drm_legacy.h" - -/** - * Called when "/proc/dri/.../name" is read. - * - * Prints the device name together with the bus id if available. - */ -int drm_name_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_minor *minor = node->minor; - struct drm_device *dev = minor->dev; - struct drm_master *master; - - mutex_lock(&dev->master_mutex); - master = dev->master; - seq_printf(m, "%s", dev->driver->name); - if (dev->dev) - seq_printf(m, " dev=%s", dev_name(dev->dev)); - if (master && master->unique) - seq_printf(m, " master=%s", master->unique); - if (dev->unique) - seq_printf(m, " unique=%s", dev->unique); - seq_printf(m, "\n"); - mutex_unlock(&dev->master_mutex); - - return 0; -} - -/** - * Called when "/proc/dri/.../clients" is read. - * - */ -int drm_clients_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - struct drm_file *priv; - kuid_t uid; - - seq_printf(m, - "%20s %5s %3s master a %5s %10s\n", - "command", - "pid", - "dev", - "uid", - "magic"); - - /* dev->filelist is sorted youngest first, but we want to present - * oldest first (i.e. kernel, servers, clients), so walk backwardss. - */ - mutex_lock(&dev->filelist_mutex); - list_for_each_entry_reverse(priv, &dev->filelist, lhead) { - struct task_struct *task; - - rcu_read_lock(); /* locks pid_task()->comm */ - task = pid_task(priv->pid, PIDTYPE_PID); - uid = task ? __task_cred(task)->euid : GLOBAL_ROOT_UID; - seq_printf(m, "%20s %5d %3d %c %c %5d %10u\n", - task ? task->comm : "", - pid_vnr(priv->pid), - priv->minor->index, - drm_is_current_master(priv) ? 'y' : 'n', - priv->authenticated ? 'y' : 'n', - from_kuid_munged(seq_user_ns(m), uid), - priv->magic); - rcu_read_unlock(); - } - mutex_unlock(&dev->filelist_mutex); - return 0; -} - -static int drm_gem_one_name_info(int id, void *ptr, void *data) -{ - struct drm_gem_object *obj = ptr; - struct seq_file *m = data; - - seq_printf(m, "%6d %8zd %7d %8d\n", - obj->name, obj->size, - obj->handle_count, - kref_read(&obj->refcount)); - return 0; -} - -int drm_gem_name_info(struct seq_file *m, void *data) -{ - struct drm_info_node *node = (struct drm_info_node *) m->private; - struct drm_device *dev = node->minor->dev; - - seq_printf(m, " name size handles refcount\n"); - - mutex_lock(&dev->object_name_lock); - idr_for_each(&dev->object_name_idr, drm_gem_one_name_info, m); - mutex_unlock(&dev->object_name_lock); - - return 0; -} diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 0c4eb4a9ab31..c7a7d7ce5d1c 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -56,11 +56,6 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr struct drm_minor *drm_minor_acquire(unsigned int minor_id); void drm_minor_release(struct drm_minor *minor); -/* drm_info.c */ -int drm_name_info(struct seq_file *m, void *data); -int drm_clients_info(struct seq_file *m, void* data); -int drm_gem_name_info(struct seq_file *m, void *data); - /* drm_vblank.c */ void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe); void drm_vblank_cleanup(struct drm_device *dev); -- cgit v1.2.3-58-ga151 From 7b24eec754ba0f0f794ab09413dcde2585b4a84b Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Thu, 22 Nov 2018 09:44:17 +0800 Subject: drm/sun4i: wait on implicit fence before display Render like lima will attach a fence to the framebuffer dma_buf, display like sun4i should wait it finish before show the framebuffer. Otherwise tearing will be observed. Signed-off-by: Qiang Yu Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181122014417.23285-1-yuq825@gmail.com --- drivers/gpu/drm/sun4i/sun4i_layer.c | 2 ++ drivers/gpu/drm/sun4i/sun8i_ui_layer.c | 2 ++ drivers/gpu/drm/sun4i/sun8i_vi_layer.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 78f77af8805a..3f51744b6e89 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -12,6 +12,7 @@ #include #include +#include #include #include "sun4i_backend.h" @@ -112,6 +113,7 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, } static const struct drm_plane_helper_funcs sun4i_backend_layer_helper_funcs = { + .prepare_fb = drm_gem_fb_prepare_fb, .atomic_disable = sun4i_backend_layer_atomic_disable, .atomic_update = sun4i_backend_layer_atomic_update, }; diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index e3fc8fa920fb..18534263a05d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -300,6 +301,7 @@ static void sun8i_ui_layer_atomic_update(struct drm_plane *plane, } static struct drm_plane_helper_funcs sun8i_ui_layer_helper_funcs = { + .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = sun8i_ui_layer_atomic_check, .atomic_disable = sun8i_ui_layer_atomic_disable, .atomic_update = sun8i_ui_layer_atomic_update, diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index 4249edfb47ed..87be898f9b7a 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -336,6 +337,7 @@ static void sun8i_vi_layer_atomic_update(struct drm_plane *plane, } static struct drm_plane_helper_funcs sun8i_vi_layer_helper_funcs = { + .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = sun8i_vi_layer_atomic_check, .atomic_disable = sun8i_vi_layer_atomic_disable, .atomic_update = sun8i_vi_layer_atomic_update, -- cgit v1.2.3-58-ga151 From 10fdb7d2ad4244c668f33706f98d019795fc63c8 Mon Sep 17 00:00:00 2001 From: Noralf Trønnes Date: Wed, 21 Nov 2018 19:02:15 +0100 Subject: drm/prime: Fix drm_gem_prime_mmap() stack use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit drivers/gpu/drm/drm_prime.c: In function 'drm_gem_prime_mmap': >> drivers/gpu/drm/drm_prime.c:688:1: warning: the frame size of 1592 bytes is larger than 1024 bytes [-Wframe-larger-than=] Fix by allocating on the heap. Fixes: 7698799f9554 ("drm/prime: Add drm_gem_prime_mmap()") Reported-by: kbuild test robot Cc: Daniel Vetter Cc: Christian König Signed-off-by: Noralf Trønnes Reviewed-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181121180215.13881-1-noralf@tronnes.org --- drivers/gpu/drm/drm_prime.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index 5737cb8c6f03..231e3f6d5f41 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -663,24 +663,33 @@ EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); */ int drm_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) { - /* Used by drm_gem_mmap() to lookup the GEM object */ - struct drm_file priv = { - .minor = obj->dev->primary, - }; - struct file fil = { - .private_data = &priv, - }; + struct drm_file *priv; + struct file *fil; int ret; - ret = drm_vma_node_allow(&obj->vma_node, &priv); + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + fil = kzalloc(sizeof(*fil), GFP_KERNEL); + if (!priv || !fil) { + ret = -ENOMEM; + goto out; + } + + /* Used by drm_gem_mmap() to lookup the GEM object */ + priv->minor = obj->dev->primary; + fil->private_data = priv; + + ret = drm_vma_node_allow(&obj->vma_node, priv); if (ret) - return ret; + goto out; vma->vm_pgoff += drm_vma_node_start(&obj->vma_node); - ret = obj->dev->driver->fops->mmap(&fil, vma); + ret = obj->dev->driver->fops->mmap(fil, vma); - drm_vma_node_revoke(&obj->vma_node, &priv); + drm_vma_node_revoke(&obj->vma_node, priv); +out: + kfree(priv); + kfree(fil); return ret; } -- cgit v1.2.3-58-ga151 From 2de42f79bb21a412f40ade8831eb6fc445cb78a4 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 22 Nov 2018 16:34:11 +0200 Subject: drm/atomic-helper: Complete fake_commit->flip_done potentially earlier MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Consider the following scenario: 1. nonblocking enable crtc 2. wait for the event 3. nonblocking disable crtc On i915 this can lead to a spurious -EBUSY from step 3 on account of non-enabled planes getting the fake_commit in step 1 and we don't complete the fake_commit-> flip_done until drm_atomic_helper_commit_hw_done() which can happen a long time after the flip event was sent out. This will become somewhat easy to hit on SKL+ once we start to add all the planes for the crtc to every modeset commit for the purposes of forcing a watermark register programming [1]. To make the race a little less pronounced let's complete fake_commit->flip_done after drm_atomic_helper_wait_for_flip_done(). For the single crtc case this should make the race quite theoretical, assuming drm_atomic_helper_wait_for_flip_done() actually has to wait for the real commit flip_done. In case the real commit flip_done gets completed singificantly before drm_atomic_helper_wait_for_flip_done(), or we are dealing with multiple crtcs whose vblanks don't line up nicely the race still exists. [1] https://patchwork.freedesktop.org/patch/262670/ Cc: Maarten Lankhorst Fixes: 080de2e5be2d ("drm/atomic: Check for busy planes/connectors before setting the commit") Testcase: igt/kms_cursor_legacy/*nonblocking-modeset-vs-cursor-atomic Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181122143412.11655-1-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/drm_atomic_helper.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 474b503a73a1..269f1a74de38 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -1456,6 +1456,9 @@ void drm_atomic_helper_wait_for_flip_done(struct drm_device *dev, DRM_ERROR("[CRTC:%d:%s] flip_done timed out\n", crtc->base.id, crtc->name); } + + if (old_state->fake_commit) + complete_all(&old_state->fake_commit->flip_done); } EXPORT_SYMBOL(drm_atomic_helper_wait_for_flip_done); -- cgit v1.2.3-58-ga151 From 10a599fabbe54a0159b5b706aaad608400acd599 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Thu, 22 Nov 2018 16:34:12 +0200 Subject: drm/atomic-helper: WARN if fake_commit->hw_done is not completed as expected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For real commits we WARN if ->hw_done hasn't been completed by the time drm_atomic_helper_commit_cleanup_done() is called. Let's do the same for the fake commit. Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20181122143412.11655-2-ville.syrjala@linux.intel.com Reviewed-by: Maarten Lankhorst --- drivers/gpu/drm/drm_atomic_helper.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/drm_atomic_helper.c b/drivers/gpu/drm/drm_atomic_helper.c index 269f1a74de38..fe8dd8aa4ae4 100644 --- a/drivers/gpu/drm/drm_atomic_helper.c +++ b/drivers/gpu/drm/drm_atomic_helper.c @@ -2216,8 +2216,10 @@ void drm_atomic_helper_commit_cleanup_done(struct drm_atomic_state *old_state) spin_unlock(&crtc->commit_lock); } - if (old_state->fake_commit) + if (old_state->fake_commit) { complete_all(&old_state->fake_commit->cleanup_done); + WARN_ON(!try_wait_for_completion(&old_state->fake_commit->hw_done)); + } } EXPORT_SYMBOL(drm_atomic_helper_commit_cleanup_done); -- cgit v1.2.3-58-ga151 From 3e70fd160cf0b1945225eaa08dd2cb8544f21cb8 Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:22 +0100 Subject: drm: remove deprecated "[__]drm_gem_object_[un]reference[_locked]" functions There are no more places where these (deprecated) functions are being used from, thus they can now be removed. Signed-off-by: Fernando Ramos Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-3-greenfoo@gluegarage.com --- include/drm/drm_gem.h | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/include/drm/drm_gem.h b/include/drm/drm_gem.h index f466ce5bde0e..c95727425284 100644 --- a/include/drm/drm_gem.h +++ b/include/drm/drm_gem.h @@ -348,56 +348,6 @@ __drm_gem_object_put(struct drm_gem_object *obj) void drm_gem_object_put_unlocked(struct drm_gem_object *obj); void drm_gem_object_put(struct drm_gem_object *obj); -/** - * drm_gem_object_reference - acquire a GEM buffer object reference - * @obj: GEM buffer object - * - * This is a compatibility alias for drm_gem_object_get() and should not be - * used by new code. - */ -static inline void drm_gem_object_reference(struct drm_gem_object *obj) -{ - drm_gem_object_get(obj); -} - -/** - * __drm_gem_object_unreference - raw function to release a GEM buffer object - * reference - * @obj: GEM buffer object - * - * This is a compatibility alias for __drm_gem_object_put() and should not be - * used by new code. - */ -static inline void __drm_gem_object_unreference(struct drm_gem_object *obj) -{ - __drm_gem_object_put(obj); -} - -/** - * drm_gem_object_unreference_unlocked - release a GEM buffer object reference - * @obj: GEM buffer object - * - * This is a compatibility alias for drm_gem_object_put_unlocked() and should - * not be used by new code. - */ -static inline void -drm_gem_object_unreference_unlocked(struct drm_gem_object *obj) -{ - drm_gem_object_put_unlocked(obj); -} - -/** - * drm_gem_object_unreference - release a GEM buffer object reference - * @obj: GEM buffer object - * - * This is a compatibility alias for drm_gem_object_put() and should not be - * used by new code. - */ -static inline void drm_gem_object_unreference(struct drm_gem_object *obj) -{ - drm_gem_object_put(obj); -} - int drm_gem_handle_create(struct drm_file *file_priv, struct drm_gem_object *obj, u32 *handlep); -- cgit v1.2.3-58-ga151 From 808bad32ea423321bff17178aebfbc507165ab3b Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:23 +0100 Subject: drm: replace "drm_dev_unref" function with "drm_dev_put" This patch unifies the naming of DRM functions for reference counting as requested on Documentation/gpu/todo.rst Signed-off-by: Fernando Ramos Acked-by: Boris Brezillon Acked-by: Alexey Brodkin Acked-by: Stefan Agner Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-4-greenfoo@gluegarage.com --- drivers/gpu/drm/arc/arcpgu_drv.c | 4 ++-- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 4 ++-- drivers/gpu/drm/mxsfb/mxsfb_drv.c | 4 ++-- drivers/gpu/drm/rcar-du/rcar_du_drv.c | 2 +- drivers/gpu/drm/shmobile/shmob_drm_drv.c | 4 ++-- drivers/gpu/drm/tve200/tve200_drv.c | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index 2af847ebca34..206a76abf771 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -190,7 +190,7 @@ err_unload: arcpgu_unload(drm); err_unref: - drm_dev_unref(drm); + drm_dev_put(drm); return ret; } @@ -201,7 +201,7 @@ static int arcpgu_remove(struct platform_device *pdev) drm_dev_unregister(drm); arcpgu_unload(drm); - drm_dev_unref(drm); + drm_dev_put(drm); return 0; } diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 83c1f46670bf..52802e6049e0 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -550,7 +550,7 @@ out_register: out_bind: kfree(priv); out_unref: - drm_dev_unref(drm); + drm_dev_put(drm); return ret; } @@ -567,7 +567,7 @@ static void etnaviv_unbind(struct device *dev) drm->dev_private = NULL; kfree(priv); - drm_dev_unref(drm); + drm_dev_put(drm); } static const struct component_master_ops etnaviv_master_ops = { diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 2393e6d16ffd..88ba003979e6 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -417,7 +417,7 @@ static int mxsfb_probe(struct platform_device *pdev) err_unload: mxsfb_unload(drm); err_free: - drm_dev_unref(drm); + drm_dev_put(drm); return ret; } @@ -428,7 +428,7 @@ static int mxsfb_remove(struct platform_device *pdev) drm_dev_unregister(drm); mxsfb_unload(drm); - drm_dev_unref(drm); + drm_dev_put(drm); return 0; } diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 7015974c247a..c6770043dcdc 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -437,7 +437,7 @@ static int rcar_du_remove(struct platform_device *pdev) drm_kms_helper_poll_fini(ddev); drm_mode_config_cleanup(ddev); - drm_dev_unref(ddev); + drm_dev_put(ddev); return 0; } diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index 6ececad6f845..8554102a6ead 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -194,7 +194,7 @@ static int shmob_drm_remove(struct platform_device *pdev) drm_kms_helper_poll_fini(ddev); drm_mode_config_cleanup(ddev); drm_irq_uninstall(ddev); - drm_dev_unref(ddev); + drm_dev_put(ddev); return 0; } @@ -290,7 +290,7 @@ err_modeset_cleanup: drm_kms_helper_poll_fini(ddev); drm_mode_config_cleanup(ddev); err_free_drm_dev: - drm_dev_unref(ddev); + drm_dev_put(ddev); return ret; } diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index 72efcecb44f7..28e2d03c0ccf 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -249,7 +249,7 @@ static int tve200_probe(struct platform_device *pdev) clk_disable: clk_disable_unprepare(priv->pclk); dev_unref: - drm_dev_unref(drm); + drm_dev_put(drm); return ret; } @@ -263,7 +263,7 @@ static int tve200_remove(struct platform_device *pdev) drm_panel_bridge_remove(priv->bridge); drm_mode_config_cleanup(drm); clk_disable_unprepare(priv->pclk); - drm_dev_unref(drm); + drm_dev_put(drm); return 0; } -- cgit v1.2.3-58-ga151 From ba1d345401476a5f7fbad622607c5a1f95e59b31 Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:24 +0100 Subject: drm: remove deprecated "drm_dev_unref" function There are no more places where this (deprecated) function is being used from, thus it can now be removed. Signed-off-by: Fernando Ramos Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-5-greenfoo@gluegarage.com --- drivers/gpu/drm/drm_drv.c | 13 ------------- include/drm/drm_drv.h | 1 - 2 files changed, 14 deletions(-) diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index aa1cef794f9a..5f7e99bf4fa4 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -704,19 +704,6 @@ void drm_dev_put(struct drm_device *dev) } EXPORT_SYMBOL(drm_dev_put); -/** - * drm_dev_unref - Drop reference of a DRM device - * @dev: device to drop reference of or NULL - * - * This is a compatibility alias for drm_dev_put() and should not be used by new - * code. - */ -void drm_dev_unref(struct drm_device *dev) -{ - drm_dev_put(dev); -} -EXPORT_SYMBOL(drm_dev_unref); - static int create_compat_control_link(struct drm_device *dev) { struct drm_minor *minor; diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index dbb2f6ad184a..252dd216cc60 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -625,7 +625,6 @@ void drm_dev_unregister(struct drm_device *dev); void drm_dev_get(struct drm_device *dev); void drm_dev_put(struct drm_device *dev); -void drm_dev_unref(struct drm_device *dev); void drm_put_dev(struct drm_device *dev); bool drm_dev_enter(struct drm_device *dev, int *idx); void drm_dev_exit(int idx); -- cgit v1.2.3-58-ga151 From 895170ce9205f3f19fb00e54e2a620389bd11038 Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:25 +0100 Subject: drm: replace "drm_connector_unreference" with "drm_connector_put" This patch unifies the naming of DRM functions for reference counting as requested on Documentation/gpu/todo.rst Signed-off-by: Fernando Ramos Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-6-greenfoo@gluegarage.com --- drivers/gpu/drm/bridge/tc358764.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/bridge/tc358764.c b/drivers/gpu/drm/bridge/tc358764.c index ee6b98efa9c2..afd491018bfc 100644 --- a/drivers/gpu/drm/bridge/tc358764.c +++ b/drivers/gpu/drm/bridge/tc358764.c @@ -379,7 +379,7 @@ static void tc358764_detach(struct drm_bridge *bridge) drm_fb_helper_remove_one_connector(drm->fb_helper, &ctx->connector); drm_panel_detach(ctx->panel); ctx->panel = NULL; - drm_connector_unreference(&ctx->connector); + drm_connector_put(&ctx->connector); } static const struct drm_bridge_funcs tc358764_bridge_funcs = { -- cgit v1.2.3-58-ga151 From 8dd0e9d3aa993af1357e1455602fe6eba2d06741 Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:26 +0100 Subject: drm: remove deprecated "drm_connector_[un]reference" functions There are no more places where this (deprecated) function is being used from, thus it can now be removed. Signed-off-by: Fernando Ramos Reviewed-by: Linus Walleij Reviewed-by: Lyude Paul Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-7-greenfoo@gluegarage.com --- include/drm/drm_connector.h | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/include/drm/drm_connector.h b/include/drm/drm_connector.h index dd0552cb7472..2f38d3598eb4 100644 --- a/include/drm/drm_connector.h +++ b/include/drm/drm_connector.h @@ -1192,30 +1192,6 @@ static inline void drm_connector_put(struct drm_connector *connector) drm_mode_object_put(&connector->base); } -/** - * drm_connector_reference - acquire a connector reference - * @connector: DRM connector - * - * This is a compatibility alias for drm_connector_get() and should not be - * used by new code. - */ -static inline void drm_connector_reference(struct drm_connector *connector) -{ - drm_connector_get(connector); -} - -/** - * drm_connector_unreference - release a connector reference - * @connector: DRM connector - * - * This is a compatibility alias for drm_connector_put() and should not be - * used by new code. - */ -static inline void drm_connector_unreference(struct drm_connector *connector) -{ - drm_connector_put(connector); -} - /** * drm_connector_is_unregistered - has the connector been unregistered from * userspace? -- cgit v1.2.3-58-ga151 From 55b446209d041383934308f7f5fc38dee813218e Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:27 +0100 Subject: drm: remove deprecated "drm_framebuffer_[un]reference" functions There are no more places where this (deprecated) function is being used from, thus it can now be removed. Signed-off-by: Fernando Ramos Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-8-greenfoo@gluegarage.com --- include/drm/drm_framebuffer.h | 24 ------------------------ 1 file changed, 24 deletions(-) diff --git a/include/drm/drm_framebuffer.h b/include/drm/drm_framebuffer.h index c50502c656e5..c94acedfb08e 100644 --- a/include/drm/drm_framebuffer.h +++ b/include/drm/drm_framebuffer.h @@ -240,30 +240,6 @@ static inline void drm_framebuffer_put(struct drm_framebuffer *fb) drm_mode_object_put(&fb->base); } -/** - * drm_framebuffer_reference - acquire a framebuffer reference - * @fb: DRM framebuffer - * - * This is a compatibility alias for drm_framebuffer_get() and should not be - * used by new code. - */ -static inline void drm_framebuffer_reference(struct drm_framebuffer *fb) -{ - drm_framebuffer_get(fb); -} - -/** - * drm_framebuffer_unreference - release a framebuffer reference - * @fb: DRM framebuffer - * - * This is a compatibility alias for drm_framebuffer_put() and should not be - * used by new code. - */ -static inline void drm_framebuffer_unreference(struct drm_framebuffer *fb) -{ - drm_framebuffer_put(fb); -} - /** * drm_framebuffer_read_refcount - read the framebuffer reference count. * @fb: framebuffer -- cgit v1.2.3-58-ga151 From 4ddf3737cb076fcc26d097453b06b49ff7f1a48b Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:28 +0100 Subject: drm: remove no longer needed drm-get-put coccinelle script The coccinelle script was used to rename some (deprecated) functions which no longer exist now. Signed-off-by: Fernando Ramos Reviewed-by: Linus Walleij Acked-by: Julia Lawall Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-9-greenfoo@gluegarage.com --- scripts/coccinelle/api/drm-get-put.cocci | 78 -------------------------------- 1 file changed, 78 deletions(-) delete mode 100644 scripts/coccinelle/api/drm-get-put.cocci diff --git a/scripts/coccinelle/api/drm-get-put.cocci b/scripts/coccinelle/api/drm-get-put.cocci deleted file mode 100644 index 3a09c97ad87d..000000000000 --- a/scripts/coccinelle/api/drm-get-put.cocci +++ /dev/null @@ -1,78 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/// -/// Use drm_*_get() and drm_*_put() helpers instead of drm_*_reference() and -/// drm_*_unreference() helpers. -/// -// Confidence: High -// Copyright: (C) 2017 NVIDIA Corporation -// Options: --no-includes --include-headers -// - -virtual patch -virtual report - -@depends on patch@ -expression object; -@@ - -( -- drm_connector_reference(object) -+ drm_connector_get(object) -| -- drm_connector_unreference(object) -+ drm_connector_put(object) -| -- drm_framebuffer_reference(object) -+ drm_framebuffer_get(object) -| -- drm_framebuffer_unreference(object) -+ drm_framebuffer_put(object) -| -- drm_gem_object_reference(object) -+ drm_gem_object_get(object) -| -- drm_gem_object_unreference(object) -+ drm_gem_object_put(object) -| -- __drm_gem_object_unreference(object) -+ __drm_gem_object_put(object) -| -- drm_gem_object_unreference_unlocked(object) -+ drm_gem_object_put_unlocked(object) -| -- drm_dev_unref(object) -+ drm_dev_put(object) -) - -@r depends on report@ -expression object; -position p; -@@ - -( -drm_connector_unreference@p(object) -| -drm_connector_reference@p(object) -| -drm_framebuffer_unreference@p(object) -| -drm_framebuffer_reference@p(object) -| -drm_gem_object_unreference@p(object) -| -drm_gem_object_reference@p(object) -| -__drm_gem_object_unreference(object) -| -drm_gem_object_unreference_unlocked(object) -| -drm_dev_unref@p(object) -) - -@script:python depends on report@ -object << r.object; -p << r.p; -@@ - -msg="WARNING: use get/put helpers to reference and dereference %s" % (object) -coccilib.report.print_report(p[0], msg) -- cgit v1.2.3-58-ga151 From a42facc82c3d5841987b8b363a8a5cc564915c3c Mon Sep 17 00:00:00 2001 From: Fernando Ramos Date: Thu, 15 Nov 2018 23:16:29 +0100 Subject: docs: drm: remove no longer relevant TODO entry This entry asked to rename all drm core "*_reference/_unrefence" functions to "*_get/_put". Now that this task is complete, we can remove this entry from the TODO list. Signed-off-by: Fernando Ramos Reviewed-by: Linus Walleij Signed-off-by: Linus Walleij Link: https://patchwork.freedesktop.org/patch/msgid/20181115221634.22715-10-greenfoo@gluegarage.com --- Documentation/gpu/todo.rst | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 31ef4adc91c9..9815b3b82bd1 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -28,23 +28,6 @@ them, but also all the virtual ones used by KVM, so everyone qualifies). Contact: Daniel Vetter, Thierry Reding, respective driver maintainers -Switch from reference/unreference to get/put --------------------------------------------- - -For some reason DRM core uses ``reference``/``unreference`` suffixes for -refcounting functions, but kernel uses ``get``/``put`` (e.g. -``kref_get``/``put()``). It would be good to switch over for consistency, and -it's shorter. Needs to be done in 3 steps for each pair of functions: - -* Create new ``get``/``put`` functions, define the old names as compatibility - wrappers -* Switch over each file/driver using a cocci-generated spatch. -* Once all users of the old names are gone, remove them. - -This way drivers/patches in the progress of getting merged won't break. - -Contact: Daniel Vetter - Convert existing KMS drivers to atomic modesetting -------------------------------------------------- -- cgit v1.2.3-58-ga151 From 686d263856a9d5e1b3f66c7795308af9e8e20d96 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:33 +0100 Subject: drm/sun4i: Cleanup video/YUV source before enabling a layer This adds a dedicated function for cleaning the video and YUV source channel layer enable bits. This function is called first on layer atomic update to make sure that there are no leftover bits from previous plane configuration that were not cleaned until now. It fixes issues when alternating between video and YUV planes, where both bits would be set eventually, leading to broken plane display. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-2-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 9 +++++++++ drivers/gpu/drm/sun4i/sun4i_backend.h | 2 ++ drivers/gpu/drm/sun4i/sun4i_layer.c | 2 ++ 3 files changed, 13 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index bf49c55b0f2c..67b4bb4f5365 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -395,6 +395,15 @@ int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer, return 0; } +void sun4i_backend_cleanup_layer(struct sun4i_backend *backend, + int layer) +{ + regmap_update_bits(backend->engine.regs, + SUN4I_BACKEND_ATTCTL_REG0(layer), + SUN4I_BACKEND_ATTCTL_REG0_LAY_VDOEN | + SUN4I_BACKEND_ATTCTL_REG0_LAY_YUVEN, 0); +} + static bool sun4i_backend_plane_uses_scaler(struct drm_plane_state *state) { u16 src_h = state->src_h >> 16; diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index e3d4c6035eb2..339dbff1cce4 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -208,5 +208,7 @@ int sun4i_backend_update_layer_frontend(struct sun4i_backend *backend, int layer, uint32_t in_fmt); int sun4i_backend_update_layer_zpos(struct sun4i_backend *backend, int layer, struct drm_plane *plane); +void sun4i_backend_cleanup_layer(struct sun4i_backend *backend, + int layer); #endif /* _SUN4I_BACKEND_H_ */ diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 3f51744b6e89..7ba0f5a6f50d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -93,6 +93,8 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, struct sun4i_backend *backend = layer->backend; struct sun4i_frontend *frontend = backend->frontend; + sun4i_backend_cleanup_layer(backend, layer->id); + if (layer_state->uses_frontend) { sun4i_frontend_init(frontend); sun4i_frontend_update_coord(frontend, plane); -- cgit v1.2.3-58-ga151 From b79a3a97f64f90dac79a9fc57a0280607306ba38 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:34 +0100 Subject: drm/sun4i: frontend: Replace ARGB with XRGB as supported format The frontend documentation (for the A33) mentions that ARGB is supported as output, but with the alpha component always set to 0xff. In practice, this means that the alpha component cannot be preserved when going through the frontend. Since the information is lost, ARGB is not properly supported. As a result, expose the matching format supported by the frontend (both for input and output) as XRGB instead of ARGB. Since ARGB was the selected format for connecting the frontend to the backend, change it to XRGB to reflect this as well. The A31 and A80 SoCs apparently have a bit to enable proper alpha, but this is not supported at this point (see the comment already in the code). Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-3-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 3 +-- drivers/gpu/drm/sun4i/sun4i_layer.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index ddf6cfa6dd23..3ea925584891 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -107,7 +107,7 @@ EXPORT_SYMBOL(sun4i_frontend_update_buffer); static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) { switch (fmt) { - case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: *val = 5; return 0; @@ -120,7 +120,6 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) { switch (fmt) { case DRM_FORMAT_XRGB8888: - case DRM_FORMAT_ARGB8888: *val = 2; return 0; diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 7ba0f5a6f50d..1d007001ea71 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -100,9 +100,9 @@ static void sun4i_backend_layer_atomic_update(struct drm_plane *plane, sun4i_frontend_update_coord(frontend, plane); sun4i_frontend_update_buffer(frontend, plane); sun4i_frontend_update_formats(frontend, plane, - DRM_FORMAT_ARGB8888); + DRM_FORMAT_XRGB8888); sun4i_backend_update_layer_frontend(backend, layer->id, - DRM_FORMAT_ARGB8888); + DRM_FORMAT_XRGB8888); sun4i_frontend_enable(frontend); } else { sun4i_backend_update_layer_formats(backend, layer->id, plane); -- cgit v1.2.3-58-ga151 From ad25d0736db00afb2c7bf355bc50437434325387 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:35 +0100 Subject: drm/sun4i: Add TODO comment about supporting scaling with the backend The backend allows integer-only scaling but can handle alpha components, unlike the frontend. It could be useful to add support for this eventually, so add a short TODO comment describing the situation. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-4-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 67b4bb4f5365..c3444246755b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -426,6 +426,11 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) if (IS_ERR(backend->frontend)) return false; + /* + * TODO: The backend alone allows 2x and 4x integer scaling, including + * support for an alpha component (which the frontend doesn't support). + * Use the backend directly instead of the frontend in this case. + */ return sun4i_backend_plane_uses_scaler(state); } -- cgit v1.2.3-58-ga151 From 3d4265f89d064df2a6952e3f24a3da4fd687cc65 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:36 +0100 Subject: drm/sun4i: backend: Add a helper and a list for supported formats In order to check whether the backend supports a specific format, an explicit list and a related helper are introduced. The prototype of this helper is added to the header so that it can be called from sun4i_layer later (when introducing tiled mode support). Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-5-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 27 +++++++++++++++++++++++++++ drivers/gpu/drm/sun4i/sun4i_backend.h | 1 + 2 files changed, 28 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index c3444246755b..7dd24eb03f89 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -155,6 +155,33 @@ static int sun4i_backend_drm_format_to_layer(u32 format, u32 *mode) return 0; } +static const uint32_t sun4i_backend_formats[] = { + DRM_FORMAT_ARGB1555, + DRM_FORMAT_ARGB4444, + DRM_FORMAT_ARGB8888, + DRM_FORMAT_BGRX8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_RGB888, + DRM_FORMAT_RGBA4444, + DRM_FORMAT_RGBA5551, + DRM_FORMAT_UYVY, + DRM_FORMAT_VYUY, + DRM_FORMAT_XRGB8888, + DRM_FORMAT_YUYV, + DRM_FORMAT_YVYU, +}; + +bool sun4i_backend_format_is_supported(uint32_t fmt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++) + if (sun4i_backend_formats[i] == fmt) + return true; + + return false; +} + int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, int layer, struct drm_plane *plane) { diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 339dbff1cce4..93db3af675b3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -198,6 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine) void sun4i_backend_layer_enable(struct sun4i_backend *backend, int layer, bool enable); +bool sun4i_backend_format_is_supported(uint32_t fmt); int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, int layer, struct drm_plane *plane); int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, -- cgit v1.2.3-58-ga151 From ee286db13395d6c228d3f9f96e7121739a6b229a Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:37 +0100 Subject: drm/sun4i: frontend: Add a helper and a list for supported formats In order to check whether the frontend supports a specific format, an explicit list and a related helper are introduced. Just like in the backend, the prototype of the helper is added to the frontend header so that it can be used later on. The helper is also exported because it will be used outside of the frontend module. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-6-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 16 ++++++++++++++++ drivers/gpu/drm/sun4i/sun4i_frontend.h | 1 + 2 files changed, 17 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 3ea925584891..0f7f8c7b3402 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -128,6 +128,22 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) } } +static const uint32_t sun4i_frontend_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +bool sun4i_frontend_format_is_supported(uint32_t fmt) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++) + if (sun4i_frontend_formats[i] == fmt) + return true; + + return false; +} +EXPORT_SYMBOL(sun4i_frontend_format_is_supported); + int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, struct drm_plane *plane, uint32_t out_fmt) { diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h index 02661ce81f3e..a9cb908ced16 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.h +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h @@ -95,5 +95,6 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, struct drm_plane *plane); int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, struct drm_plane *plane, uint32_t out_fmt); +bool sun4i_frontend_format_is_supported(uint32_t fmt); #endif /* _SUN4I_FRONTEND_H_ */ -- cgit v1.2.3-58-ga151 From aaf3880b0823113af9ed742a687e7fb1b411a201 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:38 +0100 Subject: drm/sun4i: backend: Refine the logic behind using the frontend Checking that scaling is in use is not sufficient as a condition to decide to use the frontend. Since not all layer formats are supported by the frontend, we need to check for that support first. Then, the frontend must only be enabled if the backend doesn't support the format or that scaling is required. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-7-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 7dd24eb03f89..735fea7ead0b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -449,16 +449,32 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) { struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); struct sun4i_backend *backend = layer->backend; + uint32_t format = state->fb->format->format; if (IS_ERR(backend->frontend)) return false; + if (!sun4i_frontend_format_is_supported(format)) + return false; + + if (!sun4i_backend_format_is_supported(format)) + return true; + /* * TODO: The backend alone allows 2x and 4x integer scaling, including * support for an alpha component (which the frontend doesn't support). - * Use the backend directly instead of the frontend in this case. + * Use the backend directly instead of the frontend in this case, with + * another test to return false. + */ + + if (sun4i_backend_plane_uses_scaler(state)) + return true; + + /* + * Here the format is supported by both the frontend and the backend + * and no frontend scaling is required, so use the backend directly. */ - return sun4i_backend_plane_uses_scaler(state); + return false; } static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, -- cgit v1.2.3-58-ga151 From ab6985108a53d531f0abaf06529ba148403d187d Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:39 +0100 Subject: drm/sun4i: backend: Use a specific function to check if a plane is supported Before this patch, it is assumed that a plane is supported either through the frontend or through the backend alone. However, the DRM interface does not allow finely reporting our hardware capabilities and there are cases where neither are support. In particular, some plane formats are supported by the backend and not the frontend, so they can only be supported without scaling. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-8-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 735fea7ead0b..52caf561da0e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -477,6 +477,23 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) return false; } +static bool sun4i_backend_plane_is_supported(struct drm_plane_state *state, + bool *uses_frontend) +{ + if (sun4i_backend_plane_uses_frontend(state)) { + *uses_frontend = true; + return true; + } + + *uses_frontend = false; + + /* Scaling is not supported without the frontend. */ + if (sun4i_backend_plane_uses_scaler(state)) + return false; + + return true; +} + static void sun4i_backend_atomic_begin(struct sunxi_engine *engine, struct drm_crtc_state *old_state) { @@ -517,14 +534,14 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, struct drm_framebuffer *fb = plane_state->fb; struct drm_format_name_buf format_name; - if (sun4i_backend_plane_uses_frontend(plane_state)) { + if (!sun4i_backend_plane_is_supported(plane_state, + &layer_state->uses_frontend)) + return -EINVAL; + + if (layer_state->uses_frontend) { DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", plane->index); - - layer_state->uses_frontend = true; num_frontend_planes++; - } else { - layer_state->uses_frontend = false; } DRM_DEBUG_DRIVER("Plane FB format is %s\n", -- cgit v1.2.3-58-ga151 From ae56bfbdad9b1996037a7209321cfb2ef49ea563 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:46 +0100 Subject: drm/sun4i: backend: Avoid counting YUV planes that use the frontend Our hardware has a limited number of YUV planes (usually 1) that can be supported using the backend only. However, YUV planes can also be supported by the frontend and must then not be counted when checking for that limitation. Only count the YUV plane when the frontend is not used. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-15-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 52caf561da0e..2a9569f16c81 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -542,6 +542,11 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, DRM_DEBUG_DRIVER("Using the frontend for plane %d\n", plane->index); num_frontend_planes++; + } else { + if (fb->format->is_yuv) { + DRM_DEBUG_DRIVER("Plane FB format is YUV\n"); + num_yuv_planes++; + } } DRM_DEBUG_DRIVER("Plane FB format is %s\n", @@ -550,11 +555,6 @@ static int sun4i_backend_atomic_check(struct sunxi_engine *engine, if (fb->format->has_alpha || (plane_state->alpha != DRM_BLEND_ALPHA_OPAQUE)) num_alpha_planes++; - if (fb->format->is_yuv) { - DRM_DEBUG_DRIVER("Plane FB format is YUV\n"); - num_yuv_planes++; - } - DRM_DEBUG_DRIVER("Plane zpos is %d\n", plane_state->normalized_zpos); -- cgit v1.2.3-58-ga151 From 1c29d263f6243e0007f0c61a82d1e1261efc5395 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:47 +0100 Subject: drm/sun4i: Rename sun4i_backend_layer_formats to sun4i_layer_formats Since more formats can be supported by the frontend, rename the variable listing the layer formats to avoid suggesting that the backend itself supports all the listed formats. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-16-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_layer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 1d007001ea71..155933c62f00 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -129,7 +129,7 @@ static const struct drm_plane_funcs sun4i_backend_layer_funcs = { .update_plane = drm_atomic_helper_update_plane, }; -static const uint32_t sun4i_backend_layer_formats[] = { +static const uint32_t sun4i_layer_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_ARGB4444, DRM_FORMAT_ARGB1555, @@ -158,8 +158,8 @@ static struct sun4i_layer *sun4i_layer_init_one(struct drm_device *drm, /* possible crtcs are set later */ ret = drm_universal_plane_init(drm, &layer->plane, 0, &sun4i_backend_layer_funcs, - sun4i_backend_layer_formats, - ARRAY_SIZE(sun4i_backend_layer_formats), + sun4i_layer_formats, + ARRAY_SIZE(sun4i_layer_formats), NULL, type, NULL); if (ret) { dev_err(drm->dev, "Couldn't initialize layer\n"); -- cgit v1.2.3-58-ga151 From 01260ffad2a8eff7f43218bdc93072fd068036f6 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:48 +0100 Subject: drm/sun4i: frontend: Move CSC bypass setup to format update routine In order to support YUV to RGB conversion with the frontend (which is generally used for connecting with the backend), the CSC block must not be bypassed. As a result, the bit to enable CSC bypass is moved from the runtime resume routine to the format update routine, so that it can disabled when introducing support for YUV formats later. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-17-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 0f7f8c7b3402..f54b1c4a9264 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -177,6 +177,10 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTPHASE1_REG, 0x400); regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTPHASE1_REG, 0x400); + regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG, + SUN4I_FRONTEND_BYPASS_CSC_EN, + SUN4I_FRONTEND_BYPASS_CSC_EN); + regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) | SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) | @@ -354,10 +358,6 @@ static int sun4i_frontend_runtime_resume(struct device *dev) SUN4I_FRONTEND_EN_EN, SUN4I_FRONTEND_EN_EN); - regmap_update_bits(frontend->regs, SUN4I_FRONTEND_BYPASS_REG, - SUN4I_FRONTEND_BYPASS_CSC_EN, - SUN4I_FRONTEND_BYPASS_CSC_EN); - sun4i_frontend_scaler_init(frontend); return 0; -- cgit v1.2.3-58-ga151 From 47d0f9bdb190eccbd2d9f9b6a585ae64e48f8183 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:49 +0100 Subject: drm/sun4i: frontend: Add helpers for input data mode and pixel sequence This introduces new helpers for retrieving the input data mode and pixel sequence register field values based on the DRM format instead of hardcoding these. This makes it easier to add support for more formats. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-18-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 46 ++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index f54b1c4a9264..bb5977a466f3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -116,6 +116,30 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) } } +static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val) +{ + switch (fmt) { + case DRM_FORMAT_XRGB8888: + *val = 1; + return 0; + + default: + return -EINVAL; + } +} + +static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val) +{ + switch (fmt) { + case DRM_FORMAT_XRGB8888: + *val = 1; + return 0; + + default: + return -EINVAL; + } +} + static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) { switch (fmt) { @@ -149,17 +173,29 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, { struct drm_plane_state *state = plane->state; struct drm_framebuffer *fb = state->fb; + uint32_t format = fb->format->format; u32 out_fmt_val; - u32 in_fmt_val; + u32 in_fmt_val, in_mod_val, in_ps_val; int ret; - ret = sun4i_frontend_drm_format_to_input_fmt(fb->format->format, - &in_fmt_val); + ret = sun4i_frontend_drm_format_to_input_fmt(format, &in_fmt_val); if (ret) { DRM_DEBUG_DRIVER("Invalid input format\n"); return ret; } + ret = sun4i_frontend_drm_format_to_input_mode(format, &in_mod_val); + if (ret) { + DRM_DEBUG_DRIVER("Invalid input mode\n"); + return ret; + } + + ret = sun4i_frontend_drm_format_to_input_sequence(format, &in_ps_val); + if (ret) { + DRM_DEBUG_DRIVER("Invalid pixel sequence\n"); + return ret; + } + ret = sun4i_frontend_drm_format_to_output_fmt(out_fmt, &out_fmt_val); if (ret) { DRM_DEBUG_DRIVER("Invalid output format\n"); @@ -182,9 +218,9 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, SUN4I_FRONTEND_BYPASS_CSC_EN); regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, - SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(1) | + SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(in_mod_val) | SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) | - SUN4I_FRONTEND_INPUT_FMT_PS(1)); + SUN4I_FRONTEND_INPUT_FMT_PS(in_ps_val)); /* * TODO: It look like the A31 and A80 at least will need the -- cgit v1.2.3-58-ga151 From 9579f9190487cc99ac280beda5da8ba7c3414b92 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:50 +0100 Subject: drm/sun4i: frontend: Add proper definitions for format registers This introduces proper definitions for the input and output format configuration registers instead of a macro and raw values in the code, with the intent to increase code readability and reduce indirections. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-19-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 14 ++++++-------- drivers/gpu/drm/sun4i/sun4i_frontend.h | 8 ++++---- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index bb5977a466f3..a305b731b042 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -108,7 +108,7 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) { switch (fmt) { case DRM_FORMAT_XRGB8888: - *val = 5; + *val = SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB; return 0; default: @@ -120,7 +120,7 @@ static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val) { switch (fmt) { case DRM_FORMAT_XRGB8888: - *val = 1; + *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED; return 0; default: @@ -132,7 +132,7 @@ static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val) { switch (fmt) { case DRM_FORMAT_XRGB8888: - *val = 1; + *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB; return 0; default: @@ -144,7 +144,7 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) { switch (fmt) { case DRM_FORMAT_XRGB8888: - *val = 2; + *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888; return 0; default: @@ -218,9 +218,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, SUN4I_FRONTEND_BYPASS_CSC_EN); regmap_write(frontend->regs, SUN4I_FRONTEND_INPUT_FMT_REG, - SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(in_mod_val) | - SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(in_fmt_val) | - SUN4I_FRONTEND_INPUT_FMT_PS(in_ps_val)); + in_mod_val | in_fmt_val | in_ps_val); /* * TODO: It look like the A31 and A80 at least will need the @@ -228,7 +226,7 @@ int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, * ARGB8888). */ regmap_write(frontend->regs, SUN4I_FRONTEND_OUTPUT_FMT_REG, - SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(out_fmt_val)); + out_fmt_val); return 0; } diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h index a9cb908ced16..56bd5a3f9723 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.h +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h @@ -26,12 +26,12 @@ #define SUN4I_FRONTEND_LINESTRD0_REG 0x040 #define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c -#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD(mod) ((mod) << 8) -#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT(fmt) ((fmt) << 4) -#define SUN4I_FRONTEND_INPUT_FMT_PS(ps) (ps) +#define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED (1 << 8) +#define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB (5 << 4) +#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB 1 #define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c -#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT(fmt) (fmt) +#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888 2 #define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100 #define SUN4I_FRONTEND_INSIZE(h, w) ((((h) - 1) << 16) | (((w) - 1))) -- cgit v1.2.3-58-ga151 From ae4ba1936ab97c6a2733a243370f303da3c11839 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:51 +0100 Subject: drm/sun4i: frontend: Determine input mode based on the number of planes Use the number of planes associated with the DRM format to determine the input mode configuration instead of the format iteself. This way, the helper can be used for all packed formats without future changes. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-20-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index a305b731b042..a16697b0eac5 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -118,14 +118,12 @@ static int sun4i_frontend_drm_format_to_input_fmt(uint32_t fmt, u32 *val) static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val) { - switch (fmt) { - case DRM_FORMAT_XRGB8888: + if (drm_format_num_planes(fmt) == 1) *val = SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED; - return 0; - - default: + else return -EINVAL; - } + + return 0; } static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val) -- cgit v1.2.3-58-ga151 From b636d3f97d041cbb5e782a29b282c40cbd77c0aa Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:53 +0100 Subject: drm/sun4i: frontend: Add support for the BGRX8888 input format This introduces support for the BGRX8888 input format for the frontend, with its associated pixel sequence value definition. Other fields are already configured correctly as they no longer depend on the format's fourcc directly. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-22-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 5 +++++ drivers/gpu/drm/sun4i/sun4i_frontend.h | 1 + drivers/gpu/drm/sun4i/sun4i_layer.c | 1 + 3 files changed, 7 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index a16697b0eac5..a75a74fc225d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -129,6 +129,10 @@ static int sun4i_frontend_drm_format_to_input_mode(uint32_t fmt, u32 *val) static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val) { switch (fmt) { + case DRM_FORMAT_BGRX8888: + *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX; + return 0; + case DRM_FORMAT_XRGB8888: *val = SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB; return 0; @@ -151,6 +155,7 @@ static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) } static const uint32_t sun4i_frontend_formats[] = { + DRM_FORMAT_BGRX8888, DRM_FORMAT_XRGB8888, }; diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h index 56bd5a3f9723..2ee1bccf378a 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.h +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h @@ -28,6 +28,7 @@ #define SUN4I_FRONTEND_INPUT_FMT_REG 0x04c #define SUN4I_FRONTEND_INPUT_FMT_DATA_MOD_PACKED (1 << 8) #define SUN4I_FRONTEND_INPUT_FMT_DATA_FMT_RGB (5 << 4) +#define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_BGRX 0 #define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB 1 #define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index 155933c62f00..29631e0efde3 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -133,6 +133,7 @@ static const uint32_t sun4i_layer_formats[] = { DRM_FORMAT_ARGB8888, DRM_FORMAT_ARGB4444, DRM_FORMAT_ARGB1555, + DRM_FORMAT_BGRX8888, DRM_FORMAT_RGBA5551, DRM_FORMAT_RGBA4444, DRM_FORMAT_RGB888, -- cgit v1.2.3-58-ga151 From dc7d4b655a2c4a8db1342600319a7939eafeb9af Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:55 +0100 Subject: drm/sun4i: backend: Detail the YUV to RGB values coding explanation The values in the BT601 YUV to RGB colorspace translation are not simply coded as multiples, but rather as fixed-point signed fractional values on a given number of bits. Add an explanation about that. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-24-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 2a9569f16c81..f43c4b0f1e5d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -48,8 +48,12 @@ static const u32 sunxi_rgb2yuv_coef[12] = { /* * These coefficients are taken from the A33 BSP from Allwinner. * - * The formula is for each component, each coefficient being multiplied by - * 1024 and each constant being multiplied by 16: + * The first three values of each row are coded as 13-bit signed fixed-point + * numbers, with 10 bits for the fractional part. The fourth value is a + * constant coded as a 14-bit signed fixed-point number with 4 bits for the + * fractional part. + * + * The values in table order give the following colorspace translation: * G = 1.164 * Y - 0.391 * U - 0.813 * V + 135 * R = 1.164 * Y + 1.596 * V - 222 * B = 1.164 * Y + 2.018 * U + 276 -- cgit v1.2.3-58-ga151 From 411e83069e1590cad8c29adcb04de8e73714fa9f Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:57 +0100 Subject: drm/sun4i: frontend: Apply format sub-sampling to CH1 dimensions The frontend comes with two "channels", that can be configured independently. When used in YUV mode, the first channel (CH0) represents the luminance component while the second channel (CH1) represents the chrominance. In RGB mode, both have to be configured the same way. Use variables (with the YUV terminology) for each channel's dimensions, calculating the chroma dimensions from the luma dimensions and the sub-sampling factors from the format description. Since the configured size only has pixel precision, the fractional fixed-point part of the source size is dropped for both components to ensure that the scaling factors are accurate. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-26-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index a75a74fc225d..72e0f1b1624b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -239,16 +239,24 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, struct drm_plane *plane) { struct drm_plane_state *state = plane->state; + struct drm_framebuffer *fb = state->fb; + uint32_t luma_width, luma_height; + uint32_t chroma_width, chroma_height; /* Set height and width */ DRM_DEBUG_DRIVER("Frontend size W: %u H: %u\n", state->crtc_w, state->crtc_h); + + luma_width = state->src_w >> 16; + luma_height = state->src_h >> 16; + + chroma_width = DIV_ROUND_UP(luma_width, fb->format->hsub); + chroma_height = DIV_ROUND_UP(luma_height, fb->format->vsub); + regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_INSIZE_REG, - SUN4I_FRONTEND_INSIZE(state->src_h >> 16, - state->src_w >> 16)); + SUN4I_FRONTEND_INSIZE(luma_height, luma_width)); regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_INSIZE_REG, - SUN4I_FRONTEND_INSIZE(state->src_h >> 16, - state->src_w >> 16)); + SUN4I_FRONTEND_INSIZE(chroma_height, chroma_width)); regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_OUTSIZE_REG, SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); @@ -256,14 +264,14 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, SUN4I_FRONTEND_OUTSIZE(state->crtc_h, state->crtc_w)); regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_HORZFACT_REG, - state->src_w / state->crtc_w); + (luma_width << 16) / state->crtc_w); regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_HORZFACT_REG, - state->src_w / state->crtc_w); + (chroma_width << 16) / state->crtc_w); regmap_write(frontend->regs, SUN4I_FRONTEND_CH0_VERTFACT_REG, - state->src_h / state->crtc_h); + (luma_height << 16) / state->crtc_h); regmap_write(frontend->regs, SUN4I_FRONTEND_CH1_VERTFACT_REG, - state->src_h / state->crtc_h); + (chroma_height << 16) / state->crtc_h); regmap_write_bits(frontend->regs, SUN4I_FRONTEND_FRM_CTRL_REG, SUN4I_FRONTEND_FRM_CTRL_REG_RDY, -- cgit v1.2.3-58-ga151 From 31cf282a53cf529ebe9e4bb50f0e750226f870a7 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:25:01 +0100 Subject: drm/sun4i: Make pitch even for GEM dumb alloc as per hardware constraint Our hardware requires the pitch to be an even number when using YUV formats with the frontend. Implement a driver-specific callback for GEM dumb allocation that sets the pitch accordingly. Since only the bpp is passed (and not the format), we cannot really distinguish if this alignment is really required. Since it doesn't hurt to align the pitch anyway, always do it. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-30-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_drv.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index ef773d36baf0..ccdeae6299eb 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -28,6 +28,16 @@ #include "sun4i_tcon.h" #include "sun8i_tcon_top.h" +static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv, + struct drm_device *drm, + struct drm_mode_create_dumb *args) +{ + /* The hardware only allows even pitches for YUV buffers. */ + args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), 2); + + return drm_gem_cma_dumb_create_internal(file_priv, drm, args); +} + DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); static struct drm_driver sun4i_drv_driver = { @@ -42,7 +52,7 @@ static struct drm_driver sun4i_drv_driver = { .minor = 0, /* GEM Operations */ - .dumb_create = drm_gem_cma_dumb_create, + .dumb_create = drm_sun4i_gem_dumb_create, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, -- cgit v1.2.3-58-ga151 From b36d95846117dc47cd5a7e854a862aa2b509026b Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:24:54 +0100 Subject: drm/sun4i: frontend: Add support for the BGRX8888 output format This introduces support for the BGRX8888 output format for the frontend, with its associated output format value definition. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-23-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_frontend.c | 4 ++++ drivers/gpu/drm/sun4i/sun4i_frontend.h | 1 + 2 files changed, 5 insertions(+) diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 72e0f1b1624b..5d765764bff9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -145,6 +145,10 @@ static int sun4i_frontend_drm_format_to_input_sequence(uint32_t fmt, u32 *val) static int sun4i_frontend_drm_format_to_output_fmt(uint32_t fmt, u32 *val) { switch (fmt) { + case DRM_FORMAT_BGRX8888: + *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888; + return 0; + case DRM_FORMAT_XRGB8888: *val = SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888; return 0; diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h index 2ee1bccf378a..800a193eebc2 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.h +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h @@ -32,6 +32,7 @@ #define SUN4I_FRONTEND_INPUT_FMT_DATA_PS_XRGB 1 #define SUN4I_FRONTEND_OUTPUT_FMT_REG 0x05c +#define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_BGRX8888 1 #define SUN4I_FRONTEND_OUTPUT_FMT_DATA_FMT_XRGB8888 2 #define SUN4I_FRONTEND_CH0_INSIZE_REG 0x100 -- cgit v1.2.3-58-ga151 From 02a3ce3c2a67f3c3693029bc650f0c0571d9a3a2 Mon Sep 17 00:00:00 2001 From: Paul Kocialkowski Date: Fri, 23 Nov 2018 10:25:04 +0100 Subject: drm/sun4i: Pass modifier to backend and frontend format support helpers To prepare the introduction of tiled mode support, pass the framebuffer format modifier to the helpers dealing with format support. Since only linear mode is supported for now, add corresponding checks in each helper. Signed-off-by: Paul Kocialkowski Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20181123092515.2511-33-paul.kocialkowski@bootlin.com --- drivers/gpu/drm/sun4i/sun4i_backend.c | 10 +++++++--- drivers/gpu/drm/sun4i/sun4i_backend.h | 2 +- drivers/gpu/drm/sun4i/sun4i_frontend.c | 5 ++++- drivers/gpu/drm/sun4i/sun4i_frontend.h | 2 +- 4 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index f43c4b0f1e5d..9e9255ee59cd 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -175,10 +175,13 @@ static const uint32_t sun4i_backend_formats[] = { DRM_FORMAT_YVYU, }; -bool sun4i_backend_format_is_supported(uint32_t fmt) +bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier) { unsigned int i; + if (modifier != DRM_FORMAT_MOD_LINEAR) + return false; + for (i = 0; i < ARRAY_SIZE(sun4i_backend_formats); i++) if (sun4i_backend_formats[i] == fmt) return true; @@ -454,14 +457,15 @@ static bool sun4i_backend_plane_uses_frontend(struct drm_plane_state *state) struct sun4i_layer *layer = plane_to_sun4i_layer(state->plane); struct sun4i_backend *backend = layer->backend; uint32_t format = state->fb->format->format; + uint64_t modifier = state->fb->modifier; if (IS_ERR(backend->frontend)) return false; - if (!sun4i_frontend_format_is_supported(format)) + if (!sun4i_frontend_format_is_supported(format, modifier)) return false; - if (!sun4i_backend_format_is_supported(format)) + if (!sun4i_backend_format_is_supported(format, modifier)) return true; /* diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.h b/drivers/gpu/drm/sun4i/sun4i_backend.h index 93db3af675b3..01f66463271b 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.h +++ b/drivers/gpu/drm/sun4i/sun4i_backend.h @@ -198,7 +198,7 @@ engine_to_sun4i_backend(struct sunxi_engine *engine) void sun4i_backend_layer_enable(struct sun4i_backend *backend, int layer, bool enable); -bool sun4i_backend_format_is_supported(uint32_t fmt); +bool sun4i_backend_format_is_supported(uint32_t fmt, uint64_t modifier); int sun4i_backend_update_layer_coord(struct sun4i_backend *backend, int layer, struct drm_plane *plane); int sun4i_backend_update_layer_formats(struct sun4i_backend *backend, diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 5d765764bff9..1a7ebc45747e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -163,10 +163,13 @@ static const uint32_t sun4i_frontend_formats[] = { DRM_FORMAT_XRGB8888, }; -bool sun4i_frontend_format_is_supported(uint32_t fmt) +bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier) { unsigned int i; + if (modifier != DRM_FORMAT_MOD_LINEAR) + return false; + for (i = 0; i < ARRAY_SIZE(sun4i_frontend_formats); i++) if (sun4i_frontend_formats[i] == fmt) return true; diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.h b/drivers/gpu/drm/sun4i/sun4i_frontend.h index 800a193eebc2..ad146e8d8d70 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.h +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.h @@ -97,6 +97,6 @@ void sun4i_frontend_update_coord(struct sun4i_frontend *frontend, struct drm_plane *plane); int sun4i_frontend_update_formats(struct sun4i_frontend *frontend, struct drm_plane *plane, uint32_t out_fmt); -bool sun4i_frontend_format_is_supported(uint32_t fmt); +bool sun4i_frontend_format_is_supported(uint32_t fmt, uint64_t modifier); #endif /* _SUN4I_FRONTEND_H_ */ -- cgit v1.2.3-58-ga151 From 39dea70d8a479a1c4578129466da2bc4601e47be Mon Sep 17 00:00:00 2001 From: Daniel Vetter Date: Tue, 27 Nov 2018 10:19:21 +0100 Subject: drm: Improve dumb callback docs Noticed while reviewing a patch from Eric. Also add a todo for the dumb_map_offset callbacks (it should be simple to do, but piles of work). Plus fix up vbox, because vbox. Cc: Maarten Lankhorst Cc: Maxime Ripard Cc: Sean Paul Cc: David Airlie Cc: Greg Kroah-Hartman Cc: Hans de Goede Cc: Nicholas Mc Guire Cc: Daniel Vetter Cc: Fabio Rafael da Rosa Reviewed-by: Maxime Ripard Signed-off-by: Daniel Vetter Link: https://patchwork.freedesktop.org/patch/msgid/20181127091921.8325-1-daniel.vetter@ffwll.ch --- Documentation/gpu/todo.rst | 11 +++++++++++ drivers/staging/vboxvideo/vbox_drv.c | 1 - include/drm/drm_drv.h | 9 +++++++-- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/Documentation/gpu/todo.rst b/Documentation/gpu/todo.rst index 9815b3b82bd1..ab347dec5079 100644 --- a/Documentation/gpu/todo.rst +++ b/Documentation/gpu/todo.rst @@ -28,6 +28,17 @@ them, but also all the virtual ones used by KVM, so everyone qualifies). Contact: Daniel Vetter, Thierry Reding, respective driver maintainers + +Remove custom dumb_map_offset implementations +--------------------------------------------- + +All GEM based drivers should be using drm_gem_create_mmap_offset() instead. +Audit each individual driver, make sure it'll work with the generic +implementation (there's lots of outdated locking leftovers in various +implementations), and then remove it. + +Contact: Daniel Vetter, respective driver maintainers + Convert existing KMS drivers to atomic modesetting -------------------------------------------------- diff --git a/drivers/staging/vboxvideo/vbox_drv.c b/drivers/staging/vboxvideo/vbox_drv.c index 257030460fb6..d3e23dd70c1b 100644 --- a/drivers/staging/vboxvideo/vbox_drv.c +++ b/drivers/staging/vboxvideo/vbox_drv.c @@ -279,7 +279,6 @@ static struct drm_driver driver = { .gem_free_object_unlocked = vbox_gem_free_object, .dumb_create = vbox_dumb_create, .dumb_map_offset = vbox_dumb_mmap_offset, - .dumb_destroy = drm_gem_dumb_destroy, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = drm_gem_prime_export, diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h index 252dd216cc60..35af23f5fa0d 100644 --- a/include/drm/drm_drv.h +++ b/include/drm/drm_drv.h @@ -527,8 +527,10 @@ struct drm_driver { * @dumb_map_offset: * * Allocate an offset in the drm device node's address space to be able to - * memory map a dumb buffer. GEM-based drivers must use - * drm_gem_create_mmap_offset() to implement this. + * memory map a dumb buffer. + * + * The default implementation is drm_gem_create_mmap_offset(). GEM based + * drivers must not overwrite this. * * Called by the user via ioctl. * @@ -548,6 +550,9 @@ struct drm_driver { * * Called by the user via ioctl. * + * The default implementation is drm_gem_dumb_destroy(). GEM based drivers + * must not overwrite this. + * * Returns: * * Zero on success, negative errno on failure. -- cgit v1.2.3-58-ga151 From 5d0bfe448481c9c109f5052c4ad36ef855aedc4f Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 6 Nov 2018 10:35:09 +0100 Subject: drm/meson: Add HDMI 1.4 4k modes Add the timings for the HDMI 1.4 4K modes support : - 3840x2160@30 - 3840x2160@25 - 3840x2160@24 Since the 297000Hz pixel clock is already managed and the modes are compatible with the HDMI 1.4 current HDMI PHY+Controller support, only the missing timings values needs to be added. Signed-off-by: Neil Armstrong Reviewed-by: Maxime Jourdan Link: https://patchwork.freedesktop.org/patch/msgid/1541496909-19625-1-git-send-email-narmstrong@baylibre.com --- drivers/gpu/drm/meson/meson_venc.c | 129 +++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c index 514245e69b38..bcffe8ea642c 100644 --- a/drivers/gpu/drm/meson/meson_venc.c +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -697,6 +697,132 @@ union meson_hdmi_venc_mode meson_hdmi_encp_mode_1080p60 = { }, }; +union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p24 = { + .encp = { + .dvi_settings = 0x1, + .video_mode = 0x4040, + .video_mode_adv = 0x8, + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + .video_filt_ctrl = 0x1000, + .video_filt_ctrl_present = true, + /* video_ofld_voav_ofst */ + .yfp1_htime = 140, + .yfp2_htime = 140+3840, + .max_pxcnt = 3840+1660-1, + .hspuls_begin = 2156+1920, + .hspuls_end = 44, + .hspuls_switch = 44, + .vspuls_begin = 140, + .vspuls_end = 2059+1920, + .vspuls_bline = 0, + .vspuls_eline = 4, + .havon_begin = 148, + .havon_end = 3987, + .vavon_bline = 89, + .vavon_eline = 2248, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 44, + .hso_end = 2156+1920, + .vso_begin = 2100+1920, + .vso_end = 2164+1920, + .vso_bline = 51, + .vso_eline = 53, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 2249, + }, +}; + +union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p25 = { + .encp = { + .dvi_settings = 0x1, + .video_mode = 0x4040, + .video_mode_adv = 0x8, + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + .video_filt_ctrl = 0x1000, + .video_filt_ctrl_present = true, + /* video_ofld_voav_ofst */ + .yfp1_htime = 140, + .yfp2_htime = 140+3840, + .max_pxcnt = 3840+1440-1, + .hspuls_begin = 2156+1920, + .hspuls_end = 44, + .hspuls_switch = 44, + .vspuls_begin = 140, + .vspuls_end = 2059+1920, + .vspuls_bline = 0, + .vspuls_eline = 4, + .havon_begin = 148, + .havon_end = 3987, + .vavon_bline = 89, + .vavon_eline = 2248, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 44, + .hso_end = 2156+1920, + .vso_begin = 2100+1920, + .vso_end = 2164+1920, + .vso_bline = 51, + .vso_eline = 53, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 2249, + }, +}; + +union meson_hdmi_venc_mode meson_hdmi_encp_mode_2160p30 = { + .encp = { + .dvi_settings = 0x1, + .video_mode = 0x4040, + .video_mode_adv = 0x8, + /* video_sync_mode */ + /* video_yc_dly */ + /* video_rgb_ctrl */ + .video_filt_ctrl = 0x1000, + .video_filt_ctrl_present = true, + /* video_ofld_voav_ofst */ + .yfp1_htime = 140, + .yfp2_htime = 140+3840, + .max_pxcnt = 3840+560-1, + .hspuls_begin = 2156+1920, + .hspuls_end = 44, + .hspuls_switch = 44, + .vspuls_begin = 140, + .vspuls_end = 2059+1920, + .vspuls_bline = 0, + .vspuls_eline = 4, + .havon_begin = 148, + .havon_end = 3987, + .vavon_bline = 89, + .vavon_eline = 2248, + /* eqpuls_begin */ + /* eqpuls_end */ + /* eqpuls_bline */ + /* eqpuls_eline */ + .hso_begin = 44, + .hso_end = 2156+1920, + .vso_begin = 2100+1920, + .vso_end = 2164+1920, + .vso_bline = 51, + .vso_eline = 53, + .vso_eline_present = true, + /* sy_val */ + /* sy2_val */ + .max_lncnt = 2249, + }, +}; + struct meson_hdmi_venc_vic_mode { unsigned int vic; union meson_hdmi_venc_mode *mode; @@ -717,6 +843,9 @@ struct meson_hdmi_venc_vic_mode { { 34, &meson_hdmi_encp_mode_1080p30 }, { 31, &meson_hdmi_encp_mode_1080p50 }, { 16, &meson_hdmi_encp_mode_1080p60 }, + { 93, &meson_hdmi_encp_mode_2160p24 }, + { 94, &meson_hdmi_encp_mode_2160p25 }, + { 95, &meson_hdmi_encp_mode_2160p30 }, { 0, NULL}, /* sentinel */ }; -- cgit v1.2.3-58-ga151 From ff217bc710e09360187ab5dd7d704f871c29e006 Mon Sep 17 00:00:00 2001 From: Neil Armstrong Date: Tue, 6 Nov 2018 11:54:35 +0100 Subject: drm/meson: Add support for VIC alternate timings This change is an attempt to handle the alternate clock for the CEA mode. 60Hz vs. 59.94Hz, 30Hz vs 29.97Hz or 24Hz vs 23.97Hz on the Amlogic Meson SoC DRM Driver pixel clock generation. The actual clock generation will be moved to the Common Clock framework once all the video clock are handled by the Amlogic Meson SoC clock driver, then these alternate timings will be handled in the same time in a cleaner fashion. Signed-off-by: Neil Armstrong Reviewed-by: Maxime Jourdan [narmstrong: fix maybe-uninitialized warnings after applying] Link: https://patchwork.freedesktop.org/patch/msgid/1541501675-3928-1-git-send-email-narmstrong@baylibre.com --- drivers/gpu/drm/meson/meson_dw_hdmi.c | 12 +--- drivers/gpu/drm/meson/meson_vclk.c | 127 +++++++++++++++++++++++----------- drivers/gpu/drm/meson/meson_vclk.h | 2 + 3 files changed, 89 insertions(+), 52 deletions(-) diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index df7247cd93f9..d8c5cc34e22e 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -594,17 +594,7 @@ dw_hdmi_mode_valid(struct drm_connector *connector, dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__, vclk_freq, venc_freq, hdmi_freq); - /* Finally filter by configurable vclk frequencies for VIC modes */ - switch (vclk_freq) { - case 54000: - case 74250: - case 148500: - case 297000: - case 594000: - return MODE_OK; - } - - return MODE_CLOCK_RANGE; + return meson_vclk_vic_supported_freq(vclk_freq); } /* Encoder */ diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index ae5473257f72..f6ba35a405f8 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -117,6 +117,8 @@ #define HDMI_PLL_RESET BIT(28) #define HDMI_PLL_LOCK BIT(31) +#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001) + /* VID PLL Dividers */ enum { VID_PLL_DIV_1 = 0, @@ -323,7 +325,7 @@ static void meson_venci_cvbs_clock_config(struct meson_drm *priv) enum { /* PLL O1 O2 O3 VP DV EN TX */ /* 4320 /4 /4 /1 /5 /1 => /2 /2 */ - MESON_VCLK_HDMI_ENCI_54000 = 1, + MESON_VCLK_HDMI_ENCI_54000 = 0, /* 4320 /4 /4 /1 /5 /1 => /1 /2 */ MESON_VCLK_HDMI_DDR_54000, /* 2970 /4 /1 /1 /5 /1 => /1 /2 */ @@ -339,6 +341,7 @@ enum { }; struct meson_vclk_params { + unsigned int pixel_freq; unsigned int pll_base_freq; unsigned int pll_od1; unsigned int pll_od2; @@ -347,6 +350,7 @@ struct meson_vclk_params { unsigned int vclk_div; } params[] = { [MESON_VCLK_HDMI_ENCI_54000] = { + .pixel_freq = 54000, .pll_base_freq = 4320000, .pll_od1 = 4, .pll_od2 = 4, @@ -355,6 +359,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_DDR_54000] = { + .pixel_freq = 54000, .pll_base_freq = 4320000, .pll_od1 = 4, .pll_od2 = 4, @@ -363,6 +368,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_DDR_148500] = { + .pixel_freq = 148500, .pll_base_freq = 2970000, .pll_od1 = 4, .pll_od2 = 1, @@ -371,6 +377,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_74250] = { + .pixel_freq = 74250, .pll_base_freq = 2970000, .pll_od1 = 2, .pll_od2 = 2, @@ -379,6 +386,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_148500] = { + .pixel_freq = 148500, .pll_base_freq = 2970000, .pll_od1 = 1, .pll_od2 = 2, @@ -387,6 +395,7 @@ struct meson_vclk_params { .vclk_div = 1, }, [MESON_VCLK_HDMI_297000] = { + .pixel_freq = 297000, .pll_base_freq = 2970000, .pll_od1 = 1, .pll_od2 = 1, @@ -395,6 +404,7 @@ struct meson_vclk_params { .vclk_div = 2, }, [MESON_VCLK_HDMI_594000] = { + .pixel_freq = 594000, .pll_base_freq = 5940000, .pll_od1 = 1, .pll_od2 = 1, @@ -402,6 +412,7 @@ struct meson_vclk_params { .vid_pll_div = VID_PLL_DIV_5, .vclk_div = 1, }, + { /* sentinel */ }, }; static inline unsigned int pll_od_to_reg(unsigned int od) @@ -626,12 +637,37 @@ static void meson_hdmi_pll_generic_set(struct meson_drm *priv, pll_freq); } +enum drm_mode_status +meson_vclk_vic_supported_freq(unsigned int freq) +{ + int i; + + DRM_DEBUG_DRIVER("freq = %d\n", freq); + + for (i = 0 ; params[i].pixel_freq ; ++i) { + DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n", + i, params[i].pixel_freq, + FREQ_1000_1001(params[i].pixel_freq)); + /* Match strict frequency */ + if (freq == params[i].pixel_freq) + return MODE_OK; + /* Match 1000/1001 variant */ + if (freq == FREQ_1000_1001(params[i].pixel_freq)) + return MODE_OK; + } + + return MODE_CLOCK_RANGE; +} +EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq); + static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq, unsigned int od1, unsigned int od2, unsigned int od3, unsigned int vid_pll_div, unsigned int vclk_div, unsigned int hdmi_tx_div, unsigned int venc_div, - bool hdmi_use_enci) + bool hdmi_use_enci, bool vic_alternate_clock) { + unsigned int m = 0, frac = 0; + /* Set HDMI-TX sys clock */ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, CTS_HDMI_SYS_SEL_MASK, 0); @@ -646,34 +682,38 @@ static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq, } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) { switch (pll_base_freq) { case 2970000: - meson_hdmi_pll_set_params(priv, 0x3d, 0xe00, - od1, od2, od3); + m = 0x3d; + frac = vic_alternate_clock ? 0xd02 : 0xe00; break; case 4320000: - meson_hdmi_pll_set_params(priv, 0x5a, 0, - od1, od2, od3); + m = vic_alternate_clock ? 0x59 : 0x5a; + frac = vic_alternate_clock ? 0xe8f : 0; break; case 5940000: - meson_hdmi_pll_set_params(priv, 0x7b, 0xc00, - od1, od2, od3); + m = 0x7b; + frac = vic_alternate_clock ? 0xa05 : 0xc00; break; } + + meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3); } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") || meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) { switch (pll_base_freq) { case 2970000: - meson_hdmi_pll_set_params(priv, 0x7b, 0x300, - od1, od2, od3); + m = 0x7b; + frac = vic_alternate_clock ? 0x281 : 0x300; break; case 4320000: - meson_hdmi_pll_set_params(priv, 0xb4, 0, - od1, od2, od3); + m = vic_alternate_clock ? 0xb3 : 0xb4; + frac = vic_alternate_clock ? 0x347 : 0; break; case 5940000: - meson_hdmi_pll_set_params(priv, 0xf7, 0x200, - od1, od2, od3); + m = 0xf7; + frac = vic_alternate_clock ? 0x102 : 0x200; break; } + + meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3); } /* Setup vid_pll divider */ @@ -826,6 +866,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, unsigned int vclk_freq, unsigned int venc_freq, unsigned int dac_freq, bool hdmi_use_enci) { + bool vic_alternate_clock = false; unsigned int freq; unsigned int hdmi_tx_div; unsigned int venc_div; @@ -843,7 +884,7 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, * - encp encoder */ meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0, - VID_PLL_DIV_5, 2, 1, 1, false); + VID_PLL_DIV_5, 2, 1, 1, false, false); return; } @@ -863,31 +904,35 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, return; } - switch (vclk_freq) { - case 54000: - if (hdmi_use_enci) - freq = MESON_VCLK_HDMI_ENCI_54000; - else - freq = MESON_VCLK_HDMI_DDR_54000; - break; - case 74250: - freq = MESON_VCLK_HDMI_74250; - break; - case 148500: - if (dac_freq != 148500) - freq = MESON_VCLK_HDMI_DDR_148500; - else - freq = MESON_VCLK_HDMI_148500; - break; - case 297000: - freq = MESON_VCLK_HDMI_297000; - break; - case 594000: - freq = MESON_VCLK_HDMI_594000; - break; - default: - pr_err("Fatal Error, invalid HDMI vclk freq %d\n", - vclk_freq); + for (freq = 0 ; params[freq].pixel_freq ; ++freq) { + if (vclk_freq == params[freq].pixel_freq || + vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) { + if (vclk_freq != params[freq].pixel_freq) + vic_alternate_clock = true; + else + vic_alternate_clock = false; + + if (freq == MESON_VCLK_HDMI_ENCI_54000 && + !hdmi_use_enci) + continue; + + if (freq == MESON_VCLK_HDMI_DDR_54000 && + hdmi_use_enci) + continue; + + if (freq == MESON_VCLK_HDMI_DDR_148500 && + dac_freq == vclk_freq) + continue; + + if (freq == MESON_VCLK_HDMI_148500 && + dac_freq != vclk_freq) + continue; + break; + } + } + + if (!params[freq].pixel_freq) { + pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq); return; } @@ -895,6 +940,6 @@ void meson_vclk_setup(struct meson_drm *priv, unsigned int target, params[freq].pll_od1, params[freq].pll_od2, params[freq].pll_od3, params[freq].vid_pll_div, params[freq].vclk_div, hdmi_tx_div, venc_div, - hdmi_use_enci); + hdmi_use_enci, vic_alternate_clock); } EXPORT_SYMBOL_GPL(meson_vclk_setup); diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h index 869fa3a3073e..4bd8752da02a 100644 --- a/drivers/gpu/drm/meson/meson_vclk.h +++ b/drivers/gpu/drm/meson/meson_vclk.h @@ -32,6 +32,8 @@ enum { enum drm_mode_status meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq); +enum drm_mode_status +meson_vclk_vic_supported_freq(unsigned int freq); void meson_vclk_setup(struct meson_drm *priv, unsigned int target, unsigned int vclk_freq, unsigned int venc_freq, -- cgit v1.2.3-58-ga151 From 3eb152720c734112c5069e531442463e0a2abfb3 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 8 Nov 2018 08:16:51 -0800 Subject: drm/v3d: Fix whitespace inconsistency in the header. Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-2-eric@anholt.net Reviewed-by: Boris Brezillon --- include/uapi/drm/v3d_drm.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/drm/v3d_drm.h b/include/uapi/drm/v3d_drm.h index f446656d00b1..b1e5de076b0f 100644 --- a/include/uapi/drm/v3d_drm.h +++ b/include/uapi/drm/v3d_drm.h @@ -66,7 +66,7 @@ struct drm_v3d_submit_cl { */ __u32 bcl_start; - /** End address of the BCL (first byte after the BCL) */ + /** End address of the BCL (first byte after the BCL) */ __u32 bcl_end; /* Offset of the render command list. @@ -82,7 +82,7 @@ struct drm_v3d_submit_cl { */ __u32 rcl_start; - /** End address of the RCL (first byte after the RCL) */ + /** End address of the RCL (first byte after the RCL) */ __u32 rcl_end; /** An optional sync object to wait on before starting the BCL. */ -- cgit v1.2.3-58-ga151 From e90e45f6bd45cc494a6f4cd1853c5e7cd4be7f68 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 8 Nov 2018 08:16:52 -0800 Subject: drm/v3d: Update a comment about what uses v3d_job_dependency(). I merged bin and render's paths in a late refactoring. Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-3-eric@anholt.net Reviewed-by: Boris Brezillon --- drivers/gpu/drm/v3d/v3d_sched.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c index 9243dea6e6ad..e1f2aab0717b 100644 --- a/drivers/gpu/drm/v3d/v3d_sched.c +++ b/drivers/gpu/drm/v3d/v3d_sched.c @@ -39,7 +39,7 @@ v3d_job_free(struct drm_sched_job *sched_job) } /** - * Returns the fences that the bin job depends on, one by one. + * Returns the fences that the bin or render job depends on, one by one. * v3d_job_run() won't be called until all of them have been signaled. */ static struct dma_fence * -- cgit v1.2.3-58-ga151 From 8f1cd826641d677d0f7494253ecfc3335f0bcd4e Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Thu, 8 Nov 2018 08:16:53 -0800 Subject: drm/v3d: Clean up the reservation object setup. The extra to_v3d_bo() calls came from copying this from the vc4 driver, which stored the cma gem object in the structs. v2: Fix an unused var warning Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181108161654.19888-4-eric@anholt.net Reviewed-by: Boris Brezillon (v1) --- drivers/gpu/drm/v3d/v3d_gem.c | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index b88c96911453..1e8947c7d954 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -210,14 +210,11 @@ static void v3d_attach_object_fences(struct v3d_exec_info *exec) { struct dma_fence *out_fence = exec->render_done_fence; - struct v3d_bo *bo; int i; for (i = 0; i < exec->bo_count; i++) { - bo = to_v3d_bo(&exec->bo[i]->base); - /* XXX: Use shared fences for read-only objects. */ - reservation_object_add_excl_fence(bo->resv, out_fence); + reservation_object_add_excl_fence(exec->bo[i]->resv, out_fence); } } @@ -228,11 +225,8 @@ v3d_unlock_bo_reservations(struct drm_device *dev, { int i; - for (i = 0; i < exec->bo_count; i++) { - struct v3d_bo *bo = to_v3d_bo(&exec->bo[i]->base); - - ww_mutex_unlock(&bo->resv->lock); - } + for (i = 0; i < exec->bo_count; i++) + ww_mutex_unlock(&exec->bo[i]->resv->lock); ww_acquire_fini(acquire_ctx); } @@ -251,13 +245,13 @@ v3d_lock_bo_reservations(struct drm_device *dev, { int contended_lock = -1; int i, ret; - struct v3d_bo *bo; ww_acquire_init(acquire_ctx, &reservation_ww_class); retry: if (contended_lock != -1) { - bo = to_v3d_bo(&exec->bo[contended_lock]->base); + struct v3d_bo *bo = exec->bo[contended_lock]; + ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, acquire_ctx); if (ret) { @@ -270,19 +264,16 @@ retry: if (i == contended_lock) continue; - bo = to_v3d_bo(&exec->bo[i]->base); - - ret = ww_mutex_lock_interruptible(&bo->resv->lock, acquire_ctx); + ret = ww_mutex_lock_interruptible(&exec->bo[i]->resv->lock, + acquire_ctx); if (ret) { int j; - for (j = 0; j < i; j++) { - bo = to_v3d_bo(&exec->bo[j]->base); - ww_mutex_unlock(&bo->resv->lock); - } + for (j = 0; j < i; j++) + ww_mutex_unlock(&exec->bo[j]->resv->lock); if (contended_lock != -1 && contended_lock >= i) { - bo = to_v3d_bo(&exec->bo[contended_lock]->base); + struct v3d_bo *bo = exec->bo[contended_lock]; ww_mutex_unlock(&bo->resv->lock); } @@ -303,9 +294,7 @@ retry: * before we commit the CL to the hardware. */ for (i = 0; i < exec->bo_count; i++) { - bo = to_v3d_bo(&exec->bo[i]->base); - - ret = reservation_object_reserve_shared(bo->resv, 1); + ret = reservation_object_reserve_shared(exec->bo[i]->resv, 1); if (ret) { v3d_unlock_bo_reservations(dev, exec, acquire_ctx); return ret; -- cgit v1.2.3-58-ga151 From 08f73d668048ffa3ba6b1426b6ba0a89b16aefd7 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Mon, 26 Nov 2018 13:59:28 -0800 Subject: drm/vkms: Drop custom vkms_dumb_map(). This is the same as the default drm_gem_dumb_map_offset() implementation, except that this one missed the ban on userspace mapping an imported dmabuf (which seems like intended common behavior for drivers). Signed-off-by: Eric Anholt Link: https://patchwork.freedesktop.org/patch/msgid/20181126215929.20546-1-eric@anholt.net Acked-by: Daniel Vetter --- drivers/gpu/drm/vkms/vkms_drv.c | 1 - drivers/gpu/drm/vkms/vkms_drv.h | 3 --- drivers/gpu/drm/vkms/vkms_gem.c | 26 -------------------------- 3 files changed, 30 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index a3d57e0f5ee5..83087877565c 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -68,7 +68,6 @@ static struct drm_driver vkms_driver = { .release = vkms_release, .fops = &vkms_driver_fops, .dumb_create = vkms_dumb_create, - .dumb_map_offset = vkms_dumb_map, .gem_vm_ops = &vkms_gem_vm_ops, .gem_free_object_unlocked = vkms_gem_free_object, .get_vblank_timestamp = vkms_get_vblank_timestamp, diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 1c93990693e3..e4469cd3d254 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -127,9 +127,6 @@ vm_fault_t vkms_gem_fault(struct vm_fault *vmf); int vkms_dumb_create(struct drm_file *file, struct drm_device *dev, struct drm_mode_create_dumb *args); -int vkms_dumb_map(struct drm_file *file, struct drm_device *dev, - u32 handle, u64 *offset); - void vkms_gem_free_object(struct drm_gem_object *obj); int vkms_gem_vmap(struct drm_gem_object *obj); diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c index d04e988b4cbe..80311daed47a 100644 --- a/drivers/gpu/drm/vkms/vkms_gem.c +++ b/drivers/gpu/drm/vkms/vkms_gem.c @@ -153,32 +153,6 @@ int vkms_dumb_create(struct drm_file *file, struct drm_device *dev, return 0; } -int vkms_dumb_map(struct drm_file *file, struct drm_device *dev, - u32 handle, u64 *offset) -{ - struct drm_gem_object *obj; - int ret; - - obj = drm_gem_object_lookup(file, handle); - if (!obj) - return -ENOENT; - - if (!obj->filp) { - ret = -EINVAL; - goto unref; - } - - ret = drm_gem_create_mmap_offset(obj); - if (ret) - goto unref; - - *offset = drm_vma_node_offset_addr(&obj->vma_node); -unref: - drm_gem_object_put_unlocked(obj); - - return ret; -} - static struct page **_get_pages(struct vkms_gem_object *vkms_obj) { struct drm_gem_object *gem_obj = &vkms_obj->gem; -- cgit v1.2.3-58-ga151