Commit 6c181c82 authored by Dave Airlie's avatar Dave Airlie

Merge tag 'topic/drm-misc-2016-07-14' of git://anongit.freedesktop.org/drm-intel into drm-next

I recovered dri-devel backlog from my vacation, more misc stuff:
- of_put_node fixes from Peter Chen (not all yet)
- more patches from Gustavo to use kms-native drm_crtc_vblank_* funcs
- docs sphinxification from Lukas Wunner
- bunch of fixes all over from Dan Carpenter
- more follow up work from Chris register/unregister rework in various
  places
- vgem dma-buf export (for writing testcases)
- small things all over from tons of different people

* tag 'topic/drm-misc-2016-07-14' of git://anongit.freedesktop.org/drm-intel: (52 commits)
  drm: Don't overwrite user ioctl arg unless requested
  dma-buf/sync_file: improve Kconfig description for Sync Files
  MAINTAINERS: add entry for the Sync File Framework
  drm: Resurrect atomic rmfb code
  drm/vgem: Use PAGE_KERNEL in place of x86-specific PAGE_KERNEL_IO
  qxl: silence uninitialized variable warning
  qxl: check for kmap failures
  vga_switcheroo: Sphinxify docs
  drm: Restore double clflush on the last partial cacheline
  gpu: drm: rockchip_drm_drv: add missing of_node_put after calling of_parse_phandle
  gpu: drm: sti_vtg: add missing of_node_put after calling of_parse_phandle
  gpu: drm: sti_hqvdp: add missing of_node_put after calling of_parse_phandle
  gpu: drm: sti_vdo: add missing of_node_put after calling of_parse_phandle
  gpu: drm: sti_compositor: add missing of_node_put after calling of_parse_phandle
  drm/tilcdc: use drm_crtc_handle_vblank()
  drm/rcar-du: use drm_crtc_handle_vblank()
  drm/nouveau: use drm_crtc_handle_vblank()
  drm/atmel: use drm_crtc_handle_vblank()
  drm/armada: use drm_crtc_handle_vblank()
  drm: make drm_vblank_count_and_time() static
  ...
parents 1640142b 01d3434a
...@@ -280,8 +280,8 @@ private data in the open method should free it here. ...@@ -280,8 +280,8 @@ private data in the open method should free it here.
The lastclose method should restore CRTC and plane properties to default The lastclose method should restore CRTC and plane properties to default
value, so that a subsequent open of the device will not inherit state value, so that a subsequent open of the device will not inherit state
from the previous user. It can also be used to execute delayed power from the previous user. It can also be used to execute delayed power
switching state changes, e.g. in conjunction with the vga_switcheroo switching state changes, e.g. in conjunction with the :ref:`vga_switcheroo`
infrastructure (see ?). Beyond that KMS drivers should not do any infrastructure. Beyond that KMS drivers should not do any
further cleanup. Only legacy UMS drivers might need to clean up device further cleanup. Only legacy UMS drivers might need to clean up device
state so that the vga console or an independent fbdev driver could take state so that the vga console or an independent fbdev driver could take
over. over.
......
.. _vga_switcheroo:
============== ==============
VGA Switcheroo VGA Switcheroo
============== ==============
...@@ -94,9 +96,3 @@ Public functions ...@@ -94,9 +96,3 @@ Public functions
.. kernel-doc:: include/linux/apple-gmux.h .. kernel-doc:: include/linux/apple-gmux.h
:internal: :internal:
.. WARNING: DOCPROC directive not supported: !Cdrivers/gpu/vga/vga_switcheroo.c
.. WARNING: DOCPROC directive not supported: !Cinclude/linux/vga_switcheroo.h
.. WARNING: DOCPROC directive not supported: !Cdrivers/platform/x86/apple-gmux.c
...@@ -3779,6 +3779,17 @@ F: include/linux/*fence.h ...@@ -3779,6 +3779,17 @@ F: include/linux/*fence.h
F: Documentation/dma-buf-sharing.txt F: Documentation/dma-buf-sharing.txt
T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
SYNC FILE FRAMEWORK
M: Sumit Semwal <sumit.semwal@linaro.org>
R: Gustavo Padovan <gustavo@padovan.org>
S: Maintained
L: linux-media@vger.kernel.org
L: dri-devel@lists.freedesktop.org
F: drivers/dma-buf/sync_file.c
F: include/linux/sync_file.h
F: Documentation/sync_file.txt
T: git git://git.linaro.org/people/sumitsemwal/linux-dma-buf.git
DMA GENERIC OFFLOAD ENGINE SUBSYSTEM DMA GENERIC OFFLOAD ENGINE SUBSYSTEM
M: Vinod Koul <vinod.koul@intel.com> M: Vinod Koul <vinod.koul@intel.com>
L: dmaengine@vger.kernel.org L: dmaengine@vger.kernel.org
......
menu "DMABUF options" menu "DMABUF options"
config SYNC_FILE config SYNC_FILE
bool "sync_file support for fences" bool "Explicit Synchronization Framework"
default n default n
select ANON_INODES select ANON_INODES
select DMA_SHARED_BUFFER select DMA_SHARED_BUFFER
---help--- ---help---
This option enables the fence framework synchronization to export The Sync File Framework adds explicit syncronization via
sync_files to userspace that can represent one or more fences. userspace. It enables send/receive 'struct fence' objects to/from
userspace via Sync File fds for synchronization between drivers via
userspace components. It has been ported from Android.
The first and main user for this is graphics in which a fence is
associated with a buffer. When a job is submitted to the GPU a fence
is attached to the buffer and is transferred via userspace, using Sync
Files fds, to the DRM driver for example. More details at
Documentation/sync_file.txt.
endmenu endmenu
...@@ -1712,6 +1712,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev) ...@@ -1712,6 +1712,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
amdgpu_bo_evict_vram(adev); amdgpu_bo_evict_vram(adev);
amdgpu_ib_pool_fini(adev); amdgpu_ib_pool_fini(adev);
amdgpu_fence_driver_fini(adev); amdgpu_fence_driver_fini(adev);
drm_crtc_force_disable_all(adev->ddev);
amdgpu_fbdev_fini(adev); amdgpu_fbdev_fini(adev);
r = amdgpu_fini(adev); r = amdgpu_fini(adev);
kfree(adev->ip_block_status); kfree(adev->ip_block_status);
......
...@@ -60,7 +60,10 @@ int amdgpu_driver_unload_kms(struct drm_device *dev) ...@@ -60,7 +60,10 @@ int amdgpu_driver_unload_kms(struct drm_device *dev)
if (adev->rmmio == NULL) if (adev->rmmio == NULL)
goto done_free; goto done_free;
pm_runtime_get_sync(dev->dev); if (amdgpu_device_is_px(dev)) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
}
amdgpu_amdkfd_device_fini(adev); amdgpu_amdkfd_device_fini(adev);
...@@ -135,9 +138,12 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags) ...@@ -135,9 +138,12 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
} }
out: out:
if (r) if (r) {
/* balance pm_runtime_get_sync in amdgpu_driver_unload_kms */
if (adev->rmmio && amdgpu_device_is_px(dev))
pm_runtime_put_noidle(dev->dev);
amdgpu_driver_unload_kms(dev); amdgpu_driver_unload_kms(dev);
}
return r; return r;
} }
......
...@@ -410,7 +410,7 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat) ...@@ -410,7 +410,7 @@ static void armada_drm_crtc_irq(struct armada_crtc *dcrtc, u32 stat)
DRM_ERROR("graphics underflow on crtc %u\n", dcrtc->num); DRM_ERROR("graphics underflow on crtc %u\n", dcrtc->num);
if (stat & VSYNC_IRQ) if (stat & VSYNC_IRQ)
drm_handle_vblank(dcrtc->crtc.dev, dcrtc->num); drm_crtc_handle_vblank(&dcrtc->crtc);
spin_lock(&dcrtc->irq_lock); spin_lock(&dcrtc->irq_lock);
ovl_plane = dcrtc->plane; ovl_plane = dcrtc->plane;
......
...@@ -383,7 +383,7 @@ static void atmel_hlcdc_crtc_finish_page_flip(struct atmel_hlcdc_crtc *crtc) ...@@ -383,7 +383,7 @@ static void atmel_hlcdc_crtc_finish_page_flip(struct atmel_hlcdc_crtc *crtc)
void atmel_hlcdc_crtc_irq(struct drm_crtc *c) void atmel_hlcdc_crtc_irq(struct drm_crtc *c)
{ {
drm_handle_vblank(c->dev, 0); drm_crtc_handle_vblank(c);
atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c)); atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c));
} }
......
...@@ -1589,6 +1589,72 @@ void drm_atomic_clean_old_fb(struct drm_device *dev, ...@@ -1589,6 +1589,72 @@ void drm_atomic_clean_old_fb(struct drm_device *dev,
} }
EXPORT_SYMBOL(drm_atomic_clean_old_fb); EXPORT_SYMBOL(drm_atomic_clean_old_fb);
int drm_atomic_remove_fb(struct drm_framebuffer *fb)
{
struct drm_modeset_acquire_ctx ctx;
struct drm_device *dev = fb->dev;
struct drm_atomic_state *state;
struct drm_plane *plane;
int ret = 0;
unsigned plane_mask;
state = drm_atomic_state_alloc(dev);
if (!state)
return -ENOMEM;
drm_modeset_acquire_init(&ctx, 0);
state->acquire_ctx = &ctx;
retry:
plane_mask = 0;
ret = drm_modeset_lock_all_ctx(dev, &ctx);
if (ret)
goto unlock;
drm_for_each_plane(plane, dev) {
struct drm_plane_state *plane_state;
if (plane->state->fb != fb)
continue;
plane_state = drm_atomic_get_plane_state(state, plane);
if (IS_ERR(plane_state)) {
ret = PTR_ERR(plane_state);
goto unlock;
}
drm_atomic_set_fb_for_plane(plane_state, NULL);
ret = drm_atomic_set_crtc_for_plane(plane_state, NULL);
if (ret)
goto unlock;
plane_mask |= BIT(drm_plane_index(plane));
plane->old_fb = plane->fb;
plane->fb = NULL;
}
if (plane_mask)
ret = drm_atomic_commit(state);
unlock:
if (plane_mask)
drm_atomic_clean_old_fb(dev, plane_mask, ret);
if (ret == -EDEADLK) {
drm_modeset_backoff(&ctx);
goto retry;
}
if (ret || !plane_mask)
drm_atomic_state_free(state);
drm_modeset_drop_locks(&ctx);
drm_modeset_acquire_fini(&ctx);
return ret;
}
int drm_mode_atomic_ioctl(struct drm_device *dev, int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv) void *data, struct drm_file *file_priv)
{ {
......
...@@ -136,6 +136,7 @@ drm_clflush_virt_range(void *addr, unsigned long length) ...@@ -136,6 +136,7 @@ drm_clflush_virt_range(void *addr, unsigned long length)
mb(); mb();
for (; addr < end; addr += size) for (; addr < end; addr += size)
clflushopt(addr); clflushopt(addr);
clflushopt(end - 1); /* force serialisation */
mb(); mb();
return; return;
} }
......
...@@ -396,6 +396,51 @@ void drm_mode_object_reference(struct drm_mode_object *obj) ...@@ -396,6 +396,51 @@ void drm_mode_object_reference(struct drm_mode_object *obj)
} }
EXPORT_SYMBOL(drm_mode_object_reference); EXPORT_SYMBOL(drm_mode_object_reference);
/**
* drm_crtc_force_disable - Forcibly turn off a CRTC
* @crtc: CRTC to turn off
*
* Returns:
* Zero on success, error code on failure.
*/
int drm_crtc_force_disable(struct drm_crtc *crtc)
{
struct drm_mode_set set = {
.crtc = crtc,
};
return drm_mode_set_config_internal(&set);
}
EXPORT_SYMBOL(drm_crtc_force_disable);
/**
* drm_crtc_force_disable_all - Forcibly turn off all enabled CRTCs
* @dev: DRM device whose CRTCs to turn off
*
* Drivers may want to call this on unload to ensure that all displays are
* unlit and the GPU is in a consistent, low power state. Takes modeset locks.
*
* Returns:
* Zero on success, error code on failure.
*/
int drm_crtc_force_disable_all(struct drm_device *dev)
{
struct drm_crtc *crtc;
int ret = 0;
drm_modeset_lock_all(dev);
drm_for_each_crtc(crtc, dev)
if (crtc->enabled) {
ret = drm_crtc_force_disable(crtc);
if (ret)
goto out;
}
out:
drm_modeset_unlock_all(dev);
return ret;
}
EXPORT_SYMBOL(drm_crtc_force_disable_all);
static void drm_framebuffer_free(struct kref *kref) static void drm_framebuffer_free(struct kref *kref)
{ {
struct drm_framebuffer *fb = struct drm_framebuffer *fb =
...@@ -544,8 +589,6 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) ...@@ -544,8 +589,6 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
struct drm_device *dev; struct drm_device *dev;
struct drm_crtc *crtc; struct drm_crtc *crtc;
struct drm_plane *plane; struct drm_plane *plane;
struct drm_mode_set set;
int ret;
if (!fb) if (!fb)
return; return;
...@@ -570,16 +613,17 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) ...@@ -570,16 +613,17 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
* in this manner. * in this manner.
*/ */
if (drm_framebuffer_read_refcount(fb) > 1) { if (drm_framebuffer_read_refcount(fb) > 1) {
if (dev->mode_config.funcs->atomic_commit) {
drm_atomic_remove_fb(fb);
goto out;
}
drm_modeset_lock_all(dev); drm_modeset_lock_all(dev);
/* remove from any CRTC */ /* remove from any CRTC */
drm_for_each_crtc(crtc, dev) { drm_for_each_crtc(crtc, dev) {
if (crtc->primary->fb == fb) { if (crtc->primary->fb == fb) {
/* should turn off the crtc */ /* should turn off the crtc */
memset(&set, 0, sizeof(struct drm_mode_set)); if (drm_crtc_force_disable(crtc))
set.crtc = crtc;
set.fb = NULL;
ret = drm_mode_set_config_internal(&set);
if (ret)
DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc); DRM_ERROR("failed to reset crtc %p when fb was deleted\n", crtc);
} }
} }
...@@ -591,6 +635,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb) ...@@ -591,6 +635,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
drm_modeset_unlock_all(dev); drm_modeset_unlock_all(dev);
} }
out:
drm_framebuffer_unreference(fb); drm_framebuffer_unreference(fb);
} }
EXPORT_SYMBOL(drm_framebuffer_remove); EXPORT_SYMBOL(drm_framebuffer_remove);
...@@ -1068,23 +1113,7 @@ void drm_connector_unregister(struct drm_connector *connector) ...@@ -1068,23 +1113,7 @@ void drm_connector_unregister(struct drm_connector *connector)
} }
EXPORT_SYMBOL(drm_connector_unregister); EXPORT_SYMBOL(drm_connector_unregister);
/** static int drm_connector_register_all(struct drm_device *dev)
* drm_connector_register_all - register all connectors
* @dev: drm device
*
* This function registers all connectors in sysfs and other places so that
* userspace can start to access them. drm_connector_register_all() is called
* automatically from drm_dev_register() to complete the device registration,
* if they don't call drm_connector_register() on each connector individually.
*
* When a device is unplugged and should be removed from userspace access,
* call drm_connector_unregister_all(), which is the inverse of this
* function.
*
* Returns:
* Zero on success, error code on failure.
*/
int drm_connector_register_all(struct drm_device *dev)
{ {
struct drm_connector *connector; struct drm_connector *connector;
int ret; int ret;
...@@ -1106,7 +1135,6 @@ int drm_connector_register_all(struct drm_device *dev) ...@@ -1106,7 +1135,6 @@ int drm_connector_register_all(struct drm_device *dev)
drm_connector_unregister_all(dev); drm_connector_unregister_all(dev);
return ret; return ret;
} }
EXPORT_SYMBOL(drm_connector_register_all);
/** /**
* drm_connector_unregister_all - unregister connector userspace interfaces * drm_connector_unregister_all - unregister connector userspace interfaces
......
...@@ -125,6 +125,7 @@ int drm_atomic_get_property(struct drm_mode_object *obj, ...@@ -125,6 +125,7 @@ int drm_atomic_get_property(struct drm_mode_object *obj,
struct drm_property *property, uint64_t *val); struct drm_property *property, uint64_t *val);
int drm_mode_atomic_ioctl(struct drm_device *dev, int drm_mode_atomic_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv); void *data, struct drm_file *file_priv);
int drm_atomic_remove_fb(struct drm_framebuffer *fb);
int drm_modeset_register_all(struct drm_device *dev); int drm_modeset_register_all(struct drm_device *dev);
void drm_modeset_unregister_all(struct drm_device *dev); void drm_modeset_unregister_all(struct drm_device *dev);
...@@ -355,8 +355,7 @@ int drm_dp_aux_dev_init(void) ...@@ -355,8 +355,7 @@ int drm_dp_aux_dev_init(void)
drm_dp_aux_dev_class = class_create(THIS_MODULE, "drm_dp_aux_dev"); drm_dp_aux_dev_class = class_create(THIS_MODULE, "drm_dp_aux_dev");
if (IS_ERR(drm_dp_aux_dev_class)) { if (IS_ERR(drm_dp_aux_dev_class)) {
res = PTR_ERR(drm_dp_aux_dev_class); return PTR_ERR(drm_dp_aux_dev_class);
goto out;
} }
drm_dp_aux_dev_class->dev_groups = drm_dp_aux_groups; drm_dp_aux_dev_class->dev_groups = drm_dp_aux_groups;
......
...@@ -362,9 +362,7 @@ EXPORT_SYMBOL(drm_put_dev); ...@@ -362,9 +362,7 @@ EXPORT_SYMBOL(drm_put_dev);
void drm_unplug_dev(struct drm_device *dev) void drm_unplug_dev(struct drm_device *dev)
{ {
/* for a USB device */ /* for a USB device */
drm_minor_unregister(dev, DRM_MINOR_LEGACY); drm_dev_unregister(dev);
drm_minor_unregister(dev, DRM_MINOR_RENDER);
drm_minor_unregister(dev, DRM_MINOR_CONTROL);
mutex_lock(&drm_global_mutex); mutex_lock(&drm_global_mutex);
......
...@@ -648,7 +648,7 @@ long drm_ioctl(struct file *filp, ...@@ -648,7 +648,7 @@ long drm_ioctl(struct file *filp,
int retcode = -EINVAL; int retcode = -EINVAL;
char stack_kdata[128]; char stack_kdata[128];
char *kdata = NULL; char *kdata = NULL;
unsigned int usize, asize, drv_size; unsigned int in_size, out_size, drv_size, ksize;
bool is_driver_ioctl; bool is_driver_ioctl;
dev = file_priv->minor->dev; dev = file_priv->minor->dev;
...@@ -671,9 +671,12 @@ long drm_ioctl(struct file *filp, ...@@ -671,9 +671,12 @@ long drm_ioctl(struct file *filp,
} }
drv_size = _IOC_SIZE(ioctl->cmd); drv_size = _IOC_SIZE(ioctl->cmd);
usize = _IOC_SIZE(cmd); out_size = in_size = _IOC_SIZE(cmd);
asize = max(usize, drv_size); if ((cmd & ioctl->cmd & IOC_IN) == 0)
cmd = ioctl->cmd; in_size = 0;
if ((cmd & ioctl->cmd & IOC_OUT) == 0)
out_size = 0;
ksize = max(max(in_size, out_size), drv_size);
DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n", DRM_DEBUG("pid=%d, dev=0x%lx, auth=%d, %s\n",
task_pid_nr(current), task_pid_nr(current),
...@@ -693,30 +696,24 @@ long drm_ioctl(struct file *filp, ...@@ -693,30 +696,24 @@ long drm_ioctl(struct file *filp,
if (unlikely(retcode)) if (unlikely(retcode))
goto err_i1; goto err_i1;
if (cmd & (IOC_IN | IOC_OUT)) { if (ksize <= sizeof(stack_kdata)) {
if (asize <= sizeof(stack_kdata)) { kdata = stack_kdata;
kdata = stack_kdata; } else {
} else { kdata = kmalloc(ksize, GFP_KERNEL);
kdata = kmalloc(asize, GFP_KERNEL); if (!kdata) {
if (!kdata) { retcode = -ENOMEM;
retcode = -ENOMEM; goto err_i1;
goto err_i1;
}
} }
if (asize > usize)
memset(kdata + usize, 0, asize - usize);
} }
if (cmd & IOC_IN) { if (copy_from_user(kdata, (void __user *)arg, in_size) != 0) {
if (copy_from_user(kdata, (void __user *)arg, retcode = -EFAULT;
usize) != 0) { goto err_i1;
retcode = -EFAULT;
goto err_i1;
}
} else if (cmd & IOC_OUT) {
memset(kdata, 0, usize);
} }
if (ksize > in_size)
memset(kdata + in_size, 0, ksize - in_size);
/* Enforce sane locking for kms driver ioctls. Core ioctls are /* Enforce sane locking for kms driver ioctls. Core ioctls are
* too messy still. */ * too messy still. */
if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) || if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) ||
...@@ -728,11 +725,8 @@ long drm_ioctl(struct file *filp, ...@@ -728,11 +725,8 @@ long drm_ioctl(struct file *filp,
mutex_unlock(&drm_global_mutex); mutex_unlock(&drm_global_mutex);
} }
if (cmd & IOC_OUT) { if (copy_to_user((void __user *)arg, kdata, out_size) != 0)
if (copy_to_user((void __user *)arg, kdata, retcode = -EFAULT;
usize) != 0)
retcode = -EFAULT;
}
err_i1: err_i1:
if (!ioctl) if (!ioctl)
...@@ -759,7 +753,7 @@ EXPORT_SYMBOL(drm_ioctl); ...@@ -759,7 +753,7 @@ EXPORT_SYMBOL(drm_ioctl);
* shouldn't be used by any drivers. * shouldn't be used by any drivers.
* *
* Returns: * Returns:
* True if the @nr corresponds to a DRM core ioctl numer, false otherwise. * True if the @nr corresponds to a DRM core ioctl number, false otherwise.
*/ */
bool drm_ioctl_flags(unsigned int nr, unsigned int *flags) bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
{ {
......
...@@ -532,7 +532,7 @@ int drm_irq_uninstall(struct drm_device *dev) ...@@ -532,7 +532,7 @@ int drm_irq_uninstall(struct drm_device *dev)
/* /*
* Wake up any waiters so they don't hang. This is just to paper over * Wake up any waiters so they don't hang. This is just to paper over
* isssues for UMS drivers which aren't in full control of their * issues for UMS drivers which aren't in full control of their
* vblank/irq handling. KMS drivers must ensure that vblanks are all * vblank/irq handling. KMS drivers must ensure that vblanks are all
* disabled when uninstalling the irq handler. * disabled when uninstalling the irq handler.
*/ */
...@@ -594,7 +594,7 @@ int drm_control(struct drm_device *dev, void *data, ...@@ -594,7 +594,7 @@ int drm_control(struct drm_device *dev, void *data,
return 0; return 0;
if (drm_core_check_feature(dev, DRIVER_MODESET)) if (drm_core_check_feature(dev, DRIVER_MODESET))
return 0; return 0;
/* UMS was only ever support on pci devices. */ /* UMS was only ever supported on pci devices. */
if (WARN_ON(!dev->pdev)) if (WARN_ON(!dev->pdev))
return -EINVAL; return -EINVAL;
...@@ -945,8 +945,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_count); ...@@ -945,8 +945,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_count);
* *
* This is the legacy version of drm_crtc_vblank_count_and_time(). * This is the legacy version of drm_crtc_vblank_count_and_time().
*/ */
u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, static u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
struct timeval *vblanktime) struct timeval *vblanktime)
{ {
struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
u32 vblank_count; u32 vblank_count;
...@@ -963,7 +963,6 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, ...@@ -963,7 +963,6 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
return vblank_count; return vblank_count;
} }
EXPORT_SYMBOL(drm_vblank_count_and_time);
/** /**
* drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value
...@@ -975,8 +974,6 @@ EXPORT_SYMBOL(drm_vblank_count_and_time); ...@@ -975,8 +974,6 @@ EXPORT_SYMBOL(drm_vblank_count_and_time);
* vblank events since the system was booted, including lost events due to * vblank events since the system was booted, including lost events due to
* modesetting activity. Returns corresponding system timestamp of the time * modesetting activity. Returns corresponding system timestamp of the time
* of the vblank interval that corresponds to the current vblank counter value. * of the vblank interval that corresponds to the current vblank counter value.
*
* This is the native KMS version of drm_vblank_count_and_time().
*/ */
u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *vblanktime) struct timeval *vblanktime)
...@@ -1588,12 +1585,6 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe, ...@@ -1588,12 +1585,6 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
seq = drm_vblank_count_and_time(dev, pipe, &now); seq = drm_vblank_count_and_time(dev, pipe, &now);
if ((vblwait->request.type & _DRM_VBLANK_NEXTONMISS) &&
(seq - vblwait->request.sequence) <= (1 << 23)) {
vblwait->request.sequence = seq + 1;
vblwait->reply.sequence = vblwait->request.sequence;
}
DRM_DEBUG("event on vblank count %d, current %d, crtc %u\n", DRM_DEBUG("event on vblank count %d, current %d, crtc %u\n",
vblwait->request.sequence, seq, pipe); vblwait->request.sequence, seq, pipe);
...@@ -1690,6 +1681,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data, ...@@ -1690,6 +1681,11 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
goto done; goto done;
} }
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
(seq - vblwait->request.sequence) <= (1 << 23)) {
vblwait->request.sequence = seq + 1;
}
if (flags & _DRM_VBLANK_EVENT) { if (flags & _DRM_VBLANK_EVENT) {
/* must hold on to the vblank ref until the event fires /* must hold on to the vblank ref until the event fires
* drm_vblank_put will be called asynchronously * drm_vblank_put will be called asynchronously
...@@ -1697,11 +1693,6 @@ int drm_wait_vblank(struct drm_device *dev, void *data, ...@@ -1697,11 +1693,6 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
return drm_queue_vblank_event(dev, pipe, vblwait, file_priv); return drm_queue_vblank_event(dev, pipe, vblwait, file_priv);
} }
if ((flags & _DRM_VBLANK_NEXTONMISS) &&
(seq - vblwait->request.sequence) <= (1<<23)) {
vblwait->request.sequence = seq + 1;
}
DRM_DEBUG("waiting on vblank count %d, crtc %u\n", DRM_DEBUG("waiting on vblank count %d, crtc %u\n",
vblwait->request.sequence, pipe); vblwait->request.sequence, pipe);
vblank->last_wait = vblwait->request.sequence; vblank->last_wait = vblwait->request.sequence;
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
# include <asm/agp.h> # include <asm/agp.h>
#else #else
# ifdef __powerpc__ # ifdef __powerpc__
# define PAGE_AGP __pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE) # define PAGE_AGP pgprot_noncached_wc(PAGE_KERNEL)
# else # else
# define PAGE_AGP PAGE_KERNEL # define PAGE_AGP PAGE_KERNEL
# endif # endif
......
...@@ -999,17 +999,17 @@ int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, ...@@ -999,17 +999,17 @@ int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on); EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_on);
/** /**
* mipi_dsi_set_tear_scanline() - turn on the display module's Tearing Effect * mipi_dsi_dcs_set_tear_scanline() - set the scanline to use as trigger for
* output signal on the TE signal line when display module reaches line N * the Tearing Effect output signal of the display module
* defined by STS[n:0].
* @dsi: DSI peripheral device * @dsi: DSI peripheral device
* @param: STS[10:0] * @scanline: scanline to use as trigger
*
* Return: 0 on success or a negative error code on failure * Return: 0 on success or a negative error code on failure
*/ */
int mipi_dsi_set_tear_scanline(struct mipi_dsi_device *dsi, u16 param) int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline)
{ {
u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, param >> 8, u8 payload[3] = { MIPI_DCS_SET_TEAR_SCANLINE, scanline >> 8,
param & 0xff }; scanline & 0xff };
ssize_t err; ssize_t err;
err = mipi_dsi_generic_write(dsi, payload, sizeof(payload)); err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));
...@@ -1018,7 +1018,7 @@ int mipi_dsi_set_tear_scanline(struct mipi_dsi_device *dsi, u16 param) ...@@ -1018,7 +1018,7 @@ int mipi_dsi_set_tear_scanline(struct mipi_dsi_device *dsi, u16 param)
return 0; return 0;
} }
EXPORT_SYMBOL(mipi_dsi_set_tear_scanline); EXPORT_SYMBOL(mipi_dsi_dcs_set_tear_scanline);
/** /**
* mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image * mipi_dsi_dcs_set_pixel_format() - sets the pixel format for the RGB image
......
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
static inline void *drm_vmalloc_dma(unsigned long size) static inline void *drm_vmalloc_dma(unsigned long size)
{ {
#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) #if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
return __vmalloc(size, GFP_KERNEL, PAGE_KERNEL | _PAGE_NO_CACHE); return __vmalloc(size, GFP_KERNEL, pgprot_noncached_wc(PAGE_KERNEL));
#else #else
return vmalloc_32(size); return vmalloc_32(size);
#endif #endif
......
...@@ -80,7 +80,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma) ...@@ -80,7 +80,7 @@ static pgprot_t drm_dma_prot(uint32_t map_type, struct vm_area_struct *vma)
pgprot_t tmp = vm_get_page_prot(vma->vm_flags); pgprot_t tmp = vm_get_page_prot(vma->vm_flags);
#if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE) #if defined(__powerpc__) && defined(CONFIG_NOT_COHERENT_CACHE)
tmp |= _PAGE_NO_CACHE; tmp = pgprot_noncached_wc(tmp);
#endif #endif
return tmp; return tmp;
} }
...@@ -593,7 +593,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma) ...@@ -593,7 +593,7 @@ static int drm_mmap_locked(struct file *filp, struct vm_area_struct *vma)
* pages and mappings in fault() * pages and mappings in fault()
*/ */
#if defined(__powerpc__) #if defined(__powerpc__)
pgprot_val(vma->vm_page_prot) |= _PAGE_NO_CACHE; vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
#endif #endif
vma->vm_ops = &drm_vm_ops; vma->vm_ops = &drm_vm_ops;
break; break;
......
...@@ -2,10 +2,6 @@ config DRM_EXYNOS ...@@ -2,10 +2,6 @@ config DRM_EXYNOS
tristate "DRM Support for Samsung SoC EXYNOS Series" tristate "DRM Support for Samsung SoC EXYNOS Series"
depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM) depends on OF && DRM && (ARCH_S3C64XX || ARCH_EXYNOS || ARCH_MULTIPLATFORM)
select DRM_KMS_HELPER select DRM_KMS_HELPER
select DRM_KMS_FB_HELPER
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
select VIDEOMODE_HELPERS select VIDEOMODE_HELPERS
help help
Choose this option if you have a Samsung SoC EXYNOS chipset. Choose this option if you have a Samsung SoC EXYNOS chipset.
......
...@@ -361,13 +361,8 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder, ...@@ -361,13 +361,8 @@ static int ch7006_encoder_set_property(struct drm_encoder *encoder,
/* Disable the crtc to ensure a full modeset is /* Disable the crtc to ensure a full modeset is
* performed whenever it's turned on again. */ * performed whenever it's turned on again. */
if (crtc) { if (crtc)
struct drm_mode_set modeset = { drm_crtc_force_disable(crtc);
.crtc = crtc,
};
drm_mode_set_config_internal(&modeset);
}
} }
return 0; return 0;
......
...@@ -431,7 +431,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev) ...@@ -431,7 +431,7 @@ static int mtk_mipi_tx_probe(struct platform_device *pdev)
phy_set_drvdata(phy, mipi_tx); phy_set_drvdata(phy, mipi_tx);
phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
if (IS_ERR(phy)) { if (IS_ERR(phy_provider)) {
ret = PTR_ERR(phy_provider); ret = PTR_ERR(phy_provider);
return ret; return ret;
} }
......
...@@ -125,18 +125,8 @@ nv04_display_destroy(struct drm_device *dev) ...@@ -125,18 +125,8 @@ nv04_display_destroy(struct drm_device *dev)
struct nv04_display *disp = nv04_display(dev); struct nv04_display *disp = nv04_display(dev);
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
struct nouveau_encoder *encoder; struct nouveau_encoder *encoder;
struct drm_crtc *crtc;
struct nouveau_crtc *nv_crtc; struct nouveau_crtc *nv_crtc;
/* Turn every CRTC off. */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct drm_mode_set modeset = {
.crtc = crtc,
};
drm_mode_set_config_internal(&modeset);
}
/* Restore state */ /* Restore state */
list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head) list_for_each_entry(encoder, &dev->mode_config.encoder_list, base.base.head)
encoder->enc_restore(&encoder->base.base); encoder->enc_restore(&encoder->base.base);
......
...@@ -749,13 +749,8 @@ static int nv17_tv_set_property(struct drm_encoder *encoder, ...@@ -749,13 +749,8 @@ static int nv17_tv_set_property(struct drm_encoder *encoder,
/* Disable the crtc to ensure a full modeset is /* Disable the crtc to ensure a full modeset is
* performed whenever it's turned on again. */ * performed whenever it's turned on again. */
if (crtc) { if (crtc)
struct drm_mode_set modeset = { drm_crtc_force_disable(crtc);
.crtc = crtc,
};
drm_mode_set_config_internal(&modeset);
}
} }
return 0; return 0;
......
...@@ -47,7 +47,7 @@ nouveau_display_vblank_handler(struct nvif_notify *notify) ...@@ -47,7 +47,7 @@ nouveau_display_vblank_handler(struct nvif_notify *notify)
{ {
struct nouveau_crtc *nv_crtc = struct nouveau_crtc *nv_crtc =
container_of(notify, typeof(*nv_crtc), vblank); container_of(notify, typeof(*nv_crtc), vblank);
drm_handle_vblank(nv_crtc->base.dev, nv_crtc->index); drm_crtc_handle_vblank(&nv_crtc->base);
return NVIF_NOTIFY_KEEP; return NVIF_NOTIFY_KEEP;
} }
...@@ -556,6 +556,7 @@ nouveau_display_destroy(struct drm_device *dev) ...@@ -556,6 +556,7 @@ nouveau_display_destroy(struct drm_device *dev)
nouveau_display_vblank_fini(dev); nouveau_display_vblank_fini(dev);
drm_kms_helper_poll_fini(dev); drm_kms_helper_poll_fini(dev);
drm_crtc_force_disable_all(dev);
drm_mode_config_cleanup(dev); drm_mode_config_cleanup(dev);
if (disp->dtor) if (disp->dtor)
......
...@@ -505,7 +505,11 @@ nouveau_drm_unload(struct drm_device *dev) ...@@ -505,7 +505,11 @@ nouveau_drm_unload(struct drm_device *dev)
{ {
struct nouveau_drm *drm = nouveau_drm(dev); struct nouveau_drm *drm = nouveau_drm(dev);
pm_runtime_get_sync(dev->dev); if (nouveau_runtime_pm != 0) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
}
nouveau_fbcon_fini(dev); nouveau_fbcon_fini(dev);
nouveau_accel_fini(drm); nouveau_accel_fini(drm);
nouveau_hwmon_fini(dev); nouveau_hwmon_fini(dev);
......
...@@ -203,7 +203,7 @@ qxl_push_cursor_ring_release(struct qxl_device *qdev, struct qxl_release *releas ...@@ -203,7 +203,7 @@ qxl_push_cursor_ring_release(struct qxl_device *qdev, struct qxl_release *releas
bool qxl_queue_garbage_collect(struct qxl_device *qdev, bool flush) bool qxl_queue_garbage_collect(struct qxl_device *qdev, bool flush)
{ {
if (!qxl_check_idle(qdev->release_ring)) { if (!qxl_check_idle(qdev->release_ring)) {
queue_work(qdev->gc_queue, &qdev->gc_work); schedule_work(&qdev->gc_work);
if (flush) if (flush)
flush_work(&qdev->gc_work); flush_work(&qdev->gc_work);
return true; return true;
......
...@@ -37,7 +37,6 @@ static int alloc_clips(struct qxl_device *qdev, ...@@ -37,7 +37,6 @@ static int alloc_clips(struct qxl_device *qdev,
* the qxl_clip_rects. This is *not* the same as the memory allocated * the qxl_clip_rects. This is *not* the same as the memory allocated
* on the device, it is offset to qxl_clip_rects.chunk.data */ * on the device, it is offset to qxl_clip_rects.chunk.data */
static struct qxl_rect *drawable_set_clipping(struct qxl_device *qdev, static struct qxl_rect *drawable_set_clipping(struct qxl_device *qdev,
struct qxl_drawable *drawable,
unsigned num_clips, unsigned num_clips,
struct qxl_bo *clips_bo) struct qxl_bo *clips_bo)
{ {
...@@ -136,6 +135,8 @@ static int qxl_palette_create_1bit(struct qxl_bo *palette_bo, ...@@ -136,6 +135,8 @@ static int qxl_palette_create_1bit(struct qxl_bo *palette_bo,
* correctly globaly, since that would require * correctly globaly, since that would require
* tracking all of our palettes. */ * tracking all of our palettes. */
ret = qxl_bo_kmap(palette_bo, (void **)&pal); ret = qxl_bo_kmap(palette_bo, (void **)&pal);
if (ret)
return ret;
pal->num_ents = 2; pal->num_ents = 2;
pal->unique = unique++; pal->unique = unique++;
if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) { if (visual == FB_VISUAL_TRUECOLOR || visual == FB_VISUAL_DIRECTCOLOR) {
...@@ -349,7 +350,7 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev, ...@@ -349,7 +350,7 @@ void qxl_draw_dirty_fb(struct qxl_device *qdev,
if (ret) if (ret)
goto out_release_backoff; goto out_release_backoff;
rects = drawable_set_clipping(qdev, drawable, num_clips, clips_bo); rects = drawable_set_clipping(qdev, num_clips, clips_bo);
if (!rects) if (!rects)
goto out_release_backoff; goto out_release_backoff;
......
...@@ -321,7 +321,6 @@ struct qxl_device { ...@@ -321,7 +321,6 @@ struct qxl_device {
struct qxl_bo *current_release_bo[3]; struct qxl_bo *current_release_bo[3];
int current_release_bo_offset[3]; int current_release_bo_offset[3];
struct workqueue_struct *gc_queue;
struct work_struct gc_work; struct work_struct gc_work;
struct drm_property *hotplug_mode_update_property; struct drm_property *hotplug_mode_update_property;
......
...@@ -258,7 +258,6 @@ static int qxl_device_init(struct qxl_device *qdev, ...@@ -258,7 +258,6 @@ static int qxl_device_init(struct qxl_device *qdev,
(unsigned long)qdev->surfaceram_size); (unsigned long)qdev->surfaceram_size);
qdev->gc_queue = create_singlethread_workqueue("qxl_gc");
INIT_WORK(&qdev->gc_work, qxl_gc_work); INIT_WORK(&qdev->gc_work, qxl_gc_work);
return 0; return 0;
...@@ -270,10 +269,7 @@ static void qxl_device_fini(struct qxl_device *qdev) ...@@ -270,10 +269,7 @@ static void qxl_device_fini(struct qxl_device *qdev)
qxl_bo_unref(&qdev->current_release_bo[0]); qxl_bo_unref(&qdev->current_release_bo[0]);
if (qdev->current_release_bo[1]) if (qdev->current_release_bo[1])
qxl_bo_unref(&qdev->current_release_bo[1]); qxl_bo_unref(&qdev->current_release_bo[1]);
flush_workqueue(qdev->gc_queue); flush_work(&qdev->gc_work);
destroy_workqueue(qdev->gc_queue);
qdev->gc_queue = NULL;
qxl_ring_free(qdev->command_ring); qxl_ring_free(qdev->command_ring);
qxl_ring_free(qdev->cursor_ring); qxl_ring_free(qdev->cursor_ring);
qxl_ring_free(qdev->release_ring); qxl_ring_free(qdev->release_ring);
...@@ -310,10 +306,6 @@ int qxl_driver_load(struct drm_device *dev, unsigned long flags) ...@@ -310,10 +306,6 @@ int qxl_driver_load(struct drm_device *dev, unsigned long flags)
struct qxl_device *qdev; struct qxl_device *qdev;
int r; int r;
/* require kms */
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -ENODEV;
qdev = kzalloc(sizeof(struct qxl_device), GFP_KERNEL); qdev = kzalloc(sizeof(struct qxl_device), GFP_KERNEL);
if (qdev == NULL) if (qdev == NULL)
return -ENOMEM; return -ENOMEM;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <drm/drmP.h> #include <drm/drmP.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/radeon_drm.h> #include <drm/radeon_drm.h>
#include <linux/pm_runtime.h>
#include <linux/vgaarb.h> #include <linux/vgaarb.h>
#include <linux/vga_switcheroo.h> #include <linux/vga_switcheroo.h>
#include <linux/efi.h> #include <linux/efi.h>
...@@ -1526,6 +1527,9 @@ int radeon_device_init(struct radeon_device *rdev, ...@@ -1526,6 +1527,9 @@ int radeon_device_init(struct radeon_device *rdev,
return 0; return 0;
failed: failed:
/* balance pm_runtime_get_sync() in radeon_driver_unload_kms() */
if (radeon_is_px(ddev))
pm_runtime_put_noidle(ddev->dev);
if (runtime) if (runtime)
vga_switcheroo_fini_domain_pm_ops(rdev->dev); vga_switcheroo_fini_domain_pm_ops(rdev->dev);
return r; return r;
......
...@@ -1711,6 +1711,7 @@ void radeon_modeset_fini(struct radeon_device *rdev) ...@@ -1711,6 +1711,7 @@ void radeon_modeset_fini(struct radeon_device *rdev)
radeon_afmt_fini(rdev); radeon_afmt_fini(rdev);
drm_kms_helper_poll_fini(rdev->ddev); drm_kms_helper_poll_fini(rdev->ddev);
radeon_hpd_fini(rdev); radeon_hpd_fini(rdev);
drm_crtc_force_disable_all(rdev->ddev);
drm_mode_config_cleanup(rdev->ddev); drm_mode_config_cleanup(rdev->ddev);
rdev->mode_info.mode_config_initialized = false; rdev->mode_info.mode_config_initialized = false;
} }
......
...@@ -63,7 +63,10 @@ int radeon_driver_unload_kms(struct drm_device *dev) ...@@ -63,7 +63,10 @@ int radeon_driver_unload_kms(struct drm_device *dev)
if (rdev->rmmio == NULL) if (rdev->rmmio == NULL)
goto done_free; goto done_free;
pm_runtime_get_sync(dev->dev); if (radeon_is_px(dev)) {
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
}
radeon_kfd_device_fini(rdev); radeon_kfd_device_fini(rdev);
......
...@@ -552,7 +552,7 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg) ...@@ -552,7 +552,7 @@ static irqreturn_t rcar_du_crtc_irq(int irq, void *arg)
rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK); rcar_du_crtc_write(rcrtc, DSRCR, status & DSRCR_MASK);
if (status & DSSR_FRM) { if (status & DSSR_FRM) {
drm_handle_vblank(rcrtc->crtc.dev, rcrtc->index); drm_crtc_handle_vblank(&rcrtc->crtc);
rcar_du_crtc_finish_page_flip(rcrtc); rcar_du_crtc_finish_page_flip(rcrtc);
ret = IRQ_HANDLED; ret = IRQ_HANDLED;
} }
......
...@@ -433,6 +433,7 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev) ...@@ -433,6 +433,7 @@ static int rockchip_drm_platform_probe(struct platform_device *pdev)
is_support_iommu = false; is_support_iommu = false;
} }
of_node_put(iommu);
component_match_add(dev, &match, compare_of, port->parent); component_match_add(dev, &match, compare_of, port->parent);
of_node_put(port); of_node_put(port);
} }
......
...@@ -267,10 +267,12 @@ static int sti_compositor_probe(struct platform_device *pdev) ...@@ -267,10 +267,12 @@ static int sti_compositor_probe(struct platform_device *pdev)
vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0); vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0);
if (vtg_np) if (vtg_np)
compo->vtg_main = of_vtg_find(vtg_np); compo->vtg_main = of_vtg_find(vtg_np);
of_node_put(vtg_np);
vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1); vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 1);
if (vtg_np) if (vtg_np)
compo->vtg_aux = of_vtg_find(vtg_np); compo->vtg_aux = of_vtg_find(vtg_np);
of_node_put(vtg_np);
platform_set_drvdata(pdev, compo); platform_set_drvdata(pdev, compo);
......
...@@ -580,6 +580,7 @@ static int sti_dvo_probe(struct platform_device *pdev) ...@@ -580,6 +580,7 @@ static int sti_dvo_probe(struct platform_device *pdev)
dvo->panel_node = of_parse_phandle(np, "sti,panel", 0); dvo->panel_node = of_parse_phandle(np, "sti,panel", 0);
if (!dvo->panel_node) if (!dvo->panel_node)
DRM_ERROR("No panel associated to the dvo output\n"); DRM_ERROR("No panel associated to the dvo output\n");
of_node_put(dvo->panel_node);
platform_set_drvdata(pdev, dvo); platform_set_drvdata(pdev, dvo);
......
...@@ -1363,6 +1363,7 @@ static int sti_hqvdp_probe(struct platform_device *pdev) ...@@ -1363,6 +1363,7 @@ static int sti_hqvdp_probe(struct platform_device *pdev)
vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0); vtg_np = of_parse_phandle(pdev->dev.of_node, "st,vtg", 0);
if (vtg_np) if (vtg_np)
hqvdp->vtg = of_vtg_find(vtg_np); hqvdp->vtg = of_vtg_find(vtg_np);
of_node_put(vtg_np);
platform_set_drvdata(pdev, hqvdp); platform_set_drvdata(pdev, hqvdp);
......
...@@ -432,6 +432,7 @@ static int vtg_probe(struct platform_device *pdev) ...@@ -432,6 +432,7 @@ static int vtg_probe(struct platform_device *pdev)
np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0); np = of_parse_phandle(pdev->dev.of_node, "st,slave", 0);
if (np) { if (np) {
vtg->slave = of_vtg_find(np); vtg->slave = of_vtg_find(np);
of_node_put(np);
if (!vtg->slave) if (!vtg->slave)
return -EPROBE_DEFER; return -EPROBE_DEFER;
......
...@@ -697,7 +697,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc) ...@@ -697,7 +697,7 @@ irqreturn_t tilcdc_crtc_irq(struct drm_crtc *crtc)
spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags); spin_unlock_irqrestore(&tilcdc_crtc->irq_lock, flags);
drm_handle_vblank(dev, 0); drm_crtc_handle_vblank(crtc);
if (!skip_event) { if (!skip_event) {
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
......
...@@ -94,7 +94,6 @@ static void udl_usb_disconnect(struct usb_interface *interface) ...@@ -94,7 +94,6 @@ static void udl_usb_disconnect(struct usb_interface *interface)
struct drm_device *dev = usb_get_intfdata(interface); struct drm_device *dev = usb_get_intfdata(interface);
drm_kms_helper_poll_disable(dev); drm_kms_helper_poll_disable(dev);
drm_connector_unregister_all(dev);
udl_fbdev_unplug(dev); udl_fbdev_unplug(dev);
udl_drop_usb(dev); udl_drop_usb(dev);
drm_unplug_dev(dev); drm_unplug_dev(dev);
......
...@@ -42,81 +42,38 @@ ...@@ -42,81 +42,38 @@
#define DRIVER_MAJOR 1 #define DRIVER_MAJOR 1
#define DRIVER_MINOR 0 #define DRIVER_MINOR 0
void vgem_gem_put_pages(struct drm_vgem_gem_object *obj)
{
drm_gem_put_pages(&obj->base, obj->pages, false, false);
obj->pages = NULL;
}
static void vgem_gem_free_object(struct drm_gem_object *obj) static void vgem_gem_free_object(struct drm_gem_object *obj)
{ {
struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj); struct drm_vgem_gem_object *vgem_obj = to_vgem_bo(obj);
drm_gem_free_mmap_offset(obj);
if (vgem_obj->use_dma_buf && obj->dma_buf) {
dma_buf_put(obj->dma_buf);
obj->dma_buf = NULL;
}
drm_gem_object_release(obj); drm_gem_object_release(obj);
if (vgem_obj->pages)
vgem_gem_put_pages(vgem_obj);
vgem_obj->pages = NULL;
kfree(vgem_obj); kfree(vgem_obj);
} }
int vgem_gem_get_pages(struct drm_vgem_gem_object *obj)
{
struct page **pages;
if (obj->pages || obj->use_dma_buf)
return 0;
pages = drm_gem_get_pages(&obj->base);
if (IS_ERR(pages)) {
return PTR_ERR(pages);
}
obj->pages = pages;
return 0;
}
static int vgem_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) static int vgem_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
{ {
struct drm_vgem_gem_object *obj = vma->vm_private_data; struct drm_vgem_gem_object *obj = vma->vm_private_data;
loff_t num_pages;
pgoff_t page_offset;
int ret;
/* We don't use vmf->pgoff since that has the fake offset */ /* We don't use vmf->pgoff since that has the fake offset */
page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >> unsigned long vaddr = (unsigned long)vmf->virtual_address;
PAGE_SHIFT; struct page *page;
num_pages = DIV_ROUND_UP(obj->base.size, PAGE_SIZE); page = shmem_read_mapping_page(file_inode(obj->base.filp)->i_mapping,
(vaddr - vma->vm_start) >> PAGE_SHIFT);
if (page_offset > num_pages) if (!IS_ERR(page)) {
return VM_FAULT_SIGBUS; vmf->page = page;
return 0;
ret = vm_insert_page(vma, (unsigned long)vmf->virtual_address, } else switch (PTR_ERR(page)) {
obj->pages[page_offset]); case -ENOSPC:
switch (ret) { case -ENOMEM:
case 0: return VM_FAULT_OOM;
return VM_FAULT_NOPAGE; case -EBUSY:
case -ENOMEM: return VM_FAULT_RETRY;
return VM_FAULT_OOM; case -EFAULT:
case -EBUSY: case -EINVAL:
return VM_FAULT_RETRY; return VM_FAULT_SIGBUS;
case -EFAULT: default:
case -EINVAL: WARN_ON_ONCE(PTR_ERR(page));
return VM_FAULT_SIGBUS; return VM_FAULT_SIGBUS;
default:
WARN_ON(1);
return VM_FAULT_SIGBUS;
} }
} }
...@@ -134,57 +91,43 @@ static struct drm_gem_object *vgem_gem_create(struct drm_device *dev, ...@@ -134,57 +91,43 @@ static struct drm_gem_object *vgem_gem_create(struct drm_device *dev,
unsigned long size) unsigned long size)
{ {
struct drm_vgem_gem_object *obj; struct drm_vgem_gem_object *obj;
struct drm_gem_object *gem_object; int ret;
int err;
size = roundup(size, PAGE_SIZE);
obj = kzalloc(sizeof(*obj), GFP_KERNEL); obj = kzalloc(sizeof(*obj), GFP_KERNEL);
if (!obj) if (!obj)
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
gem_object = &obj->base; ret = drm_gem_object_init(dev, &obj->base, roundup(size, PAGE_SIZE));
if (ret)
err = drm_gem_object_init(dev, gem_object, size); goto err_free;
if (err)
goto out;
err = vgem_gem_get_pages(obj);
if (err)
goto out;
err = drm_gem_handle_create(file, gem_object, handle);
if (err)
goto handle_out;
drm_gem_object_unreference_unlocked(gem_object); ret = drm_gem_handle_create(file, &obj->base, handle);
drm_gem_object_unreference_unlocked(&obj->base);
if (ret)
goto err;
return gem_object; return &obj->base;
handle_out: err_free:
drm_gem_object_release(gem_object);
out:
kfree(obj); kfree(obj);
return ERR_PTR(err); err:
return ERR_PTR(ret);
} }
static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev, static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args) struct drm_mode_create_dumb *args)
{ {
struct drm_gem_object *gem_object; struct drm_gem_object *gem_object;
uint64_t size; u64 pitch, size;
uint64_t pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
pitch = args->width * DIV_ROUND_UP(args->bpp, 8);
size = args->height * pitch; size = args->height * pitch;
if (size == 0) if (size == 0)
return -EINVAL; return -EINVAL;
gem_object = vgem_gem_create(dev, file, &args->handle, size); gem_object = vgem_gem_create(dev, file, &args->handle, size);
if (IS_ERR(gem_object))
if (IS_ERR(gem_object)) {
DRM_DEBUG_DRIVER("object creation failed\n");
return PTR_ERR(gem_object); return PTR_ERR(gem_object);
}
args->size = gem_object->size; args->size = gem_object->size;
args->pitch = pitch; args->pitch = pitch;
...@@ -194,26 +137,26 @@ static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev, ...@@ -194,26 +137,26 @@ static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
return 0; return 0;
} }
int vgem_gem_dumb_map(struct drm_file *file, struct drm_device *dev, static int vgem_gem_dumb_map(struct drm_file *file, struct drm_device *dev,
uint32_t handle, uint64_t *offset) uint32_t handle, uint64_t *offset)
{ {
int ret = 0;
struct drm_gem_object *obj; struct drm_gem_object *obj;
int ret;
obj = drm_gem_object_lookup(file, handle); obj = drm_gem_object_lookup(file, handle);
if (!obj) if (!obj)
return -ENOENT; return -ENOENT;
if (!obj->filp) {
ret = -EINVAL;
goto unref;
}
ret = drm_gem_create_mmap_offset(obj); ret = drm_gem_create_mmap_offset(obj);
if (ret) if (ret)
goto unref; goto unref;
BUG_ON(!obj->filp);
obj->filp->private_data = obj;
*offset = drm_vma_node_offset_addr(&obj->vma_node); *offset = drm_vma_node_offset_addr(&obj->vma_node);
unref: unref:
drm_gem_object_unreference_unlocked(obj); drm_gem_object_unreference_unlocked(obj);
...@@ -223,24 +166,127 @@ int vgem_gem_dumb_map(struct drm_file *file, struct drm_device *dev, ...@@ -223,24 +166,127 @@ int vgem_gem_dumb_map(struct drm_file *file, struct drm_device *dev,
static struct drm_ioctl_desc vgem_ioctls[] = { static struct drm_ioctl_desc vgem_ioctls[] = {
}; };
static int vgem_mmap(struct file *filp, struct vm_area_struct *vma)
{
unsigned long flags = vma->vm_flags;
int ret;
ret = drm_gem_mmap(filp, vma);
if (ret)
return ret;
/* Keep the WC mmaping set by drm_gem_mmap() but our pages
* are ordinary and not special.
*/
vma->vm_flags = flags | VM_DONTEXPAND | VM_DONTDUMP;
return 0;
}
static const struct file_operations vgem_driver_fops = { static const struct file_operations vgem_driver_fops = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
.open = drm_open, .open = drm_open,
.mmap = drm_gem_mmap, .mmap = vgem_mmap,
.poll = drm_poll, .poll = drm_poll,
.read = drm_read, .read = drm_read,
.unlocked_ioctl = drm_ioctl, .unlocked_ioctl = drm_ioctl,
.release = drm_release, .release = drm_release,
}; };
static int vgem_prime_pin(struct drm_gem_object *obj)
{
long n_pages = obj->size >> PAGE_SHIFT;
struct page **pages;
/* Flush the object from the CPU cache so that importers can rely
* on coherent indirect access via the exported dma-address.
*/
pages = drm_gem_get_pages(obj);
if (IS_ERR(pages))
return PTR_ERR(pages);
drm_clflush_pages(pages, n_pages);
drm_gem_put_pages(obj, pages, true, false);
return 0;
}
static struct sg_table *vgem_prime_get_sg_table(struct drm_gem_object *obj)
{
struct sg_table *st;
struct page **pages;
pages = drm_gem_get_pages(obj);
if (IS_ERR(pages))
return ERR_CAST(pages);
st = drm_prime_pages_to_sg(pages, obj->size >> PAGE_SHIFT);
drm_gem_put_pages(obj, pages, false, false);
return st;
}
static void *vgem_prime_vmap(struct drm_gem_object *obj)
{
long n_pages = obj->size >> PAGE_SHIFT;
struct page **pages;
void *addr;
pages = drm_gem_get_pages(obj);
if (IS_ERR(pages))
return NULL;
addr = vmap(pages, n_pages, 0, pgprot_writecombine(PAGE_KERNEL));
drm_gem_put_pages(obj, pages, false, false);
return addr;
}
static void vgem_prime_vunmap(struct drm_gem_object *obj, void *vaddr)
{
vunmap(vaddr);
}
static int vgem_prime_mmap(struct drm_gem_object *obj,
struct vm_area_struct *vma)
{
int ret;
if (obj->size < vma->vm_end - vma->vm_start)
return -EINVAL;
if (!obj->filp)
return -ENODEV;
ret = obj->filp->f_op->mmap(obj->filp, vma);
if (ret)
return ret;
fput(vma->vm_file);
vma->vm_file = get_file(obj->filp);
vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
return 0;
}
static struct drm_driver vgem_driver = { static struct drm_driver vgem_driver = {
.driver_features = DRIVER_GEM, .driver_features = DRIVER_GEM | DRIVER_PRIME,
.gem_free_object_unlocked = vgem_gem_free_object, .gem_free_object_unlocked = vgem_gem_free_object,
.gem_vm_ops = &vgem_gem_vm_ops, .gem_vm_ops = &vgem_gem_vm_ops,
.ioctls = vgem_ioctls, .ioctls = vgem_ioctls,
.fops = &vgem_driver_fops, .fops = &vgem_driver_fops,
.dumb_create = vgem_gem_dumb_create, .dumb_create = vgem_gem_dumb_create,
.dumb_map_offset = vgem_gem_dumb_map, .dumb_map_offset = vgem_gem_dumb_map,
.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
.gem_prime_pin = vgem_prime_pin,
.gem_prime_export = drm_gem_prime_export,
.gem_prime_get_sg_table = vgem_prime_get_sg_table,
.gem_prime_vmap = vgem_prime_vmap,
.gem_prime_vunmap = vgem_prime_vunmap,
.gem_prime_mmap = vgem_prime_mmap,
.name = DRIVER_NAME, .name = DRIVER_NAME,
.desc = DRIVER_DESC, .desc = DRIVER_DESC,
.date = DRIVER_DATE, .date = DRIVER_DATE,
...@@ -248,7 +294,7 @@ static struct drm_driver vgem_driver = { ...@@ -248,7 +294,7 @@ static struct drm_driver vgem_driver = {
.minor = DRIVER_MINOR, .minor = DRIVER_MINOR,
}; };
struct drm_device *vgem_device; static struct drm_device *vgem_device;
static int __init vgem_init(void) static int __init vgem_init(void)
{ {
...@@ -261,7 +307,6 @@ static int __init vgem_init(void) ...@@ -261,7 +307,6 @@ static int __init vgem_init(void)
} }
ret = drm_dev_register(vgem_device, 0); ret = drm_dev_register(vgem_device, 0);
if (ret) if (ret)
goto out_unref; goto out_unref;
......
...@@ -35,12 +35,6 @@ ...@@ -35,12 +35,6 @@
#define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base) #define to_vgem_bo(x) container_of(x, struct drm_vgem_gem_object, base)
struct drm_vgem_gem_object { struct drm_vgem_gem_object {
struct drm_gem_object base; struct drm_gem_object base;
struct page **pages;
bool use_dma_buf;
}; };
/* vgem_drv.c */
extern void vgem_gem_put_pages(struct drm_vgem_gem_object *obj);
extern int vgem_gem_get_pages(struct drm_vgem_gem_object *obj);
#endif #endif
...@@ -1041,8 +1041,7 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev, ...@@ -1041,8 +1041,7 @@ static struct vmw_master *vmw_master_check(struct drm_device *dev,
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
struct vmw_master *vmaster; struct vmw_master *vmaster;
if (file_priv->minor->type != DRM_MINOR_LEGACY || if (!drm_is_primary_client(file_priv) || !(flags & DRM_AUTH))
!(flags & DRM_AUTH))
return NULL; return NULL;
ret = mutex_lock_interruptible(&dev->master_mutex); ret = mutex_lock_interruptible(&dev->master_mutex);
......
...@@ -52,9 +52,9 @@ ...@@ -52,9 +52,9 @@
* *
* * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs. * * muxed: Dual GPUs with a multiplexer chip to switch outputs between GPUs.
* * muxless: Dual GPUs but only one of them is connected to outputs. * * muxless: Dual GPUs but only one of them is connected to outputs.
* The other one is merely used to offload rendering, its results * The other one is merely used to offload rendering, its results
* are copied over PCIe into the framebuffer. On Linux this is * are copied over PCIe into the framebuffer. On Linux this is
* supported with DRI PRIME. * supported with DRI PRIME.
* *
* Hybrid graphics started to appear in the late Naughties and were initially * Hybrid graphics started to appear in the late Naughties and were initially
* all muxed. Newer laptops moved to a muxless architecture for cost reasons. * all muxed. Newer laptops moved to a muxless architecture for cost reasons.
...@@ -560,21 +560,21 @@ EXPORT_SYMBOL(vga_switcheroo_unlock_ddc); ...@@ -560,21 +560,21 @@ EXPORT_SYMBOL(vga_switcheroo_unlock_ddc);
* * OFF: Power off the device not in use. * * OFF: Power off the device not in use.
* * ON: Power on the device not in use. * * ON: Power on the device not in use.
* * IGD: Switch to the integrated graphics device. * * IGD: Switch to the integrated graphics device.
* Power on the integrated GPU if necessary, power off the discrete GPU. * Power on the integrated GPU if necessary, power off the discrete GPU.
* Prerequisite is that no user space processes (e.g. Xorg, alsactl) * Prerequisite is that no user space processes (e.g. Xorg, alsactl)
* have opened device files of the GPUs or the audio client. If the * have opened device files of the GPUs or the audio client. If the
* switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/ * switch fails, the user may invoke lsof(8) or fuser(1) on /dev/dri/
* and /dev/snd/controlC1 to identify processes blocking the switch. * and /dev/snd/controlC1 to identify processes blocking the switch.
* * DIS: Switch to the discrete graphics device. * * DIS: Switch to the discrete graphics device.
* * DIGD: Delayed switch to the integrated graphics device. * * DIGD: Delayed switch to the integrated graphics device.
* This will perform the switch once the last user space process has * This will perform the switch once the last user space process has
* closed the device files of the GPUs and the audio client. * closed the device files of the GPUs and the audio client.
* * DDIS: Delayed switch to the discrete graphics device. * * DDIS: Delayed switch to the discrete graphics device.
* * MIGD: Mux-only switch to the integrated graphics device. * * MIGD: Mux-only switch to the integrated graphics device.
* Does not remap console or change the power state of either gpu. * Does not remap console or change the power state of either gpu.
* If the integrated GPU is currently off, the screen will turn black. * If the integrated GPU is currently off, the screen will turn black.
* If it is on, the screen will show whatever happens to be in VRAM. * If it is on, the screen will show whatever happens to be in VRAM.
* Either way, the user has to blindly enter the command to switch back. * Either way, the user has to blindly enter the command to switch back.
* * MDIS: Mux-only switch to the discrete graphics device. * * MDIS: Mux-only switch to the discrete graphics device.
* *
* For GPUs whose power state is controlled by the driver's runtime pm, * For GPUs whose power state is controlled by the driver's runtime pm,
......
...@@ -942,8 +942,6 @@ extern int drm_wait_vblank(struct drm_device *dev, void *data, ...@@ -942,8 +942,6 @@ extern int drm_wait_vblank(struct drm_device *dev, void *data,
struct drm_file *filp); struct drm_file *filp);
extern u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe); extern u32 drm_vblank_count(struct drm_device *dev, unsigned int pipe);
extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc); extern u32 drm_crtc_vblank_count(struct drm_crtc *crtc);
extern u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
struct timeval *vblanktime);
extern u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, extern u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc,
struct timeval *vblanktime); struct timeval *vblanktime);
extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc, extern void drm_crtc_send_vblank_event(struct drm_crtc *crtc,
......
...@@ -2588,7 +2588,6 @@ static inline unsigned drm_connector_index(struct drm_connector *connector) ...@@ -2588,7 +2588,6 @@ static inline unsigned drm_connector_index(struct drm_connector *connector)
} }
/* helpers to {un}register all connectors from sysfs for device */ /* helpers to {un}register all connectors from sysfs for device */
extern int drm_connector_register_all(struct drm_device *dev);
extern void drm_connector_unregister_all(struct drm_device *dev); extern void drm_connector_unregister_all(struct drm_device *dev);
extern __printf(5, 6) extern __printf(5, 6)
...@@ -2654,6 +2653,8 @@ extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx); ...@@ -2654,6 +2653,8 @@ extern struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
extern void drm_plane_force_disable(struct drm_plane *plane); extern void drm_plane_force_disable(struct drm_plane *plane);
extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode, extern void drm_crtc_get_hv_timing(const struct drm_display_mode *mode,
int *hdisplay, int *vdisplay); int *hdisplay, int *vdisplay);
extern int drm_crtc_force_disable(struct drm_crtc *crtc);
extern int drm_crtc_force_disable_all(struct drm_device *dev);
extern void drm_encoder_cleanup(struct drm_encoder *encoder); extern void drm_encoder_cleanup(struct drm_encoder *encoder);
......
...@@ -265,7 +265,7 @@ int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start, ...@@ -265,7 +265,7 @@ int mipi_dsi_dcs_set_column_address(struct mipi_dsi_device *dsi, u16 start,
u16 end); u16 end);
int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start, int mipi_dsi_dcs_set_page_address(struct mipi_dsi_device *dsi, u16 start,
u16 end); u16 end);
int mipi_dsi_set_tear_scanline(struct mipi_dsi_device *dsi, u16 param); int mipi_dsi_dcs_set_tear_scanline(struct mipi_dsi_device *dsi, u16 scanline);
int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi); int mipi_dsi_dcs_set_tear_off(struct mipi_dsi_device *dsi);
int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi, int mipi_dsi_dcs_set_tear_on(struct mipi_dsi_device *dsi,
enum mipi_dsi_dcs_tear_mode mode); enum mipi_dsi_dcs_tear_mode mode);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment