mirror of https://gitee.com/openkylin/linux.git
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> -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEfxcpfMSgdnQMs+QqlvcN/ahKBwoFAluaXuAACgkQlvcN/ahK BwrQHggAtcu96+plN6cDcMcoOfnQT/OG30dBER4/cpG05hEciq/NXwXBQ9dPWtqk Nkcgst28UbXTmt0UKck7ibfePLVqnN7+yRqnj3yrD28Qjrg1Ewr0go8cKlIJ8+8t E6aLvgRwx5/9sHHaeCC1K1qfowEr0Put9DQvLH2BVRM3C1Sj5BXeXMP4djb5PHGU BYGLoN9DrrVHLVARwbmzSb8V5oLED2CdRkL7WpXC2LcEGZ3jPllTN8EOoqsIMOAZ LGnpWxADVnYTA5np3O0QJsalu942T4rMPoxgCHZmuGIhEijqk7mgGWpeOmzN71Eh rXX1yyWvZenUc69Pbl7G7lQmE6DSDw== =9Mxt -----END PGP SIGNATURE----- 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: Dave Airlie <airlied@redhat.com> From: Sean Paul <sean@poorly.run> Link: https://patchwork.freedesktop.org/patch/msgid/20180913130254.GA156437@art_vandelay
This commit is contained in:
commit
2dc7bad71c
|
@ -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
|
||||
Extend virtual test driver (VKMS)
|
||||
---------------------------------
|
||||
|
||||
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.
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
.. _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.
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
// 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, ®);
|
||||
dp->link_train.link_rate = reg;
|
||||
dev_dbg(dp->dev, "final bandwidth = %.2x\n",
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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;
|
||||
break;
|
||||
case 32:
|
||||
if (depth == 24)
|
||||
fmt = DRM_FORMAT_XRGB8888;
|
||||
else if (depth == 30)
|
||||
fmt = DRM_FORMAT_XRGB2101010;
|
||||
else
|
||||
fmt = DRM_FORMAT_ARGB8888;
|
||||
fmt = DRM_FORMAT_RGB888;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
switch (depth) {
|
||||
case 24:
|
||||
fmt = DRM_FORMAT_XRGB8888;
|
||||
break;
|
||||
case 30:
|
||||
fmt = DRM_FORMAT_XRGB2101010;
|
||||
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,
|
||||
|
|
|
@ -30,24 +30,12 @@
|
|||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
|
||||
#include "qxl_drv.h"
|
||||
|
||||
#include "qxl_object.h"
|
||||
|
||||
#define QXL_DIRTY_DELAY (HZ / 30)
|
||||
|
||||
struct qxl_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct qxl_framebuffer qfb;
|
||||
struct qxl_device *qdev;
|
||||
|
||||
spinlock_t delayed_ops_lock;
|
||||
struct list_head delayed_ops;
|
||||
void *shadow;
|
||||
int size;
|
||||
};
|
||||
|
||||
static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image,
|
||||
struct qxl_device *qdev, struct fb_info *info,
|
||||
const struct fb_image *image)
|
||||
|
@ -73,13 +61,6 @@ static void qxl_fb_image_init(struct qxl_fb_image *qxl_fb_image,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
static struct fb_deferred_io qxl_defio = {
|
||||
.delay = QXL_DIRTY_DELAY,
|
||||
.deferred_io = drm_fb_helper_deferred_io,
|
||||
};
|
||||
#endif
|
||||
|
||||
static struct fb_ops qxlfb_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
DRM_FB_HELPER_DEFAULT_OPS,
|
||||
|
@ -98,26 +79,10 @@ static void qxlfb_destroy_pinned_object(struct drm_gem_object *gobj)
|
|||
drm_gem_object_put_unlocked(gobj);
|
||||
}
|
||||
|
||||
int qxl_get_handle_for_primary_fb(struct qxl_device *qdev,
|
||||
struct drm_file *file_priv,
|
||||
uint32_t *handle)
|
||||
{
|
||||
int r;
|
||||
struct drm_gem_object *gobj = qdev->fbdev_qfb->obj;
|
||||
|
||||
BUG_ON(!gobj);
|
||||
/* drm_get_handle_create adds a reference - good */
|
||||
r = drm_gem_handle_create(file_priv, gobj, handle);
|
||||
if (r)
|
||||
return r;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int qxlfb_create_pinned_object(struct qxl_fbdev *qfbdev,
|
||||
static int qxlfb_create_pinned_object(struct qxl_device *qdev,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd,
|
||||
struct drm_gem_object **gobj_p)
|
||||
{
|
||||
struct qxl_device *qdev = qfbdev->qdev;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct qxl_bo *qbo = NULL;
|
||||
int ret;
|
||||
|
@ -174,13 +139,12 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb,
|
|||
unsigned num_clips)
|
||||
{
|
||||
struct qxl_device *qdev = fb->dev->dev_private;
|
||||
struct fb_info *info = qdev->fbdev_info;
|
||||
struct qxl_fbdev *qfbdev = info->par;
|
||||
struct fb_info *info = qdev->fb_helper.fbdev;
|
||||
struct qxl_fb_image qxl_fb_image;
|
||||
struct fb_image *image = &qxl_fb_image.fb_image;
|
||||
|
||||
/* TODO: hard coding 32 bpp */
|
||||
int stride = qfbdev->qfb.base.pitches[0];
|
||||
int stride = fb->pitches[0];
|
||||
|
||||
/*
|
||||
* we are using a shadow draw buffer, at qdev->surface0_shadow
|
||||
|
@ -199,7 +163,7 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb,
|
|||
image->cmap.green = NULL;
|
||||
image->cmap.blue = NULL;
|
||||
image->cmap.transp = NULL;
|
||||
image->data = qfbdev->shadow + (clips->x1 * 4) + (stride * clips->y1);
|
||||
image->data = info->screen_base + (clips->x1 * 4) + (stride * clips->y1);
|
||||
|
||||
qxl_fb_image_init(&qxl_fb_image, qdev, info, NULL);
|
||||
qxl_draw_opaque_fb(&qxl_fb_image, stride);
|
||||
|
@ -208,21 +172,22 @@ static int qxlfb_framebuffer_dirty(struct drm_framebuffer *fb,
|
|||
}
|
||||
|
||||
static const struct drm_framebuffer_funcs qxlfb_fb_funcs = {
|
||||
.destroy = qxl_user_framebuffer_destroy,
|
||||
.destroy = drm_gem_fb_destroy,
|
||||
.create_handle = drm_gem_fb_create_handle,
|
||||
.dirty = qxlfb_framebuffer_dirty,
|
||||
};
|
||||
|
||||
static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
||||
static int qxlfb_create(struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct qxl_device *qdev = qfbdev->qdev;
|
||||
struct qxl_device *qdev =
|
||||
container_of(helper, struct qxl_device, fb_helper);
|
||||
struct fb_info *info;
|
||||
struct drm_framebuffer *fb = NULL;
|
||||
struct drm_mode_fb_cmd2 mode_cmd;
|
||||
struct drm_gem_object *gobj = NULL;
|
||||
struct qxl_bo *qbo = NULL;
|
||||
int ret;
|
||||
int size;
|
||||
int bpp = sizes->surface_bpp;
|
||||
int depth = sizes->surface_depth;
|
||||
void *shadow;
|
||||
|
@ -233,7 +198,7 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
|||
mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 1) / 8), 64);
|
||||
mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth);
|
||||
|
||||
ret = qxlfb_create_pinned_object(qfbdev, &mode_cmd, &gobj);
|
||||
ret = qxlfb_create_pinned_object(qdev, &mode_cmd, &gobj);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -247,25 +212,26 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
|||
DRM_DEBUG_DRIVER("surface0 at gpu offset %lld, mmap_offset %lld (virt %p, shadow %p)\n",
|
||||
qxl_bo_gpu_offset(qbo), qxl_bo_mmap_offset(qbo),
|
||||
qbo->kptr, shadow);
|
||||
size = mode_cmd.pitches[0] * mode_cmd.height;
|
||||
|
||||
info = drm_fb_helper_alloc_fbi(&qfbdev->helper);
|
||||
info = drm_fb_helper_alloc_fbi(helper);
|
||||
if (IS_ERR(info)) {
|
||||
ret = PTR_ERR(info);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
info->par = qfbdev;
|
||||
info->par = helper;
|
||||
|
||||
qxl_framebuffer_init(&qdev->ddev, &qfbdev->qfb, &mode_cmd, gobj,
|
||||
&qxlfb_fb_funcs);
|
||||
|
||||
fb = &qfbdev->qfb.base;
|
||||
fb = drm_gem_fbdev_fb_create(&qdev->ddev, sizes, 64, gobj,
|
||||
&qxlfb_fb_funcs);
|
||||
if (IS_ERR(fb)) {
|
||||
DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb));
|
||||
ret = PTR_ERR(fb);
|
||||
goto out_unref;
|
||||
}
|
||||
|
||||
/* setup helper with fb data */
|
||||
qfbdev->helper.fb = fb;
|
||||
qdev->fb_helper.fb = fb;
|
||||
|
||||
qfbdev->shadow = shadow;
|
||||
strcpy(info->fix.id, "qxldrmfb");
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
|
||||
|
@ -278,10 +244,10 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
|||
*/
|
||||
info->fix.smem_start = qdev->vram_base; /* TODO - correct? */
|
||||
info->fix.smem_len = gobj->size;
|
||||
info->screen_base = qfbdev->shadow;
|
||||
info->screen_base = shadow;
|
||||
info->screen_size = gobj->size;
|
||||
|
||||
drm_fb_helper_fill_var(info, &qfbdev->helper, sizes->fb_width,
|
||||
drm_fb_helper_fill_var(info, &qdev->fb_helper, sizes->fb_width,
|
||||
sizes->fb_height);
|
||||
|
||||
/* setup aperture base/size for vesafb takeover */
|
||||
|
@ -296,13 +262,9 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
|||
goto out_unref;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
info->fbdefio = &qxl_defio;
|
||||
fb_deferred_io_init(info);
|
||||
#endif
|
||||
/* XXX error handling. */
|
||||
drm_fb_helper_defio_init(helper);
|
||||
|
||||
qdev->fbdev_info = info;
|
||||
qdev->fbdev_qfb = &qfbdev->qfb;
|
||||
DRM_INFO("fb mappable at 0x%lX, size %lu\n", info->fix.smem_start, (unsigned long)info->screen_size);
|
||||
DRM_INFO("fb: depth %d, pitch %d, width %d, height %d\n",
|
||||
fb->format->depth, fb->pitches[0], fb->width, fb->height);
|
||||
|
@ -313,119 +275,26 @@ static int qxlfb_create(struct qxl_fbdev *qfbdev,
|
|||
qxl_bo_kunmap(qbo);
|
||||
qxl_bo_unpin(qbo);
|
||||
}
|
||||
if (fb && ret) {
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
drm_framebuffer_cleanup(fb);
|
||||
kfree(fb);
|
||||
}
|
||||
drm_gem_object_put_unlocked(gobj);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int qxl_fb_find_or_create_single(
|
||||
struct drm_fb_helper *helper,
|
||||
struct drm_fb_helper_surface_size *sizes)
|
||||
{
|
||||
struct qxl_fbdev *qfbdev =
|
||||
container_of(helper, struct qxl_fbdev, helper);
|
||||
int new_fb = 0;
|
||||
int ret;
|
||||
|
||||
if (!helper->fb) {
|
||||
ret = qxlfb_create(qfbdev, sizes);
|
||||
if (ret)
|
||||
return ret;
|
||||
new_fb = 1;
|
||||
}
|
||||
return new_fb;
|
||||
}
|
||||
|
||||
static int qxl_fbdev_destroy(struct drm_device *dev, struct qxl_fbdev *qfbdev)
|
||||
{
|
||||
struct qxl_framebuffer *qfb = &qfbdev->qfb;
|
||||
|
||||
drm_fb_helper_unregister_fbi(&qfbdev->helper);
|
||||
|
||||
if (qfb->obj) {
|
||||
qxlfb_destroy_pinned_object(qfb->obj);
|
||||
qfb->obj = NULL;
|
||||
}
|
||||
drm_fb_helper_fini(&qfbdev->helper);
|
||||
vfree(qfbdev->shadow);
|
||||
drm_framebuffer_cleanup(&qfb->base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct drm_fb_helper_funcs qxl_fb_helper_funcs = {
|
||||
.fb_probe = qxl_fb_find_or_create_single,
|
||||
.fb_probe = qxlfb_create,
|
||||
};
|
||||
|
||||
int qxl_fbdev_init(struct qxl_device *qdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
#ifdef CONFIG_DRM_FBDEV_EMULATION
|
||||
struct qxl_fbdev *qfbdev;
|
||||
int bpp_sel = 32; /* TODO: parameter from somewhere? */
|
||||
|
||||
qfbdev = kzalloc(sizeof(struct qxl_fbdev), GFP_KERNEL);
|
||||
if (!qfbdev)
|
||||
return -ENOMEM;
|
||||
|
||||
qfbdev->qdev = qdev;
|
||||
qdev->mode_info.qfbdev = qfbdev;
|
||||
spin_lock_init(&qfbdev->delayed_ops_lock);
|
||||
INIT_LIST_HEAD(&qfbdev->delayed_ops);
|
||||
|
||||
drm_fb_helper_prepare(&qdev->ddev, &qfbdev->helper,
|
||||
&qxl_fb_helper_funcs);
|
||||
|
||||
ret = drm_fb_helper_init(&qdev->ddev, &qfbdev->helper,
|
||||
QXLFB_CONN_LIMIT);
|
||||
if (ret)
|
||||
goto free;
|
||||
|
||||
ret = drm_fb_helper_single_add_all_connectors(&qfbdev->helper);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
||||
ret = drm_fb_helper_initial_config(&qfbdev->helper, bpp_sel);
|
||||
if (ret)
|
||||
goto fini;
|
||||
|
||||
return 0;
|
||||
|
||||
fini:
|
||||
drm_fb_helper_fini(&qfbdev->helper);
|
||||
free:
|
||||
kfree(qfbdev);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
return drm_fb_helper_fbdev_setup(&qdev->ddev, &qdev->fb_helper,
|
||||
&qxl_fb_helper_funcs, 32,
|
||||
QXLFB_CONN_LIMIT);
|
||||
}
|
||||
|
||||
void qxl_fbdev_fini(struct qxl_device *qdev)
|
||||
{
|
||||
if (!qdev->mode_info.qfbdev)
|
||||
return;
|
||||
struct fb_info *fbi = qdev->fb_helper.fbdev;
|
||||
void *shadow = fbi ? fbi->screen_buffer : NULL;
|
||||
|
||||
qxl_fbdev_destroy(&qdev->ddev, qdev->mode_info.qfbdev);
|
||||
kfree(qdev->mode_info.qfbdev);
|
||||
qdev->mode_info.qfbdev = NULL;
|
||||
}
|
||||
|
||||
void qxl_fbdev_set_suspend(struct qxl_device *qdev, int state)
|
||||
{
|
||||
if (!qdev->mode_info.qfbdev)
|
||||
return;
|
||||
|
||||
drm_fb_helper_set_suspend(&qdev->mode_info.qfbdev->helper, state);
|
||||
}
|
||||
|
||||
bool qxl_fbdev_qobj_is_fb(struct qxl_device *qdev, struct qxl_bo *qobj)
|
||||
{
|
||||
if (qobj == gem_to_qxl_bo(qdev->mode_info.qfbdev->qfb.obj))
|
||||
return true;
|
||||
return false;
|
||||
drm_fb_helper_fbdev_teardown(&qdev->ddev);
|
||||
vfree(shadow);
|
||||
}
|
||||
|
|
|
@ -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_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_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_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);
|
||||
|
|
|
@ -1,36 +1,143 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "vkms_drv.h"
|
||||
#include <linux/crc32.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
|
||||
static uint32_t _vkms_get_crc(struct vkms_crc_data *crc_data)
|
||||
/**
|
||||
* compute_crc - Compute CRC value on output frame
|
||||
*
|
||||
* @vaddr_out: address to final framebuffer
|
||||
* @crc_out: framebuffer's metadata
|
||||
*
|
||||
* returns CRC value computed using crc32 on the visible portion of
|
||||
* the final framebuffer at vaddr_out
|
||||
*/
|
||||
static uint32_t compute_crc(void *vaddr_out, struct vkms_crc_data *crc_out)
|
||||
{
|
||||
struct drm_framebuffer *fb = &crc_data->fb;
|
||||
struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
|
||||
struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
|
||||
int i, j, src_offset;
|
||||
int x_src = crc_out->src.x1 >> 16;
|
||||
int y_src = crc_out->src.y1 >> 16;
|
||||
int h_src = drm_rect_height(&crc_out->src) >> 16;
|
||||
int w_src = drm_rect_width(&crc_out->src) >> 16;
|
||||
u32 crc = 0;
|
||||
int i = 0;
|
||||
unsigned int x = crc_data->src.x1 >> 16;
|
||||
unsigned int y = crc_data->src.y1 >> 16;
|
||||
unsigned int height = drm_rect_height(&crc_data->src) >> 16;
|
||||
unsigned int width = drm_rect_width(&crc_data->src) >> 16;
|
||||
unsigned int cpp = fb->format->cpp[0];
|
||||
unsigned int src_offset;
|
||||
unsigned int size_byte = width * cpp;
|
||||
void *vaddr;
|
||||
|
||||
mutex_lock(&vkms_obj->pages_lock);
|
||||
vaddr = vkms_obj->vaddr;
|
||||
if (WARN_ON(!vaddr))
|
||||
goto out;
|
||||
|
||||
for (i = y; i < y + height; i++) {
|
||||
src_offset = fb->offsets[0] + (i * fb->pitches[0]) + (x * cpp);
|
||||
crc = crc32_le(crc, vaddr + src_offset, size_byte);
|
||||
for (i = y_src; i < y_src + h_src; ++i) {
|
||||
for (j = x_src; j < x_src + w_src; ++j) {
|
||||
src_offset = crc_out->offset
|
||||
+ (i * crc_out->pitch)
|
||||
+ (j * crc_out->cpp);
|
||||
/* XRGB format ignores Alpha channel */
|
||||
memset(vaddr_out + src_offset + 24, 0, 8);
|
||||
crc = crc32_le(crc, vaddr_out + src_offset,
|
||||
sizeof(u32));
|
||||
}
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
/**
|
||||
* blend - belnd value at vaddr_src with value at vaddr_dst
|
||||
* @vaddr_dst: destination address
|
||||
* @vaddr_src: source address
|
||||
* @crc_dst: destination framebuffer's metadata
|
||||
* @crc_src: source framebuffer's metadata
|
||||
*
|
||||
* Blend value at vaddr_src with value at vaddr_dst.
|
||||
* Currently, this function write value at vaddr_src on value
|
||||
* at vaddr_dst using buffer's metadata to locate the new values
|
||||
* from vaddr_src and their distenation at vaddr_dst.
|
||||
*
|
||||
* Todo: Use the alpha value to blend vaddr_src with vaddr_dst
|
||||
* instead of overwriting it.
|
||||
*/
|
||||
static void blend(void *vaddr_dst, void *vaddr_src,
|
||||
struct vkms_crc_data *crc_dst,
|
||||
struct vkms_crc_data *crc_src)
|
||||
{
|
||||
int i, j, j_dst, i_dst;
|
||||
int offset_src, offset_dst;
|
||||
|
||||
int x_src = crc_src->src.x1 >> 16;
|
||||
int y_src = crc_src->src.y1 >> 16;
|
||||
|
||||
int x_dst = crc_src->dst.x1;
|
||||
int y_dst = crc_src->dst.y1;
|
||||
int h_dst = drm_rect_height(&crc_src->dst);
|
||||
int w_dst = drm_rect_width(&crc_src->dst);
|
||||
|
||||
int y_limit = y_src + h_dst;
|
||||
int x_limit = x_src + w_dst;
|
||||
|
||||
for (i = y_src, i_dst = y_dst; i < y_limit; ++i) {
|
||||
for (j = x_src, j_dst = x_dst; j < x_limit; ++j) {
|
||||
offset_dst = crc_dst->offset
|
||||
+ (i_dst * crc_dst->pitch)
|
||||
+ (j_dst++ * crc_dst->cpp);
|
||||
offset_src = crc_src->offset
|
||||
+ (i * crc_src->pitch)
|
||||
+ (j * crc_src->cpp);
|
||||
|
||||
memcpy(vaddr_dst + offset_dst,
|
||||
vaddr_src + offset_src, sizeof(u32));
|
||||
}
|
||||
i_dst++;
|
||||
}
|
||||
}
|
||||
|
||||
static void compose_cursor(struct vkms_crc_data *cursor_crc,
|
||||
struct vkms_crc_data *primary_crc, void *vaddr_out)
|
||||
{
|
||||
struct drm_gem_object *cursor_obj;
|
||||
struct vkms_gem_object *cursor_vkms_obj;
|
||||
|
||||
cursor_obj = drm_gem_fb_get_obj(&cursor_crc->fb, 0);
|
||||
cursor_vkms_obj = drm_gem_to_vkms_gem(cursor_obj);
|
||||
|
||||
mutex_lock(&cursor_vkms_obj->pages_lock);
|
||||
if (!cursor_vkms_obj->vaddr) {
|
||||
DRM_WARN("cursor plane vaddr is NULL");
|
||||
goto out;
|
||||
}
|
||||
|
||||
blend(vaddr_out, cursor_vkms_obj->vaddr, primary_crc, cursor_crc);
|
||||
|
||||
out:
|
||||
mutex_unlock(&cursor_vkms_obj->pages_lock);
|
||||
}
|
||||
|
||||
static uint32_t _vkms_get_crc(struct vkms_crc_data *primary_crc,
|
||||
struct vkms_crc_data *cursor_crc)
|
||||
{
|
||||
struct drm_framebuffer *fb = &primary_crc->fb;
|
||||
struct drm_gem_object *gem_obj = drm_gem_fb_get_obj(fb, 0);
|
||||
struct vkms_gem_object *vkms_obj = drm_gem_to_vkms_gem(gem_obj);
|
||||
void *vaddr_out = kzalloc(vkms_obj->gem.size, GFP_KERNEL);
|
||||
u32 crc = 0;
|
||||
|
||||
if (!vaddr_out) {
|
||||
DRM_ERROR("Failed to allocate memory for output frame.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&vkms_obj->pages_lock);
|
||||
if (WARN_ON(!vkms_obj->vaddr)) {
|
||||
mutex_unlock(&vkms_obj->pages_lock);
|
||||
return crc;
|
||||
}
|
||||
|
||||
memcpy(vaddr_out, vkms_obj->vaddr, vkms_obj->gem.size);
|
||||
mutex_unlock(&vkms_obj->pages_lock);
|
||||
|
||||
if (cursor_crc)
|
||||
compose_cursor(cursor_crc, primary_crc, vaddr_out);
|
||||
|
||||
crc = compute_crc(vaddr_out, primary_crc);
|
||||
|
||||
kfree(vaddr_out);
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
|
@ -53,6 +160,7 @@ void vkms_crc_work_handle(struct work_struct *work)
|
|||
struct vkms_device *vdev = container_of(out, struct vkms_device,
|
||||
output);
|
||||
struct vkms_crc_data *primary_crc = NULL;
|
||||
struct vkms_crc_data *cursor_crc = NULL;
|
||||
struct drm_plane *plane;
|
||||
u32 crc32 = 0;
|
||||
u64 frame_start, frame_end;
|
||||
|
@ -77,14 +185,14 @@ void vkms_crc_work_handle(struct work_struct *work)
|
|||
if (drm_framebuffer_read_refcount(&crc_data->fb) == 0)
|
||||
continue;
|
||||
|
||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY) {
|
||||
if (plane->type == DRM_PLANE_TYPE_PRIMARY)
|
||||
primary_crc = crc_data;
|
||||
break;
|
||||
}
|
||||
else
|
||||
cursor_crc = crc_data;
|
||||
}
|
||||
|
||||
if (primary_crc)
|
||||
crc32 = _vkms_get_crc(primary_crc);
|
||||
crc32 = _vkms_get_crc(primary_crc, cursor_crc);
|
||||
|
||||
frame_end = drm_crtc_accurate_vblank_count(crtc);
|
||||
|
||||
|
|
|
@ -5,6 +5,15 @@
|
|||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
/**
|
||||
* DOC: vkms (Virtual Kernel Modesetting)
|
||||
*
|
||||
* vkms is a software-only model of a kms driver that is useful for testing,
|
||||
* or for running X (or similar) on headless machines and be able to still
|
||||
* use the GPU. vkms aims to enable a virtual display without the need for
|
||||
* a hardware display capability.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
|
@ -21,6 +30,10 @@
|
|||
|
||||
static struct vkms_device *vkms_device;
|
||||
|
||||
bool enable_cursor;
|
||||
module_param_named(enable_cursor, enable_cursor, bool, 0444);
|
||||
MODULE_PARM_DESC(enable_cursor, "Enable/Disable cursor support");
|
||||
|
||||
static const struct file_operations vkms_driver_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = drm_open,
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
#include <drm/drm_encoder.h>
|
||||
#include <linux/hrtimer.h>
|
||||
|
||||
#define XRES_MIN 32
|
||||
#define YRES_MIN 32
|
||||
#define XRES_MIN 20
|
||||
#define YRES_MIN 20
|
||||
|
||||
#define XRES_DEF 1024
|
||||
#define YRES_DEF 768
|
||||
|
@ -16,13 +16,22 @@
|
|||
#define XRES_MAX 8192
|
||||
#define YRES_MAX 8192
|
||||
|
||||
extern bool enable_cursor;
|
||||
|
||||
static const u32 vkms_formats[] = {
|
||||
DRM_FORMAT_XRGB8888,
|
||||
};
|
||||
|
||||
static const u32 vkms_cursor_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
struct vkms_crc_data {
|
||||
struct drm_rect src;
|
||||
struct drm_framebuffer fb;
|
||||
struct drm_rect src, dst;
|
||||
unsigned int offset;
|
||||
unsigned int pitch;
|
||||
unsigned int cpp;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -104,7 +113,8 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
|
|||
|
||||
int vkms_output_init(struct vkms_device *vkmsdev);
|
||||
|
||||
struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev);
|
||||
struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
|
||||
enum drm_plane_type type);
|
||||
|
||||
/* Gem stuff */
|
||||
struct drm_gem_object *vkms_gem_create(struct drm_device *dev,
|
||||
|
|
|
@ -49,14 +49,22 @@ int vkms_output_init(struct vkms_device *vkmsdev)
|
|||
struct drm_connector *connector = &output->connector;
|
||||
struct drm_encoder *encoder = &output->encoder;
|
||||
struct drm_crtc *crtc = &output->crtc;
|
||||
struct drm_plane *primary;
|
||||
struct drm_plane *primary, *cursor = NULL;
|
||||
int ret;
|
||||
|
||||
primary = vkms_plane_init(vkmsdev);
|
||||
primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY);
|
||||
if (IS_ERR(primary))
|
||||
return PTR_ERR(primary);
|
||||
|
||||
ret = vkms_crtc_init(dev, crtc, primary, NULL);
|
||||
if (enable_cursor) {
|
||||
cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR);
|
||||
if (IS_ERR(cursor)) {
|
||||
ret = PTR_ERR(cursor);
|
||||
goto err_cursor;
|
||||
}
|
||||
}
|
||||
|
||||
ret = vkms_crtc_init(dev, crtc, primary, cursor);
|
||||
if (ret)
|
||||
goto err_crtc;
|
||||
|
||||
|
@ -106,6 +114,11 @@ int vkms_output_init(struct vkms_device *vkmsdev)
|
|||
drm_crtc_cleanup(crtc);
|
||||
|
||||
err_crtc:
|
||||
if (enable_cursor)
|
||||
drm_plane_cleanup(cursor);
|
||||
|
||||
err_cursor:
|
||||
drm_plane_cleanup(primary);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -81,26 +81,33 @@ static const struct drm_plane_funcs vkms_plane_funcs = {
|
|||
.atomic_destroy_state = vkms_plane_destroy_state,
|
||||
};
|
||||
|
||||
static void vkms_primary_plane_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
static void vkms_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_state)
|
||||
{
|
||||
struct vkms_plane_state *vkms_plane_state;
|
||||
struct drm_framebuffer *fb = plane->state->fb;
|
||||
struct vkms_crc_data *crc_data;
|
||||
|
||||
if (!plane->state->crtc || !plane->state->fb)
|
||||
if (!plane->state->crtc || !fb)
|
||||
return;
|
||||
|
||||
vkms_plane_state = to_vkms_plane_state(plane->state);
|
||||
|
||||
crc_data = vkms_plane_state->crc_data;
|
||||
memcpy(&crc_data->src, &plane->state->src, sizeof(struct drm_rect));
|
||||
memcpy(&crc_data->fb, plane->state->fb, sizeof(struct drm_framebuffer));
|
||||
memcpy(&crc_data->dst, &plane->state->dst, sizeof(struct drm_rect));
|
||||
memcpy(&crc_data->fb, fb, sizeof(struct drm_framebuffer));
|
||||
drm_framebuffer_get(&crc_data->fb);
|
||||
crc_data->offset = fb->offsets[0];
|
||||
crc_data->pitch = fb->pitches[0];
|
||||
crc_data->cpp = fb->format->cpp[0];
|
||||
}
|
||||
|
||||
static int vkms_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
struct drm_crtc_state *crtc_state;
|
||||
bool can_position = false;
|
||||
int ret;
|
||||
|
||||
if (!state->fb | !state->crtc)
|
||||
|
@ -110,15 +117,18 @@ static int vkms_plane_atomic_check(struct drm_plane *plane,
|
|||
if (IS_ERR(crtc_state))
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
if (plane->type == DRM_PLANE_TYPE_CURSOR)
|
||||
can_position = true;
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
false, true);
|
||||
can_position, true);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
||||
/* for now primary plane must be visible and full screen */
|
||||
if (!state->visible)
|
||||
if (!state->visible && !can_position)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
|
@ -156,15 +166,17 @@ static void vkms_cleanup_fb(struct drm_plane *plane,
|
|||
}
|
||||
|
||||
static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = {
|
||||
.atomic_update = vkms_primary_plane_update,
|
||||
.atomic_update = vkms_plane_atomic_update,
|
||||
.atomic_check = vkms_plane_atomic_check,
|
||||
.prepare_fb = vkms_prepare_fb,
|
||||
.cleanup_fb = vkms_cleanup_fb,
|
||||
};
|
||||
|
||||
struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev)
|
||||
struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev,
|
||||
enum drm_plane_type type)
|
||||
{
|
||||
struct drm_device *dev = &vkmsdev->drm;
|
||||
const struct drm_plane_helper_funcs *funcs;
|
||||
struct drm_plane *plane;
|
||||
const u32 *formats;
|
||||
int ret, nformats;
|
||||
|
@ -173,19 +185,26 @@ struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev)
|
|||
if (!plane)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
formats = vkms_formats;
|
||||
nformats = ARRAY_SIZE(vkms_formats);
|
||||
if (type == DRM_PLANE_TYPE_CURSOR) {
|
||||
formats = vkms_cursor_formats;
|
||||
nformats = ARRAY_SIZE(vkms_cursor_formats);
|
||||
funcs = &vkms_primary_helper_funcs;
|
||||
} else {
|
||||
formats = vkms_formats;
|
||||
nformats = ARRAY_SIZE(vkms_formats);
|
||||
funcs = &vkms_primary_helper_funcs;
|
||||
}
|
||||
|
||||
ret = drm_universal_plane_init(dev, plane, 0,
|
||||
&vkms_plane_funcs,
|
||||
formats, nformats,
|
||||
NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
|
||||
NULL, type, NULL);
|
||||
if (ret) {
|
||||
kfree(plane);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
drm_plane_helper_add(plane, &vkms_primary_helper_funcs);
|
||||
drm_plane_helper_add(plane, funcs);
|
||||
|
||||
return plane;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
|
@ -1004,9 +1004,7 @@ void redraw_screen(struct vc_data *vc, int is_switch)
|
|||
clear_buffer_attributes(vc);
|
||||
}
|
||||
|
||||
/* Forcibly update if we're panicing */
|
||||
if ((update && vc->vc_mode != KD_GRAPHICS) ||
|
||||
vt_force_oops_output(vc))
|
||||
if (update && vc->vc_mode != KD_GRAPHICS)
|
||||
do_update_region(vc, vc->vc_origin, vc->vc_screenbuf_size / 2);
|
||||
}
|
||||
set_cursor(vc);
|
||||
|
@ -1046,7 +1044,6 @@ static void visual_init(struct vc_data *vc, int num, int init)
|
|||
vc->vc_hi_font_mask = 0;
|
||||
vc->vc_complement_mask = 0;
|
||||
vc->vc_can_do_color = 0;
|
||||
vc->vc_panic_force_write = false;
|
||||
vc->vc_cur_blink_ms = DEFAULT_CURSOR_BLINK_MS;
|
||||
vc->vc_sw->con_init(vc, init);
|
||||
if (!vc->vc_complement_mask)
|
||||
|
@ -2911,7 +2908,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
|
|||
goto quit;
|
||||
}
|
||||
|
||||
if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
|
||||
if (vc->vc_mode != KD_TEXT)
|
||||
goto quit;
|
||||
|
||||
/* undraw cursor first */
|
||||
|
@ -4229,8 +4226,7 @@ void do_unblank_screen(int leaving_gfx)
|
|||
return;
|
||||
}
|
||||
vc = vc_cons[fg_console].d;
|
||||
/* Try to unblank in oops case too */
|
||||
if (vc->vc_mode != KD_TEXT && !vt_force_oops_output(vc))
|
||||
if (vc->vc_mode != KD_TEXT)
|
||||
return; /* but leave console_blanked != 0 */
|
||||
|
||||
if (blankinterval) {
|
||||
|
@ -4239,7 +4235,7 @@ void do_unblank_screen(int leaving_gfx)
|
|||
}
|
||||
|
||||
console_blanked = 0;
|
||||
if (vc->vc_sw->con_blank(vc, 0, leaving_gfx) || vt_force_oops_output(vc))
|
||||
if (vc->vc_sw->con_blank(vc, 0, leaving_gfx))
|
||||
/* Low-level driver cannot restore -> do it ourselves */
|
||||
update_screen(vc);
|
||||
if (console_blank_hook)
|
||||
|
|
|
@ -284,8 +284,7 @@ static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info)
|
|||
struct fbcon_ops *ops = info->fbcon_par;
|
||||
|
||||
return (info->state != FBINFO_STATE_RUNNING ||
|
||||
vc->vc_mode != KD_TEXT || ops->graphics) &&
|
||||
!vt_force_oops_output(vc);
|
||||
vc->vc_mode != KD_TEXT || ops->graphics);
|
||||
}
|
||||
|
||||
static int get_color(struct vc_data *vc, struct fb_info *info,
|
||||
|
@ -1104,7 +1103,6 @@ static void fbcon_init(struct vc_data *vc, int init)
|
|||
if (p->userfont)
|
||||
charcnt = FNTCHARCNT(p->fontdata);
|
||||
|
||||
vc->vc_panic_force_write = !!(info->flags & FBINFO_CAN_FORCE_OUTPUT);
|
||||
vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
|
||||
vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
|
||||
if (charcnt == 256) {
|
||||
|
|
|
@ -1117,6 +1117,8 @@ static long do_fb_ioctl(struct fb_info *info, unsigned int cmd,
|
|||
if (!lock_fb_info(info))
|
||||
return -ENODEV;
|
||||
fix = info->fix;
|
||||
if (info->flags & FBINFO_HIDE_SMEM_START)
|
||||
fix.smem_start = 0;
|
||||
unlock_fb_info(info);
|
||||
|
||||
ret = copy_to_user(argp, &fix, sizeof(fix)) ? -EFAULT : 0;
|
||||
|
@ -1327,6 +1329,8 @@ static int fb_get_fscreeninfo(struct fb_info *info, unsigned int cmd,
|
|||
if (!lock_fb_info(info))
|
||||
return -ENODEV;
|
||||
fix = info->fix;
|
||||
if (info->flags & FBINFO_HIDE_SMEM_START)
|
||||
fix.smem_start = 0;
|
||||
unlock_fb_info(info);
|
||||
return do_fscreeninfo_to_user(&fix, compat_ptr(arg));
|
||||
}
|
||||
|
@ -1834,11 +1838,11 @@ EXPORT_SYMBOL(remove_conflicting_framebuffers);
|
|||
/**
|
||||
* remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
|
||||
* @pdev: PCI device
|
||||
* @resource_id: index of PCI BAR configuring framebuffer memory
|
||||
* @res_id: index of PCI BAR configuring framebuffer memory
|
||||
* @name: requesting driver name
|
||||
*
|
||||
* This function removes framebuffer devices (eg. initialized by firmware)
|
||||
* using memory range configured for @pdev's BAR @resource_id.
|
||||
* using memory range configured for @pdev's BAR @res_id.
|
||||
*
|
||||
* The function assumes that PCI device with shadowed ROM drives a primary
|
||||
* display and so kicks out vga16fb.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#define DRM_ATOMIC_H_
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_util.h>
|
||||
|
||||
/**
|
||||
* struct drm_crtc_commit - track modeset commits on a CRTC
|
||||
|
@ -373,9 +374,6 @@ void drm_atomic_state_default_release(struct drm_atomic_state *state);
|
|||
struct drm_crtc_state * __must_check
|
||||
drm_atomic_get_crtc_state(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc);
|
||||
int drm_atomic_crtc_set_property(struct drm_crtc *crtc,
|
||||
struct drm_crtc_state *state, struct drm_property *property,
|
||||
uint64_t val);
|
||||
struct drm_plane_state * __must_check
|
||||
drm_atomic_get_plane_state(struct drm_atomic_state *state,
|
||||
struct drm_plane *plane);
|
||||
|
@ -586,25 +584,6 @@ __drm_atomic_get_current_plane_state(struct drm_atomic_state *state,
|
|||
return plane->state;
|
||||
}
|
||||
|
||||
int __must_check
|
||||
drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
|
||||
const struct drm_display_mode *mode);
|
||||
int __must_check
|
||||
drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
||||
struct drm_property_blob *blob);
|
||||
int __must_check
|
||||
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_crtc *crtc);
|
||||
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_framebuffer *fb);
|
||||
void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
|
||||
struct dma_fence *fence);
|
||||
int __must_check
|
||||
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
|
||||
struct drm_crtc *crtc);
|
||||
int drm_atomic_set_writeback_fb_for_connector(
|
||||
struct drm_connector_state *conn_state,
|
||||
struct drm_framebuffer *fb);
|
||||
int __must_check
|
||||
drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc);
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_util.h>
|
||||
|
||||
struct drm_atomic_state;
|
||||
struct drm_private_obj;
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2014 Red Hat
|
||||
* Copyright (C) 2014 Intel Corp.
|
||||
* Copyright (C) 2018 Intel Corp.
|
||||
*
|
||||
* 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 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
|
||||
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
|
||||
*
|
||||
* Authors:
|
||||
* Rob Clark <robdclark@gmail.com>
|
||||
* Daniel Vetter <daniel.vetter@ffwll.ch>
|
||||
*/
|
||||
|
||||
#ifndef DRM_ATOMIC_UAPI_H_
|
||||
#define DRM_ATOMIC_UAPI_H_
|
||||
|
||||
struct drm_crtc_state;
|
||||
struct drm_display_mode;
|
||||
struct drm_property_blob;
|
||||
struct drm_plane_state;
|
||||
struct drm_crtc;
|
||||
struct drm_connector_state;
|
||||
struct dma_fence;
|
||||
struct drm_framebuffer;
|
||||
|
||||
int __must_check
|
||||
drm_atomic_set_mode_for_crtc(struct drm_crtc_state *state,
|
||||
const struct drm_display_mode *mode);
|
||||
int __must_check
|
||||
drm_atomic_set_mode_prop_for_crtc(struct drm_crtc_state *state,
|
||||
struct drm_property_blob *blob);
|
||||
int __must_check
|
||||
drm_atomic_set_crtc_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_crtc *crtc);
|
||||
void drm_atomic_set_fb_for_plane(struct drm_plane_state *plane_state,
|
||||
struct drm_framebuffer *fb);
|
||||
void drm_atomic_set_fence_for_plane(struct drm_plane_state *plane_state,
|
||||
struct dma_fence *fence);
|
||||
int __must_check
|
||||
drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
|
||||
struct drm_crtc *crtc);
|
||||
|
||||
#endif
|
|
@ -24,6 +24,7 @@
|
|||
#define __DRM_COLOR_MGMT_H__
|
||||
|
||||
#include <linux/ctype.h>
|
||||
#include <drm/drm_property.h>
|
||||
|
||||
struct drm_crtc;
|
||||
struct drm_plane;
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <linux/hdmi.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
#include <drm/drm_util.h>
|
||||
|
||||
#include <uapi/drm/drm_mode.h>
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ struct drm_printer;
|
|||
#define DRIVER_ATOMIC 0x10000
|
||||
#define DRIVER_KMS_LEGACY_CONTEXT 0x20000
|
||||
#define DRIVER_SYNCOBJ 0x40000
|
||||
#define DRIVER_PREFER_XBGR_30BPP 0x80000
|
||||
|
||||
/**
|
||||
* struct drm_driver - DRM driver structure
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_mode.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
#include <drm/drm_util.h>
|
||||
|
||||
struct drm_encoder;
|
||||
|
||||
|
|
|
@ -604,6 +604,16 @@ drm_fbdev_generic_setup(struct drm_device *dev, unsigned int preferred_bpp)
|
|||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* drm_fb_helper_remove_conflicting_framebuffers - remove firmware-configured framebuffers
|
||||
* @a: memory range, users of which are to be removed
|
||||
* @name: requesting driver name
|
||||
* @primary: also kick vga16fb if present
|
||||
*
|
||||
* This function removes framebuffer devices (initialized by firmware/bootloader)
|
||||
* which use memory range described by @a. If @a is NULL all such devices are
|
||||
* removed.
|
||||
*/
|
||||
static inline int
|
||||
drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
|
||||
const char *name, bool primary)
|
||||
|
@ -615,6 +625,18 @@ drm_fb_helper_remove_conflicting_framebuffers(struct apertures_struct *a,
|
|||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_helper_remove_conflicting_pci_framebuffers - remove firmware-configured framebuffers for PCI devices
|
||||
* @pdev: PCI device
|
||||
* @resource_id: index of PCI BAR configuring framebuffer memory
|
||||
* @name: requesting driver name
|
||||
*
|
||||
* This function removes framebuffer devices (eg. initialized by firmware)
|
||||
* using memory range configured for @pdev's BAR @resource_id.
|
||||
*
|
||||
* The function assumes that PCI device with shadowed ROM drives a primary
|
||||
* display and so kicks out vga16fb.
|
||||
*/
|
||||
static inline int
|
||||
drm_fb_helper_remove_conflicting_pci_framebuffers(struct pci_dev *pdev,
|
||||
int resource_id,
|
||||
|
|
|
@ -25,6 +25,28 @@
|
|||
#include <linux/types.h>
|
||||
#include <uapi/drm/drm_fourcc.h>
|
||||
|
||||
/*
|
||||
* DRM formats are little endian. Define host endian variants for the
|
||||
* most common formats here, to reduce the #ifdefs needed in drivers.
|
||||
*
|
||||
* Note that the DRM_FORMAT_BIG_ENDIAN flag should only be used in
|
||||
* case the format can't be specified otherwise, so we don't end up
|
||||
* with two values describing the same format.
|
||||
*/
|
||||
#ifdef __BIG_ENDIAN
|
||||
# define DRM_FORMAT_HOST_XRGB1555 (DRM_FORMAT_XRGB1555 | \
|
||||
DRM_FORMAT_BIG_ENDIAN)
|
||||
# define DRM_FORMAT_HOST_RGB565 (DRM_FORMAT_RGB565 | \
|
||||
DRM_FORMAT_BIG_ENDIAN)
|
||||
# define DRM_FORMAT_HOST_XRGB8888 DRM_FORMAT_BGRX8888
|
||||
# define DRM_FORMAT_HOST_ARGB8888 DRM_FORMAT_BGRA8888
|
||||
#else
|
||||
# define DRM_FORMAT_HOST_XRGB1555 DRM_FORMAT_XRGB1555
|
||||
# define DRM_FORMAT_HOST_RGB565 DRM_FORMAT_RGB565
|
||||
# define DRM_FORMAT_HOST_XRGB8888 DRM_FORMAT_XRGB8888
|
||||
# define DRM_FORMAT_HOST_ARGB8888 DRM_FORMAT_ARGB8888
|
||||
#endif
|
||||
|
||||
struct drm_device;
|
||||
struct drm_mode_fb_cmd2;
|
||||
|
||||
|
|
|
@ -809,6 +809,21 @@ struct drm_mode_config {
|
|||
|
||||
/* dumb ioctl parameters */
|
||||
uint32_t preferred_depth, prefer_shadow;
|
||||
bool quirk_addfb_prefer_xbgr_30bpp;
|
||||
|
||||
/**
|
||||
* @quirk_addfb_prefer_host_byte_order:
|
||||
*
|
||||
* When set to true drm_mode_addfb() will pick host byte order
|
||||
* pixel_format when calling drm_mode_addfb2(). This is how
|
||||
* drm_mode_addfb() should have worked from day one. It
|
||||
* didn't though, so we ended up with quirks in both kernel
|
||||
* and userspace drivers to deal with the broken behavior.
|
||||
* Simply fixing drm_mode_addfb() unconditionally would break
|
||||
* these drivers, so add a quirk bit here to allow drivers
|
||||
* opt-in.
|
||||
*/
|
||||
bool quirk_addfb_prefer_host_byte_order;
|
||||
|
||||
/**
|
||||
* @async_page_flip: Does this device support async flips on the primary
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
#include <drm/drm_color_mgmt.h>
|
||||
#include <drm/drm_rect.h>
|
||||
#include <drm/drm_modeset_lock.h>
|
||||
#include <drm/drm_util.h>
|
||||
|
||||
struct drm_crtc;
|
||||
struct drm_printer;
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include <linux/ctype.h>
|
||||
#include <drm/drm_mode_object.h>
|
||||
|
||||
#include <uapi/drm/drm_mode.h>
|
||||
|
||||
/**
|
||||
* struct drm_property_enum - symbolic values for enumerations
|
||||
* @value: numeric property value for this enum entry
|
||||
|
|
|
@ -131,10 +131,10 @@ drm_syncobj_fence_get(struct drm_syncobj *syncobj)
|
|||
|
||||
struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private,
|
||||
u32 handle);
|
||||
void drm_syncobj_replace_fence(struct drm_syncobj *syncobj,
|
||||
void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, u64 point,
|
||||
struct dma_fence *fence);
|
||||
int drm_syncobj_find_fence(struct drm_file *file_private,
|
||||
u32 handle,
|
||||
u32 handle, u64 point,
|
||||
struct dma_fence **fence);
|
||||
void drm_syncobj_free(struct kref *kref);
|
||||
int drm_syncobj_create(struct drm_syncobj **out_syncobj, uint32_t flags,
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Internal Header for the Direct Rendering Manager
|
||||
*
|
||||
* Copyright 2018 Intel Corporation
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _DRM_UTIL_H_
|
||||
#define _DRM_UTIL_H_
|
||||
|
||||
/* helper for handling conditionals in various for_each macros */
|
||||
#define for_each_if(condition) if (!(condition)) {} else
|
||||
|
||||
#endif
|
|
@ -141,7 +141,6 @@ struct vc_data {
|
|||
struct uni_pagedir *vc_uni_pagedir;
|
||||
struct uni_pagedir **vc_uni_pagedir_loc; /* [!] Location of uni_pagedir variable for this console */
|
||||
struct uni_screen *vc_uni_screen; /* unicode screen content */
|
||||
bool vc_panic_force_write; /* when oops/panic this VC can accept forced output/blanking */
|
||||
/* additional information is in vt_kern.h */
|
||||
};
|
||||
|
||||
|
|
|
@ -456,10 +456,13 @@ struct fb_tile_ops {
|
|||
* and host endianness. Drivers should not use this flag.
|
||||
*/
|
||||
#define FBINFO_BE_MATH 0x100000
|
||||
/*
|
||||
* Hide smem_start in the FBIOGET_FSCREENINFO IOCTL. This is used by modern DRM
|
||||
* drivers to stop userspace from trying to share buffers behind the kernel's
|
||||
* back. Instead dma-buf based buffer sharing should be used.
|
||||
*/
|
||||
#define FBINFO_HIDE_SMEM_START 0x200000
|
||||
|
||||
/* report to the VT layer that this fb driver can accept forced console
|
||||
output like oopses */
|
||||
#define FBINFO_CAN_FORCE_OUTPUT 0x200000
|
||||
|
||||
struct fb_info {
|
||||
atomic_t count;
|
||||
|
|
|
@ -135,13 +135,6 @@ extern int do_unbind_con_driver(const struct consw *csw, int first, int last,
|
|||
int deflt);
|
||||
int vty_init(const struct file_operations *console_fops);
|
||||
|
||||
static inline bool vt_force_oops_output(struct vc_data *vc)
|
||||
{
|
||||
if (oops_in_progress && vc->vc_panic_force_write && panic_timeout >= 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
extern char vt_dont_switch;
|
||||
extern int default_utf8;
|
||||
extern int global_cursor_default;
|
||||
|
|
|
@ -71,6 +71,9 @@ extern "C" {
|
|||
|
||||
#define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
|
||||
|
||||
/* Reserve 0 for the invalid format specifier */
|
||||
#define DRM_FORMAT_INVALID 0
|
||||
|
||||
/* color index */
|
||||
#define DRM_FORMAT_C8 fourcc_code('C', '8', ' ', ' ') /* [7:0] C */
|
||||
|
||||
|
|
|
@ -186,8 +186,9 @@ extern "C" {
|
|||
/*
|
||||
* DRM_MODE_REFLECT_<axis>
|
||||
*
|
||||
* Signals that the contents of a drm plane is reflected in the <axis> axis,
|
||||
* Signals that the contents of a drm plane is reflected along the <axis> axis,
|
||||
* in the same way as mirroring.
|
||||
* See kerneldoc chapter "Plane Composition Properties" for more details.
|
||||
*
|
||||
* This define is provided as a convenience, looking up the property id
|
||||
* using the name->prop id lookup is the preferred method.
|
||||
|
|
Loading…
Reference in New Issue