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:
Dave Airlie 2018-09-14 09:43:06 +10:00
commit 2dc7bad71c
85 changed files with 2332 additions and 2266 deletions

View File

@ -13,6 +13,7 @@ GPU Driver Documentation
tve200
v3d
vc4
vkms
bridge/dw-hdmi
xen-front

View File

@ -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

View File

@ -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

View File

@ -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).

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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,

View File

@ -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>

View File

@ -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;

View File

@ -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[] = {

View File

@ -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);
}

View File

@ -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;

View File

@ -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;

View File

@ -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,
};

View File

@ -554,7 +554,7 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
if (retval < 0)
return retval;
dev_info(dp->dev, "Link Training Clock Recovery success\n");
dev_dbg(dp->dev, "Link Training Clock Recovery success\n");
dp->link_train.lt_state = EQUALIZER_TRAINING;
} else {
for (lane = 0; lane < lane_count; lane++) {
@ -634,7 +634,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
if (retval < 0)
return retval;
dev_info(dp->dev, "Link Training success!\n");
dev_dbg(dp->dev, "Link Training success!\n");
analogix_dp_get_link_bandwidth(dp, &reg);
dp->link_train.link_rate = reg;
dev_dbg(dp->dev, "final bandwidth = %.2x\n",

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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
*/

View File

@ -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"

View File

@ -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"

View File

@ -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>

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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>

View File

@ -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);

View File

@ -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),

View File

@ -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);
/*

View File

@ -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>

View File

@ -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);

View File

@ -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"

View File

@ -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);
}
}

View File

@ -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>

View File

@ -25,6 +25,8 @@
#ifndef _INTEL_DISPLAY_H_
#define _INTEL_DISPLAY_H_
#include <drm/drm_util.h>
enum i915_gpio {
GPIOA,
GPIOB,

View File

@ -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>

View File

@ -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"

View File

@ -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"

View File

@ -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,

View File

@ -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"

View File

@ -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;

View File

@ -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);
}

View File

@ -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;

View File

@ -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,

View File

@ -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);
}

View File

@ -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,

View File

@ -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 = {

View File

@ -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)

View File

@ -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);
}

View File

@ -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>

View File

@ -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;

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
/*

View File

@ -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)

View File

@ -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) {

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -24,6 +24,7 @@
#define __DRM_COLOR_MGMT_H__
#include <linux/ctype.h>
#include <drm/drm_property.h>
struct drm_crtc;
struct drm_plane;

View File

@ -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>

View File

@ -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

View File

@ -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;

View File

@ -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,

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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,

32
include/drm/drm_util.h Normal file
View File

@ -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

View File

@ -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 */
};

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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.