Commit 2dc7bad7 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'drm-misc-next-2018-09-13' of git://anongit.freedesktop.org/drm/drm-misc into drm-next

drm-misc-next for 4.20:

UAPI Changes:
- Add host endian variants for the most common formats (Gerd)
- Fail ADDFB2 for big-endian drivers that don't advertise BE quirk (Gerd)
- clear smem_start in fbdev for drm drivers to avoid leaking fb addr (Daniel)

Cross-subsystem Changes:

Core Changes:
- fix drm_mode_addfb() on big endian machines (Gerd)
- add timeline point to syncobj find+replace (Chunming)
- more drmP.h removal effort (Daniel)
- split uapi portions of drm_atomic.c into drm_atomic_uapi.c (Daniel)

Driver Changes:
- bochs: Convert open-coded portions to use helpers (Peter)
- vkms: Add cursor support (Haneen)
- udmabuf: Lots of fixups (mostly cosmetic afaict) (Gerd)
- qxl: Convert to use fbdev helper (Peter)

Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Chunming Zhou <david1.zhou@amd.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Peter Wu <peter@lekensteyn.nl>
Cc: Haneen Mohammed <hamohammed.sa@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>

From: Sean Paul <sean@poorly.run>
Link: https://patchwork.freedesktop.org/patch/msgid/20180913130254.GA156437@art_vandelay
parents b1c15668 169cc4c7
......@@ -13,6 +13,7 @@ GPU Driver Documentation
tve200
v3d
vc4
vkms
bridge/dw-hdmi
xen-front
......
......@@ -287,8 +287,14 @@ Atomic Mode Setting Function Reference
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
:export:
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
:internal:
Atomic Mode Setting IOCTL and UAPI Functions
--------------------------------------------
.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
:doc: overview
.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
:export:
CRTC Abstraction
================
......@@ -566,7 +572,7 @@ Tile Group Property
Explicit Fencing Properties
---------------------------
.. kernel-doc:: drivers/gpu/drm/drm_atomic.c
.. kernel-doc:: drivers/gpu/drm/drm_atomic_uapi.c
:doc: explicit fencing properties
Existing KMS Properties
......
......@@ -127,7 +127,8 @@ interfaces to fix these issues:
the acquire context explicitly on stack and then also pass it down into
drivers explicitly so that the legacy-on-atomic functions can use them.
Except for some driver code this is done.
Except for some driver code this is done. This task should be finished by
adding WARN_ON(!drm_drv_uses_atomic_modeset) in drm_modeset_lock_all().
* A bunch of the vtable hooks are now in the wrong place: DRM has a split
between core vfunc tables (named ``drm_foo_funcs``), which are used to
......@@ -137,13 +138,6 @@ interfaces to fix these issues:
``_helper_funcs`` since they are not part of the core ABI. There's a
``FIXME`` comment in the kerneldoc for each such case in ``drm_crtc.h``.
* There's a new helper ``drm_atomic_helper_best_encoder()`` which could be
used by all atomic drivers which don't select the encoder for a given
connector at runtime. That's almost all of them, and would allow us to get
rid of a lot of ``best_encoder`` boilerplate in drivers.
This was almost done, but new drivers added a few more cases again.
Contact: Daniel Vetter
Get rid of dev->struct_mutex from GEM drivers
......@@ -164,9 +158,8 @@ private lock. The tricky part is the BO free functions, since those can't
reliably take that lock any more. Instead state needs to be protected with
suitable subordinate locks or some cleanup work pushed to a worker thread. For
performance-critical drivers it might also be better to go with a more
fine-grained per-buffer object and per-context lockings scheme. Currently the
following drivers still use ``struct_mutex``: ``msm``, ``omapdrm`` and
``udl``.
fine-grained per-buffer object and per-context lockings scheme. Currently only the
``msm`` driver still use ``struct_mutex``.
Contact: Daniel Vetter, respective driver maintainers
......@@ -190,7 +183,8 @@ Convert drivers to use simple modeset suspend/resume
Most drivers (except i915 and nouveau) that use
drm_atomic_helper_suspend/resume() can probably be converted to use
drm_mode_config_helper_suspend/resume().
drm_mode_config_helper_suspend/resume(). Also there's still open-coded version
of the atomic suspend/resume code in older atomic modeset drivers.
Contact: Maintainer of the driver you plan to convert
......@@ -246,20 +240,10 @@ Core refactorings
Clean up the DRM header mess
----------------------------
Currently the DRM subsystem has only one global header, ``drmP.h``. This is
used both for functions exported to helper libraries and drivers and functions
only used internally in the ``drm.ko`` module. The goal would be to move all
header declarations not needed outside of ``drm.ko`` into
``drivers/gpu/drm/drm_*_internal.h`` header files. ``EXPORT_SYMBOL`` also
needs to be dropped for these functions.
This would nicely tie in with the below task to create kerneldoc after the API
is cleaned up. Or with the "hide legacy cruft better" task.
Note that this is well in progress, but ``drmP.h`` is still huge. The updated
plan is to switch to per-file driver API headers, which will also structure
the kerneldoc better. This should also allow more fine-grained ``#include``
directives.
The DRM subsystem originally had only one huge global header, ``drmP.h``. This
is now split up, but many source files still include it. The remaining part of
the cleanup work here is to replace any ``#include <drm/drmP.h>`` by only the
headers needed (and fixing up any missing pre-declarations in the headers).
In the end no .c file should need to include ``drmP.h`` anymore.
......@@ -278,26 +262,6 @@ See https://dri.freedesktop.org/docs/drm/ for what's there already.
Contact: Daniel Vetter
Hide legacy cruft better
------------------------
Way back DRM supported only drivers which shadow-attached to PCI devices with
userspace or fbdev drivers setting up outputs. Modern DRM drivers take charge
of the entire device, you can spot them with the DRIVER_MODESET flag.
Unfortunately there's still large piles of legacy code around which needs to
be hidden so that driver writers don't accidentally end up using it. And to
prevent security issues in those legacy IOCTLs from being exploited on modern
drivers. This has multiple possible subtasks:
* Extract support code for legacy features into a ``drm-legacy.ko`` kernel
module and compile it only when one of the legacy drivers is enabled.
This is mostly done, the only thing left is to split up ``drm_irq.c`` into
legacy cruft and the parts needed by modern KMS drivers.
Contact: Daniel Vetter
Make panic handling work
------------------------
......@@ -396,17 +360,12 @@ converting things over. For modeset tests we also first need a bit of
infrastructure to use dumb buffers for untiled buffers, to be able to run all
the non-i915 specific modeset tests.
Contact: Daniel Vetter
Create a virtual KMS driver for testing (vkms)
----------------------------------------------
With all the latest helpers it should be fairly simple to create a virtual KMS
driver useful for testing, or for running X or similar on headless machines
(to be able to still use the GPU). This would be similar to vgem, but aimed at
the modeset side.
Extend virtual test driver (VKMS)
---------------------------------
Once the basics are there there's tons of possibilities to extend it.
See the documentation of :ref:`VKMS <vkms>` for more details. This is an ideal
internship task, since it only requires a virtual machine and can be sized to
fit the available time.
Contact: Daniel Vetter
......
.. _vkms:
==========================================
drm/vkms Virtual Kernel Modesetting
==========================================
.. kernel-doc:: drivers/gpu/drm/vkms/vkms_drv.c
:doc: vkms (Virtual Kernel Modesetting)
TODO
====
CRC API
-------
- Optimize CRC computation ``compute_crc()`` and plane blending ``blend()``
- Use the alpha value to blend vaddr_src with vaddr_dst instead of
overwriting it in ``blend()``.
- Add igt test to check cleared alpha value for XRGB plane format.
- Add igt test to check extreme alpha values i.e. fully opaque and fully
transparent (intermediate values are affected by hw-specific rounding modes).
......@@ -34,6 +34,7 @@ config UDMABUF
bool "userspace dmabuf misc driver"
default n
depends on DMA_SHARED_BUFFER
depends on MEMFD_CREATE || COMPILE_TEST
help
A driver to let userspace turn memfd regions into dma-bufs.
Qemu can use this to create host dmabufs for guest framebuffers.
......
// SPDX-License-Identifier: GPL-2.0
#include <linux/init.h>
#include <linux/module.h>
#include <linux/cred.h>
#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/miscdevice.h>
#include <linux/dma-buf.h>
#include <linux/highmem.h>
#include <linux/cred.h>
#include <linux/shmem_fs.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/memfd.h>
#include <linux/miscdevice.h>
#include <linux/module.h>
#include <linux/shmem_fs.h>
#include <linux/slab.h>
#include <linux/udmabuf.h>
#include <uapi/linux/udmabuf.h>
static const u32 list_limit = 1024; /* udmabuf_create_list->count limit */
static const size_t size_limit_mb = 64; /* total dmabuf size, in megabytes */
struct udmabuf {
u32 pagecount;
pgoff_t pagecount;
struct page **pages;
};
......@@ -23,9 +25,6 @@ static int udmabuf_vm_fault(struct vm_fault *vmf)
struct vm_area_struct *vma = vmf->vma;
struct udmabuf *ubuf = vma->vm_private_data;
if (WARN_ON(vmf->pgoff >= ubuf->pagecount))
return VM_FAULT_SIGBUS;
vmf->page = ubuf->pages[vmf->pgoff];
get_page(vmf->page);
return 0;
......@@ -52,25 +51,24 @@ static struct sg_table *map_udmabuf(struct dma_buf_attachment *at,
{
struct udmabuf *ubuf = at->dmabuf->priv;
struct sg_table *sg;
int ret;
sg = kzalloc(sizeof(*sg), GFP_KERNEL);
if (!sg)
goto err1;
if (sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->pagecount,
0, ubuf->pagecount << PAGE_SHIFT,
GFP_KERNEL) < 0)
goto err2;
return ERR_PTR(-ENOMEM);
ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->pagecount,
0, ubuf->pagecount << PAGE_SHIFT,
GFP_KERNEL);
if (ret < 0)
goto err;
if (!dma_map_sg(at->dev, sg->sgl, sg->nents, direction))
goto err3;
goto err;
return sg;
err3:
err:
sg_free_table(sg);
err2:
kfree(sg);
err1:
return ERR_PTR(-ENOMEM);
return ERR_PTR(ret);
}
static void unmap_udmabuf(struct dma_buf_attachment *at,
......@@ -106,7 +104,7 @@ static void kunmap_udmabuf(struct dma_buf *buf, unsigned long page_num,
kunmap(vaddr);
}
static struct dma_buf_ops udmabuf_ops = {
static const struct dma_buf_ops udmabuf_ops = {
.map_dma_buf = map_udmabuf,
.unmap_dma_buf = unmap_udmabuf,
.release = release_udmabuf,
......@@ -118,48 +116,54 @@ static struct dma_buf_ops udmabuf_ops = {
#define SEALS_WANTED (F_SEAL_SHRINK)
#define SEALS_DENIED (F_SEAL_WRITE)
static long udmabuf_create(struct udmabuf_create_list *head,
struct udmabuf_create_item *list)
static long udmabuf_create(const struct udmabuf_create_list *head,
const struct udmabuf_create_item *list)
{
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
struct file *memfd = NULL;
struct udmabuf *ubuf;
struct dma_buf *buf;
pgoff_t pgoff, pgcnt, pgidx, pgbuf;
pgoff_t pgoff, pgcnt, pgidx, pgbuf = 0, pglimit;
struct page *page;
int seals, ret = -EINVAL;
u32 i, flags;
ubuf = kzalloc(sizeof(struct udmabuf), GFP_KERNEL);
ubuf = kzalloc(sizeof(*ubuf), GFP_KERNEL);
if (!ubuf)
return -ENOMEM;
pglimit = (size_limit_mb * 1024 * 1024) >> PAGE_SHIFT;
for (i = 0; i < head->count; i++) {
if (!IS_ALIGNED(list[i].offset, PAGE_SIZE))
goto err_free_ubuf;
goto err;
if (!IS_ALIGNED(list[i].size, PAGE_SIZE))
goto err_free_ubuf;
goto err;
ubuf->pagecount += list[i].size >> PAGE_SHIFT;
if (ubuf->pagecount > pglimit)
goto err;
}
ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(struct page *),
ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
GFP_KERNEL);
if (!ubuf->pages) {
ret = -ENOMEM;
goto err_free_ubuf;
goto err;
}
pgbuf = 0;
for (i = 0; i < head->count; i++) {
ret = -EBADFD;
memfd = fget(list[i].memfd);
if (!memfd)
goto err_put_pages;
goto err;
if (!shmem_mapping(file_inode(memfd)->i_mapping))
goto err_put_pages;
goto err;
seals = memfd_fcntl(memfd, F_GET_SEALS, 0);
if (seals == -EINVAL ||
(seals & SEALS_WANTED) != SEALS_WANTED ||
if (seals == -EINVAL)
goto err;
ret = -EINVAL;
if ((seals & SEALS_WANTED) != SEALS_WANTED ||
(seals & SEALS_DENIED) != 0)
goto err_put_pages;
goto err;
pgoff = list[i].offset >> PAGE_SHIFT;
pgcnt = list[i].size >> PAGE_SHIFT;
for (pgidx = 0; pgidx < pgcnt; pgidx++) {
......@@ -167,13 +171,13 @@ static long udmabuf_create(struct udmabuf_create_list *head,
file_inode(memfd)->i_mapping, pgoff + pgidx);
if (IS_ERR(page)) {
ret = PTR_ERR(page);
goto err_put_pages;
goto err;
}
ubuf->pages[pgbuf++] = page;
}
fput(memfd);
memfd = NULL;
}
memfd = NULL;
exp_info.ops = &udmabuf_ops;
exp_info.size = ubuf->pagecount << PAGE_SHIFT;
......@@ -182,7 +186,7 @@ static long udmabuf_create(struct udmabuf_create_list *head,
buf = dma_buf_export(&exp_info);
if (IS_ERR(buf)) {
ret = PTR_ERR(buf);
goto err_put_pages;
goto err;
}
flags = 0;
......@@ -190,10 +194,9 @@ static long udmabuf_create(struct udmabuf_create_list *head,
flags |= O_CLOEXEC;
return dma_buf_fd(buf, flags);
err_put_pages:
err:
while (pgbuf > 0)
put_page(ubuf->pages[--pgbuf]);
err_free_ubuf:
if (memfd)
fput(memfd);
kfree(ubuf->pages);
......@@ -208,7 +211,7 @@ static long udmabuf_ioctl_create(struct file *filp, unsigned long arg)
struct udmabuf_create_item list;
if (copy_from_user(&create, (void __user *)arg,
sizeof(struct udmabuf_create)))
sizeof(create)))
return -EFAULT;
head.flags = create.flags;
......@@ -229,7 +232,7 @@ static long udmabuf_ioctl_create_list(struct file *filp, unsigned long arg)
if (copy_from_user(&head, (void __user *)arg, sizeof(head)))
return -EFAULT;
if (head.count > 1024)
if (head.count > list_limit)
return -EINVAL;
lsize = sizeof(struct udmabuf_create_item) * head.count;
list = memdup_user((void __user *)(arg + sizeof(head)), lsize);
......@@ -254,7 +257,7 @@ static long udmabuf_ioctl(struct file *filp, unsigned int ioctl,
ret = udmabuf_ioctl_create_list(filp, arg);
break;
default:
ret = -EINVAL;
ret = -ENOTTY;
break;
}
return ret;
......
......@@ -18,7 +18,8 @@ drm-y := drm_auth.o drm_bufs.o drm_cache.o \
drm_encoder.o drm_mode_object.o drm_property.o \
drm_plane.o drm_color_mgmt.o drm_print.o \
drm_dumb_buffers.o drm_mode_config.o drm_vblank.o \
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o
drm_syncobj.o drm_lease.o drm_writeback.o drm_client.o \
drm_atomic_uapi.o
drm-$(CONFIG_DRM_LIB_RANDOM) += lib/drm_random.o
drm-$(CONFIG_DRM_VM) += drm_vm.o
......
......@@ -1098,7 +1098,7 @@ static int amdgpu_syncobj_lookup_and_add_to_sync(struct amdgpu_cs_parser *p,
{
int r;
struct dma_fence *fence;
r = drm_syncobj_find_fence(p->filp, handle, &fence);
r = drm_syncobj_find_fence(p->filp, handle, 0, &fence);
if (r)
return r;
......@@ -1187,7 +1187,7 @@ static void amdgpu_cs_post_dependencies(struct amdgpu_cs_parser *p)
int i;
for (i = 0; i < p->num_post_dep_syncobjs; ++i)
drm_syncobj_replace_fence(p->post_dep_syncobjs[i], p->fence);
drm_syncobj_replace_fence(p->post_dep_syncobjs[i], 0, p->fence);
}
static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
......
......@@ -8,6 +8,7 @@
*/
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/armada_drm.h>
......
......@@ -51,11 +51,6 @@ enum bochs_types {
BOCHS_UNKNOWN,
};
struct bochs_framebuffer {
struct drm_framebuffer base;
struct drm_gem_object *obj;
};
struct bochs_device {
/* hw */
void __iomem *mmio;
......@@ -88,15 +83,11 @@ struct bochs_device {
/* fbdev */
struct {
struct bochs_framebuffer gfb;
struct drm_framebuffer *fb;
struct drm_fb_helper helper;
int size;
bool initialized;
} fb;
};
#define to_bochs_framebuffer(x) container_of(x, struct bochs_framebuffer, base)
struct bochs_bo {
struct ttm_buffer_object bo;
struct ttm_placement placement;
......@@ -126,7 +117,7 @@ static inline u64 bochs_bo_mmap_offset(struct bochs_bo *bo)
/* ---------------------------------------------------------------------- */
/* bochs_hw.c */
int bochs_hw_init(struct drm_device *dev, uint32_t flags);
int bochs_hw_init(struct drm_device *dev);
void bochs_hw_fini(struct drm_device *dev);
void bochs_hw_setmode(struct bochs_device *bochs,
......@@ -148,15 +139,9 @@ int bochs_dumb_create(struct drm_file *file, struct drm_device *dev,
int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
uint32_t handle, uint64_t *offset);
int bochs_framebuffer_init(struct drm_device *dev,
struct bochs_framebuffer *gfb,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj);
int bochs_bo_pin(struct bochs_bo *bo, u32 pl_flag, u64 *gpu_addr);
int bochs_bo_unpin(struct bochs_bo *bo);
extern const struct drm_mode_config_funcs bochs_mode_funcs;
/* bochs_kms.c */
int bochs_kms_init(struct bochs_device *bochs);
void bochs_kms_fini(struct bochs_device *bochs);
......@@ -164,3 +149,5 @@ void bochs_kms_fini(struct bochs_device *bochs);
/* bochs_fbdev.c */
int bochs_fbdev_init(struct bochs_device *bochs);
void bochs_fbdev_fini(struct bochs_device *bochs);
extern const struct drm_mode_config_funcs bochs_mode_funcs;
......@@ -35,7 +35,7 @@ static void bochs_unload(struct drm_device *dev)
dev->dev_private = NULL;
}
static int bochs_load(struct drm_device *dev, unsigned long flags)
static int bochs_load(struct drm_device *dev)
{
struct bochs_device *bochs;
int ret;
......@@ -46,7 +46,7 @@ static int bochs_load(struct drm_device *dev, unsigned long flags)
dev->dev_private = bochs;
bochs->dev = dev;
ret = bochs_hw_init(dev, flags);
ret = bochs_hw_init(dev);
if (ret)
goto err;
......@@ -82,8 +82,6 @@ static const struct file_operations bochs_fops = {
static struct drm_driver bochs_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET,
.load = bochs_load,
.unload = bochs_unload,
.fops = &bochs_fops,
.name = "bochs-drm",
.desc = "bochs dispi vga interface (qemu stdvga)",
......@@ -107,11 +105,7 @@ static int bochs_pm_suspend(struct device *dev)
drm_kms_helper_poll_disable(drm_dev);
if (bochs->fb.initialized) {
console_lock();
drm_fb_helper_set_suspend(&bochs->fb.helper, 1);
console_unlock();
}
drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 1);
return 0;
}
......@@ -124,11 +118,7 @@ static int bochs_pm_resume(struct device *dev)
drm_helper_resume_force_mode(drm_dev);
if (bochs->fb.initialized) {
console_lock();
drm_fb_helper_set_suspend(&bochs->fb.helper, 0);
console_unlock();
}
drm_fb_helper_set_suspend_unlocked(&bochs->fb.helper, 0);
drm_kms_helper_poll_enable(drm_dev);
return 0;
......@@ -146,6 +136,7 @@ static const struct dev_pm_ops bochs_pm_ops = {
static int bochs_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct drm_device *dev;
unsigned long fbsize;
int ret;
......@@ -159,14 +150,37 @@ static int bochs_pci_probe(struct pci_dev *pdev,
if (ret)
return ret;
return drm_get_pci_dev(pdev, ent, &bochs_driver);
dev = drm_dev_alloc(&bochs_driver, &pdev->dev);
if (IS_ERR(dev))
return PTR_ERR(dev);
dev->pdev = pdev;
pci_set_drvdata(pdev, dev);
ret = bochs_load(dev);
if (ret)
goto err_free_dev;
ret = drm_dev_register(dev, 0);
if (ret)
goto err_unload;
return ret;
err_unload:
bochs_unload(dev);
err_free_dev:
drm_dev_put(dev);
return ret;
}
static void bochs_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
drm_put_dev(dev);
drm_dev_unregister(dev);
bochs_unload(dev);
drm_dev_put(dev);
}
static const struct pci_device_id bochs_pci_tbl[] = {
......
......@@ -6,6 +6,7 @@
*/
#include "bochs.h"
#include <drm/drm_gem_framebuffer_helper.h>
/* ---------------------------------------------------------------------- */
......@@ -13,9 +14,7 @@ static int bochsfb_mmap(struct fb_info *info,
struct vm_area_struct *vma)
{
struct drm_fb_helper *fb_helper = info->par;
struct bochs_device *bochs =
container_of(fb_helper, struct bochs_device, fb.helper);
struct bochs_bo *bo = gem_to_bochs_bo(bochs->fb.gfb.obj);
struct bochs_bo *bo = gem_to_bochs_bo(fb_helper->fb->obj[0]);
return ttm_fbdev_mmap(vma, &bo->bo);
}
......@@ -101,19 +100,20 @@ static int bochsfb_create(struct drm_fb_helper *helper,
/* init fb device */
info = drm_fb_helper_alloc_fbi(helper);
if (IS_ERR(info))
if (IS_ERR(info)) {
DRM_ERROR("Failed to allocate fbi: %ld\n", PTR_ERR(info));
return PTR_ERR(info);
}
info->par = &bochs->fb.helper;
ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
if (ret)
return ret;
bochs->fb.size = size;
fb = drm_gem_fbdev_fb_create(bochs->dev, sizes, 0, gobj, NULL);
if (IS_ERR(fb)) {
DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb));
return PTR_ERR(fb);
}
/* setup helper */
fb = &bochs->fb.gfb.base;
bochs->fb.helper.fb = fb;
strcpy(info->fix.id, "bochsdrmfb");
......@@ -130,27 +130,6 @@ static int bochsfb_create(struct drm_fb_helper *helper,
drm_vma_offset_remove(&bo->bo.bdev->vma_manager, &bo->bo.vma_node);
info->fix.smem_start = 0;
info->fix.smem_len = size;
bochs->fb.initialized = true;
return 0;
}
static int bochs_fbdev_destroy(struct bochs_device *bochs)
{
struct bochs_framebuffer *gfb = &bochs->fb.gfb;
DRM_DEBUG_DRIVER("\n");
drm_fb_helper_unregister_fbi(&bochs->fb.helper);
if (gfb->obj) {
drm_gem_object_unreference_unlocked(gfb->obj);
gfb->obj = NULL;
}
drm_framebuffer_unregister_private(&gfb->base);
drm_framebuffer_cleanup(&gfb->base);
return 0;
}
......@@ -158,41 +137,17 @@ static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
.fb_probe = bochsfb_create,
};
const struct drm_mode_config_funcs bochs_mode_funcs = {
.fb_create = drm_gem_fb_create,
};
int bochs_fbdev_init(struct bochs_device *bochs)
{
int ret;
drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
&bochs_fb_helper_funcs);
ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper, 1);
if (ret)
return ret;
ret = drm_fb_helper_single_add_all_connectors(&bochs->fb.helper);
if (ret)
goto fini;
drm_helper_disable_unused_functions(bochs->dev);
ret = drm_fb_helper_initial_config(&bochs->fb.helper, 32);
if (ret)
goto fini;
return 0;
fini:
drm_fb_helper_fini(&bochs->fb.helper);
return ret;
return drm_fb_helper_fbdev_setup(bochs->dev, &bochs->fb.helper,
&bochs_fb_helper_funcs, 32, 1);
}
void bochs_fbdev_fini(struct bochs_device *bochs)
{
if (bochs->fb.initialized)
bochs_fbdev_destroy(bochs);
if (bochs->fb.helper.fbdev)
drm_fb_helper_fini(&bochs->fb.helper);
bochs->fb.initialized = false;
drm_fb_helper_fbdev_teardown(bochs->dev);
}
......@@ -47,7 +47,7 @@ static void bochs_dispi_write(struct bochs_device *bochs, u16 reg, u16 val)
}
}
int bochs_hw_init(struct drm_device *dev, uint32_t flags)
int bochs_hw_init(struct drm_device *dev)
{
struct bochs_device *bochs = dev->dev_private;
struct pci_dev *pdev = dev->pdev;
......
......@@ -35,14 +35,12 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
{
struct bochs_device *bochs =
container_of(crtc, struct bochs_device, crtc);
struct bochs_framebuffer *bochs_fb;
struct bochs_bo *bo;
u64 gpu_addr = 0;
int ret;
if (old_fb) {
bochs_fb = to_bochs_framebuffer(old_fb);
bo = gem_to_bochs_bo(bochs_fb->obj);
bo = gem_to_bochs_bo(old_fb->obj[0]);
ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
if (ret) {
DRM_ERROR("failed to reserve old_fb bo\n");
......@@ -55,8 +53,7 @@ static int bochs_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
if (WARN_ON(crtc->primary->fb == NULL))
return -EINVAL;
bochs_fb = to_bochs_framebuffer(crtc->primary->fb);
bo = gem_to_bochs_bo(bochs_fb->obj);
bo = gem_to_bochs_bo(crtc->primary->fb->obj[0]);
ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
if (ret)
return ret;
......
......@@ -457,77 +457,3 @@ int bochs_dumb_mmap_offset(struct drm_file *file, struct drm_device *dev,
drm_gem_object_unreference_unlocked(obj);
return 0;
}
/* ---------------------------------------------------------------------- */
static void bochs_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct bochs_framebuffer *bochs_fb = to_bochs_framebuffer(fb);
drm_gem_object_unreference_unlocked(bochs_fb->obj);
drm_framebuffer_cleanup(fb);
kfree(fb);
}
static const struct drm_framebuffer_funcs bochs_fb_funcs = {
.destroy = bochs_user_framebuffer_destroy,
};
int bochs_framebuffer_init(struct drm_device *dev,
struct bochs_framebuffer *gfb,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj)
{
int ret;
drm_helper_mode_fill_fb_struct(dev, &gfb->base, mode_cmd);
gfb->obj = obj;
ret = drm_framebuffer_init(dev, &gfb->base, &bochs_fb_funcs);
if (ret) {
DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
return ret;
}
return 0;
}
static struct drm_framebuffer *
bochs_user_framebuffer_create(struct drm_device *dev,
struct drm_file *filp,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct bochs_framebuffer *bochs_fb;
int ret;
DRM_DEBUG_DRIVER("%dx%d, format %c%c%c%c\n",
mode_cmd->width, mode_cmd->height,
(mode_cmd->pixel_format) & 0xff,
(mode_cmd->pixel_format >> 8) & 0xff,
(mode_cmd->pixel_format >> 16) & 0xff,
(mode_cmd->pixel_format >> 24) & 0xff);
if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888)
return ERR_PTR(-ENOENT);
obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]);
if (obj == NULL)
return ERR_PTR(-ENOENT);
bochs_fb = kzalloc(sizeof(*bochs_fb), GFP_KERNEL);
if (!bochs_fb) {
drm_gem_object_unreference_unlocked(obj);
return ERR_PTR(-ENOMEM);
}
ret = bochs_framebuffer_init(dev, bochs_fb, mode_cmd, obj);
if (ret) {
drm_gem_object_unreference_unlocked(obj);
kfree(bochs_fb);
return ERR_PTR(ret);
}
return &bochs_fb->base;
}
const struct drm_mode_config_funcs bochs_mode_funcs = {
.fb_create = bochs_user_framebuffer_create,
};
......@@ -554,7 +554,7 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
if (retval < 0)
return retval;
dev_info(dp->dev, "Link Training Clock Recovery success\n");
dev_dbg(dp->dev, "Link Training Clock Recovery success\n");
dp->link_train.lt_state = EQUALIZER_TRAINING;
} else {
for (lane = 0; lane < lane_count; lane++) {
......@@ -634,7 +634,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
if (retval < 0)
return retval;
dev_info(dp->dev, "Link Training success!\n");
dev_dbg(dp->dev, "Link Training success!\n");
analogix_dp_get_link_bandwidth(dp, &reg);
dp->link_train.link_rate = reg;
dev_dbg(dp->dev, "final bandwidth = %.2x\n",
......
This diff is collapsed.
......@@ -27,6 +27,7 @@
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_atomic_helper.h>
......
This diff is collapsed.
......@@ -101,6 +101,28 @@
* Without this property the rectangle is only scaled, but not rotated or
* reflected.
*
* Possbile values:
*
* "rotate-<degrees>":
* Signals that a drm plane is rotated <degrees> degrees in counter
* clockwise direction.
*
* "reflect-<axis>":
* Signals that the contents of a drm plane is reflected along the
* <axis> axis, in the same way as mirroring.
*
* reflect-x::
*
* |o | | o|
* | | -> | |
* | v| |v |
*
* reflect-y::
*
* |o | | ^|
* | | -> | |
* | v| |o |
*
* zpos:
* Z position is set up with drm_plane_create_zpos_immutable_property() and
* drm_plane_create_zpos_property(). It controls the visibility of overlapping
......
......@@ -104,6 +104,10 @@ EXPORT_SYMBOL(drm_bridge_remove);
* If non-NULL the previous bridge must be already attached by a call to this
* function.
*
* Note that bridges attached to encoders are auto-detached during encoder
* cleanup in drm_encoder_cleanup(), so drm_bridge_attach() should generally
* *not* be balanced with a drm_bridge_detach() in driver code.
*
* RETURNS:
* Zero on success, error code on failure
*/
......
......@@ -20,11 +20,15 @@
* OF THIS SOFTWARE.
*/
#include <drm/drmP.h>
#include <drm/drm_connector.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
#include <drm/drm_utils.h>
#include <drm/drm_print.h>
#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <linux/uaccess.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
......
......@@ -34,7 +34,7 @@
#include <linux/slab.h>
#include <linux/export.h>
#include <linux/dma-fence.h>
#include <drm/drmP.h>
#include <linux/uaccess.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
......@@ -42,6 +42,9 @@
#include <drm/drm_atomic.h>
#include <drm/drm_auth.h>
#include <drm/drm_debugfs_crc.h>
#include <drm/drm_drv.h>
#include <drm/drm_print.h>
#include <drm/drm_file.h>
#include "drm_crtc_internal.h"
#include "drm_internal.h"
......
......@@ -35,6 +35,7 @@
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
#include <drm/drm_fourcc.h>
......
......@@ -31,6 +31,14 @@
* and are not exported to drivers.
*/
enum drm_mode_status;
enum drm_connector_force;
struct drm_display_mode;
struct work_struct;
struct drm_connector;
struct drm_bridge;
struct edid;
/* drm_crtc.c */
int drm_mode_crtc_set_obj_prop(struct drm_mode_object *obj,
......@@ -174,6 +182,8 @@ void drm_fb_release(struct drm_file *file_priv);
int drm_mode_addfb(struct drm_device *dev, struct drm_mode_fb_cmd *or,
struct drm_file *file_priv);
int drm_mode_addfb2(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_rmfb(struct drm_device *dev, u32 fb_id,
struct drm_file *file_priv);
......@@ -181,8 +191,8 @@ int drm_mode_rmfb(struct drm_device *dev, u32 fb_id,
/* IOCTL */
int drm_mode_addfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_addfb2(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_addfb2_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_rmfb_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
int drm_mode_getfb(struct drm_device *dev,
......@@ -196,6 +206,9 @@ struct drm_minor;
int drm_atomic_debugfs_init(struct drm_minor *minor);
#endif
void drm_atomic_print_state(const struct drm_atomic_state *state);
/* drm_atomic_uapi.c */
int drm_atomic_connector_commit_dpms(struct drm_atomic_state *state,
struct drm_connector *connector,
int mode);
......@@ -205,6 +218,8 @@ int drm_atomic_set_property(struct drm_atomic_state *state,
uint64_t prop_value);
int drm_atomic_get_property(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val);
/* IOCTL */
int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv);
......
......@@ -2673,6 +2673,8 @@ __drm_fb_helper_initial_config_and_unlock(struct drm_fb_helper *fb_helper,
info = fb_helper->fbdev;
info->var.pixclock = 0;
/* don't leak any physical addresses to userspace */
info->flags |= FBINFO_HIDE_SMEM_START;
/* Need to drop locks to avoid recursive deadlock in
* register_framebuffer. This is ok because the only thing left to do is
......@@ -2821,7 +2823,9 @@ EXPORT_SYMBOL(drm_fb_helper_hotplug_event);
* The caller must to provide a &drm_fb_helper_funcs->fb_probe callback
* function.
*
* See also: drm_fb_helper_initial_config()
* Use drm_fb_helper_fbdev_teardown() to destroy the fbdev.
*
* See also: drm_fb_helper_initial_config(), drm_fbdev_generic_setup().
*
* Returns:
* Zero on success or negative error code on failure.
......@@ -3037,7 +3041,7 @@ static struct fb_deferred_io drm_fbdev_defio = {
* @fb_helper: fbdev helper structure
* @sizes: describes fbdev size and scanout surface size
*
* This function uses the client API to crate a framebuffer backed by a dumb buffer.
* This function uses the client API to create a framebuffer backed by a dumb buffer.
*
* The _sys_ versions are used for &fb_ops.fb_read, fb_write, fb_fillrect,
* fb_copyarea, fb_imageblit.
......@@ -3165,8 +3169,10 @@ static int drm_fbdev_client_hotplug(struct drm_client_dev *client)
if (dev->fb_helper)
return drm_fb_helper_hotplug_event(dev->fb_helper);
if (!dev->mode_config.num_connector)
if (!dev->mode_config.num_connector) {
DRM_DEV_DEBUG(dev->dev, "No connectors found, will not create framebuffer!\n");
return 0;
}
ret = drm_fb_helper_fbdev_setup(dev, fb_helper, &drm_fb_helper_generic_funcs,
fb_helper->preferred_bpp, 0);
......@@ -3187,13 +3193,14 @@ static const struct drm_client_funcs drm_fbdev_client_funcs = {
};
/**
* drm_fb_helper_generic_fbdev_setup() - Setup generic fbdev emulation
* drm_fbdev_generic_setup() - Setup generic fbdev emulation
* @dev: DRM device
* @preferred_bpp: Preferred bits per pixel for the device.
* @dev->mode_config.preferred_depth is used if this is zero.
*
* This function sets up generic fbdev emulation for drivers that supports
* dumb buffers with a virtual address and that can be mmap'ed.
* dumb buffers with a virtual address and that can be mmap'ed. If the driver
* does not support these functions, it could use drm_fb_helper_fbdev_setup().
*
* Restore, hotplug events and teardown are all taken care of. Drivers that do
* suspend/resume need to call drm_fb_helper_set_suspend_unlocked() themselves.
......@@ -3206,6 +3213,8 @@ static const struct drm_client_funcs drm_fbdev_client_funcs = {
* This function is safe to call even when there are no connectors present.
* Setup will be retried on the next hotplug event.
*
* The fbdev is destroyed by drm_dev_unregister().
*
* Returns:
* Zero on success or negative error code on failure.
*/
......@@ -3214,6 +3223,8 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
struct drm_fb_helper *fb_helper;
int ret;
WARN(dev->fb_helper, "fb_helper is already set!\n");
if (!drm_fbdev_emulation)
return 0;
......@@ -3224,12 +3235,15 @@ int drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
ret = drm_client_new(dev, &fb_helper->client, "fbdev", &drm_fbdev_client_funcs);
if (ret) {
kfree(fb_helper);
DRM_DEV_ERROR(dev->dev, "Failed to register client: %d\n", ret);
return ret;
}
fb_helper->preferred_bpp = preferred_bpp;
drm_fbdev_client_hotplug(&fb_helper->client);
ret = drm_fbdev_client_hotplug(&fb_helper->client);
if (ret)
DRM_DEV_DEBUG(dev->dev, "client hotplug ret=%d\n", ret);
return 0;
}
......
......@@ -45,32 +45,49 @@ static char printable_char(int c)
*/
uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
{
uint32_t fmt;
uint32_t fmt = DRM_FORMAT_INVALID;
switch (bpp) {
case 8:
fmt = DRM_FORMAT_C8;
if (depth == 8)
fmt = DRM_FORMAT_C8;
break;
case 16:
if (depth == 15)
switch (depth) {
case 15:
fmt = DRM_FORMAT_XRGB1555;
else
break;
case 16:
fmt = DRM_FORMAT_RGB565;
break;
default:
break;
}
break;
case 24:
fmt = DRM_FORMAT_RGB888;
if (depth == 24)
fmt = DRM_FORMAT_RGB888;
break;
case 32:
if (depth == 24)
switch (depth) {
case 24:
fmt = DRM_FORMAT_XRGB8888;
else if (depth == 30)
break;
case 30:
fmt = DRM_FORMAT_XRGB2101010;
else
break;
case 32:
fmt = DRM_FORMAT_ARGB8888;
break;
default:
break;
}
break;
default:
DRM_ERROR("bad bpp, assuming x8r8g8b8 pixel format\n");
fmt = DRM_FORMAT_XRGB8888;
break;
}
......
......@@ -25,6 +25,7 @@
#include <drm/drm_auth.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_print.h>
#include "drm_internal.h"
......@@ -112,18 +113,34 @@ int drm_mode_addfb(struct drm_device *dev, struct drm_mode_fb_cmd *or,
struct drm_mode_fb_cmd2 r = {};
int ret;
r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
if (r.pixel_format == DRM_FORMAT_INVALID) {
DRM_DEBUG("bad {bpp:%d, depth:%d}\n", or->bpp, or->depth);
return -EINVAL;
}
/* convert to new format and call new ioctl */
r.fb_id = or->fb_id;
r.width = or->width;
r.height = or->height;
r.pitches[0] = or->pitch;
r.pixel_format = drm_mode_legacy_fb_format(or->bpp, or->depth);
r.handles[0] = or->handle;
if (r.pixel_format == DRM_FORMAT_XRGB2101010 &&
dev->driver->driver_features & DRIVER_PREFER_XBGR_30BPP)
if (dev->mode_config.quirk_addfb_prefer_xbgr_30bpp &&
r.pixel_format == DRM_FORMAT_XRGB2101010)
r.pixel_format = DRM_FORMAT_XBGR2101010;
if (dev->mode_config.quirk_addfb_prefer_host_byte_order) {
if (r.pixel_format == DRM_FORMAT_XRGB8888)
r.pixel_format = DRM_FORMAT_HOST_XRGB8888;
if (r.pixel_format == DRM_FORMAT_ARGB8888)
r.pixel_format = DRM_FORMAT_HOST_ARGB8888;
if (r.pixel_format == DRM_FORMAT_RGB565)
r.pixel_format = DRM_FORMAT_HOST_RGB565;
if (r.pixel_format == DRM_FORMAT_XRGB1555)
r.pixel_format = DRM_FORMAT_HOST_XRGB1555;
}
ret = drm_mode_addfb2(dev, &r, file_priv);
if (ret)
return ret;
......@@ -164,7 +181,7 @@ static int framebuffer_check(struct drm_device *dev,
int i;
/* check if the format is supported at all */
info = __drm_format_info(r->pixel_format & ~DRM_FORMAT_BIG_ENDIAN);
info = __drm_format_info(r->pixel_format);
if (!info) {
struct drm_format_name_buf format_name;
......@@ -352,6 +369,30 @@ int drm_mode_addfb2(struct drm_device *dev,
return 0;
}
int drm_mode_addfb2_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
#ifdef __BIG_ENDIAN
if (!dev->mode_config.quirk_addfb_prefer_host_byte_order) {
/*
* Drivers must set the
* quirk_addfb_prefer_host_byte_order quirk to make
* the drm_mode_addfb() compat code work correctly on
* bigendian machines.
*
* If they don't they interpret pixel_format values
* incorrectly for bug compatibility, which in turn
* implies the ADDFB2 ioctl does not work correctly
* then. So block it to make userspace fallback to
* ADDFB.
*/
DRM_DEBUG_KMS("addfb2 broken on bigendian");
return -EINVAL;
}
#endif
return drm_mode_addfb2(dev, data, file_priv);
}
struct drm_mode_rmfb_work {
struct work_struct work;
struct list_head fbs;
......
......@@ -16,6 +16,7 @@
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
......
......@@ -21,9 +21,14 @@
* OTHER DEALINGS IN THE SOFTWARE.
*/
#include <drm/drm_ioctl.h>
#define DRM_IF_MAJOR 1
#define DRM_IF_MINOR 4
struct drm_prime_file_private;
struct dma_buf;
/* drm_file.c */
extern struct mutex drm_global_mutex;
struct drm_file *drm_file_alloc(struct drm_minor *minor);
......
......@@ -645,7 +645,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_UNLOCKED),
DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_UNLOCKED),
......
......@@ -20,8 +20,17 @@
* OF THIS SOFTWARE.
*/
#include <drm/drmP.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <drm/drm_plane.h>
#include <drm/drm_drv.h>
#include <drm/drm_print.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_file.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_vblank.h>
#include "drm_crtc_internal.h"
......@@ -463,7 +472,6 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_get_plane_res *plane_resp = data;
struct drm_mode_config *config;
struct drm_plane *plane;
uint32_t __user *plane_ptr;
int count = 0;
......@@ -471,7 +479,6 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
config = &dev->mode_config;
plane_ptr = u64_to_user_ptr(plane_resp->plane_id_ptr);
/*
......
......@@ -28,6 +28,7 @@
#include <drm/drm_plane_helper.h>
#include <drm/drm_rect.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_uapi.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_encoder.h>
#include <drm/drm_atomic_helper.h>
......
......@@ -56,6 +56,33 @@
#include "drm_internal.h"
#include <drm/drm_syncobj.h>
struct drm_syncobj_stub_fence {
struct dma_fence base;
spinlock_t lock;
};
static const char *drm_syncobj_stub_fence_get_name(struct dma_fence *fence)
{
return "syncobjstub";
}
static bool drm_syncobj_stub_fence_enable_signaling(struct dma_fence *fence)
{
return !dma_fence_is_signaled(fence);
}
static void drm_syncobj_stub_fence_release(struct dma_fence *f)
{
kfree(f);
}
static const struct dma_fence_ops drm_syncobj_stub_fence_ops = {
.get_driver_name = drm_syncobj_stub_fence_get_name,
.get_timeline_name = drm_syncobj_stub_fence_get_name,
.enable_signaling = drm_syncobj_stub_fence_enable_signaling,
.release = drm_syncobj_stub_fence_release,
};
/**
* drm_syncobj_find - lookup and reference a sync object.
* @file_private: drm file private pointer
......@@ -140,11 +167,13 @@ void drm_syncobj_remove_callback(struct drm_syncobj *syncobj,
/**
* drm_syncobj_replace_fence - replace fence in a sync object.
* @syncobj: Sync object to replace fence in
* @point: timeline point
* @fence: fence to install in sync file.
*
* This replaces the fence on a sync object.
* This replaces the fence on a sync object, or a timeline point fence.
*/
void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
u64 point,
struct dma_fence *fence)
{
struct dma_fence *old_fence;
......@@ -172,42 +201,19 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
}
EXPORT_SYMBOL(drm_syncobj_replace_fence);
struct drm_syncobj_null_fence {
struct dma_fence base;
spinlock_t lock;
};
static const char *drm_syncobj_null_fence_get_name(struct dma_fence *fence)
{
return "syncobjnull";
}
static bool drm_syncobj_null_fence_enable_signaling(struct dma_fence *fence)
{
dma_fence_enable_sw_signaling(fence);
return !dma_fence_is_signaled(fence);
}
static const struct dma_fence_ops drm_syncobj_null_fence_ops = {
.get_driver_name = drm_syncobj_null_fence_get_name,
.get_timeline_name = drm_syncobj_null_fence_get_name,
.enable_signaling = drm_syncobj_null_fence_enable_signaling,
.release = NULL,
};
static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
{
struct drm_syncobj_null_fence *fence;
struct drm_syncobj_stub_fence *fence;
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
if (fence == NULL)
return -ENOMEM;
spin_lock_init(&fence->lock);
dma_fence_init(&fence->base, &drm_syncobj_null_fence_ops,
dma_fence_init(&fence->base, &drm_syncobj_stub_fence_ops,
&fence->lock, 0, 0);
dma_fence_signal(&fence->base);
drm_syncobj_replace_fence(syncobj, &fence->base);
drm_syncobj_replace_fence(syncobj, 0, &fence->base);
dma_fence_put(&fence->base);
......@@ -218,6 +224,7 @@ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
* drm_syncobj_find_fence - lookup and reference the fence in a sync object
* @file_private: drm file private pointer
* @handle: sync object handle to lookup.
* @point: timeline point
* @fence: out parameter for the fence
*
* This is just a convenience function that combines drm_syncobj_find() and
......@@ -228,7 +235,7 @@ static int drm_syncobj_assign_null_handle(struct drm_syncobj *syncobj)
* dma_fence_put().
*/
int drm_syncobj_find_fence(struct drm_file *file_private,
u32 handle,
u32 handle, u64 point,
struct dma_fence **fence)
{
struct drm_syncobj *syncobj = drm_syncobj_find(file_private, handle);
......@@ -257,7 +264,7 @@ void drm_syncobj_free(struct kref *kref)
struct drm_syncobj *syncobj = container_of(kref,
struct drm_syncobj,
refcount);
drm_syncobj_replace_fence(syncobj, NULL);
drm_syncobj_replace_fence(syncobj, 0, NULL);
kfree(syncobj);
}
EXPORT_SYMBOL(drm_syncobj_free);
......@@ -297,7 +304,7 @@ int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
}
if (fence)
drm_syncobj_replace_fence(syncobj, fence);
drm_syncobj_replace_fence(syncobj, 0, fence);
*out_syncobj = syncobj;
return 0;
......@@ -482,7 +489,7 @@ static int drm_syncobj_import_sync_file_fence(struct drm_file *file_private,
return -ENOENT;
}
drm_syncobj_replace_fence(syncobj, fence);
drm_syncobj_replace_fence(syncobj, 0, fence);
dma_fence_put(fence);
drm_syncobj_put(syncobj);
return 0;
......@@ -499,7 +506,7 @@ static int drm_syncobj_export_sync_file(struct drm_file *file_private,
if (fd < 0)
return fd;
ret = drm_syncobj_find_fence(file_private, handle, &fence);
ret = drm_syncobj_find_fence(file_private, handle, 0, &fence);
if (ret)
goto err_put_fd;
......@@ -964,7 +971,7 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data,
return ret;
for (i = 0; i < args->count_handles; i++)
drm_syncobj_replace_fence(syncobjs[i], NULL);
drm_syncobj_replace_fence(syncobjs[i], 0, NULL);
drm_syncobj_array_free(syncobjs, args->count_handles);
......
......@@ -52,6 +52,7 @@
#include <drm/drm_gem.h>
#include <drm/drm_auth.h>
#include <drm/drm_cache.h>
#include <drm/drm_util.h>
#include "i915_params.h"
#include "i915_reg.h"
......
......@@ -2181,7 +2181,7 @@ signal_fence_array(struct i915_execbuffer *eb,
if (!(flags & I915_EXEC_FENCE_SIGNAL))
continue;
drm_syncobj_replace_fence(syncobj, fence);
drm_syncobj_replace_fence(syncobj, 0, fence);
}
}
......
......@@ -46,6 +46,7 @@
#include <drm/drm_crtc_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_rect.h>
#include <drm/drm_atomic_uapi.h>
#include <linux/dma_remapping.h>
#include <linux/reservation.h>
......
......@@ -25,6 +25,8 @@
#ifndef _INTEL_DISPLAY_H_
#define _INTEL_DISPLAY_H_
#include <drm/drm_util.h>
enum i915_gpio {
GPIOA,
GPIOB,
......
......@@ -2,6 +2,8 @@
#ifndef _INTEL_RINGBUFFER_H_
#define _INTEL_RINGBUFFER_H_
#include <drm/drm_util.h>
#include <linux/hashtable.h>
#include <linux/seqlock.h>
......
......@@ -21,6 +21,8 @@
#include <linux/debugfs.h>
#include <linux/dma-buf.h>
#include <drm/drm_atomic_uapi.h>
#include "msm_drv.h"
#include "dpu_kms.h"
#include "dpu_formats.h"
......
......@@ -15,6 +15,8 @@
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <drm/drm_atomic_uapi.h>
#include "msm_drv.h"
#include "msm_gem.h"
#include "msm_kms.h"
......
......@@ -2174,7 +2174,7 @@ nv50_display_create(struct drm_device *dev)
nouveau_display(dev)->fini = nv50_display_fini;
disp->disp = &nouveau_display(dev)->disp;
dev->mode_config.funcs = &nv50_disp_func;
dev->driver->driver_features |= DRIVER_PREFER_XBGR_30BPP;
dev->mode_config.quirk_addfb_prefer_xbgr_30bpp = true;
/* small shared memory area we use for notifiers and semaphores */
ret = nouveau_bo_new(&drm->client, 4096, 0x1000, TTM_PL_FLAG_VRAM,
......
......@@ -32,6 +32,8 @@
#include <drm/drm_edid.h>
#include <drm/drm_encoder.h>
#include <drm/drm_dp_helper.h>
#include <drm/drm_util.h>
#include "nouveau_crtc.h"
#include "nouveau_encoder.h"
......
......@@ -379,7 +379,6 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
FBINFO_HWACCEL_FILLRECT |
FBINFO_HWACCEL_IMAGEBLIT;
info->flags |= FBINFO_CAN_FORCE_OUTPUT;
info->fbops = &nouveau_fbcon_sw_ops;
info->fix.smem_start = fb->nvbo->bo.mem.bus.base +
fb->nvbo->bo.mem.bus.offset;
......
......@@ -28,6 +28,7 @@
#include <drm/drm_plane_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic.h>
#include <drm/drm_gem_framebuffer_helper.h>
#include "qxl_drv.h"
#include "qxl_object.h"
......@@ -388,17 +389,6 @@ static const struct drm_crtc_funcs qxl_crtc_funcs = {
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
};
void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
struct qxl_bo *bo = gem_to_qxl_bo(qxl_fb->obj);
WARN_ON(bo->shadow);
drm_gem_object_put_unlocked(qxl_fb->obj);
drm_framebuffer_cleanup(fb);
kfree(qxl_fb);
}
static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
struct drm_file *file_priv,
unsigned flags, unsigned color,
......@@ -406,15 +396,14 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
unsigned num_clips)
{
/* TODO: vmwgfx where this was cribbed from had locking. Why? */
struct qxl_framebuffer *qxl_fb = to_qxl_framebuffer(fb);
struct qxl_device *qdev = qxl_fb->base.dev->dev_private;
struct qxl_device *qdev = fb->dev->dev_private;
struct drm_clip_rect norect;
struct qxl_bo *qobj;
int inc = 1;
drm_modeset_lock_all(fb->dev);
qobj = gem_to_qxl_bo(qxl_fb->obj);
qobj = gem_to_qxl_bo(fb->obj[0]);
/* if we aren't primary surface ignore this */
if (!qobj->is_primary) {
drm_modeset_unlock_all(fb->dev);
......@@ -432,7 +421,7 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
inc = 2; /* skip source rects */
}
qxl_draw_dirty_fb(qdev, qxl_fb, qobj, flags, color,
qxl_draw_dirty_fb(qdev, fb, qobj, flags, color,
clips, num_clips, inc);
drm_modeset_unlock_all(fb->dev);
......@@ -441,31 +430,11 @@ static int qxl_framebuffer_surface_dirty(struct drm_framebuffer *fb,
}
static const struct drm_framebuffer_funcs qxl_fb_funcs = {
.destroy = qxl_user_framebuffer_destroy,
.destroy = drm_gem_fb_destroy,
.dirty = qxl_framebuffer_surface_dirty,
/* TODO?
* .create_handle = qxl_user_framebuffer_create_handle, */
.create_handle = drm_gem_fb_create_handle,
};
int
qxl_framebuffer_init(struct drm_device *dev,
struct qxl_framebuffer *qfb,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj,
const struct drm_framebuffer_funcs *funcs)
{
int ret;
qfb->obj = obj;
drm_helper_mode_fill_fb_struct(dev, &qfb->base, mode_cmd);
ret = drm_framebuffer_init(dev, &qfb->base, funcs);
if (ret) {
qfb->obj = NULL;
return ret;
}
return 0;
}
static void qxl_crtc_atomic_enable(struct drm_crtc *crtc,
struct drm_crtc_state *old_state)
{
......@@ -488,14 +457,12 @@ static int qxl_primary_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
struct qxl_device *qdev = plane->dev->dev_private;
struct qxl_framebuffer *qfb;
struct qxl_bo *bo;
if (!state->crtc || !state->fb)
return 0;
qfb = to_qxl_framebuffer(state->fb);
bo = gem_to_qxl_bo(qfb->obj);
bo = gem_to_qxl_bo(state->fb->obj[0]);
if (bo->surf.stride * bo->surf.height > qdev->vram_size) {
DRM_ERROR("Mode doesn't fit in vram size (vgamem)");
......@@ -556,23 +523,19 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct qxl_device *qdev = plane->dev->dev_private;
struct qxl_framebuffer *qfb =
to_qxl_framebuffer(plane->state->fb);
struct qxl_framebuffer *qfb_old;
struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
struct qxl_bo *bo = gem_to_qxl_bo(plane->state->fb->obj[0]);
struct qxl_bo *bo_old;
struct drm_clip_rect norect = {
.x1 = 0,
.y1 = 0,
.x2 = qfb->base.width,
.y2 = qfb->base.height
.x2 = plane->state->fb->width,
.y2 = plane->state->fb->height
};
int ret;
bool same_shadow = false;
if (old_state->fb) {
qfb_old = to_qxl_framebuffer(old_state->fb);
bo_old = gem_to_qxl_bo(qfb_old->obj);
bo_old = gem_to_qxl_bo(old_state->fb->obj[0]);
} else {
bo_old = NULL;
}
......@@ -602,7 +565,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
bo->is_primary = true;
}
qxl_draw_dirty_fb(qdev, qfb, bo, 0, 0, &norect, 1, 1);
qxl_draw_dirty_fb(qdev, plane->state->fb, bo, 0, 0, &norect, 1, 1);
}
static void qxl_primary_atomic_disable(struct drm_plane *plane,
......@@ -611,9 +574,7 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane,
struct qxl_device *qdev = plane->dev->dev_private;
if (old_state->fb) {
struct qxl_framebuffer *qfb =
to_qxl_framebuffer(old_state->fb);
struct qxl_bo *bo = gem_to_qxl_bo(qfb->obj);
struct qxl_bo *bo = gem_to_qxl_bo(old_state->fb->obj[0]);
if (bo->is_primary) {
qxl_io_destroy_primary(qdev);
......@@ -645,7 +606,7 @@ static void qxl_cursor_atomic_update(struct drm_plane *plane,
return;
if (fb != old_state->fb) {
obj = to_qxl_framebuffer(fb)->obj;
obj = fb->obj[0];
user_bo = gem_to_qxl_bo(obj);
/* pinning is done in the prepare/cleanup framevbuffer */
......@@ -765,13 +726,13 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
if (!new_state->fb)
return 0;
obj = to_qxl_framebuffer(new_state->fb)->obj;
obj = new_state->fb->obj[0];
user_bo = gem_to_qxl_bo(obj);
if (plane->type == DRM_PLANE_TYPE_PRIMARY &&
user_bo->is_dumb && !user_bo->shadow) {
if (plane->state->fb) {
obj = to_qxl_framebuffer(plane->state->fb)->obj;
obj = plane->state->fb->obj[0];
old_bo = gem_to_qxl_bo(obj);
}
if (old_bo && old_bo->shadow &&
......@@ -815,7 +776,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane,
return;
}
obj = to_qxl_framebuffer(old_state->fb)->obj;
obj = old_state->fb->obj[0];
user_bo = gem_to_qxl_bo(obj);
qxl_bo_unpin(user_bo);
......@@ -1115,26 +1076,8 @@ qxl_user_framebuffer_create(struct drm_device *dev,
struct drm_file *file_priv,
const struct drm_mode_fb_cmd2 *mode_cmd)
{
struct drm_gem_object *obj;
struct qxl_framebuffer *qxl_fb;
int ret;
obj = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
if (!obj)
return NULL;
qxl_fb = kzalloc(sizeof(*qxl_fb), GFP_KERNEL);
if (qxl_fb == NULL)
return NULL;
ret = qxl_framebuffer_init(dev, qxl_fb, mode_cmd, obj, &qxl_fb_funcs);
if (ret) {
kfree(qxl_fb);
drm_gem_object_put_unlocked(obj);
return NULL;
}
return &qxl_fb->base;
return drm_gem_fb_create_with_funcs(dev, file_priv, mode_cmd,
&qxl_fb_funcs);
}
static const struct drm_mode_config_funcs qxl_mode_funcs = {
......@@ -1221,7 +1164,6 @@ int qxl_modeset_init(struct qxl_device *qdev)
}
qxl_display_read_client_monitors_config(qdev);
qdev->mode_info.mode_config_initialized = true;
drm_mode_config_reset(&qdev->ddev);
......@@ -1237,8 +1179,5 @@ void qxl_modeset_fini(struct qxl_device *qdev)
qxl_fbdev_fini(qdev);
qxl_destroy_monitors_object(qdev);
if (qdev->mode_info.mode_config_initialized) {
drm_mode_config_cleanup(&qdev->ddev);
qdev->mode_info.mode_config_initialized = false;
}
drm_mode_config_cleanup(&qdev->ddev);
}
......@@ -262,7 +262,7 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image,
* by treating them differently in the server.
*/
void qxl_draw_dirty_fb(struct qxl_device *qdev,
struct qxl_framebuffer *qxl_fb,
struct drm_framebuffer *fb,
struct qxl_bo *bo,
unsigned flags, unsigned color,
struct drm_clip_rect *clips,
......@@ -281,9 +281,9 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
struct qxl_drawable *drawable;
struct qxl_rect drawable_rect;
struct qxl_rect *rects;
int stride = qxl_fb->base.pitches[0];
int stride = fb->pitches[0];
/* depth is not actually interesting, we don't mask with it */
int depth = qxl_fb->base.format->cpp[0] * 8;
int depth = fb->format->cpp[0] * 8;
uint8_t *surface_base;
struct qxl_release *release;
struct qxl_bo *clips_bo;
......
......@@ -38,6 +38,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_encoder.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_gem.h>
#include <drm/drmP.h>
#include <drm/ttm/ttm_bo_api.h>
......@@ -121,15 +122,9 @@ struct qxl_output {
struct drm_encoder enc;
};
struct qxl_framebuffer {
struct drm_framebuffer base;
struct drm_gem_object *obj;
};
#define to_qxl_crtc(x) container_of(x, struct qxl_crtc, base)
#define drm_connector_to_qxl_output(x) container_of(x, struct qxl_output, base)
#define drm_encoder_to_qxl_output(x) container_of(x, struct qxl_output, enc)
#define to_qxl_framebuffer(x) container_of(x, struct qxl_framebuffer, base)
struct qxl_mman {
struct ttm_bo_global_ref bo_global_ref;
......@@ -138,13 +133,6 @@ struct qxl_mman {
struct ttm_bo_device bdev;
};
struct qxl_mode_info {
bool mode_config_initialized;
/* pointer to fbdev info structure */
struct qxl_fbdev *qfbdev;
};
struct qxl_memslot {
uint8_t generation;
......@@ -232,10 +220,9 @@ struct qxl_device {
void *ram;
struct qxl_mman mman;
struct qxl_gem gem;
struct qxl_mode_info mode_info;
struct fb_info *fbdev_info;
struct qxl_framebuffer *fbdev_qfb;
struct drm_fb_helper fb_helper;
void *ram_physical;
struct qxl_ring *release_ring;
......@@ -349,19 +336,8 @@ qxl_bo_physical_address(struct qxl_device *qdev, struct qxl_bo *bo,
int qxl_fbdev_init(struct qxl_device *qdev);
void qxl_fbdev_fini(struct qxl_device *qdev);
int qxl_get_handle_for_primary_fb(struct qxl_device *qdev,
struct drm_file *file_priv,
uint32_t *handle);
void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state);
/* qxl_display.c */
void qxl_user_framebuffer_destroy(struct drm_framebuffer *fb);
int
qxl_framebuffer_init(struct drm_device *dev,
struct qxl_framebuffer *rfb,
const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object *obj,
const struct drm_framebuffer_funcs *funcs);
void qxl_display_read_client_monitors_config(struct qxl_device *qdev);
int qxl_create_monitors_object(struct qxl_device *qdev);
int qxl_destroy_monitors_object(struct qxl_device *qdev);
......@@ -471,7 +447,7 @@ void qxl_draw_opaque_fb(const struct qxl_fb_image *qxl_fb_image,
int stride /* filled in if 0 */);
void qxl_draw_dirty_fb(struct qxl_device *qdev,
struct qxl_framebuffer *qxl_fb,
struct drm_framebuffer *fb,
struct qxl_bo *bo,
unsigned flags, unsigned color,
struct drm_clip_rect *clips,
......
This diff is collapsed.
......@@ -448,6 +448,11 @@ static int rockchip_drm_platform_remove(struct platform_device *pdev)
return 0;
}
static void rockchip_drm_platform_shutdown(struct platform_device *pdev)
{
rockchip_drm_platform_remove(pdev);
}
static const struct of_device_id rockchip_drm_dt_ids[] = {
{ .compatible = "rockchip,display-subsystem", },
{ /* sentinel */ },
......@@ -457,6 +462,7 @@ MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids);
static struct platform_driver rockchip_drm_platform_driver = {
.probe = rockchip_drm_platform_probe,
.remove = rockchip_drm_platform_remove,
.shutdown = rockchip_drm_platform_shutdown,
.driver = {
.name = "rockchip-drm",
.of_match_table = rockchip_drm_dt_ids,
......
......@@ -12,6 +12,7 @@
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_connector.h>
#include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_encoder.h>
......@@ -277,10 +278,64 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
}
static void sun4i_tcon0_mode_set_dithering(struct sun4i_tcon *tcon,
const struct drm_connector *connector)
{
u32 bus_format = 0;
u32 val = 0;
/* XXX Would this ever happen? */
if (!connector)
return;
/*
* FIXME: Undocumented bits
*
* The whole dithering process and these parameters are not
* explained in the vendor documents or BSP kernel code.
*/
regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PR_REG, 0x11111111);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PG_REG, 0x11111111);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_PB_REG, 0x11111111);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LR_REG, 0x11111111);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LG_REG, 0x11111111);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_SEED_LB_REG, 0x11111111);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL0_REG, 0x01010000);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL1_REG, 0x15151111);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL2_REG, 0x57575555);
regmap_write(tcon->regs, SUN4I_TCON0_FRM_TBL3_REG, 0x7f7f7777);
/* Do dithering if panel only supports 6 bits per color */
if (connector->display_info.bpc == 6)
val |= SUN4I_TCON0_FRM_CTL_EN;
if (connector->display_info.num_bus_formats == 1)
bus_format = connector->display_info.bus_formats[0];
/* Check the connection format */
switch (bus_format) {
case MEDIA_BUS_FMT_RGB565_1X16:
/* R and B components are only 5 bits deep */
val |= SUN4I_TCON0_FRM_CTL_MODE_R;
val |= SUN4I_TCON0_FRM_CTL_MODE_B;
case MEDIA_BUS_FMT_RGB666_1X18:
case MEDIA_BUS_FMT_RGB666_1X7X3_SPWG:
/* Fall through: enable dithering */
val |= SUN4I_TCON0_FRM_CTL_EN;
break;
}
/* Write dithering settings */
regmap_write(tcon->regs, SUN4I_TCON_FRM_CTL_REG, val);
}
static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
struct mipi_dsi_device *device,
const struct drm_encoder *encoder,
const struct drm_display_mode *mode)
{
/* TODO support normal CPU interface modes */
struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
struct mipi_dsi_device *device = dsi->device;
u8 bpp = mipi_dsi_pixel_format_to_bpp(device->format);
u8 lanes = device->lanes;
u32 block_space, start_delay;
......@@ -291,6 +346,9 @@ static void sun4i_tcon0_mode_set_cpu(struct sun4i_tcon *tcon,
sun4i_tcon0_mode_set_common(tcon, mode);
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
SUN4I_TCON0_CTL_IF_MASK,
SUN4I_TCON0_CTL_IF_8080);
......@@ -356,6 +414,9 @@ static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
tcon->dclk_max_div = 7;
sun4i_tcon0_mode_set_common(tcon, mode);
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, sun4i_tcon_get_connector(encoder));
/* Adjust clock delay */
clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
......@@ -429,6 +490,9 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon,
tcon->dclk_max_div = 127;
sun4i_tcon0_mode_set_common(tcon, mode);
/* Set dithering if needed */
sun4i_tcon0_mode_set_dithering(tcon, tcon->panel->connector);
/* Adjust clock delay */
clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
......@@ -610,16 +674,10 @@ void sun4i_tcon_mode_set(struct sun4i_tcon *tcon,
const struct drm_encoder *encoder,
const struct drm_display_mode *mode)
{
struct sun6i_dsi *dsi;
switch (encoder->encoder_type) {
case DRM_MODE_ENCODER_DSI:
/*
* This is not really elegant, but it's the "cleaner"
* way I could think of...
*/
dsi = encoder_to_sun6i_dsi(encoder);
sun4i_tcon0_mode_set_cpu(tcon, dsi->device, mode);
/* DSI is tied to special case of CPU interface */
sun4i_tcon0_mode_set_cpu(tcon, encoder, mode);
break;
case DRM_MODE_ENCODER_LVDS:
sun4i_tcon0_mode_set_lvds(tcon, encoder, mode);
......@@ -916,7 +974,8 @@ static bool sun4i_tcon_connected_to_tcon_top(struct device_node *node)
remote = of_graph_get_remote_node(node, 0, -1);
if (remote) {
ret = !!of_match_node(sun8i_tcon_top_of_table, remote);
ret = !!(IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
of_match_node(sun8i_tcon_top_of_table, remote));
of_node_put(remote);
}
......@@ -1344,13 +1403,20 @@ static int sun8i_r40_tcon_tv_set_mux(struct sun4i_tcon *tcon,
if (!pdev)
return -EINVAL;
if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP) &&
encoder->encoder_type == DRM_MODE_ENCODER_TMDS) {
ret = sun8i_tcon_top_set_hdmi_src(&pdev->dev, id);
if (ret)
return ret;
}
return sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
if (IS_ENABLED(CONFIG_DRM_SUN8I_TCON_TOP)) {
ret = sun8i_tcon_top_de_config(&pdev->dev, tcon->id, id);
if (ret)
return ret;
}
return 0;
}
static const struct sun4i_tcon_quirks sun4i_a10_quirks = {
......
......@@ -37,18 +37,21 @@
#define SUN4I_TCON_GINT1_REG 0x8
#define SUN4I_TCON_FRM_CTL_REG 0x10
#define SUN4I_TCON_FRM_CTL_EN BIT(31)
#define SUN4I_TCON_FRM_SEED_PR_REG 0x14
#define SUN4I_TCON_FRM_SEED_PG_REG 0x18
#define SUN4I_TCON_FRM_SEED_PB_REG 0x1c
#define SUN4I_TCON_FRM_SEED_LR_REG 0x20
#define SUN4I_TCON_FRM_SEED_LG_REG 0x24
#define SUN4I_TCON_FRM_SEED_LB_REG 0x28
#define SUN4I_TCON_FRM_TBL0_REG 0x2c
#define SUN4I_TCON_FRM_TBL1_REG 0x30
#define SUN4I_TCON_FRM_TBL2_REG 0x34
#define SUN4I_TCON_FRM_TBL3_REG 0x38
#define SUN4I_TCON0_FRM_CTL_EN BIT(31)
#define SUN4I_TCON0_FRM_CTL_MODE_R BIT(6)
#define SUN4I_TCON0_FRM_CTL_MODE_G BIT(5)
#define SUN4I_TCON0_FRM_CTL_MODE_B BIT(4)
#define SUN4I_TCON0_FRM_SEED_PR_REG 0x14
#define SUN4I_TCON0_FRM_SEED_PG_REG 0x18
#define SUN4I_TCON0_FRM_SEED_PB_REG 0x1c
#define SUN4I_TCON0_FRM_SEED_LR_REG 0x20
#define SUN4I_TCON0_FRM_SEED_LG_REG 0x24
#define SUN4I_TCON0_FRM_SEED_LB_REG 0x28
#define SUN4I_TCON0_FRM_TBL0_REG 0x2c
#define SUN4I_TCON0_FRM_TBL1_REG 0x30
#define SUN4I_TCON0_FRM_TBL2_REG 0x34
#define SUN4I_TCON0_FRM_TBL3_REG 0x38
#define SUN4I_TCON0_CTL_REG 0x40
#define SUN4I_TCON0_CTL_TCON_ENABLE BIT(31)
......
......@@ -521,12 +521,12 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
kref_init(&exec->refcount);
ret = drm_syncobj_find_fence(file_priv, args->in_sync_bcl,
&exec->bin.in_fence);
0, &exec->bin.in_fence);
if (ret == -EINVAL)
goto fail;
ret = drm_syncobj_find_fence(file_priv, args->in_sync_rcl,
&exec->render.in_fence);
0, &exec->render.in_fence);
if (ret == -EINVAL)
goto fail;
......@@ -584,7 +584,7 @@ v3d_submit_cl_ioctl(struct drm_device *dev, void *data,
/* Update the return sync object for the */
sync_out = drm_syncobj_find(file_priv, args->out_sync);
if (sync_out) {
drm_syncobj_replace_fence(sync_out,
drm_syncobj_replace_fence(sync_out, 0,
&exec->render.base.s_fence->finished);
drm_syncobj_put(sync_out);
}
......
......@@ -35,6 +35,7 @@
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_atomic_uapi.h>
#include <linux/clk.h>
#include <drm/drm_fb_cma_helper.h>
#include <linux/component.h>
......
......@@ -681,7 +681,7 @@ vc4_queue_submit(struct drm_device *dev, struct vc4_exec_info *exec,
exec->fence = &fence->base;
if (out_sync)
drm_syncobj_replace_fence(out_sync, exec->fence);
drm_syncobj_replace_fence(out_sync, 0, exec->fence);
vc4_update_bo_seqnos(exec, seqno);
......@@ -1173,7 +1173,7 @@ vc4_submit_cl_ioctl(struct drm_device *dev, void *data,
if (args->in_sync) {
ret = drm_syncobj_find_fence(file_priv, args->in_sync,
&in_fence);
0, &in_fence);
if (ret)
goto fail;
......
......@@ -22,6 +22,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_fb_cma_helper.h>
#include <drm/drm_plane_helper.h>
#include <drm/drm_atomic_uapi.h>
#include "uapi/drm/vc4_drm.h"
#include "vc4_drv.h"
......
......@@ -75,12 +75,9 @@ virtio_gpu_framebuffer_init(struct drm_device *dev,
struct drm_gem_object *obj)
{
int ret;
struct virtio_gpu_object *bo;
vgfb->base.obj[0] = obj;
bo = gem_to_virtio_gpu_obj(obj);
drm_helper_mode_fill_fb_struct(dev, &vgfb->base, mode_cmd);
ret = drm_framebuffer_init(dev, &vgfb->base, &virtio_gpu_fb_funcs);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -155,8 +155,7 @@ static int vboxfb_create(struct drm_fb_helper *helper,
* The last flag forces a mode set on VT switches even if the kernel
* does not think it is needed.
*/
info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT |
FBINFO_MISC_ALWAYS_SETPAR;
info->flags = FBINFO_DEFAULT | FBINFO_MISC_ALWAYS_SETPAR;
info->fbops = &vboxfb_ops;
/*
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -110,7 +110,4 @@ static inline bool drm_can_sleep(void)
return true;
}
/* helper for handling conditionals in various for_each macros */
#define for_each_if(condition) if (!(condition)) {} else
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment