diff options
author | Dave Airlie <airlied@redhat.com> | 2019-08-09 09:04:15 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2019-08-09 09:04:31 +0300 |
commit | b0383c0653c4bd2d2732c5767ec8fa223b3d6efd (patch) | |
tree | 213d1647c83a9bdbe9446d7ab81d9c80a44be188 /drivers/gpu | |
parent | dce14e36aea23183ccd315fbc6b0fca027bf73f5 (diff) | |
parent | cc8f12996e24b102a086a253055ecc58c437c31d (diff) | |
download | linux-b0383c0653c4bd2d2732c5767ec8fa223b3d6efd.tar.xz |
Merge tag 'drm-misc-next-2019-08-08' of git://anongit.freedesktop.org/drm/drm-misc into drm-next
drm-misc-next for 5.4:
UAPI Changes:
- HDCP: Add a Content protection type property
Cross-subsystem Changes:
Core Changes:
- Continue to rework the include dependencies
- fb: Remove the unused drm_gem_fbdev_fb_create function
- drm-dp-helper: Make the link rate calculation more tolerant to
non-explicitly defined, yet supported, rates
- fb-helper: Map DRM client buffer only when required, and instanciate a
shadow buffer when the device has a dirty function or says so
- connector: Add a helper to link the DDC adapter used by that connector to
the userspace
- vblank: Switch from DRM_WAIT_ON to wait_event_interruptible_timeout
- dma-buf: Fix a stack corruption
- ttm: Embed a drm_gem_object struct to make ttm_buffer_object a
superclass of GEM, and convert drivers to use it.
- hdcp: Improvements to report the content protection type to the
userspace
Driver Changes:
- Remove drm_gem_prime_import/export from being defined in the drivers
- Drop DRM_AUTH usage from drivers
- Continue to drop drmP.h
- Convert drivers to the connector ddc helper
- ingenic: Add support for more panel-related cases
- komeda: Support for dual-link
- lima: Reduce logging
- mpag200: Fix the cursor support
- panfrost: Export GPU features register to userspace through an ioctl
- pl111: Remove the CLD pads wiring support from the DT
- rockchip: Rework to use DRM PSR helpers, fix a bug in the VOP_WIN_GET
macro
- sun4i: Improve support for color encoding and range
- tinydrm: Rework SPI support, improve MIPI-DBI support, move to drm/tiny
- vkms: Rework of the CRC tracking
- bridges:
- sii902x: Add support for audio graph card
- tc358767: Rework AUX data handling code
- ti-sn65dsi86: Add Debugfs and proper DSI mode flags support
- panels
- Support for GiantPlus GPM940B0, Sharp LQ070Y3DG3B, Ortustech
COM37H3M, Novatek NT39016, Sharp LS020B1DD01D, Raydium RM67191,
Boe Himax8279d, Sharp LD-D5116Z01B
- Conversion of the device tree bindings to the YAML description
- jh057n00900: Rework the enable / disable path
- fbdev:
- ssd1307fb: Support more devices based on that controller
Signed-off-by: Dave Airlie <airlied@redhat.com>
From: Maxime Ripard <maxime.ripard@bootlin.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190808121423.xzpedzkpyecvsiy4@flea
Diffstat (limited to 'drivers/gpu')
455 files changed, 7536 insertions, 5610 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 3c88420e3497..e67c194c2aca 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -24,6 +24,10 @@ menuconfig DRM details. You should also select and configure AGP (/dev/agpgart) support if it is available for your platform. +config DRM_MIPI_DBI + tristate + depends on DRM + config DRM_MIPI_DSI bool depends on DRM @@ -336,7 +340,7 @@ source "drivers/gpu/drm/mxsfb/Kconfig" source "drivers/gpu/drm/meson/Kconfig" -source "drivers/gpu/drm/tinydrm/Kconfig" +source "drivers/gpu/drm/tiny/Kconfig" source "drivers/gpu/drm/pl111/Kconfig" diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile index 9f0d2ee35794..10f8329a8b71 100644 --- a/drivers/gpu/drm/Makefile +++ b/drivers/gpu/drm/Makefile @@ -55,6 +55,7 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/ obj-$(CONFIG_DRM) += drm.o +obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o obj-y += arm/ @@ -111,7 +112,7 @@ obj-$(CONFIG_DRM_ARCPGU)+= arc/ obj-y += hisilicon/ obj-$(CONFIG_DRM_ZTE) += zte/ obj-$(CONFIG_DRM_MXSFB) += mxsfb/ -obj-$(CONFIG_DRM_TINYDRM) += tinydrm/ +obj-y += tiny/ obj-$(CONFIG_DRM_PL111) += pl111/ obj-$(CONFIG_DRM_TVE200) += tve200/ obj-$(CONFIG_DRM_XEN) += xen/ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 6a5c96e519b1..9410ffceee15 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -218,7 +218,7 @@ void amdgpu_amdkfd_unreserve_memory_limit(struct amdgpu_bo *bo) static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo, struct amdgpu_amdkfd_fence *ef) { - struct reservation_object *resv = bo->tbo.resv; + struct reservation_object *resv = bo->tbo.base.resv; struct reservation_object_list *old, *new; unsigned int i, j, k; @@ -812,7 +812,7 @@ static int process_sync_pds_resv(struct amdkfd_process_info *process_info, struct amdgpu_bo *pd = peer_vm->root.base.bo; ret = amdgpu_sync_resv(NULL, - sync, pd->tbo.resv, + sync, pd->tbo.base.resv, AMDGPU_FENCE_OWNER_KFD, false); if (ret) return ret; @@ -887,7 +887,7 @@ static int init_kfd_vm(struct amdgpu_vm *vm, void **process_info, AMDGPU_FENCE_OWNER_KFD, false); if (ret) goto wait_pd_fail; - ret = reservation_object_reserve_shared(vm->root.base.bo->tbo.resv, 1); + ret = reservation_object_reserve_shared(vm->root.base.bo->tbo.base.resv, 1); if (ret) goto reserve_shared_fail; amdgpu_bo_fence(vm->root.base.bo, @@ -2133,7 +2133,7 @@ int amdgpu_amdkfd_add_gws_to_process(void *info, void *gws, struct kgd_mem **mem * Add process eviction fence to bo so they can * evict each other. */ - ret = reservation_object_reserve_shared(gws_bo->tbo.resv, 1); + ret = reservation_object_reserve_shared(gws_bo->tbo.base.resv, 1); if (ret) goto reserve_shared_fail; amdgpu_bo_fence(gws_bo, &process_info->eviction_fence->base, true); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c index 73b2ede773d3..ece55c8fa673 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_connectors.c @@ -1505,6 +1505,7 @@ amdgpu_connector_add(struct amdgpu_device *adev, struct amdgpu_connector_atom_dig *amdgpu_dig_connector; struct drm_encoder *encoder; struct amdgpu_encoder *amdgpu_encoder; + struct i2c_adapter *ddc = NULL; uint32_t subpixel_order = SubPixelNone; bool shared_ddc = false; bool is_dp_bridge = false; @@ -1574,17 +1575,21 @@ amdgpu_connector_add(struct amdgpu_device *adev, amdgpu_connector->con_priv = amdgpu_dig_connector; if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); - if (amdgpu_connector->ddc_bus) + if (amdgpu_connector->ddc_bus) { has_aux = true; - else + ddc = &amdgpu_connector->ddc_bus->adapter; + } else { DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } } switch (connector_type) { case DRM_MODE_CONNECTOR_VGA: case DRM_MODE_CONNECTOR_DVIA: default: - drm_connector_init(dev, &amdgpu_connector->base, - &amdgpu_connector_dp_funcs, connector_type); + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_dp_funcs, + connector_type, + ddc); drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs); connector->interlace_allowed = true; @@ -1602,8 +1607,10 @@ amdgpu_connector_add(struct amdgpu_device *adev, case DRM_MODE_CONNECTOR_HDMIA: case DRM_MODE_CONNECTOR_HDMIB: case DRM_MODE_CONNECTOR_DisplayPort: - drm_connector_init(dev, &amdgpu_connector->base, - &amdgpu_connector_dp_funcs, connector_type); + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_dp_funcs, + connector_type, + ddc); drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs); drm_object_attach_property(&amdgpu_connector->base.base, @@ -1644,8 +1651,10 @@ amdgpu_connector_add(struct amdgpu_device *adev, break; case DRM_MODE_CONNECTOR_LVDS: case DRM_MODE_CONNECTOR_eDP: - drm_connector_init(dev, &amdgpu_connector->base, - &amdgpu_connector_edp_funcs, connector_type); + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_edp_funcs, + connector_type, + ddc); drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs); drm_object_attach_property(&amdgpu_connector->base.base, @@ -1659,13 +1668,18 @@ amdgpu_connector_add(struct amdgpu_device *adev, } else { switch (connector_type) { case DRM_MODE_CONNECTOR_VGA: - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_vga_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs); if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); if (!amdgpu_connector->ddc_bus) DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + else + ddc = &amdgpu_connector->ddc_bus->adapter; } + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_vga_funcs, + connector_type, + ddc); + drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs); amdgpu_connector->dac_load_detect = true; drm_object_attach_property(&amdgpu_connector->base.base, adev->mode_info.load_detect_property, @@ -1679,13 +1693,18 @@ amdgpu_connector_add(struct amdgpu_device *adev, connector->doublescan_allowed = true; break; case DRM_MODE_CONNECTOR_DVIA: - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_vga_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs); if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); if (!amdgpu_connector->ddc_bus) DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + else + ddc = &amdgpu_connector->ddc_bus->adapter; } + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_vga_funcs, + connector_type, + ddc); + drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_vga_helper_funcs); amdgpu_connector->dac_load_detect = true; drm_object_attach_property(&amdgpu_connector->base.base, adev->mode_info.load_detect_property, @@ -1704,13 +1723,18 @@ amdgpu_connector_add(struct amdgpu_device *adev, if (!amdgpu_dig_connector) goto failed; amdgpu_connector->con_priv = amdgpu_dig_connector; - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dvi_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs); if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); if (!amdgpu_connector->ddc_bus) DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + else + ddc = &amdgpu_connector->ddc_bus->adapter; } + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_dvi_funcs, + connector_type, + ddc); + drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs); subpixel_order = SubPixelHorizontalRGB; drm_object_attach_property(&amdgpu_connector->base.base, adev->mode_info.coherent_mode_property, @@ -1754,13 +1778,18 @@ amdgpu_connector_add(struct amdgpu_device *adev, if (!amdgpu_dig_connector) goto failed; amdgpu_connector->con_priv = amdgpu_dig_connector; - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dvi_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs); if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); if (!amdgpu_connector->ddc_bus) DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + else + ddc = &amdgpu_connector->ddc_bus->adapter; } + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_dvi_funcs, + connector_type, + ddc); + drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dvi_helper_funcs); drm_object_attach_property(&amdgpu_connector->base.base, adev->mode_info.coherent_mode_property, 1); @@ -1796,15 +1825,20 @@ amdgpu_connector_add(struct amdgpu_device *adev, if (!amdgpu_dig_connector) goto failed; amdgpu_connector->con_priv = amdgpu_dig_connector; - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_dp_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs); if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); - if (amdgpu_connector->ddc_bus) + if (amdgpu_connector->ddc_bus) { has_aux = true; - else + ddc = &amdgpu_connector->ddc_bus->adapter; + } else { DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } } + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_dp_funcs, + connector_type, + ddc); + drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs); subpixel_order = SubPixelHorizontalRGB; drm_object_attach_property(&amdgpu_connector->base.base, adev->mode_info.coherent_mode_property, @@ -1838,15 +1872,20 @@ amdgpu_connector_add(struct amdgpu_device *adev, if (!amdgpu_dig_connector) goto failed; amdgpu_connector->con_priv = amdgpu_dig_connector; - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_edp_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs); if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); - if (amdgpu_connector->ddc_bus) + if (amdgpu_connector->ddc_bus) { has_aux = true; - else + ddc = &amdgpu_connector->ddc_bus->adapter; + } else { DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + } } + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_edp_funcs, + connector_type, + ddc); + drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_dp_helper_funcs); drm_object_attach_property(&amdgpu_connector->base.base, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); @@ -1859,13 +1898,18 @@ amdgpu_connector_add(struct amdgpu_device *adev, if (!amdgpu_dig_connector) goto failed; amdgpu_connector->con_priv = amdgpu_dig_connector; - drm_connector_init(dev, &amdgpu_connector->base, &amdgpu_connector_lvds_funcs, connector_type); - drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_lvds_helper_funcs); if (i2c_bus->valid) { amdgpu_connector->ddc_bus = amdgpu_i2c_lookup(adev, i2c_bus); if (!amdgpu_connector->ddc_bus) DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n"); + else + ddc = &amdgpu_connector->ddc_bus->adapter; } + drm_connector_init_with_ddc(dev, &amdgpu_connector->base, + &amdgpu_connector_lvds_funcs, + connector_type, + ddc); + drm_connector_helper_add(&amdgpu_connector->base, &amdgpu_connector_lvds_helper_funcs); drm_object_attach_property(&amdgpu_connector->base.base, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 4e4094f842e7..9ccf32c5456a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -402,7 +402,7 @@ static int amdgpu_cs_bo_validate(struct amdgpu_cs_parser *p, struct ttm_operation_ctx ctx = { .interruptible = true, .no_wait_gpu = false, - .resv = bo->tbo.resv, + .resv = bo->tbo.base.resv, .flags = 0 }; uint32_t domain; @@ -730,7 +730,7 @@ static int amdgpu_cs_sync_rings(struct amdgpu_cs_parser *p) list_for_each_entry(e, &p->validated, tv.head) { struct amdgpu_bo *bo = ttm_to_amdgpu_bo(e->tv.bo); - struct reservation_object *resv = bo->tbo.resv; + struct reservation_object *resv = bo->tbo.base.resv; r = amdgpu_sync_resv(p->adev, &p->job->sync, resv, p->filp, amdgpu_bo_explicit_sync(bo)); @@ -1727,7 +1727,7 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser, *map = mapping; /* Double check that the BO is reserved by this CS */ - if (READ_ONCE((*bo)->tbo.resv->lock.ctx) != &parser->ticket) + if (reservation_object_locking_ctx((*bo)->tbo.base.resv) != &parser->ticket) return -EINVAL; if (!((*bo)->flags & AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c index 535650967b1a..b5d020e15c35 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_display.c @@ -204,7 +204,7 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc, goto unpin; } - r = reservation_object_get_fences_rcu(new_abo->tbo.resv, &work->excl, + r = reservation_object_get_fences_rcu(new_abo->tbo.base.resv, &work->excl, &work->shared_count, &work->shared); if (unlikely(r != 0)) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c index 489041df1f45..b88e27da7c28 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.c @@ -216,7 +216,7 @@ static int amdgpu_dma_buf_map_attach(struct dma_buf *dma_buf, * fences on the reservation object into a single exclusive * fence. */ - r = __reservation_object_make_exclusive(bo->tbo.resv); + r = __reservation_object_make_exclusive(bo->tbo.base.resv); if (r) goto error_unreserve; } @@ -268,20 +268,6 @@ error: } /** - * amdgpu_gem_prime_res_obj - &drm_driver.gem_prime_res_obj implementation - * @obj: GEM BO - * - * Returns: - * The BO's reservation object. - */ -struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *obj) -{ - struct amdgpu_bo *bo = gem_to_amdgpu_bo(obj); - - return bo->tbo.resv; -} - -/** * amdgpu_dma_buf_begin_cpu_access - &dma_buf_ops.begin_cpu_access implementation * @dma_buf: Shared DMA buffer * @direction: Direction of DMA transfer @@ -339,14 +325,12 @@ const struct dma_buf_ops amdgpu_dmabuf_ops = { * @gobj: GEM BO * @flags: Flags such as DRM_CLOEXEC and DRM_RDWR. * - * The main work is done by the &drm_gem_prime_export helper, which in turn - * uses &amdgpu_gem_prime_res_obj. + * The main work is done by the &drm_gem_prime_export helper. * * Returns: * Shared DMA buffer representing the GEM BO from the given device. */ -struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *gobj, +struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj, int flags) { struct amdgpu_bo *bo = gem_to_amdgpu_bo(gobj); @@ -356,9 +340,9 @@ struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev, bo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID) return ERR_PTR(-EPERM); - buf = drm_gem_prime_export(dev, gobj, flags); + buf = drm_gem_prime_export(gobj, flags); if (!IS_ERR(buf)) { - buf->file->f_mapping = dev->anon_inode->i_mapping; + buf->file->f_mapping = gobj->dev->anon_inode->i_mapping; buf->ops = &amdgpu_dmabuf_ops; } @@ -396,7 +380,7 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, bp.flags = 0; bp.type = ttm_bo_type_sg; bp.resv = resv; - ww_mutex_lock(&resv->lock, NULL); + reservation_object_lock(resv, NULL); ret = amdgpu_bo_create(adev, &bp, &bo); if (ret) goto error; @@ -408,11 +392,11 @@ amdgpu_gem_prime_import_sg_table(struct drm_device *dev, if (attach->dmabuf->ops != &amdgpu_dmabuf_ops) bo->prime_shared_count = 1; - ww_mutex_unlock(&resv->lock); - return &bo->gem_base; + reservation_object_unlock(resv); + return &bo->tbo.base; error: - ww_mutex_unlock(&resv->lock); + reservation_object_unlock(resv); return ERR_PTR(ret); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h index c7056cbe8685..5012e6ab58f1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dma_buf.h @@ -30,12 +30,10 @@ struct drm_gem_object * amdgpu_gem_prime_import_sg_table(struct drm_device *dev, struct dma_buf_attachment *attach, struct sg_table *sg); -struct dma_buf *amdgpu_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *gobj, +struct dma_buf *amdgpu_gem_prime_export(struct drm_gem_object *gobj, int flags); struct drm_gem_object *amdgpu_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); -struct reservation_object *amdgpu_gem_prime_res_obj(struct drm_gem_object *); void *amdgpu_gem_prime_vmap(struct drm_gem_object *obj); void amdgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); int amdgpu_gem_prime_mmap(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 5376328d3fd0..6d24b422e0ff 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -1373,7 +1373,7 @@ static struct drm_driver kms_driver = { .driver_features = DRIVER_USE_AGP | DRIVER_ATOMIC | DRIVER_GEM | - DRIVER_PRIME | DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ, + DRIVER_RENDER | DRIVER_MODESET | DRIVER_SYNCOBJ, .load = amdgpu_driver_load_kms, .open = amdgpu_driver_open_kms, .postclose = amdgpu_driver_postclose_kms, @@ -1397,7 +1397,6 @@ static struct drm_driver kms_driver = { .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = amdgpu_gem_prime_export, .gem_prime_import = amdgpu_gem_prime_import, - .gem_prime_res_obj = amdgpu_gem_prime_res_obj, .gem_prime_get_sg_table = amdgpu_gem_prime_get_sg_table, .gem_prime_import_sg_table = amdgpu_gem_prime_import_sg_table, .gem_prime_vmap = amdgpu_gem_prime_vmap, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index 939f8305511b..bff9173a1a94 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -85,7 +85,7 @@ retry: } return r; } - *obj = &bo->gem_base; + *obj = &bo->tbo.base; return 0; } @@ -134,7 +134,7 @@ int amdgpu_gem_object_open(struct drm_gem_object *obj, return -EPERM; if (abo->flags & AMDGPU_GEM_CREATE_VM_ALWAYS_VALID && - abo->tbo.resv != vm->root.base.bo->tbo.resv) + abo->tbo.base.resv != vm->root.base.bo->tbo.base.resv) return -EPERM; r = amdgpu_bo_reserve(abo, false); @@ -252,7 +252,7 @@ int amdgpu_gem_create_ioctl(struct drm_device *dev, void *data, if (r) return r; - resv = vm->root.base.bo->tbo.resv; + resv = vm->root.base.bo->tbo.base.resv; } r = amdgpu_gem_object_create(adev, size, args->in.alignment, @@ -433,7 +433,7 @@ int amdgpu_gem_wait_idle_ioctl(struct drm_device *dev, void *data, return -ENOENT; } robj = gem_to_amdgpu_bo(gobj); - ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, + ret = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, timeout); /* ret == 0 means not signaled, @@ -689,7 +689,7 @@ int amdgpu_gem_op_ioctl(struct drm_device *dev, void *data, struct drm_amdgpu_gem_create_in info; void __user *out = u64_to_user_ptr(args->value); - info.bo_size = robj->gem_base.size; + info.bo_size = robj->tbo.base.size; info.alignment = robj->tbo.mem.page_alignment << PAGE_SHIFT; info.domains = robj->preferred_domains; info.domain_flags = robj->flags; @@ -819,8 +819,8 @@ static int amdgpu_debugfs_gem_bo_info(int id, void *ptr, void *data) if (pin_count) seq_printf(m, " pin count %d", pin_count); - dma_buf = READ_ONCE(bo->gem_base.dma_buf); - attachment = READ_ONCE(bo->gem_base.import_attach); + dma_buf = READ_ONCE(bo->tbo.base.dma_buf); + attachment = READ_ONCE(bo->tbo.base.import_attach); if (attachment) seq_printf(m, " imported from %p", dma_buf); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h index b8ba6e27c61f..2f17150e26e1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.h @@ -31,7 +31,7 @@ */ #define AMDGPU_GEM_DOMAIN_MAX 0x3 -#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, gem_base) +#define gem_to_amdgpu_bo(gobj) container_of((gobj), struct amdgpu_bo, tbo.base) void amdgpu_gem_object_free(struct drm_gem_object *obj); int amdgpu_gem_object_open(struct drm_gem_object *obj, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 0cf7e8606fd3..252f71e90953 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -1088,7 +1088,7 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev, amdgpu_vm_fini(adev, &fpriv->vm); if (pasid) - amdgpu_pasid_free_delayed(pd->tbo.resv, pasid); + amdgpu_pasid_free_delayed(pd->tbo.base.resv, pasid); amdgpu_bo_unref(&pd); idr_for_each_entry(&fpriv->bo_list_handles, list, handle) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c index 3971c201f320..50022acc8a81 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mn.c @@ -179,7 +179,7 @@ static void amdgpu_mn_invalidate_node(struct amdgpu_mn_node *node, if (!amdgpu_ttm_tt_affect_userptr(bo->tbo.ttm, start, end)) continue; - r = reservation_object_wait_timeout_rcu(bo->tbo.resv, + r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, true, false, MAX_SCHEDULE_TIMEOUT); if (r <= 0) DRM_ERROR("(%ld) failed to wait for user bo\n", r); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c index bea6f298dfdc..8ae44d383a13 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.c @@ -85,9 +85,9 @@ static void amdgpu_bo_destroy(struct ttm_buffer_object *tbo) amdgpu_bo_kunmap(bo); - if (bo->gem_base.import_attach) - drm_prime_gem_destroy(&bo->gem_base, bo->tbo.sg); - drm_gem_object_release(&bo->gem_base); + if (bo->tbo.base.import_attach) + drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg); + drm_gem_object_release(&bo->tbo.base); /* in case amdgpu_device_recover_vram got NULL of bo->parent */ if (!list_empty(&bo->shadow_list)) { mutex_lock(&adev->shadow_list_lock); @@ -454,7 +454,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, bo = kzalloc(sizeof(struct amdgpu_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; - drm_gem_private_object_init(adev->ddev, &bo->gem_base, size); + drm_gem_private_object_init(adev->ddev, &bo->tbo.base, size); INIT_LIST_HEAD(&bo->shadow_list); bo->vm_bo = NULL; bo->preferred_domains = bp->preferred_domain ? bp->preferred_domain : @@ -521,7 +521,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, bo->tbo.mem.placement & TTM_PL_FLAG_VRAM) { struct dma_fence *fence; - r = amdgpu_fill_buffer(bo, 0, bo->tbo.resv, &fence); + r = amdgpu_fill_buffer(bo, 0, bo->tbo.base.resv, &fence); if (unlikely(r)) goto fail_unreserve; @@ -544,7 +544,7 @@ static int amdgpu_bo_do_create(struct amdgpu_device *adev, fail_unreserve: if (!bp->resv) - ww_mutex_unlock(&bo->tbo.resv->lock); + reservation_object_unlock(bo->tbo.base.resv); amdgpu_bo_unref(&bo); return r; } @@ -565,7 +565,7 @@ static int amdgpu_bo_create_shadow(struct amdgpu_device *adev, bp.flags = AMDGPU_GEM_CREATE_CPU_GTT_USWC | AMDGPU_GEM_CREATE_SHADOW; bp.type = ttm_bo_type_kernel; - bp.resv = bo->tbo.resv; + bp.resv = bo->tbo.base.resv; r = amdgpu_bo_do_create(adev, &bp, &bo->shadow); if (!r) { @@ -606,13 +606,13 @@ int amdgpu_bo_create(struct amdgpu_device *adev, if ((flags & AMDGPU_GEM_CREATE_SHADOW) && !(adev->flags & AMD_IS_APU)) { if (!bp->resv) - WARN_ON(reservation_object_lock((*bo_ptr)->tbo.resv, + WARN_ON(reservation_object_lock((*bo_ptr)->tbo.base.resv, NULL)); r = amdgpu_bo_create_shadow(adev, bp->size, *bo_ptr); if (!bp->resv) - reservation_object_unlock((*bo_ptr)->tbo.resv); + reservation_object_unlock((*bo_ptr)->tbo.base.resv); if (r) amdgpu_bo_unref(bo_ptr); @@ -709,7 +709,7 @@ int amdgpu_bo_kmap(struct amdgpu_bo *bo, void **ptr) return 0; } - r = reservation_object_wait_timeout_rcu(bo->tbo.resv, false, false, + r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, false, false, MAX_SCHEDULE_TIMEOUT); if (r < 0) return r; @@ -1087,7 +1087,7 @@ int amdgpu_bo_set_tiling_flags(struct amdgpu_bo *bo, u64 tiling_flags) */ void amdgpu_bo_get_tiling_flags(struct amdgpu_bo *bo, u64 *tiling_flags) { - lockdep_assert_held(&bo->tbo.resv->lock.base); + reservation_object_assert_held(bo->tbo.base.resv); if (tiling_flags) *tiling_flags = bo->tiling_flags; @@ -1283,7 +1283,7 @@ int amdgpu_bo_fault_reserve_notify(struct ttm_buffer_object *bo) void amdgpu_bo_fence(struct amdgpu_bo *bo, struct dma_fence *fence, bool shared) { - struct reservation_object *resv = bo->tbo.resv; + struct reservation_object *resv = bo->tbo.base.resv; if (shared) reservation_object_add_shared_fence(resv, fence); @@ -1308,7 +1308,7 @@ int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr) int r; amdgpu_sync_create(&sync); - amdgpu_sync_resv(adev, &sync, bo->tbo.resv, owner, false); + amdgpu_sync_resv(adev, &sync, bo->tbo.base.resv, owner, false); r = amdgpu_sync_wait(&sync, intr); amdgpu_sync_free(&sync); @@ -1328,7 +1328,7 @@ int amdgpu_bo_sync_wait(struct amdgpu_bo *bo, void *owner, bool intr) u64 amdgpu_bo_gpu_offset(struct amdgpu_bo *bo) { WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_SYSTEM); - WARN_ON_ONCE(!ww_mutex_is_locked(&bo->tbo.resv->lock) && + WARN_ON_ONCE(!reservation_object_is_locked(bo->tbo.base.resv) && !bo->pin_count && bo->tbo.type != ttm_bo_type_kernel); WARN_ON_ONCE(bo->tbo.mem.start == AMDGPU_BO_INVALID_OFFSET); WARN_ON_ONCE(bo->tbo.mem.mem_type == TTM_PL_VRAM && diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h index d60593cc436e..113fb2feb437 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_object.h @@ -94,7 +94,6 @@ struct amdgpu_bo { /* per VM structure for page tables and with virtual addresses */ struct amdgpu_vm_bo_base *vm_bo; /* Constant after initialization */ - struct drm_gem_object gem_base; struct amdgpu_bo *parent; struct amdgpu_bo *shadow; @@ -192,7 +191,7 @@ static inline unsigned amdgpu_bo_gpu_page_alignment(struct amdgpu_bo *bo) */ static inline u64 amdgpu_bo_mmap_offset(struct amdgpu_bo *bo) { - return drm_vma_node_offset_addr(&bo->tbo.vma_node); + return drm_vma_node_offset_addr(&bo->tbo.base.vma_node); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index e51b48ac48eb..63e7d1e01b76 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -227,7 +227,7 @@ static int amdgpu_verify_access(struct ttm_buffer_object *bo, struct file *filp) if (amdgpu_ttm_tt_get_usermm(bo->ttm)) return -EPERM; - return drm_vma_node_verify_access(&abo->gem_base.vma_node, + return drm_vma_node_verify_access(&abo->tbo.base.vma_node, filp->private_data); } @@ -440,7 +440,7 @@ static int amdgpu_move_blit(struct ttm_buffer_object *bo, r = amdgpu_ttm_copy_mem_to_mem(adev, &src, &dst, new_mem->num_pages << PAGE_SHIFT, - bo->resv, &fence); + bo->base.resv, &fence); if (r) goto error; @@ -1478,18 +1478,18 @@ static bool amdgpu_ttm_bo_eviction_valuable(struct ttm_buffer_object *bo, * cleanly handle page faults. */ if (bo->type == ttm_bo_type_kernel && - !reservation_object_test_signaled_rcu(bo->resv, true)) + !reservation_object_test_signaled_rcu(bo->base.resv, true)) return false; /* If bo is a KFD BO, check if the bo belongs to the current process. * If true, then return false as any KFD process needs all its BOs to * be resident to run successfully */ - flist = reservation_object_get_list(bo->resv); + flist = reservation_object_get_list(bo->base.resv); if (flist) { for (i = 0; i < flist->shared_count; ++i) { f = rcu_dereference_protected(flist->shared[i], - reservation_object_held(bo->resv)); + reservation_object_held(bo->base.resv)); if (amdkfd_fence_check_mm(f, current->mm)) return false; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c index 5b2fea3b4a2c..f858607b17a5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c @@ -1073,7 +1073,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, ib->length_dw = 16; if (direct) { - r = reservation_object_wait_timeout_rcu(bo->tbo.resv, + r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, true, false, msecs_to_jiffies(10)); if (r == 0) @@ -1085,7 +1085,7 @@ static int amdgpu_uvd_send_msg(struct amdgpu_ring *ring, struct amdgpu_bo *bo, if (r) goto err_free; } else { - r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.resv, + r = amdgpu_sync_resv(adev, &job->sync, bo->tbo.base.resv, AMDGPU_FENCE_OWNER_UNDEFINED, false); if (r) goto err_free; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 24c3c05e2fb7..95eef0ac2829 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -302,7 +302,7 @@ static void amdgpu_vm_bo_base_init(struct amdgpu_vm_bo_base *base, base->next = bo->vm_bo; bo->vm_bo = base; - if (bo->tbo.resv != vm->root.base.bo->tbo.resv) + if (bo->tbo.base.resv != vm->root.base.bo->tbo.base.resv) return; vm->bulk_moveable = false; @@ -583,7 +583,7 @@ void amdgpu_vm_del_from_lru_notify(struct ttm_buffer_object *bo) for (bo_base = abo->vm_bo; bo_base; bo_base = bo_base->next) { struct amdgpu_vm *vm = bo_base->vm; - if (abo->tbo.resv == vm->root.base.bo->tbo.resv) + if (abo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) vm->bulk_moveable = false; } @@ -834,7 +834,7 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm, bp->flags |= AMDGPU_GEM_CREATE_SHADOW; bp->type = ttm_bo_type_kernel; if (vm->root.base.bo) - bp->resv = vm->root.base.bo->tbo.resv; + bp->resv = vm->root.base.bo->tbo.base.resv; } /** @@ -1702,7 +1702,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, ttm = container_of(bo->tbo.ttm, struct ttm_dma_tt, ttm); pages_addr = ttm->dma_address; } - exclusive = reservation_object_get_excl(bo->tbo.resv); + exclusive = reservation_object_get_excl(bo->tbo.base.resv); } if (bo) { @@ -1712,7 +1712,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, flags = 0x0; } - if (clear || (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv)) + if (clear || (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv)) last_update = &vm->last_update; else last_update = &bo_va->last_pt_update; @@ -1743,7 +1743,7 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, * the evicted list so that it gets validated again on the * next command submission. */ - if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv) { + if (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) { uint32_t mem_type = bo->tbo.mem.mem_type; if (!(bo->preferred_domains & amdgpu_mem_type_to_domain(mem_type))) @@ -1879,7 +1879,7 @@ static void amdgpu_vm_free_mapping(struct amdgpu_device *adev, */ static void amdgpu_vm_prt_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) { - struct reservation_object *resv = vm->root.base.bo->tbo.resv; + struct reservation_object *resv = vm->root.base.bo->tbo.base.resv; struct dma_fence *excl, **shared; unsigned i, shared_count; int r; @@ -1993,7 +1993,7 @@ int amdgpu_vm_handle_moved(struct amdgpu_device *adev, while (!list_empty(&vm->invalidated)) { bo_va = list_first_entry(&vm->invalidated, struct amdgpu_bo_va, base.vm_status); - resv = bo_va->base.bo->tbo.resv; + resv = bo_va->base.bo->tbo.base.resv; spin_unlock(&vm->invalidated_lock); /* Try to reserve the BO to avoid clearing its ptes */ @@ -2084,7 +2084,7 @@ static void amdgpu_vm_bo_insert_map(struct amdgpu_device *adev, if (mapping->flags & AMDGPU_PTE_PRT) amdgpu_vm_prt_get(adev); - if (bo && bo->tbo.resv == vm->root.base.bo->tbo.resv && + if (bo && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv && !bo_va->base.moved) { list_move(&bo_va->base.vm_status, &vm->moved); } @@ -2416,7 +2416,8 @@ void amdgpu_vm_bo_trace_cs(struct amdgpu_vm *vm, struct ww_acquire_ctx *ticket) struct amdgpu_bo *bo; bo = mapping->bo_va->base.bo; - if (READ_ONCE(bo->tbo.resv->lock.ctx) != ticket) + if (reservation_object_locking_ctx(bo->tbo.base.resv) != + ticket) continue; } @@ -2443,7 +2444,7 @@ void amdgpu_vm_bo_rmv(struct amdgpu_device *adev, struct amdgpu_vm_bo_base **base; if (bo) { - if (bo->tbo.resv == vm->root.base.bo->tbo.resv) + if (bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) vm->bulk_moveable = false; for (base = &bo_va->base.bo->vm_bo; *base; @@ -2507,7 +2508,7 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, for (bo_base = bo->vm_bo; bo_base; bo_base = bo_base->next) { struct amdgpu_vm *vm = bo_base->vm; - if (evicted && bo->tbo.resv == vm->root.base.bo->tbo.resv) { + if (evicted && bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) { amdgpu_vm_bo_evicted(bo_base); continue; } @@ -2518,7 +2519,7 @@ void amdgpu_vm_bo_invalidate(struct amdgpu_device *adev, if (bo->tbo.type == ttm_bo_type_kernel) amdgpu_vm_bo_relocated(bo_base); - else if (bo->tbo.resv == vm->root.base.bo->tbo.resv) + else if (bo->tbo.base.resv == vm->root.base.bo->tbo.base.resv) amdgpu_vm_bo_moved(bo_base); else amdgpu_vm_bo_invalidated(bo_base); @@ -2648,7 +2649,7 @@ void amdgpu_vm_adjust_size(struct amdgpu_device *adev, uint32_t min_vm_size, */ long amdgpu_vm_wait_idle(struct amdgpu_vm *vm, long timeout) { - return reservation_object_wait_timeout_rcu(vm->root.base.bo->tbo.resv, + return reservation_object_wait_timeout_rcu(vm->root.base.bo->tbo.base.resv, true, true, timeout); } @@ -2723,7 +2724,7 @@ int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm, if (r) goto error_free_root; - r = reservation_object_reserve_shared(root->tbo.resv, 1); + r = reservation_object_reserve_shared(root->tbo.base.resv, 1); if (r) goto error_unreserve; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c index ddd181f5ed37..61fc584cbb1a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c @@ -72,7 +72,7 @@ static int amdgpu_vm_sdma_prepare(struct amdgpu_vm_update_params *p, if (r) return r; - r = amdgpu_sync_resv(p->adev, &p->job->sync, root->tbo.resv, + r = amdgpu_sync_resv(p->adev, &p->job->sync, root->tbo.base.resv, owner, false); if (r) return r; diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c index 4a29f72334d0..381a5345f195 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c @@ -5693,7 +5693,7 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state, * deadlock during GPU reset when this fence will not signal * but we hold reservation lock for the BO. */ - r = reservation_object_wait_timeout_rcu(abo->tbo.resv, true, + r = reservation_object_wait_timeout_rcu(abo->tbo.base.resv, true, false, msecs_to_jiffies(5000)); if (unlikely(r <= 0)) diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c index 6e205ee36ac3..16218a202b59 100644 --- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c +++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_mst_types.c @@ -156,6 +156,26 @@ dm_dp_mst_connector_destroy(struct drm_connector *connector) kfree(amdgpu_dm_connector); } +static int +amdgpu_dm_mst_connector_late_register(struct drm_connector *connector) +{ + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + struct drm_dp_mst_port *port = amdgpu_dm_connector->port; + + return drm_dp_mst_connector_late_register(connector, port); +} + +static void +amdgpu_dm_mst_connector_early_unregister(struct drm_connector *connector) +{ + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + struct drm_dp_mst_port *port = amdgpu_dm_connector->port; + + drm_dp_mst_connector_early_unregister(connector, port); +} + static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .detect = dm_dp_mst_detect, .fill_modes = drm_helper_probe_single_connector_modes, @@ -164,7 +184,9 @@ static const struct drm_connector_funcs dm_dp_mst_connector_funcs = { .atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state, .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, .atomic_set_property = amdgpu_dm_connector_atomic_set_property, - .atomic_get_property = amdgpu_dm_connector_atomic_get_property + .atomic_get_property = amdgpu_dm_connector_atomic_get_property, + .late_register = amdgpu_dm_mst_connector_late_register, + .early_unregister = amdgpu_dm_mst_connector_early_unregister, }; static int dm_dp_mst_get_modes(struct drm_connector *connector) @@ -388,7 +410,7 @@ void amdgpu_dm_initialize_dp_connector(struct amdgpu_display_manager *dm, struct amdgpu_dm_connector *aconnector) { aconnector->dm_dp_aux.aux.name = "dmdc"; - aconnector->dm_dp_aux.aux.dev = dm->adev->dev; + aconnector->dm_dp_aux.aux.dev = aconnector->base.kdev; aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer; aconnector->dm_dp_aux.ddc_service = aconnector->dc_link->ddc; diff --git a/drivers/gpu/drm/arc/arcpgu_drv.c b/drivers/gpu/drm/arc/arcpgu_drv.c index af60c6d7a5f4..6b7f791685ec 100644 --- a/drivers/gpu/drm/arc/arcpgu_drv.c +++ b/drivers/gpu/drm/arc/arcpgu_drv.c @@ -135,8 +135,7 @@ static int arcpgu_debugfs_init(struct drm_minor *minor) #endif static struct drm_driver arcpgu_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .name = "arcpgu", .desc = "ARC PGU Controller", .date = "20160219", @@ -150,8 +149,6 @@ static struct drm_driver arcpgu_drm_driver = { .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_print_info = drm_gem_cma_print_info, .gem_vm_ops = &drm_gem_cma_vm_ops, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c index 4073a452e24a..55a8cc94808a 100644 --- a/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c +++ b/drivers/gpu/drm/arm/display/komeda/d71/d71_component.c @@ -4,8 +4,6 @@ * Author: James.Qian.Wang <james.qian.wang@arm.com> * */ - -#include <drm/drm_print.h> #include "d71_dev.h" #include "komeda_kms.h" #include "malidp_io.h" @@ -804,7 +802,7 @@ static int d71_downscaling_clk_check(struct komeda_pipeline *pipe, denominator = (mode->htotal - 1) * v_out - 2 * v_in; } - return aclk_rate * denominator >= mode->clock * 1000 * fraction ? + return aclk_rate * denominator >= mode->crtc_clock * 1000 * fraction ? 0 : -EINVAL; } @@ -1032,21 +1030,31 @@ static void d71_timing_ctrlr_update(struct komeda_component *c, struct komeda_component_state *state) { struct drm_crtc_state *crtc_st = state->crtc->state; + struct drm_display_mode *mode = &crtc_st->adjusted_mode; u32 __iomem *reg = c->reg; - struct videomode vm; + u32 hactive, hfront_porch, hback_porch, hsync_len; + u32 vactive, vfront_porch, vback_porch, vsync_len; u32 value; - drm_display_mode_to_videomode(&crtc_st->adjusted_mode, &vm); - - malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(vm.hactive, vm.vactive)); - malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(vm.hfront_porch, - vm.hback_porch)); - malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vm.vfront_porch, - vm.vback_porch)); - - value = BS_SYNC_VSW(vm.vsync_len) | BS_SYNC_HSW(vm.hsync_len); - value |= vm.flags & DISPLAY_FLAGS_VSYNC_HIGH ? BS_SYNC_VSP : 0; - value |= vm.flags & DISPLAY_FLAGS_HSYNC_HIGH ? BS_SYNC_HSP : 0; + hactive = mode->crtc_hdisplay; + hfront_porch = mode->crtc_hsync_start - mode->crtc_hdisplay; + hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; + hback_porch = mode->crtc_htotal - mode->crtc_hsync_end; + + vactive = mode->crtc_vdisplay; + vfront_porch = mode->crtc_vsync_start - mode->crtc_vdisplay; + vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; + vback_porch = mode->crtc_vtotal - mode->crtc_vsync_end; + + malidp_write32(reg, BS_ACTIVESIZE, HV_SIZE(hactive, vactive)); + malidp_write32(reg, BS_HINTERVALS, BS_H_INTVALS(hfront_porch, + hback_porch)); + malidp_write32(reg, BS_VINTERVALS, BS_V_INTVALS(vfront_porch, + vback_porch)); + + value = BS_SYNC_VSW(vsync_len) | BS_SYNC_HSW(hsync_len); + value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BS_SYNC_VSP : 0; + value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BS_SYNC_HSP : 0; malidp_write32(reg, BS_SYNC, value); malidp_write32(reg, BS_PROG_LINE, D71_DEFAULT_PREPRETCH_LINE - 1); @@ -1054,6 +1062,10 @@ static void d71_timing_ctrlr_update(struct komeda_component *c, /* configure bs control register */ value = BS_CTRL_EN | BS_CTRL_VM; + if (c->pipeline->dual_link) { + malidp_write32(reg, BS_DRIFT_TO, hfront_porch + 16); + value |= BS_CTRL_DL; + } malidp_write32(reg, BLK_CONTROL, value); } diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c index f4400788ab94..fa9a4593bb37 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_crtc.c @@ -27,8 +27,8 @@ static void komeda_crtc_update_clock_ratio(struct komeda_crtc_state *kcrtc_st) return; } - pxlclk = kcrtc_st->base.adjusted_mode.clock * 1000; - aclk = komeda_calc_aclk(kcrtc_st); + pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000; + aclk = komeda_crtc_get_aclk(kcrtc_st); kcrtc_st->clock_ratio = div64_u64(aclk << 32, pxlclk); } @@ -74,14 +74,6 @@ komeda_crtc_atomic_check(struct drm_crtc *crtc, return 0; } -unsigned long komeda_calc_aclk(struct komeda_crtc_state *kcrtc_st) -{ - struct komeda_dev *mdev = kcrtc_st->base.crtc->dev->dev_private; - unsigned long pxlclk = kcrtc_st->base.adjusted_mode.clock; - - return clk_round_rate(mdev->aclk, pxlclk * 1000); -} - /* For active a crtc, mainly need two parts of preparation * 1. adjust display operation mode. * 2. enable needed clk @@ -92,7 +84,7 @@ komeda_crtc_prepare(struct komeda_crtc *kcrtc) struct komeda_dev *mdev = kcrtc->base.dev->dev_private; struct komeda_pipeline *master = kcrtc->master; struct komeda_crtc_state *kcrtc_st = to_kcrtc_st(kcrtc->base.state); - unsigned long pxlclk_rate = kcrtc_st->base.adjusted_mode.clock * 1000; + struct drm_display_mode *mode = &kcrtc_st->base.adjusted_mode; u32 new_mode; int err; @@ -118,7 +110,7 @@ komeda_crtc_prepare(struct komeda_crtc *kcrtc) * to enable it again. */ if (new_mode != KOMEDA_MODE_DUAL_DISP) { - err = clk_set_rate(mdev->aclk, komeda_calc_aclk(kcrtc_st)); + err = clk_set_rate(mdev->aclk, komeda_crtc_get_aclk(kcrtc_st)); if (err) DRM_ERROR("failed to set aclk.\n"); err = clk_prepare_enable(mdev->aclk); @@ -126,7 +118,7 @@ komeda_crtc_prepare(struct komeda_crtc *kcrtc) DRM_ERROR("failed to enable aclk.\n"); } - err = clk_set_rate(master->pxlclk, pxlclk_rate); + err = clk_set_rate(master->pxlclk, mode->crtc_clock * 1000); if (err) DRM_ERROR("failed to set pxlclk for pipe%d\n", master->id); err = clk_prepare_enable(master->pxlclk); @@ -342,29 +334,58 @@ komeda_crtc_atomic_flush(struct drm_crtc *crtc, komeda_crtc_do_flush(crtc, old); } +/* Returns the minimum frequency of the aclk rate (main engine clock) in Hz */ +static unsigned long +komeda_calc_min_aclk_rate(struct komeda_crtc *kcrtc, + unsigned long pxlclk) +{ + /* Once dual-link one display pipeline drives two display outputs, + * the aclk needs run on the double rate of pxlclk + */ + if (kcrtc->master->dual_link) + return pxlclk * 2; + else + return pxlclk; +} + +/* Get current aclk rate that specified by state */ +unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st) +{ + struct drm_crtc *crtc = kcrtc_st->base.crtc; + struct komeda_dev *mdev = crtc->dev->dev_private; + unsigned long pxlclk = kcrtc_st->base.adjusted_mode.crtc_clock * 1000; + unsigned long min_aclk; + + min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), pxlclk); + + return clk_round_rate(mdev->aclk, min_aclk); +} + static enum drm_mode_status komeda_crtc_mode_valid(struct drm_crtc *crtc, const struct drm_display_mode *m) { struct komeda_dev *mdev = crtc->dev->dev_private; struct komeda_crtc *kcrtc = to_kcrtc(crtc); struct komeda_pipeline *master = kcrtc->master; - long mode_clk, pxlclk; + unsigned long min_pxlclk, min_aclk; if (m->flags & DRM_MODE_FLAG_INTERLACE) return MODE_NO_INTERLACE; - mode_clk = m->clock * 1000; - pxlclk = clk_round_rate(master->pxlclk, mode_clk); - if (pxlclk != mode_clk) { - DRM_DEBUG_ATOMIC("pxlclk doesn't support %ld Hz\n", mode_clk); + min_pxlclk = m->clock * 1000; + if (master->dual_link) + min_pxlclk /= 2; + + if (min_pxlclk != clk_round_rate(master->pxlclk, min_pxlclk)) { + DRM_DEBUG_ATOMIC("pxlclk doesn't support %lu Hz\n", min_pxlclk); return MODE_NOCLOCK; } - /* main engine clock must be faster than pxlclk*/ - if (clk_round_rate(mdev->aclk, mode_clk) < pxlclk) { - DRM_DEBUG_ATOMIC("engine clk can't satisfy the requirement of %s-clk: %ld.\n", - m->name, pxlclk); + min_aclk = komeda_calc_min_aclk_rate(to_kcrtc(crtc), min_pxlclk); + if (clk_round_rate(mdev->aclk, min_aclk) < min_aclk) { + DRM_DEBUG_ATOMIC("engine clk can't satisfy the requirement of %s-clk: %lu.\n", + m->name, min_pxlclk); return MODE_CLOCK_HIGH; } @@ -377,10 +398,22 @@ static bool komeda_crtc_mode_fixup(struct drm_crtc *crtc, struct drm_display_mode *adjusted_mode) { struct komeda_crtc *kcrtc = to_kcrtc(crtc); - struct komeda_pipeline *master = kcrtc->master; - long mode_clk = m->clock * 1000; + unsigned long clk_rate; + + drm_mode_set_crtcinfo(adjusted_mode, 0); + /* In dual link half the horizontal settings */ + if (kcrtc->master->dual_link) { + adjusted_mode->crtc_clock /= 2; + adjusted_mode->crtc_hdisplay /= 2; + adjusted_mode->crtc_hsync_start /= 2; + adjusted_mode->crtc_hsync_end /= 2; + adjusted_mode->crtc_htotal /= 2; + } - adjusted_mode->clock = clk_round_rate(master->pxlclk, mode_clk) / 1000; + clk_rate = adjusted_mode->crtc_clock * 1000; + /* crtc_clock will be used as the komeda output pixel clock */ + adjusted_mode->crtc_clock = clk_round_rate(kcrtc->master->pxlclk, + clk_rate) / 1000; return true; } @@ -488,10 +521,8 @@ int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms, else sprintf(str, "None"); - DRM_INFO("crtc%d: master(pipe-%d) slave(%s) output: %s.\n", - kms->n_crtcs, master->id, str, - master->of_output_dev ? - master->of_output_dev->full_name : "None"); + DRM_INFO("CRTC-%d: master(pipe-%d) slave(%s).\n", + kms->n_crtcs, master->id, str); kms->n_crtcs++; } diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c index 5a118984de33..1ff7f4b2c620 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_dev.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_dev.c @@ -121,11 +121,14 @@ static int komeda_parse_pipe_dt(struct komeda_dev *mdev, struct device_node *np) pipe->pxlclk = clk; /* enum ports */ - pipe->of_output_dev = + pipe->of_output_links[0] = of_graph_get_remote_node(np, KOMEDA_OF_PORT_OUTPUT, 0); + pipe->of_output_links[1] = + of_graph_get_remote_node(np, KOMEDA_OF_PORT_OUTPUT, 1); pipe->of_output_port = of_graph_get_port_by_id(np, KOMEDA_OF_PORT_OUTPUT); + pipe->dual_link = pipe->of_output_links[0] && pipe->of_output_links[1]; pipe->of_node = np; return 0; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c index cfa5068d9d1e..69ace6f9055d 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c @@ -83,11 +83,12 @@ static int compare_of(struct device *dev, void *data) static void komeda_add_slave(struct device *master, struct component_match **match, - struct device_node *np, int port) + struct device_node *np, + u32 port, u32 endpoint) { struct device_node *remote; - remote = of_graph_get_remote_node(np, port, 0); + remote = of_graph_get_remote_node(np, port, endpoint); if (remote) { drm_of_component_match_add(master, match, compare_of, remote); of_node_put(remote); @@ -108,7 +109,8 @@ static int komeda_platform_probe(struct platform_device *pdev) continue; /* add connector */ - komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT); + komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT, 0); + komeda_add_slave(dev, &match, child, KOMEDA_OF_PORT_OUTPUT, 1); } return component_master_add_with_match(dev, &komeda_master_ops, match); diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c index 419a8b0e5de8..89191a555c84 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.c @@ -55,16 +55,13 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data) } static struct drm_driver komeda_kms_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | - DRIVER_PRIME | DRIVER_HAVE_IRQ, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .lastclose = drm_fb_helper_lastclose, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = komeda_gem_cma_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h index 8c89fc245b83..45c498e15e7a 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_kms.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_kms.h @@ -14,8 +14,6 @@ #include <drm/drm_device.h> #include <drm/drm_writeback.h> #include <drm/drm_print.h> -#include <video/videomode.h> -#include <video/display_timing.h> /** * struct komeda_plane - komeda instance of drm_plane @@ -168,7 +166,7 @@ static inline bool has_flip_h(u32 rot) return !!(rotation & DRM_MODE_REFLECT_X); } -unsigned long komeda_calc_aclk(struct komeda_crtc_state *kcrtc_st); +unsigned long komeda_crtc_get_aclk(struct komeda_crtc_state *kcrtc_st); int komeda_kms_setup_crtcs(struct komeda_kms_dev *kms, struct komeda_dev *mdev); diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c index 78e44d9e1520..452e505a1fd3 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.c @@ -54,7 +54,8 @@ void komeda_pipeline_destroy(struct komeda_dev *mdev, clk_put(pipe->pxlclk); - of_node_put(pipe->of_output_dev); + of_node_put(pipe->of_output_links[0]); + of_node_put(pipe->of_output_links[1]); of_node_put(pipe->of_output_port); of_node_put(pipe->of_node); @@ -246,9 +247,15 @@ static void komeda_pipeline_dump(struct komeda_pipeline *pipe) struct komeda_component *c; int id; - DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s\n", + DRM_INFO("Pipeline-%d: n_layers: %d, n_scalers: %d, output: %s.\n", pipe->id, pipe->n_layers, pipe->n_scalers, - pipe->of_output_dev ? pipe->of_output_dev->full_name : "none"); + pipe->dual_link ? "dual-link" : "single-link"); + DRM_INFO(" output_link[0]: %s.\n", + pipe->of_output_links[0] ? + pipe->of_output_links[0]->full_name : "none"); + DRM_INFO(" output_link[1]: %s.\n", + pipe->of_output_links[1] ? + pipe->of_output_links[1]->full_name : "none"); dp_for_each_set_bit(id, pipe->avail_comps) { c = komeda_pipeline_get_component(pipe, id); @@ -305,6 +312,12 @@ static void komeda_pipeline_assemble(struct komeda_pipeline *pipe) layer->right = komeda_get_layer_split_right_layer(pipe, layer); } + + if (pipe->dual_link && !pipe->ctrlr->supports_dual_link) { + pipe->dual_link = false; + DRM_WARN("PIPE-%d doesn't support dual-link, ignore DT dual-link configuration.\n", + pipe->id); + } } /* if pipeline_A accept another pipeline_B's component as input, treat diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h index a90bcbb3cb23..a7a84e66549d 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline.h @@ -416,8 +416,10 @@ struct komeda_pipeline { struct device_node *of_node; /** @of_output_port: pipeline output port */ struct device_node *of_output_port; - /** @of_output_dev: output connector device node */ - struct device_node *of_output_dev; + /** @of_output_links: output connector device nodes */ + struct device_node *of_output_links[2]; + /** @dual_link: true if of_output_links[0] and [1] are both valid */ + bool dual_link; }; /** diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c index 950235af1e79..ea26bc9c2d00 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_pipeline_state.c @@ -473,7 +473,7 @@ komeda_scaler_check_cfg(struct komeda_scaler *scaler, err = pipe->funcs->downscaling_clk_check(pipe, &kcrtc_st->base.adjusted_mode, - komeda_calc_aclk(kcrtc_st), dflow); + komeda_crtc_get_aclk(kcrtc_st), dflow); if (err) { DRM_DEBUG_ATOMIC("aclk can't satisfy the clock requirement of the downscaling\n"); return err; diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c index c095af154216..98e915e325dd 100644 --- a/drivers/gpu/drm/arm/display/komeda/komeda_plane.c +++ b/drivers/gpu/drm/arm/display/komeda/komeda_plane.c @@ -158,7 +158,7 @@ static void komeda_plane_reset(struct drm_plane *plane) static struct drm_plane_state * komeda_plane_atomic_duplicate_state(struct drm_plane *plane) { - struct komeda_plane_state *new, *old; + struct komeda_plane_state *new; if (WARN_ON(!plane->state)) return NULL; @@ -169,8 +169,6 @@ komeda_plane_atomic_duplicate_state(struct drm_plane *plane) __drm_atomic_helper_plane_duplicate_state(plane, &new->base); - old = to_kplane_st(plane->state); - return &new->base; } diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c index 8fc0b884c428..27c46a2838c5 100644 --- a/drivers/gpu/drm/arm/hdlcd_drv.c +++ b/drivers/gpu/drm/arm/hdlcd_drv.c @@ -229,9 +229,7 @@ static int hdlcd_debugfs_init(struct drm_minor *minor) DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver hdlcd_driver = { - .driver_features = DRIVER_GEM | - DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .irq_handler = hdlcd_irq, .irq_preinstall = hdlcd_irq_preinstall, .irq_postinstall = hdlcd_irq_postinstall, @@ -242,8 +240,6 @@ static struct drm_driver hdlcd_driver = { .dumb_create = drm_gem_cma_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c index f25ec4382277..c27ff456eddc 100644 --- a/drivers/gpu/drm/arm/malidp_drv.c +++ b/drivers/gpu/drm/arm/malidp_drv.c @@ -561,15 +561,12 @@ static int malidp_debugfs_init(struct drm_minor *minor) #endif //CONFIG_DEBUG_FS static struct drm_driver malidp_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | - DRIVER_PRIME, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = malidp_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c index 50af399d7f6f..380be66d4c6e 100644 --- a/drivers/gpu/drm/arm/malidp_hw.c +++ b/drivers/gpu/drm/arm/malidp_hw.c @@ -385,6 +385,7 @@ int malidp_format_get_bpp(u32 fmt) switch (fmt) { case DRM_FORMAT_VUY101010: bpp = 30; + break; case DRM_FORMAT_YUV420_10BIT: bpp = 15; break; @@ -1309,7 +1310,7 @@ static irqreturn_t malidp_se_irq(int irq, void *arg) break; case MW_RESTART: drm_writeback_signal_completion(&malidp->mw_connector, 0); - /* fall through to a new start */ + /* fall through - to a new start */ case MW_START: /* writeback started, need to emulate one-shot mode */ hw->disable_memwrite(hwdev); diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c index 521464f08ccd..055c92bc88bf 100644 --- a/drivers/gpu/drm/armada/armada_drv.c +++ b/drivers/gpu/drm/armada/armada_drv.c @@ -40,8 +40,7 @@ static struct drm_driver armada_drm_driver = { .name = "armada-drm", .desc = "Armada SoC DRM", .date = "20120730", - .driver_features = DRIVER_GEM | DRIVER_MODESET | - DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .ioctls = armada_ioctls, .fops = &armada_drm_fops, }; diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c index 874b2968a866..60c509784fa3 100644 --- a/drivers/gpu/drm/armada/armada_gem.c +++ b/drivers/gpu/drm/armada/armada_gem.c @@ -482,8 +482,7 @@ static const struct dma_buf_ops armada_gem_prime_dmabuf_ops = { }; struct dma_buf * -armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, - int flags) +armada_gem_prime_export(struct drm_gem_object *obj, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); @@ -492,7 +491,7 @@ armada_gem_prime_export(struct drm_device *dev, struct drm_gem_object *obj, exp_info.flags = O_RDWR; exp_info.priv = obj; - return drm_gem_dmabuf_export(dev, &exp_info); + return drm_gem_dmabuf_export(obj->dev, &exp_info); } struct drm_gem_object * diff --git a/drivers/gpu/drm/armada/armada_gem.h b/drivers/gpu/drm/armada/armada_gem.h index 1dd80540b8ce..de04cc2c8f0e 100644 --- a/drivers/gpu/drm/armada/armada_gem.h +++ b/drivers/gpu/drm/armada/armada_gem.h @@ -32,8 +32,7 @@ struct armada_gem_object *armada_gem_alloc_private_object(struct drm_device *, size_t); int armada_gem_dumb_create(struct drm_file *, struct drm_device *, struct drm_mode_create_dumb *); -struct dma_buf *armada_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, int flags); +struct dma_buf *armada_gem_prime_export(struct drm_gem_object *obj, int flags); struct drm_gem_object *armada_gem_prime_import(struct drm_device *, struct dma_buf *); int armada_gem_map_import(struct armada_gem_object *); diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c index eeb22eccd1fc..ada2f6aca906 100644 --- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c +++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c @@ -194,8 +194,7 @@ static void aspeed_gfx_unload(struct drm_device *drm) DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver aspeed_gfx_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | - DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .gem_create_object = drm_cma_gem_create_object_default_funcs, .dumb_create = drm_gem_cma_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, diff --git a/drivers/gpu/drm/ast/Makefile b/drivers/gpu/drm/ast/Makefile index b086dae17013..561f7c4199e4 100644 --- a/drivers/gpu/drm/ast/Makefile +++ b/drivers/gpu/drm/ast/Makefile @@ -3,6 +3,6 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -ast-y := ast_drv.o ast_main.o ast_mode.o ast_fb.o ast_ttm.o ast_post.o ast_dp501.o +ast-y := ast_drv.o ast_main.o ast_mode.o ast_ttm.o ast_post.o ast_dp501.o obj-$(CONFIG_DRM_AST) := ast.o diff --git a/drivers/gpu/drm/ast/ast_dp501.c b/drivers/gpu/drm/ast/ast_dp501.c index 4c7375b45281..98cd69269263 100644 --- a/drivers/gpu/drm/ast/ast_dp501.c +++ b/drivers/gpu/drm/ast/ast_dp501.c @@ -1,8 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 +#include <linux/delay.h> #include <linux/firmware.h> -#include <drm/drmP.h> +#include <linux/module.h> + #include "ast_drv.h" + MODULE_FIRMWARE("ast_dp501_fw.bin"); static int ast_load_dp501_microcode(struct drm_device *dev) diff --git a/drivers/gpu/drm/ast/ast_drv.c b/drivers/gpu/drm/ast/ast_drv.c index 3811997e78c4..6ed6ff49efc0 100644 --- a/drivers/gpu/drm/ast/ast_drv.c +++ b/drivers/gpu/drm/ast/ast_drv.c @@ -25,12 +25,17 @@ /* * Authors: Dave Airlie <airlied@redhat.com> */ -#include <linux/module.h> + #include <linux/console.h> +#include <linux/module.h> +#include <linux/pci.h> -#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_gem_vram_helper.h> +#include <drm/drm_pci.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vram_mm_helper.h> #include "ast_drv.h" @@ -100,28 +105,21 @@ ast_pci_remove(struct pci_dev *pdev) static int ast_drm_freeze(struct drm_device *dev) { drm_kms_helper_poll_disable(dev); - pci_save_state(dev->pdev); + drm_fb_helper_set_suspend_unlocked(dev->fb_helper, true); - console_lock(); - ast_fbdev_set_suspend(dev, 1); - console_unlock(); return 0; } static int ast_drm_thaw(struct drm_device *dev) { - int error = 0; - ast_post_gpu(dev); drm_mode_config_reset(dev); drm_helper_resume_force_mode(dev); + drm_fb_helper_set_suspend_unlocked(dev->fb_helper, false); - console_lock(); - ast_fbdev_set_suspend(dev, 0); - console_unlock(); - return error; + return 0; } static int ast_drm_resume(struct drm_device *dev) diff --git a/drivers/gpu/drm/ast/ast_drv.h b/drivers/gpu/drm/ast/ast_drv.h index 684e15e64a62..244cc7c382af 100644 --- a/drivers/gpu/drm/ast/ast_drv.h +++ b/drivers/gpu/drm/ast/ast_drv.h @@ -28,17 +28,18 @@ #ifndef __AST_DRV_H__ #define __AST_DRV_H__ -#include <drm/drm_encoder.h> -#include <drm/drm_fb_helper.h> - -#include <drm/drm_gem.h> -#include <drm/drm_gem_vram_helper.h> - -#include <drm/drm_vram_mm_helper.h> - +#include <linux/types.h> +#include <linux/io.h> #include <linux/i2c.h> #include <linux/i2c-algo-bit.h> +#include <drm/drm_connector.h> +#include <drm/drm_crtc.h> +#include <drm/drm_encoder.h> +#include <drm/drm_mode.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_fb_helper.h> + #define DRIVER_AUTHOR "Dave Airlie" #define DRIVER_NAME "ast" @@ -81,8 +82,6 @@ enum ast_tx_chip { #define AST_DRAM_4Gx16 7 #define AST_DRAM_8Gx16 8 -struct ast_fbdev; - struct ast_private { struct drm_device *dev; @@ -96,8 +95,6 @@ struct ast_private { uint32_t mclk; uint32_t vram_size; - struct ast_fbdev *fbdev; - int fb_mtrr; struct drm_gem_object *cursor_cache; @@ -239,24 +236,9 @@ struct ast_encoder { struct drm_encoder base; }; -struct ast_framebuffer { - struct drm_framebuffer base; - struct drm_gem_object *obj; -}; - -struct ast_fbdev { - struct drm_fb_helper helper; /* must be first */ - struct ast_framebuffer afb; - void *sysram; - int size; - int x1, y1, x2, y2; /* dirty rect */ - spinlock_t dirty_lock; -}; - #define to_ast_crtc(x) container_of(x, struct ast_crtc, base) #define to_ast_connector(x) container_of(x, struct ast_connector, base) #define to_ast_encoder(x) container_of(x, struct ast_encoder, base) -#define to_ast_framebuffer(x) container_of(x, struct ast_framebuffer, base) struct ast_vbios_stdtable { u8 misc; @@ -296,16 +278,6 @@ struct ast_vbios_mode_info { extern int ast_mode_init(struct drm_device *dev); extern void ast_mode_fini(struct drm_device *dev); -int ast_framebuffer_init(struct drm_device *dev, - struct ast_framebuffer *ast_fb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); - -int ast_fbdev_init(struct drm_device *dev); -void ast_fbdev_fini(struct drm_device *dev); -void ast_fbdev_set_suspend(struct drm_device *dev, int state); -void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr); - #define AST_MM_ALIGN_SHIFT 4 #define AST_MM_ALIGN_MASK ((1 << AST_MM_ALIGN_SHIFT) - 1) diff --git a/drivers/gpu/drm/ast/ast_fb.c b/drivers/gpu/drm/ast/ast_fb.c deleted file mode 100644 index 8200b25dad16..000000000000 --- a/drivers/gpu/drm/ast/ast_fb.c +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright 2012 Red Hat Inc. - * - * 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, sub license, 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS 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. - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial portions - * of the Software. - * - */ -/* - * Authors: Dave Airlie <airlied@redhat.com> - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/mm.h> -#include <linux/tty.h> -#include <linux/sysrq.h> -#include <linux/delay.h> -#include <linux/init.h> - - -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_util.h> -#include <drm/drm_crtc_helper.h> - -#include "ast_drv.h" - -static void ast_dirty_update(struct ast_fbdev *afbdev, - int x, int y, int width, int height) -{ - int i; - struct drm_gem_vram_object *gbo; - int src_offset, dst_offset; - int bpp = afbdev->afb.base.format->cpp[0]; - int ret; - u8 *dst; - bool unmap = false; - bool store_for_later = false; - int x2, y2; - unsigned long flags; - - gbo = drm_gem_vram_of_gem(afbdev->afb.obj); - - if (drm_can_sleep()) { - /* We pin the BO so it won't be moved during the - * update. The actual location, video RAM or system - * memory, is not important. - */ - ret = drm_gem_vram_pin(gbo, 0); - if (ret) { - if (ret != -EBUSY) - return; - store_for_later = true; - } - } else { - store_for_later = true; - } - - x2 = x + width - 1; - y2 = y + height - 1; - spin_lock_irqsave(&afbdev->dirty_lock, flags); - - if (afbdev->y1 < y) - y = afbdev->y1; - if (afbdev->y2 > y2) - y2 = afbdev->y2; - if (afbdev->x1 < x) - x = afbdev->x1; - if (afbdev->x2 > x2) - x2 = afbdev->x2; - - if (store_for_later) { - afbdev->x1 = x; - afbdev->x2 = x2; - afbdev->y1 = y; - afbdev->y2 = y2; - spin_unlock_irqrestore(&afbdev->dirty_lock, flags); - return; - } - - afbdev->x1 = afbdev->y1 = INT_MAX; - afbdev->x2 = afbdev->y2 = 0; - spin_unlock_irqrestore(&afbdev->dirty_lock, flags); - - dst = drm_gem_vram_kmap(gbo, false, NULL); - if (IS_ERR(dst)) { - DRM_ERROR("failed to kmap fb updates\n"); - goto out; - } else if (!dst) { - dst = drm_gem_vram_kmap(gbo, true, NULL); - if (IS_ERR(dst)) { - DRM_ERROR("failed to kmap fb updates\n"); - goto out; - } - unmap = true; - } - - for (i = y; i <= y2; i++) { - /* assume equal stride for now */ - src_offset = dst_offset = - i * afbdev->afb.base.pitches[0] + (x * bpp); - memcpy_toio(dst + dst_offset, afbdev->sysram + src_offset, - (x2 - x + 1) * bpp); - } - - if (unmap) - drm_gem_vram_kunmap(gbo); - -out: - drm_gem_vram_unpin(gbo); -} - -static void ast_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct ast_fbdev *afbdev = info->par; - drm_fb_helper_sys_fillrect(info, rect); - ast_dirty_update(afbdev, rect->dx, rect->dy, rect->width, - rect->height); -} - -static void ast_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - struct ast_fbdev *afbdev = info->par; - drm_fb_helper_sys_copyarea(info, area); - ast_dirty_update(afbdev, area->dx, area->dy, area->width, - area->height); -} - -static void ast_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct ast_fbdev *afbdev = info->par; - drm_fb_helper_sys_imageblit(info, image); - ast_dirty_update(afbdev, image->dx, image->dy, image->width, - image->height); -} - -static struct fb_ops astfb_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = ast_fillrect, - .fb_copyarea = ast_copyarea, - .fb_imageblit = ast_imageblit, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, -}; - -static int astfb_create_object(struct ast_fbdev *afbdev, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object **gobj_p) -{ - struct drm_device *dev = afbdev->helper.dev; - u32 size; - struct drm_gem_object *gobj; - int ret = 0; - - size = mode_cmd->pitches[0] * mode_cmd->height; - ret = ast_gem_create(dev, size, true, &gobj); - if (ret) - return ret; - - *gobj_p = gobj; - return ret; -} - -static int astfb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct ast_fbdev *afbdev = - container_of(helper, struct ast_fbdev, helper); - struct drm_device *dev = afbdev->helper.dev; - struct drm_mode_fb_cmd2 mode_cmd; - struct drm_framebuffer *fb; - struct fb_info *info; - int size, ret; - void *sysram; - struct drm_gem_object *gobj = NULL; - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7)/8); - - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - - size = mode_cmd.pitches[0] * mode_cmd.height; - - ret = astfb_create_object(afbdev, &mode_cmd, &gobj); - if (ret) { - DRM_ERROR("failed to create fbcon backing object %d\n", ret); - return ret; - } - - sysram = vmalloc(size); - if (!sysram) - return -ENOMEM; - - info = drm_fb_helper_alloc_fbi(helper); - if (IS_ERR(info)) { - ret = PTR_ERR(info); - goto out; - } - ret = ast_framebuffer_init(dev, &afbdev->afb, &mode_cmd, gobj); - if (ret) - goto out; - - afbdev->sysram = sysram; - afbdev->size = size; - - fb = &afbdev->afb.base; - afbdev->helper.fb = fb; - - info->fbops = &astfb_ops; - - info->apertures->ranges[0].base = pci_resource_start(dev->pdev, 0); - info->apertures->ranges[0].size = pci_resource_len(dev->pdev, 0); - - drm_fb_helper_fill_info(info, &afbdev->helper, sizes); - - info->screen_base = sysram; - info->screen_size = size; - - info->pixmap.flags = FB_PIXMAP_SYSTEM; - - DRM_DEBUG_KMS("allocated %dx%d\n", - fb->width, fb->height); - - return 0; - -out: - vfree(sysram); - return ret; -} - -static const struct drm_fb_helper_funcs ast_fb_helper_funcs = { - .fb_probe = astfb_create, -}; - -static void ast_fbdev_destroy(struct drm_device *dev, - struct ast_fbdev *afbdev) -{ - struct ast_framebuffer *afb = &afbdev->afb; - - drm_helper_force_disable_all(dev); - drm_fb_helper_unregister_fbi(&afbdev->helper); - - if (afb->obj) { - drm_gem_object_put_unlocked(afb->obj); - afb->obj = NULL; - } - drm_fb_helper_fini(&afbdev->helper); - - vfree(afbdev->sysram); - drm_framebuffer_unregister_private(&afb->base); - drm_framebuffer_cleanup(&afb->base); -} - -int ast_fbdev_init(struct drm_device *dev) -{ - struct ast_private *ast = dev->dev_private; - struct ast_fbdev *afbdev; - int ret; - - afbdev = kzalloc(sizeof(struct ast_fbdev), GFP_KERNEL); - if (!afbdev) - return -ENOMEM; - - ast->fbdev = afbdev; - spin_lock_init(&afbdev->dirty_lock); - - drm_fb_helper_prepare(dev, &afbdev->helper, &ast_fb_helper_funcs); - - ret = drm_fb_helper_init(dev, &afbdev->helper, 1); - if (ret) - goto free; - - ret = drm_fb_helper_single_add_all_connectors(&afbdev->helper); - if (ret) - goto fini; - - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(dev); - - ret = drm_fb_helper_initial_config(&afbdev->helper, 32); - if (ret) - goto fini; - - return 0; - -fini: - drm_fb_helper_fini(&afbdev->helper); -free: - kfree(afbdev); - return ret; -} - -void ast_fbdev_fini(struct drm_device *dev) -{ - struct ast_private *ast = dev->dev_private; - - if (!ast->fbdev) - return; - - ast_fbdev_destroy(dev, ast->fbdev); - kfree(ast->fbdev); - ast->fbdev = NULL; -} - -void ast_fbdev_set_suspend(struct drm_device *dev, int state) -{ - struct ast_private *ast = dev->dev_private; - - if (!ast->fbdev) - return; - - drm_fb_helper_set_suspend(&ast->fbdev->helper, state); -} - -void ast_fbdev_set_base(struct ast_private *ast, unsigned long gpu_addr) -{ - ast->fbdev->helper.fbdev->fix.smem_start = - ast->fbdev->helper.fbdev->apertures->ranges[0].base + gpu_addr; - ast->fbdev->helper.fbdev->fix.smem_len = ast->vram_size - gpu_addr; -} diff --git a/drivers/gpu/drm/ast/ast_main.c b/drivers/gpu/drm/ast/ast_main.c index 4c7e31cb45ff..dab77b2bc8ac 100644 --- a/drivers/gpu/drm/ast/ast_main.c +++ b/drivers/gpu/drm/ast/ast_main.c @@ -25,12 +25,17 @@ /* * Authors: Dave Airlie <airlied@redhat.com> */ -#include <drm/drmP.h> -#include "ast_drv.h" +#include <linux/pci.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_gem_vram_helper.h> +#include <drm/drm_vram_mm_helper.h> + +#include "ast_drv.h" void ast_set_index_reg_mask(struct ast_private *ast, uint32_t base, uint8_t index, @@ -383,67 +388,8 @@ static int ast_get_dram_info(struct drm_device *dev) return 0; } -static void ast_user_framebuffer_destroy(struct drm_framebuffer *fb) -{ - struct ast_framebuffer *ast_fb = to_ast_framebuffer(fb); - - drm_gem_object_put_unlocked(ast_fb->obj); - drm_framebuffer_cleanup(fb); - kfree(ast_fb); -} - -static const struct drm_framebuffer_funcs ast_fb_funcs = { - .destroy = ast_user_framebuffer_destroy, -}; - - -int ast_framebuffer_init(struct drm_device *dev, - struct ast_framebuffer *ast_fb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj) -{ - int ret; - - drm_helper_mode_fill_fb_struct(dev, &ast_fb->base, mode_cmd); - ast_fb->obj = obj; - ret = drm_framebuffer_init(dev, &ast_fb->base, &ast_fb_funcs); - if (ret) { - DRM_ERROR("framebuffer init failed %d\n", ret); - return ret; - } - return 0; -} - -static struct drm_framebuffer * -ast_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 ast_framebuffer *ast_fb; - int ret; - - obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]); - if (obj == NULL) - return ERR_PTR(-ENOENT); - - ast_fb = kzalloc(sizeof(*ast_fb), GFP_KERNEL); - if (!ast_fb) { - drm_gem_object_put_unlocked(obj); - return ERR_PTR(-ENOMEM); - } - - ret = ast_framebuffer_init(dev, ast_fb, mode_cmd, obj); - if (ret) { - drm_gem_object_put_unlocked(obj); - kfree(ast_fb); - return ERR_PTR(ret); - } - return &ast_fb->base; -} - static const struct drm_mode_config_funcs ast_mode_funcs = { - .fb_create = ast_user_framebuffer_create, + .fb_create = drm_gem_fb_create }; static u32 ast_get_vram_info(struct drm_device *dev) @@ -561,7 +507,7 @@ int ast_driver_load(struct drm_device *dev, unsigned long flags) if (ret) goto out_free; - ret = ast_fbdev_init(dev); + ret = drm_fbdev_generic_setup(dev, 32); if (ret) goto out_free; @@ -579,7 +525,6 @@ void ast_driver_unload(struct drm_device *dev) ast_release_firmware(dev); kfree(ast->dp501_fw_addr); ast_mode_fini(dev); - ast_fbdev_fini(dev); drm_mode_config_cleanup(dev); ast_mm_fini(ast); @@ -609,6 +554,6 @@ int ast_gem_create(struct drm_device *dev, DRM_ERROR("failed to allocate GEM object\n"); return ret; } - *obj = &gbo->gem; + *obj = &gbo->bo.base; return 0; } diff --git a/drivers/gpu/drm/ast/ast_mode.c b/drivers/gpu/drm/ast/ast_mode.c index ffccbef962a4..1c899a6e87b7 100644 --- a/drivers/gpu/drm/ast/ast_mode.c +++ b/drivers/gpu/drm/ast/ast_mode.c @@ -27,14 +27,18 @@ /* * Authors: Dave Airlie <airlied@redhat.com> */ + #include <linux/export.h> -#include <drm/drmP.h> +#include <linux/pci.h> + #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_vram_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include "ast_drv.h" +#include "ast_drv.h" #include "ast_tables.h" static struct ast_i2c_chan *ast_i2c_create(struct drm_device *dev); @@ -525,28 +529,16 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int atomic) { - struct ast_private *ast = crtc->dev->dev_private; - struct drm_gem_object *obj; - struct ast_framebuffer *ast_fb; struct drm_gem_vram_object *gbo; int ret; s64 gpu_addr; - void *base; if (!atomic && fb) { - ast_fb = to_ast_framebuffer(fb); - obj = ast_fb->obj; - gbo = drm_gem_vram_of_gem(obj); - - /* unmap if console */ - if (&ast->fbdev->afb == ast_fb) - drm_gem_vram_kunmap(gbo); + gbo = drm_gem_vram_of_gem(fb->obj[0]); drm_gem_vram_unpin(gbo); } - ast_fb = to_ast_framebuffer(crtc->primary->fb); - obj = ast_fb->obj; - gbo = drm_gem_vram_of_gem(obj); + gbo = drm_gem_vram_of_gem(crtc->primary->fb->obj[0]); ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) @@ -557,17 +549,6 @@ static int ast_crtc_do_set_base(struct drm_crtc *crtc, goto err_drm_gem_vram_unpin; } - if (&ast->fbdev->afb == ast_fb) { - /* if pushing console in kmap it */ - base = drm_gem_vram_kmap(gbo, true, NULL); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - DRM_ERROR("failed to kmap fbcon\n"); - } else { - ast_fbdev_set_base(ast, gpu_addr); - } - } - ast_set_offset_reg(crtc); ast_set_start_address_crt1(crtc, (u32)gpu_addr); @@ -624,14 +605,10 @@ static void ast_crtc_disable(struct drm_crtc *crtc) DRM_DEBUG_KMS("\n"); ast_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); if (crtc->primary->fb) { - struct ast_private *ast = crtc->dev->dev_private; - struct ast_framebuffer *ast_fb = to_ast_framebuffer(crtc->primary->fb); - struct drm_gem_object *obj = ast_fb->obj; - struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj); - - /* unmap if console */ - if (&ast->fbdev->afb == ast_fb) - drm_gem_vram_kunmap(gbo); + struct drm_framebuffer *fb = crtc->primary->fb; + struct drm_gem_vram_object *gbo = + drm_gem_vram_of_gem(fb->obj[0]); + drm_gem_vram_unpin(gbo); } crtc->primary->fb = NULL; @@ -890,7 +867,14 @@ static int ast_connector_init(struct drm_device *dev) return -ENOMEM; connector = &ast_connector->base; - drm_connector_init(dev, connector, &ast_connector_funcs, DRM_MODE_CONNECTOR_VGA); + ast_connector->i2c = ast_i2c_create(dev); + if (!ast_connector->i2c) + DRM_ERROR("failed to add ddc bus for connector\n"); + + drm_connector_init_with_ddc(dev, connector, + &ast_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &ast_connector->i2c->adapter); drm_connector_helper_add(connector, &ast_connector_helper_funcs); @@ -904,10 +888,6 @@ static int ast_connector_init(struct drm_device *dev) encoder = list_first_entry(&dev->mode_config.encoder_list, struct drm_encoder, head); drm_connector_attach_encoder(connector, encoder); - ast_connector->i2c = ast_i2c_create(dev); - if (!ast_connector->i2c) - DRM_ERROR("failed to add ddc bus for connector\n"); - return 0; } diff --git a/drivers/gpu/drm/ast/ast_post.c b/drivers/gpu/drm/ast/ast_post.c index f7d421359d56..e1d9cdf6ec1d 100644 --- a/drivers/gpu/drm/ast/ast_post.c +++ b/drivers/gpu/drm/ast/ast_post.c @@ -26,10 +26,13 @@ * Authors: Dave Airlie <airlied@redhat.com> */ -#include <drm/drmP.h> -#include "ast_drv.h" +#include <linux/delay.h> +#include <linux/pci.h> + +#include <drm/drm_print.h> #include "ast_dram_tables.h" +#include "ast_drv.h" static void ast_post_chip_2300(struct drm_device *dev); static void ast_post_chip_2500(struct drm_device *dev); diff --git a/drivers/gpu/drm/ast/ast_ttm.c b/drivers/gpu/drm/ast/ast_ttm.c index 779c53efee8e..c52d92294171 100644 --- a/drivers/gpu/drm/ast/ast_ttm.c +++ b/drivers/gpu/drm/ast/ast_ttm.c @@ -25,7 +25,12 @@ /* * Authors: Dave Airlie <airlied@redhat.com> */ -#include <drm/drmP.h> + +#include <linux/pci.h> + +#include <drm/drm_print.h> +#include <drm/drm_gem_vram_helper.h> +#include <drm/drm_vram_mm_helper.h> #include "ast_drv.h" diff --git a/drivers/gpu/drm/ati_pcigart.c b/drivers/gpu/drm/ati_pcigart.c index 2a413e291a60..580aa2676358 100644 --- a/drivers/gpu/drm/ati_pcigart.c +++ b/drivers/gpu/drm/ati_pcigart.c @@ -35,7 +35,6 @@ #include <drm/ati_pcigart.h> #include <drm/drm_device.h> -#include <drm/drm_os_linux.h> #include <drm/drm_pci.h> #include <drm/drm_print.h> @@ -169,6 +168,7 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga page_base = (u32) entry->busaddr[i]; for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { + u32 offset; u32 val; switch(gart_info->gart_reg_if) { @@ -184,10 +184,12 @@ int drm_ati_pcigart_init(struct drm_device *dev, struct drm_ati_pcigart_info *ga break; } if (gart_info->gart_table_location == - DRM_ATI_GART_MAIN) + DRM_ATI_GART_MAIN) { pci_gart[gart_idx] = cpu_to_le32(val); - else - DRM_WRITE32(map, gart_idx * sizeof(u32), val); + } else { + offset = gart_idx * sizeof(u32); + writel(val, (void __iomem *)map->handle + offset); + } gart_idx++; page_base += ATI_PCIGART_PAGE_SIZE; } diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 6c6c7cf3c3e8..f2e73e6d46b8 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -8,15 +8,19 @@ */ #include <linux/clk.h> +#include <linux/mfd/atmel-hlcdc.h> +#include <linux/pinctrl/consumer.h> #include <linux/pm.h> #include <linux/pm_runtime.h> -#include <linux/pinctrl/consumer.h> +#include <video/videomode.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> +#include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> - -#include <video/videomode.h> +#include <drm/drm_vblank.h> #include "atmel_hlcdc_dc.h" diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 9bab6e5ba76b..92640298ad41 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -11,8 +11,20 @@ #include <linux/clk.h> #include <linux/irq.h> #include <linux/irqchip.h> +#include <linux/mfd/atmel-hlcdc.h> #include <linux/module.h> #include <linux/pm_runtime.h> +#include <linux/platform_device.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_irq.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "atmel_hlcdc_dc.h" @@ -823,9 +835,7 @@ static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev) DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver atmel_hlcdc_dc_driver = { - .driver_features = DRIVER_GEM | - DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .irq_handler = atmel_hlcdc_dc_irq_handler, .irq_preinstall = atmel_hlcdc_dc_irq_uninstall, .irq_postinstall = atmel_hlcdc_dc_irq_postinstall, @@ -834,8 +844,6 @@ static struct drm_driver atmel_hlcdc_dc_driver = { .gem_vm_ops = &drm_gem_cma_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index 7300e3fd273e..469d4507e576 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -11,23 +11,9 @@ #ifndef DRM_ATMEL_HLCDC_H #define DRM_ATMEL_HLCDC_H -#include <linux/clk.h> -#include <linux/dmapool.h> -#include <linux/irqdomain.h> -#include <linux/mfd/atmel-hlcdc.h> -#include <linux/pwm.h> - -#include <drm/drm_atomic.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_crtc.h> -#include <drm/drm_probe_helper.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_fb_cma_helper.h> -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_panel.h> -#include <drm/drm_plane_helper.h> -#include <drm/drmP.h> +#include <linux/regmap.h> + +#include <drm/drm_plane.h> #define ATMEL_HLCDC_LAYER_CHER 0x0 #define ATMEL_HLCDC_LAYER_CHDR 0x4 diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c index 7e08318b262e..375fa84c548b 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c @@ -8,9 +8,10 @@ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> */ +#include <linux/media-bus-format.h> #include <linux/of_graph.h> -#include <drm/drmP.h> +#include <drm/drm_encoder.h> #include <drm/drm_of.h> #include <drm/drm_bridge.h> diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 4127aca212bb..89f5a756fa37 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -6,6 +6,16 @@ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> */ +#include <linux/dmapool.h> +#include <linux/mfd/atmel-hlcdc.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_plane_helper.h> + #include "atmel_hlcdc_dc.h" /** @@ -361,7 +371,7 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_HLCDC_LAYER_DMA_CFG, cfg); - cfg = ATMEL_HLCDC_LAYER_DMA; + cfg = ATMEL_HLCDC_LAYER_DMA | ATMEL_HLCDC_LAYER_REP; if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) { cfg |= ATMEL_HLCDC_LAYER_OVR | ATMEL_HLCDC_LAYER_ITER2BL | diff --git a/drivers/gpu/drm/bochs/bochs.h b/drivers/gpu/drm/bochs/bochs.h index 2a65434500ee..68483a2fc12c 100644 --- a/drivers/gpu/drm/bochs/bochs.h +++ b/drivers/gpu/drm/bochs/bochs.h @@ -1,17 +1,15 @@ /* SPDX-License-Identifier: GPL-2.0 */ + #include <linux/io.h> #include <linux/console.h> -#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_simple_kms_helper.h> - #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> - +#include <drm/drm_simple_kms_helper.h> #include <drm/drm_vram_mm_helper.h> /* ---------------------------------------------------------------------- */ diff --git a/drivers/gpu/drm/bochs/bochs_drv.c b/drivers/gpu/drm/bochs/bochs_drv.c index 8f3a5bda9d03..770e1625d05e 100644 --- a/drivers/gpu/drm/bochs/bochs_drv.c +++ b/drivers/gpu/drm/bochs/bochs_drv.c @@ -2,11 +2,10 @@ /* */ -#include <linux/mm.h> #include <linux/module.h> -#include <linux/slab.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_probe_helper.h> +#include <linux/pci.h> + +#include <drm/drm_drv.h> #include <drm/drm_atomic_helper.h> #include "bochs.h" @@ -65,8 +64,7 @@ static const struct file_operations bochs_fops = { }; static struct drm_driver bochs_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC | - DRIVER_PRIME, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &bochs_fops, .name = "bochs-drm", .desc = "bochs dispi vga interface (qemu stdvga)", @@ -74,7 +72,6 @@ static struct drm_driver bochs_driver = { .major = 1, .minor = 0, DRM_GEM_VRAM_DRIVER, - DRM_GEM_VRAM_DRIVER_PRIME, }; /* ---------------------------------------------------------------------- */ @@ -83,16 +80,14 @@ static struct drm_driver bochs_driver = { #ifdef CONFIG_PM_SLEEP static int bochs_pm_suspend(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct drm_device *drm_dev = dev_get_drvdata(dev); return drm_mode_config_helper_suspend(drm_dev); } static int bochs_pm_resume(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct drm_device *drm_dev = dev_get_drvdata(dev); return drm_mode_config_helper_resume(drm_dev); } diff --git a/drivers/gpu/drm/bochs/bochs_hw.c b/drivers/gpu/drm/bochs/bochs_hw.c index ebfea8744fe6..e567bdfa2ab8 100644 --- a/drivers/gpu/drm/bochs/bochs_hw.c +++ b/drivers/gpu/drm/bochs/bochs_hw.c @@ -2,6 +2,10 @@ /* */ +#include <linux/pci.h> + +#include <drm/drm_fourcc.h> + #include "bochs.h" /* ---------------------------------------------------------------------- */ diff --git a/drivers/gpu/drm/bochs/bochs_kms.c b/drivers/gpu/drm/bochs/bochs_kms.c index 359030d5d818..02a9c1ed165b 100644 --- a/drivers/gpu/drm/bochs/bochs_kms.c +++ b/drivers/gpu/drm/bochs/bochs_kms.c @@ -2,12 +2,14 @@ /* */ -#include "bochs.h" +#include <linux/moduleparam.h> + #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> -#include <drm/drm_atomic_uapi.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + +#include "bochs.h" static int defx = 1024; static int defy = 768; diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig index e4e22bbae2a7..1cc9f502c1f2 100644 --- a/drivers/gpu/drm/bridge/Kconfig +++ b/drivers/gpu/drm/bridge/Kconfig @@ -21,7 +21,7 @@ config DRM_ANALOGIX_ANX78XX select DRM_KMS_HELPER select REGMAP_I2C ---help--- - ANX78XX is an ultra-low Full-HD SlimPort transmitter + ANX78XX is an ultra-low power Full-HD SlimPort transmitter designed for portable devices. The ANX78XX transforms the HDMI output of an application processor to MyDP or DisplayPort. diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c index f6d2681f6927..98bccace8c1c 100644 --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c @@ -874,9 +874,6 @@ static int adv7511_bridge_attach(struct drm_bridge *bridge) &adv7511_connector_helper_funcs); drm_connector_attach_encoder(&adv->connector, bridge->encoder); - if (adv->type == ADV7533) - ret = adv7533_attach_dsi(adv); - if (adv->i2c_main->irq) regmap_write(adv->regmap, ADV7511_REG_INT_ENABLE(0), ADV7511_INT0_HPD); @@ -1222,8 +1219,17 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id) drm_bridge_add(&adv7511->bridge); adv7511_audio_init(dev, adv7511); + + if (adv7511->type == ADV7533) { + ret = adv7533_attach_dsi(adv7511); + if (ret) + goto err_remove_bridge; + } + return 0; +err_remove_bridge: + drm_bridge_remove(&adv7511->bridge); err_unregister_cec: i2c_unregister_device(adv7511->i2c_cec); if (adv7511->cec_clk) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 3f7f4880be09..f2f7f69d6cc3 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -19,6 +19,7 @@ #include <linux/platform_device.h> #include <drm/bridge/analogix_dp.h> +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_device.h> @@ -101,63 +102,7 @@ static int analogix_dp_detect_hpd(struct analogix_dp_device *dp) return 0; } -int analogix_dp_psr_enabled(struct analogix_dp_device *dp) -{ - - return dp->psr_enable; -} -EXPORT_SYMBOL_GPL(analogix_dp_psr_enabled); - -int analogix_dp_enable_psr(struct analogix_dp_device *dp) -{ - struct dp_sdp psr_vsc; - - if (!dp->psr_enable) - return 0; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.db[0] = 0; - psr_vsc.db[1] = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; - - return analogix_dp_send_psr_spd(dp, &psr_vsc, true); -} -EXPORT_SYMBOL_GPL(analogix_dp_enable_psr); - -int analogix_dp_disable_psr(struct analogix_dp_device *dp) -{ - struct dp_sdp psr_vsc; - int ret; - - if (!dp->psr_enable) - return 0; - - /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ - memset(&psr_vsc, 0, sizeof(psr_vsc)); - psr_vsc.sdp_header.HB0 = 0; - psr_vsc.sdp_header.HB1 = 0x7; - psr_vsc.sdp_header.HB2 = 0x2; - psr_vsc.sdp_header.HB3 = 0x8; - - psr_vsc.db[0] = 0; - psr_vsc.db[1] = 0; - - ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0); - if (ret != 1) { - dev_err(dp->dev, "Failed to set DP Power0 %d\n", ret); - return ret; - } - - return analogix_dp_send_psr_spd(dp, &psr_vsc, false); -} -EXPORT_SYMBOL_GPL(analogix_dp_disable_psr); - -static int analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) +static bool analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) { unsigned char psr_version; int ret; @@ -165,14 +110,11 @@ static int analogix_dp_detect_sink_psr(struct analogix_dp_device *dp) ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_SUPPORT, &psr_version); if (ret != 1) { dev_err(dp->dev, "failed to get PSR version, disable it\n"); - return ret; + return false; } dev_dbg(dp->dev, "Panel PSR version : %x\n", psr_version); - - dp->psr_enable = (psr_version & DP_PSR_IS_SUPPORTED) ? true : false; - - return 0; + return psr_version & DP_PSR_IS_SUPPORTED; } static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) @@ -195,7 +137,7 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) } /* Main-Link transmitter remains active during PSR active states */ - psr_en = DP_PSR_MAIN_LINK_ACTIVE | DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_CRC_VERIFICATION; ret = drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en); if (ret != 1) { dev_err(dp->dev, "failed to set panel psr\n"); @@ -203,8 +145,7 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) } /* Enable psr function */ - psr_en = DP_PSR_ENABLE | DP_PSR_MAIN_LINK_ACTIVE | - DP_PSR_CRC_VERIFICATION; + psr_en = DP_PSR_ENABLE | DP_PSR_CRC_VERIFICATION; ret = drm_dp_dpcd_writeb(&dp->aux, DP_PSR_EN_CFG, psr_en); if (ret != 1) { dev_err(dp->dev, "failed to set panel psr\n"); @@ -213,10 +154,11 @@ static int analogix_dp_enable_sink_psr(struct analogix_dp_device *dp) analogix_dp_enable_psr_crc(dp); + dp->psr_supported = true; + return 0; end: dev_err(dp->dev, "enable psr fail, force to disable psr\n"); - dp->psr_enable = false; return ret; } @@ -1031,24 +973,90 @@ static int analogix_dp_commit(struct analogix_dp_device *dp) } } - ret = analogix_dp_detect_sink_psr(dp); + /* Check whether panel supports fast training */ + ret = analogix_dp_fast_link_train_detection(dp); if (ret) return ret; - if (dp->psr_enable) { + if (analogix_dp_detect_sink_psr(dp)) { ret = analogix_dp_enable_sink_psr(dp); if (ret) return ret; } - /* Check whether panel supports fast training */ - ret = analogix_dp_fast_link_train_detection(dp); - if (ret) - dp->psr_enable = false; + return ret; +} + +static int analogix_dp_enable_psr(struct analogix_dp_device *dp) +{ + struct dp_sdp psr_vsc; + int ret; + u8 sink; + + ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &sink); + if (ret != 1) + DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n", ret); + else if (sink == DP_PSR_SINK_ACTIVE_RFB) + return 0; + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + psr_vsc.db[0] = 0; + psr_vsc.db[1] = EDP_VSC_PSR_STATE_ACTIVE | EDP_VSC_PSR_CRC_VALUES_VALID; + + ret = analogix_dp_send_psr_spd(dp, &psr_vsc, true); + if (!ret) + analogix_dp_set_analog_power_down(dp, POWER_ALL, true); return ret; } +static int analogix_dp_disable_psr(struct analogix_dp_device *dp) +{ + struct dp_sdp psr_vsc; + int ret; + u8 sink; + + analogix_dp_set_analog_power_down(dp, POWER_ALL, false); + + ret = drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D0); + if (ret != 1) { + DRM_DEV_ERROR(dp->dev, "Failed to set DP Power0 %d\n", ret); + return ret; + } + + ret = drm_dp_dpcd_readb(&dp->aux, DP_PSR_STATUS, &sink); + if (ret != 1) { + DRM_DEV_ERROR(dp->dev, "Failed to read psr status %d\n", ret); + return ret; + } else if (sink == DP_PSR_SINK_INACTIVE) { + DRM_DEV_ERROR(dp->dev, "sink inactive, skip disable psr"); + return 0; + } + + ret = analogix_dp_train_link(dp); + if (ret) { + DRM_DEV_ERROR(dp->dev, "Failed to train the link %d\n", ret); + return ret; + } + + /* Prepare VSC packet as per EDP 1.4 spec, Table 6.9 */ + memset(&psr_vsc, 0, sizeof(psr_vsc)); + psr_vsc.sdp_header.HB0 = 0; + psr_vsc.sdp_header.HB1 = 0x7; + psr_vsc.sdp_header.HB2 = 0x2; + psr_vsc.sdp_header.HB3 = 0x8; + + psr_vsc.db[0] = 0; + psr_vsc.db[1] = 0; + + return analogix_dp_send_psr_spd(dp, &psr_vsc, true); +} + /* * This function is a bit of a catch-all for panel preparation, hopefully * simplifying the logic of functions that need to prepare/unprepare the panel @@ -1139,9 +1147,37 @@ analogix_dp_best_encoder(struct drm_connector *connector) return dp->encoder; } + +static int analogix_dp_atomic_check(struct drm_connector *connector, + struct drm_atomic_state *state) +{ + struct analogix_dp_device *dp = to_dp(connector); + struct drm_connector_state *conn_state; + struct drm_crtc_state *crtc_state; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (WARN_ON(!conn_state)) + return -ENODEV; + + conn_state->self_refresh_aware = true; + + if (!conn_state->crtc) + return 0; + + crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc); + if (!crtc_state) + return 0; + + if (crtc_state->self_refresh_active && !dp->psr_supported) + return -EINVAL; + + return 0; +} + static const struct drm_connector_helper_funcs analogix_dp_connector_helper_funcs = { .get_modes = analogix_dp_get_modes, .best_encoder = analogix_dp_best_encoder, + .atomic_check = analogix_dp_atomic_check, }; static enum drm_connector_status @@ -1233,11 +1269,42 @@ static int analogix_dp_bridge_attach(struct drm_bridge *bridge) return 0; } -static void analogix_dp_bridge_pre_enable(struct drm_bridge *bridge) +static +struct drm_crtc *analogix_dp_get_new_crtc(struct analogix_dp_device *dp, + struct drm_atomic_state *state) +{ + struct drm_encoder *encoder = dp->encoder; + struct drm_connector *connector; + struct drm_connector_state *conn_state; + + connector = drm_atomic_get_new_connector_for_encoder(state, encoder); + if (!connector) + return NULL; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return NULL; + + return conn_state->crtc; +} + +static void analogix_dp_bridge_atomic_pre_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct analogix_dp_device *dp = bridge->driver_private; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; int ret; + crtc = analogix_dp_get_new_crtc(dp, state); + if (!crtc) + return; + + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); + /* Don't touch the panel if we're coming back from PSR */ + if (old_crtc_state && old_crtc_state->self_refresh_active) + return; + ret = analogix_dp_prepare_panel(dp, true, true); if (ret) DRM_ERROR("failed to setup the panel ret = %d\n", ret); @@ -1298,10 +1365,27 @@ out_dp_clk_pre: return ret; } -static void analogix_dp_bridge_enable(struct drm_bridge *bridge) +static void analogix_dp_bridge_atomic_enable(struct drm_bridge *bridge, + struct drm_atomic_state *state) { struct analogix_dp_device *dp = bridge->driver_private; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; int timeout_loop = 0; + int ret; + + crtc = analogix_dp_get_new_crtc(dp, state); + if (!crtc) + return; + + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); + /* Not a full enable, just disable PSR and continue */ + if (old_crtc_state && old_crtc_state->self_refresh_active) { + ret = analogix_dp_disable_psr(dp); + if (ret) + DRM_ERROR("Failed to disable psr %d\n", ret); + return; + } if (dp->dpms_mode == DRM_MODE_DPMS_ON) return; @@ -1350,11 +1434,56 @@ static void analogix_dp_bridge_disable(struct drm_bridge *bridge) if (ret) DRM_ERROR("failed to setup the panel ret = %d\n", ret); - dp->psr_enable = false; dp->fast_train_enable = false; + dp->psr_supported = false; dp->dpms_mode = DRM_MODE_DPMS_OFF; } +static void analogix_dp_bridge_atomic_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct analogix_dp_device *dp = bridge->driver_private; + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state = NULL; + + crtc = analogix_dp_get_new_crtc(dp, state); + if (!crtc) + goto out; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + if (!new_crtc_state) + goto out; + + /* Don't do a full disable on PSR transitions */ + if (new_crtc_state->self_refresh_active) + return; + +out: + analogix_dp_bridge_disable(bridge); +} + +static +void analogix_dp_bridge_atomic_post_disable(struct drm_bridge *bridge, + struct drm_atomic_state *state) +{ + struct analogix_dp_device *dp = bridge->driver_private; + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state; + int ret; + + crtc = analogix_dp_get_new_crtc(dp, state); + if (!crtc) + return; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + if (!new_crtc_state || !new_crtc_state->self_refresh_active) + return; + + ret = analogix_dp_enable_psr(dp); + if (ret) + DRM_ERROR("Failed to enable psr (%d)\n", ret); +} + static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, const struct drm_display_mode *orig_mode, const struct drm_display_mode *mode) @@ -1432,16 +1561,11 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge, video->interlaced = true; } -static void analogix_dp_bridge_nop(struct drm_bridge *bridge) -{ - /* do nothing */ -} - static const struct drm_bridge_funcs analogix_dp_bridge_funcs = { - .pre_enable = analogix_dp_bridge_pre_enable, - .enable = analogix_dp_bridge_enable, - .disable = analogix_dp_bridge_disable, - .post_disable = analogix_dp_bridge_nop, + .atomic_pre_enable = analogix_dp_bridge_atomic_pre_enable, + .atomic_enable = analogix_dp_bridge_atomic_enable, + .atomic_disable = analogix_dp_bridge_atomic_disable, + .atomic_post_disable = analogix_dp_bridge_atomic_post_disable, .mode_set = analogix_dp_bridge_mode_set, .attach = analogix_dp_bridge_attach, }; diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index da058252dcaf..c051502d7fbf 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -171,8 +171,8 @@ struct analogix_dp_device { int dpms_mode; struct gpio_desc *hpd_gpiod; bool force_hpd; - bool psr_enable; bool fast_train_enable; + bool psr_supported; struct mutex panel_lock; bool panel_is_modeset; diff --git a/drivers/gpu/drm/bridge/dumb-vga-dac.c b/drivers/gpu/drm/bridge/dumb-vga-dac.c index d32885b906ae..8ef6539ae78a 100644 --- a/drivers/gpu/drm/bridge/dumb-vga-dac.c +++ b/drivers/gpu/drm/bridge/dumb-vga-dac.c @@ -111,8 +111,10 @@ static int dumb_vga_attach(struct drm_bridge *bridge) drm_connector_helper_add(&vga->connector, &dumb_vga_con_helper_funcs); - ret = drm_connector_init(bridge->dev, &vga->connector, - &dumb_vga_con_funcs, DRM_MODE_CONNECTOR_VGA); + ret = drm_connector_init_with_ddc(bridge->dev, &vga->connector, + &dumb_vga_con_funcs, + DRM_MODE_CONNECTOR_VGA, + vga->ddc); if (ret) { DRM_ERROR("Failed to initialize connector\n"); return ret; diff --git a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c index 79311f8354bd..6e81e5db57f2 100644 --- a/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c +++ b/drivers/gpu/drm/bridge/megachips-stdpxxxx-ge-b850v3-fw.c @@ -19,7 +19,6 @@ * Host -> LVDS|--(STDP4028)--|DP -> DP|--(STDP2690)--|DP++ -> Video output */ -#include <linux/gpio.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/of.h> diff --git a/drivers/gpu/drm/bridge/nxp-ptn3460.c b/drivers/gpu/drm/bridge/nxp-ptn3460.c index 98bc650b8c95..d4a1cc5052c3 100644 --- a/drivers/gpu/drm/bridge/nxp-ptn3460.c +++ b/drivers/gpu/drm/bridge/nxp-ptn3460.c @@ -6,13 +6,10 @@ */ #include <linux/delay.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> #include <linux/of.h> -#include <linux/of_gpio.h> - #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_edid.h> diff --git a/drivers/gpu/drm/bridge/parade-ps8622.c b/drivers/gpu/drm/bridge/parade-ps8622.c index 2d88146e4836..93c68e2e9484 100644 --- a/drivers/gpu/drm/bridge/parade-ps8622.c +++ b/drivers/gpu/drm/bridge/parade-ps8622.c @@ -8,7 +8,6 @@ #include <linux/backlight.h> #include <linux/delay.h> #include <linux/err.h> -#include <linux/gpio.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/module.h> diff --git a/drivers/gpu/drm/bridge/sii902x.c b/drivers/gpu/drm/bridge/sii902x.c index dd7aa466b280..38f75ac580df 100644 --- a/drivers/gpu/drm/bridge/sii902x.c +++ b/drivers/gpu/drm/bridge/sii902x.c @@ -158,6 +158,8 @@ #define SII902X_I2C_BUS_ACQUISITION_TIMEOUT_MS 500 +#define SII902X_AUDIO_PORT_INDEX 3 + struct sii902x { struct i2c_client *i2c; struct regmap *regmap; @@ -568,13 +570,14 @@ static int sii902x_audio_hw_params(struct device *dev, void *data, return ret; } - mclk_rate = clk_get_rate(sii902x->audio.mclk); - - ret = sii902x_select_mclk_div(&i2s_config_reg, params->sample_rate, - mclk_rate); - if (mclk_rate != ret * params->sample_rate) - dev_dbg(dev, "Inaccurate reference clock (%ld/%d != %u)\n", - mclk_rate, ret, params->sample_rate); + if (sii902x->audio.mclk) { + mclk_rate = clk_get_rate(sii902x->audio.mclk); + ret = sii902x_select_mclk_div(&i2s_config_reg, + params->sample_rate, mclk_rate); + if (mclk_rate != ret * params->sample_rate) + dev_dbg(dev, "Inaccurate reference clock (%ld/%d != %u)\n", + mclk_rate, ret, params->sample_rate); + } mutex_lock(&sii902x->mutex); @@ -662,7 +665,8 @@ static void sii902x_audio_shutdown(struct device *dev, void *data) clk_disable_unprepare(sii902x->audio.mclk); } -int sii902x_audio_digital_mute(struct device *dev, void *data, bool enable) +static int sii902x_audio_digital_mute(struct device *dev, + void *data, bool enable) { struct sii902x *sii902x = dev_get_drvdata(dev); @@ -690,11 +694,32 @@ static int sii902x_audio_get_eld(struct device *dev, void *data, return 0; } +static int sii902x_audio_get_dai_id(struct snd_soc_component *component, + struct device_node *endpoint) +{ + struct of_endpoint of_ep; + int ret; + + ret = of_graph_parse_endpoint(endpoint, &of_ep); + if (ret < 0) + return ret; + + /* + * HDMI sound should be located at reg = <3> + * Return expected DAI index 0. + */ + if (of_ep.port == SII902X_AUDIO_PORT_INDEX) + return 0; + + return -EINVAL; +} + static const struct hdmi_codec_ops sii902x_audio_codec_ops = { .hw_params = sii902x_audio_hw_params, .audio_shutdown = sii902x_audio_shutdown, .digital_mute = sii902x_audio_digital_mute, .get_eld = sii902x_audio_get_eld, + .get_dai_id = sii902x_audio_get_dai_id, }; static int sii902x_audio_codec_init(struct sii902x *sii902x, @@ -750,10 +775,11 @@ static int sii902x_audio_codec_init(struct sii902x *sii902x, sii902x->audio.i2s_fifo_sequence[i] |= audio_fifo_id[i] | i2s_lane_id[lanes[i]] | SII902X_TPI_I2S_FIFO_ENABLE; + sii902x->audio.mclk = devm_clk_get_optional(dev, "mclk"); if (IS_ERR(sii902x->audio.mclk)) { dev_err(dev, "%s: No clock (audio mclk) found: %ld\n", __func__, PTR_ERR(sii902x->audio.mclk)); - return 0; + return PTR_ERR(sii902x->audio.mclk); } sii902x->audio.pdev = platform_device_register_data( diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c index c6490949d9db..83b94b66e464 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi.c @@ -508,8 +508,14 @@ static void hdmi_set_cts_n(struct dw_hdmi *hdmi, unsigned int cts, /* nshift factor = 0 */ hdmi_modb(hdmi, 0, HDMI_AUD_CTS3_N_SHIFT_MASK, HDMI_AUD_CTS3); - hdmi_writeb(hdmi, ((cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK) | - HDMI_AUD_CTS3_CTS_MANUAL, HDMI_AUD_CTS3); + /* Use automatic CTS generation mode when CTS is not set */ + if (cts) + hdmi_writeb(hdmi, ((cts >> 16) & + HDMI_AUD_CTS3_AUDCTS19_16_MASK) | + HDMI_AUD_CTS3_CTS_MANUAL, + HDMI_AUD_CTS3); + else + hdmi_writeb(hdmi, 0, HDMI_AUD_CTS3); hdmi_writeb(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2); hdmi_writeb(hdmi, cts & 0xff, HDMI_AUD_CTS1); @@ -579,24 +585,33 @@ static void hdmi_set_clk_regenerator(struct dw_hdmi *hdmi, { unsigned long ftdms = pixel_clk; unsigned int n, cts; + u8 config3; u64 tmp; n = hdmi_compute_n(sample_rate, pixel_clk); - /* - * Compute the CTS value from the N value. Note that CTS and N - * can be up to 20 bits in total, so we need 64-bit math. Also - * note that our TDMS clock is not fully accurate; it is accurate - * to kHz. This can introduce an unnecessary remainder in the - * calculation below, so we don't try to warn about that. - */ - tmp = (u64)ftdms * n; - do_div(tmp, 128 * sample_rate); - cts = tmp; + config3 = hdmi_readb(hdmi, HDMI_CONFIG3_ID); - dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n", - __func__, sample_rate, ftdms / 1000000, (ftdms / 1000) % 1000, - n, cts); + /* Only compute CTS when using internal AHB audio */ + if (config3 & HDMI_CONFIG3_AHBAUDDMA) { + /* + * Compute the CTS value from the N value. Note that CTS and N + * can be up to 20 bits in total, so we need 64-bit math. Also + * note that our TDMS clock is not fully accurate; it is + * accurate to kHz. This can introduce an unnecessary remainder + * in the calculation below, so we don't try to warn about that. + */ + tmp = (u64)ftdms * n; + do_div(tmp, 128 * sample_rate); + cts = tmp; + + dev_dbg(hdmi->dev, "%s: fs=%uHz ftdms=%lu.%03luMHz N=%d cts=%d\n", + __func__, sample_rate, + ftdms / 1000000, (ftdms / 1000) % 1000, + n, cts); + } else { + cts = 0; + } spin_lock_irq(&hdmi->audio_lock); hdmi->audio_n = n; @@ -2185,8 +2200,10 @@ static int dw_hdmi_bridge_attach(struct drm_bridge *bridge) drm_connector_helper_add(connector, &dw_hdmi_connector_helper_funcs); - drm_connector_init(bridge->dev, connector, &dw_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA); + drm_connector_init_with_ddc(bridge->dev, connector, + &dw_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + hdmi->ddc); drm_connector_attach_encoder(connector, encoder); diff --git a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c index 281c58bab1a1..675442bfc1bd 100644 --- a/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c +++ b/drivers/gpu/drm/bridge/synopsys/dw-mipi-dsi.c @@ -10,6 +10,7 @@ #include <linux/clk.h> #include <linux/component.h> +#include <linux/debugfs.h> #include <linux/iopoll.h> #include <linux/module.h> #include <linux/of_device.h> @@ -89,6 +90,8 @@ #define VID_MODE_TYPE_NON_BURST_SYNC_EVENTS 0x1 #define VID_MODE_TYPE_BURST 0x2 #define VID_MODE_TYPE_MASK 0x3 +#define VID_MODE_VPG_ENABLE BIT(16) +#define VID_MODE_VPG_HORIZONTAL BIT(24) #define DSI_VID_PKT_SIZE 0x3c #define VID_PKT_SIZE(p) ((p) & 0x3fff) @@ -233,6 +236,13 @@ struct dw_mipi_dsi { u32 format; unsigned long mode_flags; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs; + + bool vpg; + bool vpg_horizontal; +#endif /* CONFIG_DEBUG_FS */ + struct dw_mipi_dsi *master; /* dual-dsi master ptr */ struct dw_mipi_dsi *slave; /* dual-dsi slave ptr */ @@ -518,6 +528,13 @@ static void dw_mipi_dsi_video_mode_config(struct dw_mipi_dsi *dsi) else val |= VID_MODE_TYPE_NON_BURST_SYNC_EVENTS; +#ifdef CONFIG_DEBUG_FS + if (dsi->vpg) { + val |= VID_MODE_VPG_ENABLE; + val |= dsi->vpg_horizontal ? VID_MODE_VPG_HORIZONTAL : 0; + } +#endif /* CONFIG_DEBUG_FS */ + dsi_write(dsi, DSI_VID_MODE_CFG, val); } @@ -930,6 +947,33 @@ static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = { .attach = dw_mipi_dsi_bridge_attach, }; +#ifdef CONFIG_DEBUG_FS + +static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi) +{ + dsi->debugfs = debugfs_create_dir(dev_name(dsi->dev), NULL); + if (IS_ERR(dsi->debugfs)) { + dev_err(dsi->dev, "failed to create debugfs root\n"); + return; + } + + debugfs_create_bool("vpg", 0660, dsi->debugfs, &dsi->vpg); + debugfs_create_bool("vpg_horizontal", 0660, dsi->debugfs, + &dsi->vpg_horizontal); +} + +static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) +{ + debugfs_remove_recursive(dsi->debugfs); +} + +#else + +static void dw_mipi_dsi_debugfs_init(struct dw_mipi_dsi *dsi) { } +static void dw_mipi_dsi_debugfs_remove(struct dw_mipi_dsi *dsi) { } + +#endif /* CONFIG_DEBUG_FS */ + static struct dw_mipi_dsi * __dw_mipi_dsi_probe(struct platform_device *pdev, const struct dw_mipi_dsi_plat_data *plat_data) @@ -1000,6 +1044,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, clk_disable_unprepare(dsi->pclk); } + dw_mipi_dsi_debugfs_init(dsi); pm_runtime_enable(dev); dsi->dsi_host.ops = &dw_mipi_dsi_host_ops; @@ -1007,6 +1052,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev, ret = mipi_dsi_host_register(&dsi->dsi_host); if (ret) { dev_err(dev, "Failed to register MIPI host: %d\n", ret); + dw_mipi_dsi_debugfs_remove(dsi); return ERR_PTR(ret); } @@ -1024,6 +1070,7 @@ static void __dw_mipi_dsi_remove(struct dw_mipi_dsi *dsi) mipi_dsi_host_unregister(&dsi->dsi_host); pm_runtime_disable(dsi->dev); + dw_mipi_dsi_debugfs_remove(dsi); } void dw_mipi_dsi_set_slave(struct dw_mipi_dsi *dsi, struct dw_mipi_dsi *slave) diff --git a/drivers/gpu/drm/bridge/tc358767.c b/drivers/gpu/drm/bridge/tc358767.c index 13ade28a36a8..42f03a985ac0 100644 --- a/drivers/gpu/drm/bridge/tc358767.c +++ b/drivers/gpu/drm/bridge/tc358767.c @@ -15,6 +15,7 @@ * Author: Rob Clark <robdclark@gmail.com> */ +#include <linux/bitfield.h> #include <linux/clk.h> #include <linux/device.h> #include <linux/gpio/consumer.h> @@ -47,6 +48,7 @@ /* Video Path */ #define VPCTRL0 0x0450 +#define VSDELAY GENMASK(31, 20) #define OPXLFMT_RGB666 (0 << 8) #define OPXLFMT_RGB888 (1 << 8) #define FRMSYNC_DISABLED (0 << 4) /* Video Timing Gen Disabled */ @@ -54,9 +56,17 @@ #define MSF_DISABLED (0 << 0) /* Magic Square FRC disabled */ #define MSF_ENABLED (1 << 0) /* Magic Square FRC enabled */ #define HTIM01 0x0454 +#define HPW GENMASK(8, 0) +#define HBPR GENMASK(24, 16) #define HTIM02 0x0458 +#define HDISPR GENMASK(10, 0) +#define HFPR GENMASK(24, 16) #define VTIM01 0x045c +#define VSPR GENMASK(7, 0) +#define VBPR GENMASK(23, 16) #define VTIM02 0x0460 +#define VFPR GENMASK(23, 16) +#define VDISPR GENMASK(10, 0) #define VFUEN0 0x0464 #define VFUEN BIT(0) /* Video Frame Timing Upload */ @@ -70,6 +80,13 @@ #define DP0_VIDSRC_DSI_RX (1 << 0) #define DP0_VIDSRC_DPI_RX (2 << 0) #define DP0_VIDSRC_COLOR_BAR (3 << 0) +#define SYSRSTENB 0x050c +#define ENBI2C (1 << 0) +#define ENBLCD0 (1 << 2) +#define ENBBM (1 << 3) +#define ENBDSIRX (1 << 4) +#define ENBREG (1 << 5) +#define ENBHDCP (1 << 8) #define GPIOM 0x0540 #define GPIOC 0x0544 #define GPIOO 0x0548 @@ -99,19 +116,35 @@ /* Main Channel */ #define DP0_SECSAMPLE 0x0640 #define DP0_VIDSYNCDELAY 0x0644 +#define VID_SYNC_DLY GENMASK(15, 0) +#define THRESH_DLY GENMASK(31, 16) + #define DP0_TOTALVAL 0x0648 +#define H_TOTAL GENMASK(15, 0) +#define V_TOTAL GENMASK(31, 16) #define DP0_STARTVAL 0x064c +#define H_START GENMASK(15, 0) +#define V_START GENMASK(31, 16) #define DP0_ACTIVEVAL 0x0650 +#define H_ACT GENMASK(15, 0) +#define V_ACT GENMASK(31, 16) + #define DP0_SYNCVAL 0x0654 +#define VS_WIDTH GENMASK(30, 16) +#define HS_WIDTH GENMASK(14, 0) #define SYNCVAL_HS_POL_ACTIVE_LOW (1 << 15) #define SYNCVAL_VS_POL_ACTIVE_LOW (1 << 31) #define DP0_MISC 0x0658 #define TU_SIZE_RECOMMENDED (63) /* LSCLK cycles per TU */ +#define MAX_TU_SYMBOL GENMASK(28, 23) +#define TU_SIZE GENMASK(21, 16) #define BPC_6 (0 << 5) #define BPC_8 (1 << 5) /* AUX channel */ #define DP0_AUXCFG0 0x0660 +#define DP0_AUXCFG0_BSIZE GENMASK(11, 8) +#define DP0_AUXCFG0_ADDR_ONLY BIT(4) #define DP0_AUXCFG1 0x0664 #define AUX_RX_FILTER_EN BIT(16) @@ -119,10 +152,10 @@ #define DP0_AUXWDATA(i) (0x066c + (i) * 4) #define DP0_AUXRDATA(i) (0x067c + (i) * 4) #define DP0_AUXSTATUS 0x068c -#define AUX_STATUS_MASK 0xf0 -#define AUX_STATUS_SHIFT 4 -#define AUX_TIMEOUT BIT(1) -#define AUX_BUSY BIT(0) +#define AUX_BYTES GENMASK(15, 8) +#define AUX_STATUS GENMASK(7, 4) +#define AUX_TIMEOUT BIT(1) +#define AUX_BUSY BIT(0) #define DP0_AUXI2CADR 0x0698 /* Link Training */ @@ -183,6 +216,12 @@ /* Test & Debug */ #define TSTCTL 0x0a00 +#define COLOR_R GENMASK(31, 24) +#define COLOR_G GENMASK(23, 16) +#define COLOR_B GENMASK(15, 8) +#define ENI2CFILTER BIT(4) +#define COLOR_BAR_MODE GENMASK(1, 0) +#define COLOR_BAR_MODE_BARS 2 #define PLL_DBG 0x0a04 static bool tc_test_pattern; @@ -241,137 +280,131 @@ static inline struct tc_data *connector_to_tc(struct drm_connector *c) return container_of(c, struct tc_data, connector); } -/* Simple macros to avoid repeated error checks */ -#define tc_write(reg, var) \ - do { \ - ret = regmap_write(tc->regmap, reg, var); \ - if (ret) \ - goto err; \ - } while (0) -#define tc_read(reg, var) \ - do { \ - ret = regmap_read(tc->regmap, reg, var); \ - if (ret) \ - goto err; \ - } while (0) - -static inline int tc_poll_timeout(struct regmap *map, unsigned int addr, +static inline int tc_poll_timeout(struct tc_data *tc, unsigned int addr, unsigned int cond_mask, unsigned int cond_value, unsigned long sleep_us, u64 timeout_us) { - ktime_t timeout = ktime_add_us(ktime_get(), timeout_us); unsigned int val; - int ret; - for (;;) { - ret = regmap_read(map, addr, &val); - if (ret) - break; - if ((val & cond_mask) == cond_value) - break; - if (timeout_us && ktime_compare(ktime_get(), timeout) > 0) { - ret = regmap_read(map, addr, &val); - break; - } - if (sleep_us) - usleep_range((sleep_us >> 2) + 1, sleep_us); - } - return ret ?: (((val & cond_mask) == cond_value) ? 0 : -ETIMEDOUT); + return regmap_read_poll_timeout(tc->regmap, addr, val, + (val & cond_mask) == cond_value, + sleep_us, timeout_us); } -static int tc_aux_wait_busy(struct tc_data *tc, unsigned int timeout_ms) +static int tc_aux_wait_busy(struct tc_data *tc) { - return tc_poll_timeout(tc->regmap, DP0_AUXSTATUS, AUX_BUSY, 0, - 1000, 1000 * timeout_ms); + return tc_poll_timeout(tc, DP0_AUXSTATUS, AUX_BUSY, 0, 1000, 100000); } -static int tc_aux_get_status(struct tc_data *tc, u8 *reply) +static int tc_aux_write_data(struct tc_data *tc, const void *data, + size_t size) { - int ret; - u32 value; + u32 auxwdata[DP_AUX_MAX_PAYLOAD_BYTES / sizeof(u32)] = { 0 }; + int ret, count = ALIGN(size, sizeof(u32)); - ret = regmap_read(tc->regmap, DP0_AUXSTATUS, &value); - if (ret < 0) + memcpy(auxwdata, data, size); + + ret = regmap_raw_write(tc->regmap, DP0_AUXWDATA(0), auxwdata, count); + if (ret) return ret; - if (value & AUX_BUSY) { - dev_err(tc->dev, "aux busy!\n"); - return -EBUSY; - } + return size; +} - if (value & AUX_TIMEOUT) { - dev_err(tc->dev, "aux access timeout!\n"); - return -ETIMEDOUT; - } +static int tc_aux_read_data(struct tc_data *tc, void *data, size_t size) +{ + u32 auxrdata[DP_AUX_MAX_PAYLOAD_BYTES / sizeof(u32)]; + int ret, count = ALIGN(size, sizeof(u32)); - *reply = (value & AUX_STATUS_MASK) >> AUX_STATUS_SHIFT; - return 0; + ret = regmap_raw_read(tc->regmap, DP0_AUXRDATA(0), auxrdata, count); + if (ret) + return ret; + + memcpy(data, auxrdata, size); + + return size; +} + +static u32 tc_auxcfg0(struct drm_dp_aux_msg *msg, size_t size) +{ + u32 auxcfg0 = msg->request; + + if (size) + auxcfg0 |= FIELD_PREP(DP0_AUXCFG0_BSIZE, size - 1); + else + auxcfg0 |= DP0_AUXCFG0_ADDR_ONLY; + + return auxcfg0; } static ssize_t tc_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg) { struct tc_data *tc = aux_to_tc(aux); - size_t size = min_t(size_t, 8, msg->size); + size_t size = min_t(size_t, DP_AUX_MAX_PAYLOAD_BYTES - 1, msg->size); u8 request = msg->request & ~DP_AUX_I2C_MOT; - u8 *buf = msg->buffer; - u32 tmp = 0; - int i = 0; + u32 auxstatus; int ret; - if (size == 0) - return 0; - - ret = tc_aux_wait_busy(tc, 100); + ret = tc_aux_wait_busy(tc); if (ret) - goto err; + return ret; - if (request == DP_AUX_I2C_WRITE || request == DP_AUX_NATIVE_WRITE) { - /* Store data */ - while (i < size) { - if (request == DP_AUX_NATIVE_WRITE) - tmp = tmp | (buf[i] << (8 * (i & 0x3))); - else - tmp = (tmp << 8) | buf[i]; - i++; - if (((i % 4) == 0) || (i == size)) { - tc_write(DP0_AUXWDATA((i - 1) >> 2), tmp); - tmp = 0; - } + switch (request) { + case DP_AUX_NATIVE_READ: + case DP_AUX_I2C_READ: + break; + case DP_AUX_NATIVE_WRITE: + case DP_AUX_I2C_WRITE: + if (size) { + ret = tc_aux_write_data(tc, msg->buffer, size); + if (ret < 0) + return ret; } - } else if (request != DP_AUX_I2C_READ && - request != DP_AUX_NATIVE_READ) { + break; + default: return -EINVAL; } /* Store address */ - tc_write(DP0_AUXADDR, msg->address); + ret = regmap_write(tc->regmap, DP0_AUXADDR, msg->address); + if (ret) + return ret; /* Start transfer */ - tc_write(DP0_AUXCFG0, ((size - 1) << 8) | request); + ret = regmap_write(tc->regmap, DP0_AUXCFG0, tc_auxcfg0(msg, size)); + if (ret) + return ret; - ret = tc_aux_wait_busy(tc, 100); + ret = tc_aux_wait_busy(tc); if (ret) - goto err; + return ret; - ret = tc_aux_get_status(tc, &msg->reply); + ret = regmap_read(tc->regmap, DP0_AUXSTATUS, &auxstatus); if (ret) - goto err; + return ret; - if (request == DP_AUX_I2C_READ || request == DP_AUX_NATIVE_READ) { - /* Read data */ - while (i < size) { - if ((i % 4) == 0) - tc_read(DP0_AUXRDATA(i >> 2), &tmp); - buf[i] = tmp & 0xff; - tmp = tmp >> 8; - i++; - } + if (auxstatus & AUX_TIMEOUT) + return -ETIMEDOUT; + /* + * For some reason address-only DP_AUX_I2C_WRITE (MOT), still + * reports 1 byte transferred in its status. To deal we that + * we ignore aux_bytes field if we know that this was an + * address-only transfer + */ + if (size) + size = FIELD_GET(AUX_BYTES, auxstatus); + msg->reply = FIELD_GET(AUX_STATUS, auxstatus); + + switch (request) { + case DP_AUX_NATIVE_READ: + case DP_AUX_I2C_READ: + if (size) + return tc_aux_read_data(tc, msg->buffer, size); + break; } return size; -err: - return ret; } static const char * const training_pattern1_errors[] = { @@ -411,10 +444,18 @@ static u32 tc_srcctrl(struct tc_data *tc) return reg; } -static void tc_wait_pll_lock(struct tc_data *tc) +static int tc_pllupdate(struct tc_data *tc, unsigned int pllctrl) { + int ret; + + ret = regmap_write(tc->regmap, pllctrl, PLLUPDATE | PLLEN); + if (ret) + return ret; + /* Wait for PLL to lock: up to 2.09 ms, depending on refclk */ usleep_range(3000, 6000); + + return 0; } static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) @@ -428,6 +469,7 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) int ext_div[] = {1, 2, 3, 5, 7}; int best_pixelclock = 0; int vco_hi = 0; + u32 pxl_pllparam; dev_dbg(tc->dev, "PLL: requested %d pixelclock, ref %d\n", pixelclock, refclk); @@ -497,24 +539,23 @@ static int tc_pxl_pll_en(struct tc_data *tc, u32 refclk, u32 pixelclock) best_mul = 0; /* Power up PLL and switch to bypass */ - tc_write(PXL_PLLCTRL, PLLBYP | PLLEN); - - tc_write(PXL_PLLPARAM, - (vco_hi << 24) | /* For PLL VCO >= 300 MHz = 1 */ - (ext_div[best_pre] << 20) | /* External Pre-divider */ - (ext_div[best_post] << 16) | /* External Post-divider */ - IN_SEL_REFCLK | /* Use RefClk as PLL input */ - (best_div << 8) | /* Divider for PLL RefClk */ - (best_mul << 0)); /* Multiplier for PLL */ + ret = regmap_write(tc->regmap, PXL_PLLCTRL, PLLBYP | PLLEN); + if (ret) + return ret; - /* Force PLL parameter update and disable bypass */ - tc_write(PXL_PLLCTRL, PLLUPDATE | PLLEN); + pxl_pllparam = vco_hi << 24; /* For PLL VCO >= 300 MHz = 1 */ + pxl_pllparam |= ext_div[best_pre] << 20; /* External Pre-divider */ + pxl_pllparam |= ext_div[best_post] << 16; /* External Post-divider */ + pxl_pllparam |= IN_SEL_REFCLK; /* Use RefClk as PLL input */ + pxl_pllparam |= best_div << 8; /* Divider for PLL RefClk */ + pxl_pllparam |= best_mul; /* Multiplier for PLL */ - tc_wait_pll_lock(tc); + ret = regmap_write(tc->regmap, PXL_PLLPARAM, pxl_pllparam); + if (ret) + return ret; - return 0; -err: - return ret; + /* Force PLL parameter update and disable bypass */ + return tc_pllupdate(tc, PXL_PLLCTRL); } static int tc_pxl_pll_dis(struct tc_data *tc) @@ -525,7 +566,6 @@ static int tc_pxl_pll_dis(struct tc_data *tc) static int tc_stream_clock_calc(struct tc_data *tc) { - int ret; /* * If the Stream clock and Link Symbol clock are * asynchronous with each other, the value of M changes over @@ -541,56 +581,63 @@ static int tc_stream_clock_calc(struct tc_data *tc) * M/N = f_STRMCLK / f_LSCLK * */ - tc_write(DP0_VIDMNGEN1, 32768); - - return 0; -err: - return ret; + return regmap_write(tc->regmap, DP0_VIDMNGEN1, 32768); } -static int tc_aux_link_setup(struct tc_data *tc) +static int tc_set_syspllparam(struct tc_data *tc) { unsigned long rate; - u32 value; - int ret; + u32 pllparam = SYSCLK_SEL_LSCLK | LSCLK_DIV_2; rate = clk_get_rate(tc->refclk); switch (rate) { case 38400000: - value = REF_FREQ_38M4; + pllparam |= REF_FREQ_38M4; break; case 26000000: - value = REF_FREQ_26M; + pllparam |= REF_FREQ_26M; break; case 19200000: - value = REF_FREQ_19M2; + pllparam |= REF_FREQ_19M2; break; case 13000000: - value = REF_FREQ_13M; + pllparam |= REF_FREQ_13M; break; default: dev_err(tc->dev, "Invalid refclk rate: %lu Hz\n", rate); return -EINVAL; } - /* Setup DP-PHY / PLL */ - value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; - tc_write(SYS_PLLPARAM, value); + return regmap_write(tc->regmap, SYS_PLLPARAM, pllparam); +} + +static int tc_aux_link_setup(struct tc_data *tc) +{ + int ret; + u32 dp0_auxcfg1; - tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | PHY_A0_EN); + /* Setup DP-PHY / PLL */ + ret = tc_set_syspllparam(tc); + if (ret) + goto err; + ret = regmap_write(tc->regmap, DP_PHY_CTRL, + BGREN | PWR_SW_EN | PHY_A0_EN); + if (ret) + goto err; /* * Initially PLLs are in bypass. Force PLL parameter update, * disable PLL bypass, enable PLL */ - tc_write(DP0_PLLCTRL, PLLUPDATE | PLLEN); - tc_wait_pll_lock(tc); + ret = tc_pllupdate(tc, DP0_PLLCTRL); + if (ret) + goto err; - tc_write(DP1_PLLCTRL, PLLUPDATE | PLLEN); - tc_wait_pll_lock(tc); + ret = tc_pllupdate(tc, DP1_PLLCTRL); + if (ret) + goto err; - ret = tc_poll_timeout(tc->regmap, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, - 1000); + ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000); if (ret == -ETIMEDOUT) { dev_err(tc->dev, "Timeout waiting for PHY to become ready"); return ret; @@ -599,9 +646,13 @@ static int tc_aux_link_setup(struct tc_data *tc) } /* Setup AUX link */ - tc_write(DP0_AUXCFG1, AUX_RX_FILTER_EN | - (0x06 << 8) | /* Aux Bit Period Calculator Threshold */ - (0x3f << 0)); /* Aux Response Timeout Timer */ + dp0_auxcfg1 = AUX_RX_FILTER_EN; + dp0_auxcfg1 |= 0x06 << 8; /* Aux Bit Period Calculator Threshold */ + dp0_auxcfg1 |= 0x3f << 0; /* Aux Response Timeout Timer */ + + ret = regmap_write(tc->regmap, DP0_AUXCFG1, dp0_auxcfg1); + if (ret) + goto err; return 0; err: @@ -612,8 +663,7 @@ err: static int tc_get_display_props(struct tc_data *tc) { int ret; - /* temp buffer */ - u8 tmp[8]; + u8 reg; /* Read DP Rx Link Capability */ ret = drm_dp_link_probe(&tc->aux, &tc->link.base); @@ -629,21 +679,21 @@ static int tc_get_display_props(struct tc_data *tc) tc->link.base.num_lanes = 2; } - ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, tmp); + ret = drm_dp_dpcd_readb(&tc->aux, DP_MAX_DOWNSPREAD, ®); if (ret < 0) goto err_dpcd_read; - tc->link.spread = tmp[0] & DP_MAX_DOWNSPREAD_0_5; + tc->link.spread = reg & DP_MAX_DOWNSPREAD_0_5; - ret = drm_dp_dpcd_readb(&tc->aux, DP_MAIN_LINK_CHANNEL_CODING, tmp); + ret = drm_dp_dpcd_readb(&tc->aux, DP_MAIN_LINK_CHANNEL_CODING, ®); if (ret < 0) goto err_dpcd_read; tc->link.scrambler_dis = false; /* read assr */ - ret = drm_dp_dpcd_readb(&tc->aux, DP_EDP_CONFIGURATION_SET, tmp); + ret = drm_dp_dpcd_readb(&tc->aux, DP_EDP_CONFIGURATION_SET, ®); if (ret < 0) goto err_dpcd_read; - tc->link.assr = tmp[0] & DP_ALTERNATE_SCRAMBLER_RESET_ENABLE; + tc->link.assr = reg & DP_ALTERNATE_SCRAMBLER_RESET_ENABLE; dev_dbg(tc->dev, "DPCD rev: %d.%d, rate: %s, lanes: %d, framing: %s\n", tc->link.base.revision >> 4, tc->link.base.revision & 0x0f, @@ -677,6 +727,7 @@ static int tc_set_video_mode(struct tc_data *tc, int upper_margin = mode->vtotal - mode->vsync_end; int lower_margin = mode->vsync_start - mode->vdisplay; int vsync_len = mode->vsync_end - mode->vsync_start; + u32 dp0_syncval; /* * Recommended maximum number of symbols transferred in a transfer unit: @@ -701,156 +752,193 @@ static int tc_set_video_mode(struct tc_data *tc, * assume we do not need any delay when DPI is a source of * sync signals */ - tc_write(VPCTRL0, (0 << 20) /* VSDELAY */ | - OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED); - tc_write(HTIM01, (ALIGN(left_margin, 2) << 16) | /* H back porch */ - (ALIGN(hsync_len, 2) << 0)); /* Hsync */ - tc_write(HTIM02, (ALIGN(right_margin, 2) << 16) | /* H front porch */ - (ALIGN(mode->hdisplay, 2) << 0)); /* width */ - tc_write(VTIM01, (upper_margin << 16) | /* V back porch */ - (vsync_len << 0)); /* Vsync */ - tc_write(VTIM02, (lower_margin << 16) | /* V front porch */ - (mode->vdisplay << 0)); /* height */ - tc_write(VFUEN0, VFUEN); /* update settings */ + ret = regmap_write(tc->regmap, VPCTRL0, + FIELD_PREP(VSDELAY, 0) | + OPXLFMT_RGB888 | FRMSYNC_DISABLED | MSF_DISABLED); + if (ret) + return ret; + + ret = regmap_write(tc->regmap, HTIM01, + FIELD_PREP(HBPR, ALIGN(left_margin, 2)) | + FIELD_PREP(HPW, ALIGN(hsync_len, 2))); + if (ret) + return ret; + + ret = regmap_write(tc->regmap, HTIM02, + FIELD_PREP(HDISPR, ALIGN(mode->hdisplay, 2)) | + FIELD_PREP(HFPR, ALIGN(right_margin, 2))); + if (ret) + return ret; + + ret = regmap_write(tc->regmap, VTIM01, + FIELD_PREP(VBPR, upper_margin) | + FIELD_PREP(VSPR, vsync_len)); + if (ret) + return ret; + + ret = regmap_write(tc->regmap, VTIM02, + FIELD_PREP(VFPR, lower_margin) | + FIELD_PREP(VDISPR, mode->vdisplay)); + if (ret) + return ret; + + ret = regmap_write(tc->regmap, VFUEN0, VFUEN); /* update settings */ + if (ret) + return ret; /* Test pattern settings */ - tc_write(TSTCTL, - (120 << 24) | /* Red Color component value */ - (20 << 16) | /* Green Color component value */ - (99 << 8) | /* Blue Color component value */ - (1 << 4) | /* Enable I2C Filter */ - (2 << 0) | /* Color bar Mode */ - 0); + ret = regmap_write(tc->regmap, TSTCTL, + FIELD_PREP(COLOR_R, 120) | + FIELD_PREP(COLOR_G, 20) | + FIELD_PREP(COLOR_B, 99) | + ENI2CFILTER | + FIELD_PREP(COLOR_BAR_MODE, COLOR_BAR_MODE_BARS)); + if (ret) + return ret; /* DP Main Stream Attributes */ vid_sync_dly = hsync_len + left_margin + mode->hdisplay; - tc_write(DP0_VIDSYNCDELAY, - (max_tu_symbol << 16) | /* thresh_dly */ - (vid_sync_dly << 0)); + ret = regmap_write(tc->regmap, DP0_VIDSYNCDELAY, + FIELD_PREP(THRESH_DLY, max_tu_symbol) | + FIELD_PREP(VID_SYNC_DLY, vid_sync_dly)); + + ret = regmap_write(tc->regmap, DP0_TOTALVAL, + FIELD_PREP(H_TOTAL, mode->htotal) | + FIELD_PREP(V_TOTAL, mode->vtotal)); + if (ret) + return ret; + + ret = regmap_write(tc->regmap, DP0_STARTVAL, + FIELD_PREP(H_START, left_margin + hsync_len) | + FIELD_PREP(V_START, upper_margin + vsync_len)); + if (ret) + return ret; - tc_write(DP0_TOTALVAL, (mode->vtotal << 16) | (mode->htotal)); + ret = regmap_write(tc->regmap, DP0_ACTIVEVAL, + FIELD_PREP(V_ACT, mode->vdisplay) | + FIELD_PREP(H_ACT, mode->hdisplay)); + if (ret) + return ret; - tc_write(DP0_STARTVAL, - ((upper_margin + vsync_len) << 16) | - ((left_margin + hsync_len) << 0)); + dp0_syncval = FIELD_PREP(VS_WIDTH, vsync_len) | + FIELD_PREP(HS_WIDTH, hsync_len); - tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay)); + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + dp0_syncval |= SYNCVAL_VS_POL_ACTIVE_LOW; - tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) | - ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) | - ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0)); + if (mode->flags & DRM_MODE_FLAG_NHSYNC) + dp0_syncval |= SYNCVAL_HS_POL_ACTIVE_LOW; - tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | - DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888); + ret = regmap_write(tc->regmap, DP0_SYNCVAL, dp0_syncval); + if (ret) + return ret; - tc_write(DP0_MISC, (max_tu_symbol << 23) | (TU_SIZE_RECOMMENDED << 16) | + ret = regmap_write(tc->regmap, DPIPXLFMT, + VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW | + DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | + DPI_BPP_RGB888); + if (ret) + return ret; + + ret = regmap_write(tc->regmap, DP0_MISC, + FIELD_PREP(MAX_TU_SYMBOL, max_tu_symbol) | + FIELD_PREP(TU_SIZE, TU_SIZE_RECOMMENDED) | BPC_8); + if (ret) + return ret; return 0; -err: - return ret; } static int tc_wait_link_training(struct tc_data *tc) { - u32 timeout = 1000; u32 value; int ret; - do { - udelay(1); - tc_read(DP0_LTSTAT, &value); - } while ((!(value & LT_LOOPDONE)) && (--timeout)); - - if (timeout == 0) { + ret = tc_poll_timeout(tc, DP0_LTSTAT, LT_LOOPDONE, + LT_LOOPDONE, 1, 1000); + if (ret) { dev_err(tc->dev, "Link training timeout waiting for LT_LOOPDONE!\n"); - return -ETIMEDOUT; + return ret; } - return (value >> 8) & 0x7; + ret = regmap_read(tc->regmap, DP0_LTSTAT, &value); + if (ret) + return ret; -err: - return ret; + return (value >> 8) & 0x7; } static int tc_main_link_enable(struct tc_data *tc) { struct drm_dp_aux *aux = &tc->aux; struct device *dev = tc->dev; - unsigned int rate; u32 dp_phy_ctrl; - int timeout; u32 value; int ret; - u8 tmp[8]; + u8 tmp[DP_LINK_STATUS_SIZE]; dev_dbg(tc->dev, "link enable\n"); - tc_read(DP0CTL, &value); - if (WARN_ON(value & DP_EN)) - tc_write(DP0CTL, 0); + ret = regmap_read(tc->regmap, DP0CTL, &value); + if (ret) + return ret; + + if (WARN_ON(value & DP_EN)) { + ret = regmap_write(tc->regmap, DP0CTL, 0); + if (ret) + return ret; + } - tc_write(DP0_SRCCTRL, tc_srcctrl(tc)); + ret = regmap_write(tc->regmap, DP0_SRCCTRL, tc_srcctrl(tc)); + if (ret) + return ret; /* SSCG and BW27 on DP1 must be set to the same as on DP0 */ - tc_write(DP1_SRCCTRL, + ret = regmap_write(tc->regmap, DP1_SRCCTRL, (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) | ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0)); + if (ret) + return ret; - rate = clk_get_rate(tc->refclk); - switch (rate) { - case 38400000: - value = REF_FREQ_38M4; - break; - case 26000000: - value = REF_FREQ_26M; - break; - case 19200000: - value = REF_FREQ_19M2; - break; - case 13000000: - value = REF_FREQ_13M; - break; - default: - return -EINVAL; - } - value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2; - tc_write(SYS_PLLPARAM, value); + ret = tc_set_syspllparam(tc); + if (ret) + return ret; /* Setup Main Link */ dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN; if (tc->link.base.num_lanes == 2) dp_phy_ctrl |= PHY_2LANE; - tc_write(DP_PHY_CTRL, dp_phy_ctrl); + + ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl); + if (ret) + return ret; /* PLL setup */ - tc_write(DP0_PLLCTRL, PLLUPDATE | PLLEN); - tc_wait_pll_lock(tc); + ret = tc_pllupdate(tc, DP0_PLLCTRL); + if (ret) + return ret; - tc_write(DP1_PLLCTRL, PLLUPDATE | PLLEN); - tc_wait_pll_lock(tc); + ret = tc_pllupdate(tc, DP1_PLLCTRL); + if (ret) + return ret; /* Reset/Enable Main Links */ dp_phy_ctrl |= DP_PHY_RST | PHY_M1_RST | PHY_M0_RST; - tc_write(DP_PHY_CTRL, dp_phy_ctrl); + ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl); usleep_range(100, 200); dp_phy_ctrl &= ~(DP_PHY_RST | PHY_M1_RST | PHY_M0_RST); - tc_write(DP_PHY_CTRL, dp_phy_ctrl); - - timeout = 1000; - do { - tc_read(DP_PHY_CTRL, &value); - udelay(1); - } while ((!(value & PHY_RDY)) && (--timeout)); + ret = regmap_write(tc->regmap, DP_PHY_CTRL, dp_phy_ctrl); - if (timeout == 0) { + ret = tc_poll_timeout(tc, DP_PHY_CTRL, PHY_RDY, PHY_RDY, 1, 1000); + if (ret) { dev_err(dev, "timeout waiting for phy become ready"); - return -ETIMEDOUT; + return ret; } /* Set misc: 8 bits per color */ ret = regmap_update_bits(tc->regmap, DP0_MISC, BPC_8, BPC_8); if (ret) - goto err; + return ret; /* * ASSR mode @@ -903,53 +991,71 @@ static int tc_main_link_enable(struct tc_data *tc) /* Clock-Recovery */ /* Set DPCD 0x102 for Training Pattern 1 */ - tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE | - DP_TRAINING_PATTERN_1); + ret = regmap_write(tc->regmap, DP0_SNKLTCTRL, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_1); + if (ret) + return ret; - tc_write(DP0_LTLOOPCTRL, - (15 << 28) | /* Defer Iteration Count */ - (15 << 24) | /* Loop Iteration Count */ - (0xd << 0)); /* Loop Timer Delay */ + ret = regmap_write(tc->regmap, DP0_LTLOOPCTRL, + (15 << 28) | /* Defer Iteration Count */ + (15 << 24) | /* Loop Iteration Count */ + (0xd << 0)); /* Loop Timer Delay */ + if (ret) + return ret; - tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS | - DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP1); + ret = regmap_write(tc->regmap, DP0_SRCCTRL, + tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS | + DP0_SRCCTRL_AUTOCORRECT | + DP0_SRCCTRL_TP1); + if (ret) + return ret; /* Enable DP0 to start Link Training */ - tc_write(DP0CTL, - ((tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) ? EF_EN : 0) | - DP_EN); + ret = regmap_write(tc->regmap, DP0CTL, + ((tc->link.base.capabilities & + DP_LINK_CAP_ENHANCED_FRAMING) ? EF_EN : 0) | + DP_EN); + if (ret) + return ret; /* wait */ + ret = tc_wait_link_training(tc); if (ret < 0) - goto err; + return ret; if (ret) { dev_err(tc->dev, "Link training phase 1 failed: %s\n", training_pattern1_errors[ret]); - ret = -ENODEV; - goto err; + return -ENODEV; } /* Channel Equalization */ /* Set DPCD 0x102 for Training Pattern 2 */ - tc_write(DP0_SNKLTCTRL, DP_LINK_SCRAMBLING_DISABLE | - DP_TRAINING_PATTERN_2); + ret = regmap_write(tc->regmap, DP0_SNKLTCTRL, + DP_LINK_SCRAMBLING_DISABLE | + DP_TRAINING_PATTERN_2); + if (ret) + return ret; - tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS | - DP0_SRCCTRL_AUTOCORRECT | DP0_SRCCTRL_TP2); + ret = regmap_write(tc->regmap, DP0_SRCCTRL, + tc_srcctrl(tc) | DP0_SRCCTRL_SCRMBLDIS | + DP0_SRCCTRL_AUTOCORRECT | + DP0_SRCCTRL_TP2); + if (ret) + return ret; /* wait */ ret = tc_wait_link_training(tc); if (ret < 0) - goto err; + return ret; if (ret) { dev_err(tc->dev, "Link training phase 2 failed: %s\n", training_pattern2_errors[ret]); - ret = -ENODEV; - goto err; + return -ENODEV; } /* @@ -962,7 +1068,10 @@ static int tc_main_link_enable(struct tc_data *tc) */ /* Clear Training Pattern, set AutoCorrect Mode = 1 */ - tc_write(DP0_SRCCTRL, tc_srcctrl(tc) | DP0_SRCCTRL_AUTOCORRECT); + ret = regmap_write(tc->regmap, DP0_SRCCTRL, tc_srcctrl(tc) | + DP0_SRCCTRL_AUTOCORRECT); + if (ret) + return ret; /* Clear DPCD 0x102 */ /* Note: Can Not use DP0_SNKLTCTRL (0x06E4) short cut */ @@ -1006,7 +1115,7 @@ static int tc_main_link_enable(struct tc_data *tc) dev_err(dev, "0x0205 SINK_STATUS: 0x%02x\n", tmp[3]); dev_err(dev, "0x0206 ADJUST_REQUEST_LANE0_1: 0x%02x\n", tmp[4]); dev_err(dev, "0x0207 ADJUST_REQUEST_LANE2_3: 0x%02x\n", tmp[5]); - goto err; + return ret; } return 0; @@ -1015,7 +1124,6 @@ err_dpcd_read: return ret; err_dpcd_write: dev_err(tc->dev, "Failed to write DPCD: %d\n", ret); -err: return ret; } @@ -1025,12 +1133,11 @@ static int tc_main_link_disable(struct tc_data *tc) dev_dbg(tc->dev, "link disable\n"); - tc_write(DP0_SRCCTRL, 0); - tc_write(DP0CTL, 0); + ret = regmap_write(tc->regmap, DP0_SRCCTRL, 0); + if (ret) + return ret; - return 0; -err: - return ret; + return regmap_write(tc->regmap, DP0CTL, 0); } static int tc_stream_enable(struct tc_data *tc) @@ -1045,7 +1152,7 @@ static int tc_stream_enable(struct tc_data *tc) ret = tc_pxl_pll_en(tc, clk_get_rate(tc->refclk), 1000 * tc->mode.clock); if (ret) - goto err; + return ret; } ret = tc_set_video_mode(tc, &tc->mode); @@ -1060,7 +1167,9 @@ static int tc_stream_enable(struct tc_data *tc) value = VID_MN_GEN | DP_EN; if (tc->link.base.capabilities & DP_LINK_CAP_ENHANCED_FRAMING) value |= EF_EN; - tc_write(DP0CTL, value); + ret = regmap_write(tc->regmap, DP0CTL, value); + if (ret) + return ret; /* * VID_EN assertion should be delayed by at least N * LSCLK * cycles from the time VID_MN_GEN is enabled in order to @@ -1070,36 +1179,35 @@ static int tc_stream_enable(struct tc_data *tc) */ usleep_range(500, 1000); value |= VID_EN; - tc_write(DP0CTL, value); + ret = regmap_write(tc->regmap, DP0CTL, value); + if (ret) + return ret; /* Set input interface */ value = DP0_AUDSRC_NO_INPUT; if (tc_test_pattern) value |= DP0_VIDSRC_COLOR_BAR; else value |= DP0_VIDSRC_DPI_RX; - tc_write(SYSCTRL, value); + ret = regmap_write(tc->regmap, SYSCTRL, value); + if (ret) + return ret; return 0; -err: - return ret; } static int tc_stream_disable(struct tc_data *tc) { int ret; - u32 val; dev_dbg(tc->dev, "disable video stream\n"); - tc_read(DP0CTL, &val); - val &= ~VID_EN; - tc_write(DP0CTL, val); + ret = regmap_update_bits(tc->regmap, DP0CTL, VID_EN, 0); + if (ret) + return ret; tc_pxl_pll_dis(tc); return 0; -err: - return ret; } static void tc_bridge_pre_enable(struct drm_bridge *bridge) @@ -1251,7 +1359,9 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne return connector_status_unknown; } - tc_read(GPIOI, &val); + ret = regmap_read(tc->regmap, GPIOI, &val); + if (ret) + return connector_status_unknown; conn = val & BIT(tc->hpd_pin); @@ -1259,9 +1369,6 @@ static enum drm_connector_status tc_connector_detect(struct drm_connector *conne return connector_status_connected; else return connector_status_disconnected; - -err: - return connector_status_unknown; } static const struct drm_connector_funcs tc_connector_funcs = { @@ -1497,6 +1604,22 @@ static int tc_probe(struct i2c_client *client, const struct i2c_device_id *id) tc->assr = (tc->rev == 0x6601); /* Enable ASSR for eDP panels */ + if (!tc->reset_gpio) { + /* + * If the reset pin isn't present, do a software reset. It isn't + * as thorough as the hardware reset, as we can't reset the I2C + * communication block for obvious reasons, but it's getting the + * chip into a defined state. + */ + regmap_update_bits(tc->regmap, SYSRSTENB, + ENBLCD0 | ENBBM | ENBDSIRX | ENBREG | ENBHDCP, + 0); + regmap_update_bits(tc->regmap, SYSRSTENB, + ENBLCD0 | ENBBM | ENBDSIRX | ENBREG | ENBHDCP, + ENBLCD0 | ENBBM | ENBDSIRX | ENBREG | ENBHDCP); + usleep_range(5000, 10000); + } + if (tc->hpd_pin >= 0) { u32 lcnt_reg = tc->hpd_pin == 0 ? INT_GP0_LCNT : INT_GP1_LCNT; u32 h_lc = INT_GPIO_H(tc->hpd_pin) | INT_GPIO_LC(tc->hpd_pin); diff --git a/drivers/gpu/drm/bridge/ti-sn65dsi86.c b/drivers/gpu/drm/bridge/ti-sn65dsi86.c index b77a52d05061..0a580957c8cf 100644 --- a/drivers/gpu/drm/bridge/ti-sn65dsi86.c +++ b/drivers/gpu/drm/bridge/ti-sn65dsi86.c @@ -1,9 +1,11 @@ // SPDX-License-Identifier: GPL-2.0 /* * Copyright (c) 2018, The Linux Foundation. All rights reserved. + * datasheet: http://www.ti.com/lit/ds/symlink/sn65dsi86.pdf */ #include <linux/clk.h> +#include <linux/debugfs.h> #include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/iopoll.h> @@ -90,6 +92,7 @@ struct ti_sn_bridge { struct drm_dp_aux aux; struct drm_bridge bridge; struct drm_connector connector; + struct dentry *debugfs; struct device_node *host_node; struct mipi_dsi_device *dsi; struct clk *refclk; @@ -155,6 +158,42 @@ static const struct dev_pm_ops ti_sn_bridge_pm_ops = { SET_RUNTIME_PM_OPS(ti_sn_bridge_suspend, ti_sn_bridge_resume, NULL) }; +static int status_show(struct seq_file *s, void *data) +{ + struct ti_sn_bridge *pdata = s->private; + unsigned int reg, val; + + seq_puts(s, "STATUS REGISTERS:\n"); + + pm_runtime_get_sync(pdata->dev); + + /* IRQ Status Registers, see Table 31 in datasheet */ + for (reg = 0xf0; reg <= 0xf8; reg++) { + regmap_read(pdata->regmap, reg, &val); + seq_printf(s, "[0x%02x] = 0x%08x\n", reg, val); + } + + pm_runtime_put(pdata->dev); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(status); + +static void ti_sn_debugfs_init(struct ti_sn_bridge *pdata) +{ + pdata->debugfs = debugfs_create_dir(dev_name(pdata->dev), NULL); + + debugfs_create_file("status", 0600, pdata->debugfs, pdata, + &status_fops); +} + +static void ti_sn_debugfs_remove(struct ti_sn_bridge *pdata) +{ + debugfs_remove_recursive(pdata->debugfs); + pdata->debugfs = NULL; +} + /* Connector funcs */ static struct ti_sn_bridge * connector_to_ti_sn_bridge(struct drm_connector *connector) @@ -275,8 +314,7 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge) /* TODO: setting to 4 lanes always for now */ dsi->lanes = 4; dsi->format = MIPI_DSI_FMT_RGB888; - dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | - MIPI_DSI_MODE_EOT_PACKET | MIPI_DSI_MODE_VIDEO_HSE; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO; /* check if continuous dsi clock is required or not */ pm_runtime_get_sync(pdata->dev); @@ -731,6 +769,8 @@ static int ti_sn_bridge_probe(struct i2c_client *client, drm_bridge_add(&pdata->bridge); + ti_sn_debugfs_init(pdata); + return 0; } @@ -741,6 +781,8 @@ static int ti_sn_bridge_remove(struct i2c_client *client) if (!pdata) return -EINVAL; + ti_sn_debugfs_remove(pdata); + of_node_put(pdata->host_node); pm_runtime_disable(pdata->dev); diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c index dbf35c7bc85e..61cc2354ef1b 100644 --- a/drivers/gpu/drm/bridge/ti-tfp410.c +++ b/drivers/gpu/drm/bridge/ti-tfp410.c @@ -134,8 +134,10 @@ static int tfp410_attach(struct drm_bridge *bridge) drm_connector_helper_add(&dvi->connector, &tfp410_con_helper_funcs); - ret = drm_connector_init(bridge->dev, &dvi->connector, - &tfp410_con_funcs, dvi->connector_type); + ret = drm_connector_init_with_ddc(bridge->dev, &dvi->connector, + &tfp410_con_funcs, + dvi->connector_type, + dvi->ddc); if (ret) { dev_err(dvi->dev, "drm_connector_init() failed: %d\n", ret); return ret; diff --git a/drivers/gpu/drm/cirrus/cirrus.c b/drivers/gpu/drm/cirrus/cirrus.c index be4ea370ba31..36a69aec8a4b 100644 --- a/drivers/gpu/drm/cirrus/cirrus.c +++ b/drivers/gpu/drm/cirrus/cirrus.c @@ -513,7 +513,7 @@ static void cirrus_mode_config_init(struct cirrus_device *cirrus) DEFINE_DRM_GEM_SHMEM_FOPS(cirrus_fops); static struct drm_driver cirrus_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_PRIME, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .name = DRIVER_NAME, .desc = DRIVER_DESC, diff --git a/drivers/gpu/drm/drm_agpsupport.c b/drivers/gpu/drm/drm_agpsupport.c index 117b8ee98243..6e09f27fd9d6 100644 --- a/drivers/gpu/drm/drm_agpsupport.c +++ b/drivers/gpu/drm/drm_agpsupport.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_agpsupport.c * DRM support for AGP/GART backend * @@ -465,46 +465,3 @@ void drm_legacy_agp_clear(struct drm_device *dev) dev->agp->acquired = 0; dev->agp->enabled = 0; } - -/** - * Binds a collection of pages into AGP memory at the given offset, returning - * the AGP memory structure containing them. - * - * No reference is held on the pages during this time -- it is up to the - * caller to handle that. - */ -struct agp_memory * -drm_agp_bind_pages(struct drm_device *dev, - struct page **pages, - unsigned long num_pages, - uint32_t gtt_offset, - u32 type) -{ - struct agp_memory *mem; - int ret, i; - - DRM_DEBUG("\n"); - - mem = agp_allocate_memory(dev->agp->bridge, num_pages, - type); - if (mem == NULL) { - DRM_ERROR("Failed to allocate memory for %ld pages\n", - num_pages); - return NULL; - } - - for (i = 0; i < num_pages; i++) - mem->pages[i] = pages[i]; - mem->page_count = num_pages; - - mem->is_flushed = true; - ret = agp_bind_memory(mem, gtt_offset / PAGE_SIZE); - if (ret != 0) { - DRM_ERROR("Failed to bind AGP memory: %d\n", ret); - agp_free_memory(mem); - return NULL; - } - - return mem; -} -EXPORT_SYMBOL(drm_agp_bind_pages); diff --git a/drivers/gpu/drm/drm_atomic_uapi.c b/drivers/gpu/drm/drm_atomic_uapi.c index abe38bdf85ae..19ae119f1a5d 100644 --- a/drivers/gpu/drm/drm_atomic_uapi.c +++ b/drivers/gpu/drm/drm_atomic_uapi.c @@ -747,6 +747,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector, return -EINVAL; } state->content_protection = val; + } else if (property == config->hdcp_content_type_property) { + state->hdcp_content_type = val; } else if (property == connector->colorspace_property) { state->colorspace = val; } else if (property == config->writeback_fb_id_property) { @@ -831,6 +833,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector, state->hdr_output_metadata->base.id : 0; } else if (property == config->content_protection_property) { *val = state->content_protection; + } else if (property == config->hdcp_content_type_property) { + *val = state->hdcp_content_type; } else if (property == config->writeback_fb_id_property) { /* Writeback framebuffer is one-shot, write and forget */ *val = 0; diff --git a/drivers/gpu/drm/drm_client.c b/drivers/gpu/drm/drm_client.c index e1dafb0cc5e2..d9a2e3695525 100644 --- a/drivers/gpu/drm/drm_client.c +++ b/drivers/gpu/drm/drm_client.c @@ -59,7 +59,6 @@ static void drm_client_close(struct drm_client_dev *client) drm_file_free(client->file); } -EXPORT_SYMBOL(drm_client_close); /** * drm_client_init - Initialise a DRM client diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c index b3f2cf7eae9c..354798bad576 100644 --- a/drivers/gpu/drm/drm_connector.c +++ b/drivers/gpu/drm/drm_connector.c @@ -92,6 +92,7 @@ static struct drm_conn_prop_enum_list drm_connector_enum_list[] = { { DRM_MODE_CONNECTOR_DSI, "DSI" }, { DRM_MODE_CONNECTOR_DPI, "DPI" }, { DRM_MODE_CONNECTOR_WRITEBACK, "Writeback" }, + { DRM_MODE_CONNECTOR_SPI, "SPI" }, }; void drm_connector_ida_init(void) @@ -140,8 +141,7 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector) } DRM_DEBUG_KMS("cmdline mode for connector %s %s %dx%d@%dHz%s%s%s\n", - connector->name, - mode->name, + connector->name, mode->name, mode->xres, mode->yres, mode->refresh_specified ? mode->refresh : 60, mode->rb ? " reduced blanking" : "", @@ -298,6 +298,41 @@ out_put: EXPORT_SYMBOL(drm_connector_init); /** + * drm_connector_init_with_ddc - Init a preallocated connector + * @dev: DRM device + * @connector: the connector to init + * @funcs: callbacks for this connector + * @connector_type: user visible type of the connector + * @ddc: pointer to the associated ddc adapter + * + * Initialises a preallocated connector. Connectors should be + * subclassed as part of driver connector objects. + * + * Ensures that the ddc field of the connector is correctly set. + * + * Returns: + * Zero on success, error code on failure. + */ +int drm_connector_init_with_ddc(struct drm_device *dev, + struct drm_connector *connector, + const struct drm_connector_funcs *funcs, + int connector_type, + struct i2c_adapter *ddc) +{ + int ret; + + ret = drm_connector_init(dev, connector, funcs, connector_type); + if (ret) + return ret; + + /* provide ddc symlink in sysfs */ + connector->ddc = ddc; + + return ret; +} +EXPORT_SYMBOL(drm_connector_init_with_ddc); + +/** * drm_connector_attach_edid_property - attach edid property. * @connector: the connector * @@ -948,10 +983,70 @@ static const struct drm_prop_enum_list hdmi_colorspaces[] = { * - If the state is DESIRED, kernel should attempt to re-authenticate the * link whenever possible. This includes across disable/enable, dpms, * hotplug, downstream device changes, link status failures, etc.. - * - Userspace is responsible for polling the property to determine when - * the value transitions from ENABLED to DESIRED. This signifies the link - * is no longer protected and userspace should take appropriate action - * (whatever that might be). + * - Kernel sends uevent with the connector id and property id through + * @drm_hdcp_update_content_protection, upon below kernel triggered + * scenarios: + * DESIRED -> ENABLED (authentication success) + * ENABLED -> DESIRED (termination of authentication) + * - Please note no uevents for userspace triggered property state changes, + * which can't fail such as + * DESIRED/ENABLED -> UNDESIRED + * UNDESIRED -> DESIRED + * - Userspace is responsible for polling the property or listen to uevents + * to determine when the value transitions from ENABLED to DESIRED. + * This signifies the link is no longer protected and userspace should + * take appropriate action (whatever that might be). + * + * HDCP Content Type: + * This Enum property is used by the userspace to declare the content type + * of the display stream, to kernel. Here display stream stands for any + * display content that userspace intended to display through HDCP + * encryption. + * + * Content Type of a stream is decided by the owner of the stream, as + * "HDCP Type0" or "HDCP Type1". + * + * The value of the property can be one of the below: + * - "HDCP Type0": DRM_MODE_HDCP_CONTENT_TYPE0 = 0 + * - "HDCP Type1": DRM_MODE_HDCP_CONTENT_TYPE1 = 1 + * + * When kernel starts the HDCP authentication (see "Content Protection" + * for details), it uses the content type in "HDCP Content Type" + * for performing the HDCP authentication with the display sink. + * + * Please note in HDCP spec versions, a link can be authenticated with + * HDCP 2.2 for Content Type 0/Content Type 1. Where as a link can be + * authenticated with HDCP1.4 only for Content Type 0(though it is implicit + * in nature. As there is no reference for Content Type in HDCP1.4). + * + * HDCP2.2 authentication protocol itself takes the "Content Type" as a + * parameter, which is a input for the DP HDCP2.2 encryption algo. + * + * In case of Type 0 content protection request, kernel driver can choose + * either of HDCP spec versions 1.4 and 2.2. When HDCP2.2 is used for + * "HDCP Type 0", a HDCP 2.2 capable repeater in the downstream can send + * that content to a HDCP 1.4 authenticated HDCP sink (Type0 link). + * But if the content is classified as "HDCP Type 1", above mentioned + * HDCP 2.2 repeater wont send the content to the HDCP sink as it can't + * authenticate the HDCP1.4 capable sink for "HDCP Type 1". + * + * Please note userspace can be ignorant of the HDCP versions used by the + * kernel driver to achieve the "HDCP Content Type". + * + * At current scenario, classifying a content as Type 1 ensures that the + * content will be displayed only through the HDCP2.2 encrypted link. + * + * Note that the HDCP Content Type property is introduced at HDCP 2.2, and + * defaults to type 0. It is only exposed by drivers supporting HDCP 2.2 + * (hence supporting Type 0 and Type 1). Based on how next versions of + * HDCP specs are defined content Type could be used for higher versions + * too. + * + * If content type is changed when "Content Protection" is not UNDESIRED, + * then kernel will disable the HDCP and re-enable with new type in the + * same atomic commit. And when "Content Protection" is ENABLED, it means + * that link is HDCP authenticated and encrypted, for the transmission of + * the Type of stream mentioned at "HDCP Content Type". * * HDR_OUTPUT_METADATA: * Connector property to enable userspace to send HDR Metadata to diff --git a/drivers/gpu/drm/drm_debugfs_crc.c b/drivers/gpu/drm/drm_debugfs_crc.c index 7ca486d750e9..be1b7ba92ffe 100644 --- a/drivers/gpu/drm/drm_debugfs_crc.c +++ b/drivers/gpu/drm/drm_debugfs_crc.c @@ -66,9 +66,18 @@ * the reported CRCs of frames that should have the same contents. * * On the driver side the implementation effort is minimal, drivers only need to - * implement &drm_crtc_funcs.set_crc_source. The debugfs files are automatically - * set up if that vfunc is set. CRC samples need to be captured in the driver by - * calling drm_crtc_add_crc_entry(). + * implement &drm_crtc_funcs.set_crc_source and &drm_crtc_funcs.verify_crc_source. + * The debugfs files are automatically set up if those vfuncs are set. CRC samples + * need to be captured in the driver by calling drm_crtc_add_crc_entry(). + * Depending on the driver and HW requirements, &drm_crtc_funcs.set_crc_source + * may result in a commit (even a full modeset). + * + * CRC results must be reliable across non-full-modeset atomic commits, so if a + * commit via DRM_IOCTL_MODE_ATOMIC would disable or otherwise interfere with + * CRC generation, then the driver must mark that commit as a full modeset + * (drm_atomic_crtc_needs_modeset() should return true). As a result, to ensure + * consistent results, generic userspace must re-setup CRC generation after a + * legacy SETCRTC or an atomic commit with DRM_MODE_ATOMIC_ALLOW_MODESET. */ static int crc_control_show(struct seq_file *m, void *data) diff --git a/drivers/gpu/drm/drm_dma.c b/drivers/gpu/drm/drm_dma.c index 5ef0227eaa0e..e45b07890c5a 100644 --- a/drivers/gpu/drm/drm_dma.c +++ b/drivers/gpu/drm/drm_dma.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_dma.c * DMA IOCTL and function support * diff --git a/drivers/gpu/drm/drm_dp_aux_dev.c b/drivers/gpu/drm/drm_dp_aux_dev.c index 5be28e3295f3..0cfb386754c3 100644 --- a/drivers/gpu/drm/drm_dp_aux_dev.c +++ b/drivers/gpu/drm/drm_dp_aux_dev.c @@ -37,6 +37,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_dp_helper.h> +#include <drm/drm_dp_mst_helper.h> #include <drm/drm_print.h> #include "drm_crtc_helper_internal.h" @@ -82,8 +83,7 @@ static struct drm_dp_aux_dev *alloc_drm_dp_aux_dev(struct drm_dp_aux *aux) kref_init(&aux_dev->refcount); mutex_lock(&aux_idr_mutex); - index = idr_alloc_cyclic(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, - GFP_KERNEL); + index = idr_alloc(&aux_idr, aux_dev, 0, DRM_AUX_MINORS, GFP_KERNEL); mutex_unlock(&aux_idr_mutex); if (index < 0) { kfree(aux_dev); @@ -163,7 +163,12 @@ static ssize_t auxdev_read_iter(struct kiocb *iocb, struct iov_iter *to) break; } - res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo); + if (aux_dev->aux->is_remote) + res = drm_dp_mst_dpcd_read(aux_dev->aux, pos, buf, + todo); + else + res = drm_dp_dpcd_read(aux_dev->aux, pos, buf, todo); + if (res <= 0) break; @@ -210,7 +215,12 @@ static ssize_t auxdev_write_iter(struct kiocb *iocb, struct iov_iter *from) break; } - res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo); + if (aux_dev->aux->is_remote) + res = drm_dp_mst_dpcd_write(aux_dev->aux, pos, buf, + todo); + else + res = drm_dp_dpcd_write(aux_dev->aux, pos, buf, todo); + if (res <= 0) break; diff --git a/drivers/gpu/drm/drm_dp_helper.c b/drivers/gpu/drm/drm_dp_helper.c index 0b994d083a89..ffc68d305afe 100644 --- a/drivers/gpu/drm/drm_dp_helper.c +++ b/drivers/gpu/drm/drm_dp_helper.c @@ -152,38 +152,15 @@ EXPORT_SYMBOL(drm_dp_link_train_channel_eq_delay); u8 drm_dp_link_rate_to_bw_code(int link_rate) { - switch (link_rate) { - default: - WARN(1, "unknown DP link rate %d, using %x\n", link_rate, - DP_LINK_BW_1_62); - /* fall through */ - case 162000: - return DP_LINK_BW_1_62; - case 270000: - return DP_LINK_BW_2_7; - case 540000: - return DP_LINK_BW_5_4; - case 810000: - return DP_LINK_BW_8_1; - } + /* Spec says link_bw = link_rate / 0.27Gbps */ + return link_rate / 27000; } EXPORT_SYMBOL(drm_dp_link_rate_to_bw_code); int drm_dp_bw_code_to_link_rate(u8 link_bw) { - switch (link_bw) { - default: - WARN(1, "unknown DP link BW code %x, using 162000\n", link_bw); - /* fall through */ - case DP_LINK_BW_1_62: - return 162000; - case DP_LINK_BW_2_7: - return 270000; - case DP_LINK_BW_5_4: - return 540000; - case DP_LINK_BW_8_1: - return 810000; - } + /* Spec says link_rate = link_bw * 0.27Gbps */ + return link_bw * 27000; } EXPORT_SYMBOL(drm_dp_bw_code_to_link_rate); diff --git a/drivers/gpu/drm/drm_dp_mst_topology.c b/drivers/gpu/drm/drm_dp_mst_topology.c index 0984b9a34d55..82add736e17d 100644 --- a/drivers/gpu/drm/drm_dp_mst_topology.c +++ b/drivers/gpu/drm/drm_dp_mst_topology.c @@ -36,6 +36,8 @@ #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> +#include "drm_crtc_helper_internal.h" + /** * DOC: dp mst helper * @@ -53,6 +55,9 @@ static int drm_dp_dpcd_write_payload(struct drm_dp_mst_topology_mgr *mgr, int id, struct drm_dp_payload *payload); +static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr, + struct drm_dp_mst_port *port, + int offset, int size, u8 *bytes); static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, int offset, int size, u8 *bytes); @@ -1483,6 +1488,52 @@ static bool drm_dp_port_setup_pdt(struct drm_dp_mst_port *port) return send_link; } +/** + * drm_dp_mst_dpcd_read() - read a series of bytes from the DPCD via sideband + * @aux: Fake sideband AUX CH + * @offset: address of the (first) register to read + * @buffer: buffer to store the register values + * @size: number of bytes in @buffer + * + * Performs the same functionality for remote devices via + * sideband messaging as drm_dp_dpcd_read() does for local + * devices via actual AUX CH. + * + * Return: Number of bytes read, or negative error code on failure. + */ +ssize_t drm_dp_mst_dpcd_read(struct drm_dp_aux *aux, + unsigned int offset, void *buffer, size_t size) +{ + struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, + aux); + + return drm_dp_send_dpcd_read(port->mgr, port, + offset, size, buffer); +} + +/** + * drm_dp_mst_dpcd_write() - write a series of bytes to the DPCD via sideband + * @aux: Fake sideband AUX CH + * @offset: address of the (first) register to write + * @buffer: buffer containing the values to write + * @size: number of bytes in @buffer + * + * Performs the same functionality for remote devices via + * sideband messaging as drm_dp_dpcd_write() does for local + * devices via actual AUX CH. + * + * Return: 0 on success, negative error code on failure. + */ +ssize_t drm_dp_mst_dpcd_write(struct drm_dp_aux *aux, + unsigned int offset, void *buffer, size_t size) +{ + struct drm_dp_mst_port *port = container_of(aux, struct drm_dp_mst_port, + aux); + + return drm_dp_send_dpcd_write(port->mgr, port, + offset, size, buffer); +} + static void drm_dp_check_mstb_guid(struct drm_dp_mst_branch *mstb, u8 *guid) { int ret; @@ -1526,6 +1577,46 @@ static void build_mst_prop_path(const struct drm_dp_mst_branch *mstb, strlcat(proppath, temp, proppath_size); } +/** + * drm_dp_mst_connector_late_register() - Late MST connector registration + * @connector: The MST connector + * @port: The MST port for this connector + * + * Helper to register the remote aux device for this MST port. Drivers should + * call this from their mst connector's late_register hook to enable MST aux + * devices. + * + * Return: 0 on success, negative error code on failure. + */ +int drm_dp_mst_connector_late_register(struct drm_connector *connector, + struct drm_dp_mst_port *port) +{ + DRM_DEBUG_KMS("registering %s remote bus for %s\n", + port->aux.name, connector->kdev->kobj.name); + + port->aux.dev = connector->kdev; + return drm_dp_aux_register_devnode(&port->aux); +} +EXPORT_SYMBOL(drm_dp_mst_connector_late_register); + +/** + * drm_dp_mst_connector_early_unregister() - Early MST connector unregistration + * @connector: The MST connector + * @port: The MST port for this connector + * + * Helper to unregister the remote aux device for this MST port, registered by + * drm_dp_mst_connector_late_register(). Drivers should call this from their mst + * connector's early_unregister hook. + */ +void drm_dp_mst_connector_early_unregister(struct drm_connector *connector, + struct drm_dp_mst_port *port) +{ + DRM_DEBUG_KMS("unregistering %s remote bus for %s\n", + port->aux.name, connector->kdev->kobj.name); + drm_dp_aux_unregister_devnode(&port->aux); +} +EXPORT_SYMBOL(drm_dp_mst_connector_early_unregister); + static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, struct drm_device *dev, struct drm_dp_link_addr_reply_port *port_msg) @@ -1548,6 +1639,7 @@ static void drm_dp_add_port(struct drm_dp_mst_branch *mstb, port->mgr = mstb->mgr; port->aux.name = "DPMST"; port->aux.dev = dev->dev; + port->aux.is_remote = true; /* * Make sure the memory allocation for our parent branch stays @@ -1816,7 +1908,6 @@ static bool drm_dp_validate_guid(struct drm_dp_mst_topology_mgr *mgr, return false; } -#if 0 static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 offset, u8 num_bytes) { struct drm_dp_sideband_msg_req_body req; @@ -1829,7 +1920,6 @@ static int build_dpcd_read(struct drm_dp_sideband_msg_tx *msg, u8 port_num, u32 return 0; } -#endif static int drm_dp_send_sideband_msg(struct drm_dp_mst_topology_mgr *mgr, bool up, u8 *msg, int len) @@ -2441,26 +2531,58 @@ int drm_dp_update_payload_part2(struct drm_dp_mst_topology_mgr *mgr) } EXPORT_SYMBOL(drm_dp_update_payload_part2); -#if 0 /* unused as of yet */ static int drm_dp_send_dpcd_read(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, - int offset, int size) + int offset, int size, u8 *bytes) { int len; + int ret = 0; struct drm_dp_sideband_msg_tx *txmsg; + struct drm_dp_mst_branch *mstb; + + mstb = drm_dp_mst_topology_get_mstb_validated(mgr, port->parent); + if (!mstb) + return -EINVAL; txmsg = kzalloc(sizeof(*txmsg), GFP_KERNEL); - if (!txmsg) - return -ENOMEM; + if (!txmsg) { + ret = -ENOMEM; + goto fail_put; + } - len = build_dpcd_read(txmsg, port->port_num, 0, 8); + len = build_dpcd_read(txmsg, port->port_num, offset, size); txmsg->dst = port->parent; drm_dp_queue_down_tx(mgr, txmsg); - return 0; + ret = drm_dp_mst_wait_tx_reply(mstb, txmsg); + if (ret < 0) + goto fail_free; + + /* DPCD read should never be NACKed */ + if (txmsg->reply.reply_type == 1) { + DRM_ERROR("mstb %p port %d: DPCD read on addr 0x%x for %d bytes NAKed\n", + mstb, port->port_num, offset, size); + ret = -EIO; + goto fail_free; + } + + if (txmsg->reply.u.remote_dpcd_read_ack.num_bytes != size) { + ret = -EPROTO; + goto fail_free; + } + + ret = min_t(size_t, txmsg->reply.u.remote_dpcd_read_ack.num_bytes, + size); + memcpy(bytes, txmsg->reply.u.remote_dpcd_read_ack.bytes, ret); + +fail_free: + kfree(txmsg); +fail_put: + drm_dp_mst_topology_put_mstb(mstb); + + return ret; } -#endif static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr, struct drm_dp_mst_port *port, @@ -2489,7 +2611,7 @@ static int drm_dp_send_dpcd_write(struct drm_dp_mst_topology_mgr *mgr, ret = drm_dp_mst_wait_tx_reply(mstb, txmsg); if (ret > 0) { if (txmsg->reply.reply_type == DP_SIDEBAND_REPLY_NAK) - ret = -EINVAL; + ret = -EIO; else ret = 0; } diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c index 9d00947ca447..e652305d8f98 100644 --- a/drivers/gpu/drm/drm_drv.c +++ b/drivers/gpu/drm/drm_drv.c @@ -978,14 +978,14 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags) if (ret) goto err_minors; - dev->registered = true; - if (dev->driver->load) { ret = dev->driver->load(dev, flags); if (ret) goto err_minors; } + dev->registered = true; + if (drm_core_check_feature(dev, DRIVER_MODESET)) drm_modeset_register_all(dev); diff --git a/drivers/gpu/drm/drm_file.c b/drivers/gpu/drm/drm_file.c index 754af25fe255..ea34bc991858 100644 --- a/drivers/gpu/drm/drm_file.c +++ b/drivers/gpu/drm/drm_file.c @@ -147,8 +147,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor) if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) drm_syncobj_open(file); - if (drm_core_check_feature(dev, DRIVER_PRIME)) - drm_prime_init_file_private(&file->prime); + drm_prime_init_file_private(&file->prime); if (dev->driver->open) { ret = dev->driver->open(dev, file); @@ -159,8 +158,7 @@ struct drm_file *drm_file_alloc(struct drm_minor *minor) return file; out_prime_destroy: - if (drm_core_check_feature(dev, DRIVER_PRIME)) - drm_prime_destroy_file_private(&file->prime); + drm_prime_destroy_file_private(&file->prime); if (drm_core_check_feature(dev, DRIVER_SYNCOBJ)) drm_syncobj_release(file); if (drm_core_check_feature(dev, DRIVER_GEM)) @@ -253,8 +251,7 @@ void drm_file_free(struct drm_file *file) if (dev->driver->postclose) dev->driver->postclose(dev, file); - if (drm_core_check_feature(dev, DRIVER_PRIME)) - drm_prime_destroy_file_private(&file->prime); + drm_prime_destroy_file_private(&file->prime); WARN_ON(!list_empty(&file->event_list)); diff --git a/drivers/gpu/drm/drm_gem.c b/drivers/gpu/drm/drm_gem.c index a8c4468f03d9..afc38cece3f5 100644 --- a/drivers/gpu/drm/drm_gem.c +++ b/drivers/gpu/drm/drm_gem.c @@ -39,6 +39,7 @@ #include <linux/mem_encrypt.h> #include <linux/pagevec.h> +#include <drm/drm.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> @@ -254,8 +255,7 @@ drm_gem_object_release_handle(int id, void *ptr, void *data) else if (dev->driver->gem_close_object) dev->driver->gem_close_object(obj, file_priv); - if (drm_core_check_feature(dev, DRIVER_PRIME)) - drm_gem_remove_prime_handles(obj, file_priv); + drm_gem_remove_prime_handles(obj, file_priv); drm_vma_node_revoke(&obj->vma_node, file_priv); drm_gem_object_handle_put_unlocked(obj); @@ -1288,8 +1288,8 @@ retry: if (contended != -1) { struct drm_gem_object *obj = objs[contended]; - ret = ww_mutex_lock_slow_interruptible(&obj->resv->lock, - acquire_ctx); + ret = reservation_object_lock_slow_interruptible(obj->resv, + acquire_ctx); if (ret) { ww_acquire_done(acquire_ctx); return ret; @@ -1300,16 +1300,16 @@ retry: if (i == contended) continue; - ret = ww_mutex_lock_interruptible(&objs[i]->resv->lock, - acquire_ctx); + ret = reservation_object_lock_interruptible(objs[i]->resv, + acquire_ctx); if (ret) { int j; for (j = 0; j < i; j++) - ww_mutex_unlock(&objs[j]->resv->lock); + reservation_object_unlock(objs[j]->resv); if (contended != -1 && contended >= i) - ww_mutex_unlock(&objs[contended]->resv->lock); + reservation_object_unlock(objs[contended]->resv); if (ret == -EDEADLK) { contended = i; @@ -1334,7 +1334,7 @@ drm_gem_unlock_reservations(struct drm_gem_object **objs, int count, int i; for (i = 0; i < count; i++) - ww_mutex_unlock(&objs[i]->resv->lock); + reservation_object_unlock(objs[i]->resv); ww_acquire_fini(acquire_ctx); } diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c index 8fcbabf02dfd..f61304054786 100644 --- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c +++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c @@ -271,11 +271,11 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty); * @plane: Plane * @state: Plane state the fence will be attached to * - * This function prepares a GEM backed framebuffer for scanout by checking if - * the plane framebuffer has a DMA-BUF attached. If it does, it extracts the - * exclusive fence and attaches it to the plane state for the atomic helper to - * wait on. This function can be used as the &drm_plane_helper_funcs.prepare_fb - * callback. + * This function extracts the exclusive fence from &drm_gem_object.resv and + * attaches it to plane state for the atomic helper to wait on. This is + * necessary to correctly implement implicit synchronization for any buffers + * shared as a struct &dma_buf. This function can be used as the + * &drm_plane_helper_funcs.prepare_fb callback. * * There is no need for &drm_plane_helper_funcs.cleanup_fb hook for simple * gem based framebuffer drivers which have their buffers always pinned in @@ -287,17 +287,15 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_create_with_dirty); int drm_gem_fb_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) { - struct dma_buf *dma_buf; + struct drm_gem_object *obj; struct dma_fence *fence; if (!state->fb) return 0; - dma_buf = drm_gem_fb_get_obj(state->fb, 0)->dma_buf; - if (dma_buf) { - fence = reservation_object_get_excl_rcu(dma_buf->resv); - drm_atomic_set_fence_for_plane(state, fence); - } + obj = drm_gem_fb_get_obj(state->fb, 0); + fence = reservation_object_get_excl_rcu(obj->resv); + drm_atomic_set_fence_for_plane(state, fence); return 0; } @@ -309,10 +307,11 @@ EXPORT_SYMBOL_GPL(drm_gem_fb_prepare_fb); * @pipe: Simple display pipe * @plane_state: Plane state * - * This function uses drm_gem_fb_prepare_fb() to check if the plane FB has a - * &dma_buf attached, extracts the exclusive fence and attaches it to plane - * state for the atomic helper to wait on. Drivers can use this as their - * &drm_simple_display_pipe_funcs.prepare_fb callback. + * This function uses drm_gem_fb_prepare_fb() to extract the exclusive fence + * from &drm_gem_object.resv and attaches it to plane state for the atomic + * helper to wait on. This is necessary to correctly implement implicit + * synchronization for any buffers shared as a struct &dma_buf. Drivers can use + * this as their &drm_simple_display_pipe_funcs.prepare_fb callback. * * See drm_atomic_set_fence_for_plane() for a discussion of implicit and * explicit fencing in atomic modeset updates. @@ -323,46 +322,3 @@ int drm_gem_fb_simple_display_pipe_prepare_fb(struct drm_simple_display_pipe *pi return drm_gem_fb_prepare_fb(&pipe->plane, plane_state); } EXPORT_SYMBOL(drm_gem_fb_simple_display_pipe_prepare_fb); - -/** - * drm_gem_fbdev_fb_create - Create a GEM backed &drm_framebuffer for fbdev - * emulation - * @dev: DRM device - * @sizes: fbdev size description - * @pitch_align: Optional pitch alignment - * @obj: GEM object backing the framebuffer - * @funcs: Optional vtable to be used for the new framebuffer object when the - * dirty callback is needed. - * - * This function creates a framebuffer from a &drm_fb_helper_surface_size - * description for use in the &drm_fb_helper_funcs.fb_probe callback. - * - * Returns: - * Pointer to a &drm_framebuffer on success or an error pointer on failure. - */ -struct drm_framebuffer * -drm_gem_fbdev_fb_create(struct drm_device *dev, - struct drm_fb_helper_surface_size *sizes, - unsigned int pitch_align, struct drm_gem_object *obj, - const struct drm_framebuffer_funcs *funcs) -{ - struct drm_mode_fb_cmd2 mode_cmd = { 0 }; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = sizes->surface_width * - DIV_ROUND_UP(sizes->surface_bpp, 8); - if (pitch_align) - mode_cmd.pitches[0] = roundup(mode_cmd.pitches[0], - pitch_align); - mode_cmd.pixel_format = drm_driver_legacy_fb_format(dev, sizes->surface_bpp, - sizes->surface_depth); - if (obj->size < mode_cmd.pitches[0] * mode_cmd.height) - return ERR_PTR(-EINVAL); - - if (!funcs) - funcs = &drm_gem_fb_funcs; - - return drm_gem_fb_alloc(dev, &mode_cmd, &obj, 1, funcs); -} -EXPORT_SYMBOL(drm_gem_fbdev_fb_create); diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c index 472ea5d81f82..2f64667ac805 100644 --- a/drivers/gpu/drm/drm_gem_shmem_helper.c +++ b/drivers/gpu/drm/drm_gem_shmem_helper.c @@ -10,6 +10,7 @@ #include <linux/slab.h> #include <linux/vmalloc.h> +#include <drm/drm.h> #include <drm/drm_device.h> #include <drm/drm_drv.h> #include <drm/drm_gem_shmem_helper.h> diff --git a/drivers/gpu/drm/drm_gem_vram_helper.c b/drivers/gpu/drm/drm_gem_vram_helper.c index 4de782ca26b2..fd751078bae1 100644 --- a/drivers/gpu/drm/drm_gem_vram_helper.c +++ b/drivers/gpu/drm/drm_gem_vram_helper.c @@ -7,6 +7,8 @@ #include <drm/drm_vram_mm_helper.h> #include <drm/ttm/ttm_page_alloc.h> +static const struct drm_gem_object_funcs drm_gem_vram_object_funcs; + /** * DOC: overview * @@ -24,7 +26,7 @@ static void drm_gem_vram_cleanup(struct drm_gem_vram_object *gbo) * TTM buffer object in 'bo' has already been cleaned * up; only release the GEM object. */ - drm_gem_object_release(&gbo->gem); + drm_gem_object_release(&gbo->bo.base); } static void drm_gem_vram_destroy(struct drm_gem_vram_object *gbo) @@ -80,7 +82,10 @@ static int drm_gem_vram_init(struct drm_device *dev, int ret; size_t acc_size; - ret = drm_gem_object_init(dev, &gbo->gem, size); + if (!gbo->bo.base.funcs) + gbo->bo.base.funcs = &drm_gem_vram_object_funcs; + + ret = drm_gem_object_init(dev, &gbo->bo.base, size); if (ret) return ret; @@ -98,7 +103,7 @@ static int drm_gem_vram_init(struct drm_device *dev, return 0; err_drm_gem_object_release: - drm_gem_object_release(&gbo->gem); + drm_gem_object_release(&gbo->bo.base); return ret; } @@ -163,7 +168,7 @@ EXPORT_SYMBOL(drm_gem_vram_put); */ u64 drm_gem_vram_mmap_offset(struct drm_gem_vram_object *gbo) { - return drm_vma_node_offset_addr(&gbo->bo.vma_node); + return drm_vma_node_offset_addr(&gbo->bo.base.vma_node); } EXPORT_SYMBOL(drm_gem_vram_mmap_offset); @@ -378,11 +383,11 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file, if (IS_ERR(gbo)) return PTR_ERR(gbo); - ret = drm_gem_handle_create(file, &gbo->gem, &handle); + ret = drm_gem_handle_create(file, &gbo->bo.base, &handle); if (ret) goto err_drm_gem_object_put_unlocked; - drm_gem_object_put_unlocked(&gbo->gem); + drm_gem_object_put_unlocked(&gbo->bo.base); args->pitch = pitch; args->size = size; @@ -391,7 +396,7 @@ int drm_gem_vram_fill_create_dumb(struct drm_file *file, return 0; err_drm_gem_object_put_unlocked: - drm_gem_object_put_unlocked(&gbo->gem); + drm_gem_object_put_unlocked(&gbo->bo.base); return ret; } EXPORT_SYMBOL(drm_gem_vram_fill_create_dumb); @@ -441,7 +446,7 @@ int drm_gem_vram_bo_driver_verify_access(struct ttm_buffer_object *bo, { struct drm_gem_vram_object *gbo = drm_gem_vram_of_bo(bo); - return drm_vma_node_verify_access(&gbo->gem.vma_node, + return drm_vma_node_verify_access(&gbo->bo.base.vma_node, filp->private_data); } EXPORT_SYMBOL(drm_gem_vram_bo_driver_verify_access); @@ -460,21 +465,24 @@ const struct drm_vram_mm_funcs drm_gem_vram_mm_funcs = { EXPORT_SYMBOL(drm_gem_vram_mm_funcs); /* - * Helpers for struct drm_driver + * Helpers for struct drm_gem_object_funcs */ /** - * drm_gem_vram_driver_gem_free_object_unlocked() - \ - Implements &struct drm_driver.gem_free_object_unlocked - * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem + * drm_gem_vram_object_free() - \ + Implements &struct drm_gem_object_funcs.free + * @gem: GEM object. Refers to &struct drm_gem_vram_object.gem */ -void drm_gem_vram_driver_gem_free_object_unlocked(struct drm_gem_object *gem) +static void drm_gem_vram_object_free(struct drm_gem_object *gem) { struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); drm_gem_vram_put(gbo); } -EXPORT_SYMBOL(drm_gem_vram_driver_gem_free_object_unlocked); + +/* + * Helpers for dump buffers + */ /** * drm_gem_vram_driver_create_dumb() - \ @@ -536,19 +544,19 @@ int drm_gem_vram_driver_dumb_mmap_offset(struct drm_file *file, EXPORT_SYMBOL(drm_gem_vram_driver_dumb_mmap_offset); /* - * PRIME helpers for struct drm_driver + * PRIME helpers */ /** - * drm_gem_vram_driver_gem_prime_pin() - \ - Implements &struct drm_driver.gem_prime_pin + * drm_gem_vram_object_pin() - \ + Implements &struct drm_gem_object_funcs.pin * @gem: The GEM object to pin * * Returns: * 0 on success, or * a negative errno code otherwise. */ -int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *gem) +static int drm_gem_vram_object_pin(struct drm_gem_object *gem) { struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); @@ -562,31 +570,29 @@ int drm_gem_vram_driver_gem_prime_pin(struct drm_gem_object *gem) */ return drm_gem_vram_pin(gbo, 0); } -EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_pin); /** - * drm_gem_vram_driver_gem_prime_unpin() - \ - Implements &struct drm_driver.gem_prime_unpin + * drm_gem_vram_object_unpin() - \ + Implements &struct drm_gem_object_funcs.unpin * @gem: The GEM object to unpin */ -void drm_gem_vram_driver_gem_prime_unpin(struct drm_gem_object *gem) +static void drm_gem_vram_object_unpin(struct drm_gem_object *gem) { struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); drm_gem_vram_unpin(gbo); } -EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_unpin); /** - * drm_gem_vram_driver_gem_prime_vmap() - \ - Implements &struct drm_driver.gem_prime_vmap + * drm_gem_vram_object_vmap() - \ + Implements &struct drm_gem_object_funcs.vmap * @gem: The GEM object to map * * Returns: * The buffers virtual address on success, or * NULL otherwise. */ -void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *gem) +static void *drm_gem_vram_object_vmap(struct drm_gem_object *gem) { struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); int ret; @@ -602,40 +608,30 @@ void *drm_gem_vram_driver_gem_prime_vmap(struct drm_gem_object *gem) } return base; } -EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vmap); /** - * drm_gem_vram_driver_gem_prime_vunmap() - \ - Implements &struct drm_driver.gem_prime_vunmap + * drm_gem_vram_object_vunmap() - \ + Implements &struct drm_gem_object_funcs.vunmap * @gem: The GEM object to unmap * @vaddr: The mapping's base address */ -void drm_gem_vram_driver_gem_prime_vunmap(struct drm_gem_object *gem, - void *vaddr) +static void drm_gem_vram_object_vunmap(struct drm_gem_object *gem, + void *vaddr) { struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); drm_gem_vram_kunmap(gbo); drm_gem_vram_unpin(gbo); } -EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_vunmap); -/** - * drm_gem_vram_driver_gem_prime_mmap() - \ - Implements &struct drm_driver.gem_prime_mmap - * @gem: The GEM object to map - * @vma: The VMA describing the mapping - * - * Returns: - * 0 on success, or - * a negative errno code otherwise. +/* + * GEM object funcs */ -int drm_gem_vram_driver_gem_prime_mmap(struct drm_gem_object *gem, - struct vm_area_struct *vma) -{ - struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(gem); - gbo->gem.vma_node.vm_node.start = gbo->bo.vma_node.vm_node.start; - return drm_gem_prime_mmap(gem, vma); -} -EXPORT_SYMBOL(drm_gem_vram_driver_gem_prime_mmap); +static const struct drm_gem_object_funcs drm_gem_vram_object_funcs = { + .free = drm_gem_vram_object_free, + .pin = drm_gem_vram_object_pin, + .unpin = drm_gem_vram_object_unpin, + .vmap = drm_gem_vram_object_vmap, + .vunmap = drm_gem_vram_object_vunmap +}; diff --git a/drivers/gpu/drm/drm_hdcp.c b/drivers/gpu/drm/drm_hdcp.c index cd837bd409f7..9191633a3c43 100644 --- a/drivers/gpu/drm/drm_hdcp.c +++ b/drivers/gpu/drm/drm_hdcp.c @@ -271,6 +271,13 @@ exit: * * SRM should be presented in the name of "display_hdcp_srm.bin". * + * Format of the SRM table, that userspace needs to write into the binary file, + * is defined at: + * 1. Renewability chapter on 55th page of HDCP 1.4 specification + * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20Specification%20Rev1_4_Secure.pdf + * 2. Renewability chapter on 63rd page of HDCP 2.2 specification + * https://www.digital-cp.com/sites/default/files/specifications/HDCP%20on%20HDMI%20Specification%20Rev2_2_Final1.pdf + * * Returns: * TRUE on any of the KSV is revoked, else FALSE. */ @@ -344,23 +351,45 @@ static struct drm_prop_enum_list drm_cp_enum_list[] = { }; DRM_ENUM_NAME_FN(drm_get_content_protection_name, drm_cp_enum_list) +static struct drm_prop_enum_list drm_hdcp_content_type_enum_list[] = { + { DRM_MODE_HDCP_CONTENT_TYPE0, "HDCP Type0" }, + { DRM_MODE_HDCP_CONTENT_TYPE1, "HDCP Type1" }, +}; +DRM_ENUM_NAME_FN(drm_get_hdcp_content_type_name, + drm_hdcp_content_type_enum_list) + /** * drm_connector_attach_content_protection_property - attach content protection * property * * @connector: connector to attach CP property on. + * @hdcp_content_type: is HDCP Content Type property needed for connector * * This is used to add support for content protection on select connectors. * Content Protection is intentionally vague to allow for different underlying * technologies, however it is most implemented by HDCP. * + * When hdcp_content_type is true enum property called HDCP Content Type is + * created (if it is not already) and attached to the connector. + * + * This property is used for sending the protected content's stream type + * from userspace to kernel on selected connectors. Protected content provider + * will decide their type of their content and declare the same to kernel. + * + * Content type will be used during the HDCP 2.2 authentication. + * Content type will be set to &drm_connector_state.hdcp_content_type. + * * The content protection will be set to &drm_connector_state.content_protection * + * When kernel triggered content protection state change like DESIRED->ENABLED + * and ENABLED->DESIRED, will use drm_hdcp_update_content_protection() to update + * the content protection state of a connector. + * * Returns: * Zero on success, negative errno on failure. */ int drm_connector_attach_content_protection_property( - struct drm_connector *connector) + struct drm_connector *connector, bool hdcp_content_type) { struct drm_device *dev = connector->dev; struct drm_property *prop = @@ -377,6 +406,52 @@ int drm_connector_attach_content_protection_property( DRM_MODE_CONTENT_PROTECTION_UNDESIRED); dev->mode_config.content_protection_property = prop; + if (!hdcp_content_type) + return 0; + + prop = dev->mode_config.hdcp_content_type_property; + if (!prop) + prop = drm_property_create_enum(dev, 0, "HDCP Content Type", + drm_hdcp_content_type_enum_list, + ARRAY_SIZE( + drm_hdcp_content_type_enum_list)); + if (!prop) + return -ENOMEM; + + drm_object_attach_property(&connector->base, prop, + DRM_MODE_HDCP_CONTENT_TYPE0); + dev->mode_config.hdcp_content_type_property = prop; + return 0; } EXPORT_SYMBOL(drm_connector_attach_content_protection_property); + +/** + * drm_hdcp_update_content_protection - Updates the content protection state + * of a connector + * + * @connector: drm_connector on which content protection state needs an update + * @val: New state of the content protection property + * + * This function can be used by display drivers, to update the kernel triggered + * content protection state changes of a drm_connector such as DESIRED->ENABLED + * and ENABLED->DESIRED. No uevent for DESIRED->UNDESIRED or ENABLED->UNDESIRED, + * as userspace is triggering such state change and kernel performs it without + * fail.This function update the new state of the property into the connector's + * state and generate an uevent to notify the userspace. + */ +void drm_hdcp_update_content_protection(struct drm_connector *connector, + u64 val) +{ + struct drm_device *dev = connector->dev; + struct drm_connector_state *state = connector->state; + + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex)); + if (state->content_protection == val) + return; + + state->content_protection = val; + drm_sysfs_connector_status_event(connector, + dev->mode_config.content_protection_property); +} +EXPORT_SYMBOL(drm_hdcp_update_content_protection); diff --git a/drivers/gpu/drm/drm_ioc32.c b/drivers/gpu/drm/drm_ioc32.c index a16b6dc2fa47..22c7fd7196c8 100644 --- a/drivers/gpu/drm/drm_ioc32.c +++ b/drivers/gpu/drm/drm_ioc32.c @@ -108,7 +108,7 @@ static int compat_drm_version(struct file *file, unsigned int cmd, .desc = compat_ptr(v32.desc), }; err = drm_ioctl_kernel(file, drm_version, &v, - DRM_UNLOCKED|DRM_RENDER_ALLOW); + DRM_RENDER_ALLOW); if (err) return err; @@ -142,7 +142,7 @@ static int compat_drm_getunique(struct file *file, unsigned int cmd, .unique = compat_ptr(uq32.unique), }; - err = drm_ioctl_kernel(file, drm_getunique, &uq, DRM_UNLOCKED); + err = drm_ioctl_kernel(file, drm_getunique, &uq, 0); if (err) return err; @@ -181,7 +181,7 @@ static int compat_drm_getmap(struct file *file, unsigned int cmd, return -EFAULT; map.offset = m32.offset; - err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, DRM_UNLOCKED); + err = drm_ioctl_kernel(file, drm_legacy_getmap_ioctl, &map, 0); if (err) return err; @@ -267,7 +267,7 @@ static int compat_drm_getclient(struct file *file, unsigned int cmd, client.idx = c32.idx; - err = drm_ioctl_kernel(file, drm_getclient, &client, DRM_UNLOCKED); + err = drm_ioctl_kernel(file, drm_getclient, &client, 0); if (err) return err; @@ -297,7 +297,7 @@ static int compat_drm_getstats(struct file *file, unsigned int cmd, drm_stats32_t __user *argp = (void __user *)arg; int err; - err = drm_ioctl_kernel(file, drm_noop, NULL, DRM_UNLOCKED); + err = drm_ioctl_kernel(file, drm_noop, NULL, 0); if (err) return err; @@ -895,8 +895,7 @@ static int compat_drm_mode_addfb2(struct file *file, unsigned int cmd, sizeof(req64.modifier))) return -EFAULT; - err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, - DRM_UNLOCKED); + err = drm_ioctl_kernel(file, drm_mode_addfb2, &req64, 0); if (err) return err; diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index bd810454d239..f675a3bb2c88 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -570,24 +570,23 @@ EXPORT_SYMBOL(drm_ioctl_permit); /* Ioctl table */ static const struct drm_ioctl_desc drm_ioctls[] = { - DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, - DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), - DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, DRM_UNLOCKED), + DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_legacy_getmap_ioctl, 0), - DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_UNLOCKED | DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_SET_CLIENT_CAP, drm_setclientcap, 0), + DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER), DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_UNLOCKED|DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_MASTER), DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_legacy_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_legacy_rmmap_ioctl, DRM_AUTH), @@ -595,8 +594,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_legacy_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_legacy_getsareactx, DRM_AUTH), - DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_UNLOCKED|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_UNLOCKED|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_SET_MASTER, drm_setmaster_ioctl, DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_DROP_MASTER, drm_dropmaster_ioctl, DRM_ROOT_ONLY), DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_legacy_addctx, DRM_AUTH|DRM_ROOT_ONLY), DRM_LEGACY_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_legacy_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), @@ -642,74 +641,74 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED), - - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_UNLOCKED), - - DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_UNLOCKED|DRM_RENDER_ALLOW), - - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER|DRM_UNLOCKED), - 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_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), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, DRM_UNLOCKED), + DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, 0), + + DRM_IOCTL_DEF(DRM_IOCTL_PRIME_HANDLE_TO_FD, drm_prime_handle_to_fd_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_PRIME_FD_TO_HANDLE, drm_prime_fd_to_handle_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANERESOURCES, drm_mode_getplane_res, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPLANE, drm_mode_getplane, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPLANE, drm_mode_setplane, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_noop, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_noop, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_connector_property_set_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB2, drm_mode_addfb2_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_GETPROPERTIES, drm_mode_obj_get_properties_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_OBJ_SETPROPERTY, drm_mode_obj_set_property_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR2, drm_mode_cursor2_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATOMIC, drm_mode_atomic_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATEPROPBLOB, drm_mode_createblob_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROYPROPBLOB, drm_mode_destroyblob_ioctl, 0), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_CREATE, drm_syncobj_create_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_DESTROY, drm_syncobj_destroy_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD, drm_syncobj_handle_to_fd_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE, drm_syncobj_fd_to_handle_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TRANSFER, drm_syncobj_transfer_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, drm_syncobj_timeline_wait_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_RESET, drm_syncobj_reset_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_SIGNAL, drm_syncobj_timeline_signal_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_QUERY, drm_syncobj_query_ioctl, - DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER|DRM_UNLOCKED), - DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER|DRM_UNLOCKED), + DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_CRTC_GET_SEQUENCE, drm_crtc_get_sequence_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_CRTC_QUEUE_SEQUENCE, drm_crtc_queue_sequence_ioctl, 0), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_LEASE, drm_mode_create_lease_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_LIST_LESSEES, drm_mode_list_lessees_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_GET_LEASE, drm_mode_get_lease_ioctl, DRM_MASTER), + DRM_IOCTL_DEF(DRM_IOCTL_MODE_REVOKE_LEASE, drm_mode_revoke_lease_ioctl, DRM_MASTER), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) @@ -777,7 +776,7 @@ long drm_ioctl_kernel(struct file *file, drm_ioctl_t *func, void *kdata, return retcode; /* Enforce sane locking for modern driver ioctls. */ - if (!drm_core_check_feature(dev, DRIVER_LEGACY) || + if (likely(!drm_core_check_feature(dev, DRIVER_LEGACY)) || (flags & DRM_UNLOCKED)) retcode = func(dev, kdata, file_priv); else { diff --git a/drivers/gpu/drm/drm_legacy_misc.c b/drivers/gpu/drm/drm_legacy_misc.c index 4d3a11cfd979..8f54e6a78b6f 100644 --- a/drivers/gpu/drm/drm_legacy_misc.c +++ b/drivers/gpu/drm/drm_legacy_misc.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_legacy_misc.c * Misc legacy support functions. * diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 68b18b0e290c..2e8ce99d0baa 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_lock.c * IOCTLs for locking * diff --git a/drivers/gpu/drm/drm_memory.c b/drivers/gpu/drm/drm_memory.c index b634e1670190..0bec6dbb0142 100644 --- a/drivers/gpu/drm/drm_memory.c +++ b/drivers/gpu/drm/drm_memory.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_memory.c * Memory management wrappers for DRM * diff --git a/drivers/gpu/drm/tinydrm/mipi-dbi.c b/drivers/gpu/drm/drm_mipi_dbi.c index ca9da654fc6f..1961f713aaab 100644 --- a/drivers/gpu/drm/tinydrm/mipi-dbi.c +++ b/drivers/gpu/drm/drm_mipi_dbi.c @@ -13,17 +13,18 @@ #include <linux/regulator/consumer.h> #include <linux/spi/spi.h> +#include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> -#include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_format_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_vblank.h> +#include <drm/drm_mipi_dbi.h> +#include <drm/drm_modes.h> +#include <drm/drm_probe_helper.h> #include <drm/drm_rect.h> -#include <drm/tinydrm/mipi-dbi.h> -#include <drm/tinydrm/tinydrm-helpers.h> +#include <drm/drm_vblank.h> #include <video/mipi_display.h> #define MIPI_DBI_MAX_SPI_READ_SPEED 2000000 /* 2MHz */ @@ -98,17 +99,17 @@ static const u8 mipi_dbi_dcs_read_commands[] = { 0, /* sentinel */ }; -static bool mipi_dbi_command_is_read(struct mipi_dbi *mipi, u8 cmd) +static bool mipi_dbi_command_is_read(struct mipi_dbi *dbi, u8 cmd) { unsigned int i; - if (!mipi->read_commands) + if (!dbi->read_commands) return false; for (i = 0; i < 0xff; i++) { - if (!mipi->read_commands[i]) + if (!dbi->read_commands[i]) return false; - if (cmd == mipi->read_commands[i]) + if (cmd == dbi->read_commands[i]) return true; } @@ -117,7 +118,7 @@ static bool mipi_dbi_command_is_read(struct mipi_dbi *mipi, u8 cmd) /** * mipi_dbi_command_read - MIPI DCS read command - * @mipi: MIPI structure + * @dbi: MIPI DBI structure * @cmd: Command * @val: Value read * @@ -126,21 +127,21 @@ static bool mipi_dbi_command_is_read(struct mipi_dbi *mipi, u8 cmd) * Returns: * Zero on success, negative error code on failure. */ -int mipi_dbi_command_read(struct mipi_dbi *mipi, u8 cmd, u8 *val) +int mipi_dbi_command_read(struct mipi_dbi *dbi, u8 cmd, u8 *val) { - if (!mipi->read_commands) + if (!dbi->read_commands) return -EACCES; - if (!mipi_dbi_command_is_read(mipi, cmd)) + if (!mipi_dbi_command_is_read(dbi, cmd)) return -EINVAL; - return mipi_dbi_command_buf(mipi, cmd, val, 1); + return mipi_dbi_command_buf(dbi, cmd, val, 1); } EXPORT_SYMBOL(mipi_dbi_command_read); /** * mipi_dbi_command_buf - MIPI DCS command with parameter(s) in an array - * @mipi: MIPI structure + * @dbi: MIPI DBI structure * @cmd: Command * @data: Parameter buffer * @len: Buffer length @@ -148,7 +149,7 @@ EXPORT_SYMBOL(mipi_dbi_command_read); * Returns: * Zero on success, negative error code on failure. */ -int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len) +int mipi_dbi_command_buf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len) { u8 *cmdbuf; int ret; @@ -158,9 +159,9 @@ int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len) if (!cmdbuf) return -ENOMEM; - mutex_lock(&mipi->cmdlock); - ret = mipi->command(mipi, cmdbuf, data, len); - mutex_unlock(&mipi->cmdlock); + mutex_lock(&dbi->cmdlock); + ret = dbi->command(dbi, cmdbuf, data, len); + mutex_unlock(&dbi->cmdlock); kfree(cmdbuf); @@ -169,7 +170,7 @@ int mipi_dbi_command_buf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len) EXPORT_SYMBOL(mipi_dbi_command_buf); /* This should only be used by mipi_dbi_command() */ -int mipi_dbi_command_stackbuf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t len) +int mipi_dbi_command_stackbuf(struct mipi_dbi *dbi, u8 cmd, u8 *data, size_t len) { u8 *buf; int ret; @@ -178,7 +179,7 @@ int mipi_dbi_command_stackbuf(struct mipi_dbi *mipi, u8 cmd, u8 *data, size_t le if (!buf) return -ENOMEM; - ret = mipi_dbi_command_buf(mipi, cmd, buf, len); + ret = mipi_dbi_command_buf(dbi, cmd, buf, len); kfree(buf); @@ -199,8 +200,9 @@ EXPORT_SYMBOL(mipi_dbi_command_stackbuf); int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb, struct drm_rect *clip, bool swap) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct dma_buf_attachment *import_attach = cma_obj->base.import_attach; + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem); + struct dma_buf_attachment *import_attach = gem->import_attach; struct drm_format_name_buf format_name; void *src = cma_obj->vaddr; int ret = 0; @@ -238,16 +240,18 @@ EXPORT_SYMBOL(mipi_dbi_buf_copy); static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { - struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev); + struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0); + struct drm_gem_cma_object *cma_obj = to_drm_gem_cma_obj(gem); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; - bool swap = mipi->swap_bytes; + struct mipi_dbi *dbi = &dbidev->dbi; + bool swap = dbi->swap_bytes; int idx, ret = 0; bool full; void *tr; - if (!mipi->enabled) + if (!dbidev->enabled) return; if (!drm_dev_enter(fb->dev, &idx)) @@ -257,24 +261,24 @@ static void mipi_dbi_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); - if (!mipi->dc || !full || swap || + if (!dbi->dc || !full || swap || fb->format->format == DRM_FORMAT_XRGB8888) { - tr = mipi->tx_buf; - ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap); + tr = dbidev->tx_buf; + ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap); if (ret) goto err_msg; } else { tr = cma_obj->vaddr; } - mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, + mipi_dbi_command(dbi, MIPI_DCS_SET_COLUMN_ADDRESS, (rect->x1 >> 8) & 0xff, rect->x1 & 0xff, ((rect->x2 - 1) >> 8) & 0xff, (rect->x2 - 1) & 0xff); - mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, + mipi_dbi_command(dbi, MIPI_DCS_SET_PAGE_ADDRESS, (rect->y1 >> 8) & 0xff, rect->y1 & 0xff, ((rect->y2 - 1) >> 8) & 0xff, (rect->y2 - 1) & 0xff); - ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, tr, + ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, tr, width * height * 2); err_msg: if (ret) @@ -312,7 +316,7 @@ EXPORT_SYMBOL(mipi_dbi_pipe_update); /** * mipi_dbi_enable_flush - MIPI DBI enable helper - * @mipi: MIPI DBI structure + * @dbidev: MIPI DBI device structure * @crtc_state: CRTC state * @plane_state: Plane state * @@ -324,7 +328,7 @@ EXPORT_SYMBOL(mipi_dbi_pipe_update); * framebuffer flushing, can't use this function since they both use the same * flushing code. */ -void mipi_dbi_enable_flush(struct mipi_dbi *mipi, +void mipi_dbi_enable_flush(struct mipi_dbi_dev *dbidev, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { @@ -337,36 +341,37 @@ void mipi_dbi_enable_flush(struct mipi_dbi *mipi, }; int idx; - if (!drm_dev_enter(&mipi->drm, &idx)) + if (!drm_dev_enter(&dbidev->drm, &idx)) return; - mipi->enabled = true; + dbidev->enabled = true; mipi_dbi_fb_dirty(fb, &rect); - backlight_enable(mipi->backlight); + backlight_enable(dbidev->backlight); drm_dev_exit(idx); } EXPORT_SYMBOL(mipi_dbi_enable_flush); -static void mipi_dbi_blank(struct mipi_dbi *mipi) +static void mipi_dbi_blank(struct mipi_dbi_dev *dbidev) { - struct drm_device *drm = &mipi->drm; + struct drm_device *drm = &dbidev->drm; u16 height = drm->mode_config.min_height; u16 width = drm->mode_config.min_width; + struct mipi_dbi *dbi = &dbidev->dbi; size_t len = width * height * 2; int idx; if (!drm_dev_enter(drm, &idx)) return; - memset(mipi->tx_buf, 0, len); + memset(dbidev->tx_buf, 0, len); - mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0, + mipi_dbi_command(dbi, MIPI_DCS_SET_COLUMN_ADDRESS, 0, 0, (width >> 8) & 0xFF, (width - 1) & 0xFF); - mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0, + mipi_dbi_command(dbi, MIPI_DCS_SET_PAGE_ADDRESS, 0, 0, (height >> 8) & 0xFF, (height - 1) & 0xFF); - mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, - (u8 *)mipi->tx_buf, len); + mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, + (u8 *)dbidev->tx_buf, len); drm_dev_exit(idx); } @@ -381,25 +386,79 @@ static void mipi_dbi_blank(struct mipi_dbi *mipi) */ void mipi_dbi_pipe_disable(struct drm_simple_display_pipe *pipe) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); - if (!mipi->enabled) + if (!dbidev->enabled) return; DRM_DEBUG_KMS("\n"); - mipi->enabled = false; + dbidev->enabled = false; - if (mipi->backlight) - backlight_disable(mipi->backlight); + if (dbidev->backlight) + backlight_disable(dbidev->backlight); else - mipi_dbi_blank(mipi); + mipi_dbi_blank(dbidev); - if (mipi->regulator) - regulator_disable(mipi->regulator); + if (dbidev->regulator) + regulator_disable(dbidev->regulator); } EXPORT_SYMBOL(mipi_dbi_pipe_disable); +static int mipi_dbi_connector_get_modes(struct drm_connector *connector) +{ + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(connector->dev); + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, &dbidev->mode); + if (!mode) { + DRM_ERROR("Failed to duplicate mode\n"); + return 0; + } + + if (mode->name[0] == '\0') + drm_mode_set_name(mode); + + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + if (mode->width_mm) { + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + } + + return 1; +} + +static const struct drm_connector_helper_funcs mipi_dbi_connector_hfuncs = { + .get_modes = mipi_dbi_connector_get_modes, +}; + +static const struct drm_connector_funcs mipi_dbi_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int mipi_dbi_rotate_mode(struct drm_display_mode *mode, + unsigned int rotation) +{ + if (rotation == 0 || rotation == 180) { + return 0; + } else if (rotation == 90 || rotation == 270) { + swap(mode->hdisplay, mode->vdisplay); + swap(mode->hsync_start, mode->vsync_start); + swap(mode->hsync_end, mode->vsync_end); + swap(mode->htotal, mode->vtotal); + swap(mode->width_mm, mode->height_mm); + return 0; + } else { + return -EINVAL; + } +} + static const struct drm_mode_config_funcs mipi_dbi_mode_config_funcs = { .fb_create = drm_gem_fb_create_with_dirty, .atomic_check = drm_atomic_helper_check, @@ -412,60 +471,111 @@ static const uint32_t mipi_dbi_formats[] = { }; /** - * mipi_dbi_init - MIPI DBI initialization - * @mipi: &mipi_dbi structure to initialize + * mipi_dbi_dev_init_with_formats - MIPI DBI device initialization with custom formats + * @dbidev: MIPI DBI device structure to initialize * @funcs: Display pipe functions + * @formats: Array of supported formats (DRM_FORMAT\_\*). + * @format_count: Number of elements in @formats * @mode: Display mode * @rotation: Initial rotation in degrees Counter Clock Wise + * @tx_buf_size: Allocate a transmit buffer of this size. * * This function sets up a &drm_simple_display_pipe with a &drm_connector that * has one fixed &drm_display_mode which is rotated according to @rotation. * This mode is used to set the mode config min/max width/height properties. - * Additionally &mipi_dbi.tx_buf is allocated. * - * Supported formats: Native RGB565 and emulated XRGB8888. + * Use mipi_dbi_dev_init() if you don't need custom formats. + * + * Note: + * Some of the helper functions expects RGB565 to be the default format and the + * transmit buffer sized to fit that. * * Returns: * Zero on success, negative error code on failure. */ -int mipi_dbi_init(struct mipi_dbi *mipi, - const struct drm_simple_display_pipe_funcs *funcs, - const struct drm_display_mode *mode, unsigned int rotation) +int mipi_dbi_dev_init_with_formats(struct mipi_dbi_dev *dbidev, + const struct drm_simple_display_pipe_funcs *funcs, + const uint32_t *formats, unsigned int format_count, + const struct drm_display_mode *mode, + unsigned int rotation, size_t tx_buf_size) { - size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16); - struct drm_device *drm = &mipi->drm; + static const uint64_t modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID + }; + struct drm_device *drm = &dbidev->drm; int ret; - if (!mipi->command) + if (!dbidev->dbi.command) return -EINVAL; - mutex_init(&mipi->cmdlock); - - mipi->tx_buf = devm_kmalloc(drm->dev, bufsize, GFP_KERNEL); - if (!mipi->tx_buf) + dbidev->tx_buf = devm_kmalloc(drm->dev, tx_buf_size, GFP_KERNEL); + if (!dbidev->tx_buf) return -ENOMEM; - /* TODO: Maybe add DRM_MODE_CONNECTOR_SPI */ - ret = tinydrm_display_pipe_init(drm, &mipi->pipe, funcs, - DRM_MODE_CONNECTOR_VIRTUAL, - mipi_dbi_formats, - ARRAY_SIZE(mipi_dbi_formats), mode, - rotation); + drm_mode_copy(&dbidev->mode, mode); + ret = mipi_dbi_rotate_mode(&dbidev->mode, rotation); + if (ret) { + DRM_ERROR("Illegal rotation value %u\n", rotation); + return -EINVAL; + } + + drm_connector_helper_add(&dbidev->connector, &mipi_dbi_connector_hfuncs); + ret = drm_connector_init(drm, &dbidev->connector, &mipi_dbi_connector_funcs, + DRM_MODE_CONNECTOR_SPI); + if (ret) + return ret; + + ret = drm_simple_display_pipe_init(drm, &dbidev->pipe, funcs, formats, format_count, + modifiers, &dbidev->connector); if (ret) return ret; - drm_plane_enable_fb_damage_clips(&mipi->pipe.plane); + drm_plane_enable_fb_damage_clips(&dbidev->pipe.plane); drm->mode_config.funcs = &mipi_dbi_mode_config_funcs; - drm->mode_config.preferred_depth = 16; - mipi->rotation = rotation; + drm->mode_config.min_width = dbidev->mode.hdisplay; + drm->mode_config.max_width = dbidev->mode.hdisplay; + drm->mode_config.min_height = dbidev->mode.vdisplay; + drm->mode_config.max_height = dbidev->mode.vdisplay; + dbidev->rotation = rotation; - DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n", - drm->mode_config.preferred_depth, rotation); + DRM_DEBUG_KMS("rotation = %u\n", rotation); return 0; } -EXPORT_SYMBOL(mipi_dbi_init); +EXPORT_SYMBOL(mipi_dbi_dev_init_with_formats); + +/** + * mipi_dbi_dev_init - MIPI DBI device initialization + * @dbidev: MIPI DBI device structure to initialize + * @funcs: Display pipe functions + * @mode: Display mode + * @rotation: Initial rotation in degrees Counter Clock Wise + * + * This function sets up a &drm_simple_display_pipe with a &drm_connector that + * has one fixed &drm_display_mode which is rotated according to @rotation. + * This mode is used to set the mode config min/max width/height properties. + * Additionally &mipi_dbi.tx_buf is allocated. + * + * Supported formats: Native RGB565 and emulated XRGB8888. + * + * Returns: + * Zero on success, negative error code on failure. + */ +int mipi_dbi_dev_init(struct mipi_dbi_dev *dbidev, + const struct drm_simple_display_pipe_funcs *funcs, + const struct drm_display_mode *mode, unsigned int rotation) +{ + size_t bufsize = mode->vdisplay * mode->hdisplay * sizeof(u16); + + dbidev->drm.mode_config.preferred_depth = 16; + + return mipi_dbi_dev_init_with_formats(dbidev, funcs, mipi_dbi_formats, + ARRAY_SIZE(mipi_dbi_formats), mode, + rotation, bufsize); +} +EXPORT_SYMBOL(mipi_dbi_dev_init); /** * mipi_dbi_release - DRM driver release helper @@ -477,37 +587,37 @@ EXPORT_SYMBOL(mipi_dbi_init); */ void mipi_dbi_release(struct drm_device *drm) { - struct mipi_dbi *dbi = drm_to_mipi_dbi(drm); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(drm); DRM_DEBUG_DRIVER("\n"); drm_mode_config_cleanup(drm); drm_dev_fini(drm); - kfree(dbi); + kfree(dbidev); } EXPORT_SYMBOL(mipi_dbi_release); /** * mipi_dbi_hw_reset - Hardware reset of controller - * @mipi: MIPI DBI structure + * @dbi: MIPI DBI structure * * Reset controller if the &mipi_dbi->reset gpio is set. */ -void mipi_dbi_hw_reset(struct mipi_dbi *mipi) +void mipi_dbi_hw_reset(struct mipi_dbi *dbi) { - if (!mipi->reset) + if (!dbi->reset) return; - gpiod_set_value_cansleep(mipi->reset, 0); + gpiod_set_value_cansleep(dbi->reset, 0); usleep_range(20, 1000); - gpiod_set_value_cansleep(mipi->reset, 1); + gpiod_set_value_cansleep(dbi->reset, 1); msleep(120); } EXPORT_SYMBOL(mipi_dbi_hw_reset); /** * mipi_dbi_display_is_on - Check if display is on - * @mipi: MIPI DBI structure + * @dbi: MIPI DBI structure * * This function checks the Power Mode register (if readable) to see if * display output is turned on. This can be used to see if the bootloader @@ -517,11 +627,11 @@ EXPORT_SYMBOL(mipi_dbi_hw_reset); * Returns: * true if the display can be verified to be on, false otherwise. */ -bool mipi_dbi_display_is_on(struct mipi_dbi *mipi) +bool mipi_dbi_display_is_on(struct mipi_dbi *dbi) { u8 val; - if (mipi_dbi_command_read(mipi, MIPI_DCS_GET_POWER_MODE, &val)) + if (mipi_dbi_command_read(dbi, MIPI_DCS_GET_POWER_MODE, &val)) return false; val &= ~DCS_POWER_MODE_RESERVED_MASK; @@ -537,28 +647,29 @@ bool mipi_dbi_display_is_on(struct mipi_dbi *mipi) } EXPORT_SYMBOL(mipi_dbi_display_is_on); -static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi *mipi, bool cond) +static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi_dev *dbidev, bool cond) { - struct device *dev = mipi->drm.dev; + struct device *dev = dbidev->drm.dev; + struct mipi_dbi *dbi = &dbidev->dbi; int ret; - if (mipi->regulator) { - ret = regulator_enable(mipi->regulator); + if (dbidev->regulator) { + ret = regulator_enable(dbidev->regulator); if (ret) { DRM_DEV_ERROR(dev, "Failed to enable regulator (%d)\n", ret); return ret; } } - if (cond && mipi_dbi_display_is_on(mipi)) + if (cond && mipi_dbi_display_is_on(dbi)) return 1; - mipi_dbi_hw_reset(mipi); - ret = mipi_dbi_command(mipi, MIPI_DCS_SOFT_RESET); + mipi_dbi_hw_reset(dbi); + ret = mipi_dbi_command(dbi, MIPI_DCS_SOFT_RESET); if (ret) { DRM_DEV_ERROR(dev, "Failed to send reset command (%d)\n", ret); - if (mipi->regulator) - regulator_disable(mipi->regulator); + if (dbidev->regulator) + regulator_disable(dbidev->regulator); return ret; } @@ -567,7 +678,7 @@ static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi *mipi, bool cond) * per MIPI DSC spec should wait 5ms after soft reset. If we didn't, * we assume worst case and wait 120ms. */ - if (mipi->reset) + if (dbi->reset) usleep_range(5000, 20000); else msleep(120); @@ -577,7 +688,7 @@ static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi *mipi, bool cond) /** * mipi_dbi_poweron_reset - MIPI DBI poweron and reset - * @mipi: MIPI DBI structure + * @dbidev: MIPI DBI device structure * * This function enables the regulator if used and does a hardware and software * reset. @@ -585,15 +696,15 @@ static int mipi_dbi_poweron_reset_conditional(struct mipi_dbi *mipi, bool cond) * Returns: * Zero on success, or a negative error code. */ -int mipi_dbi_poweron_reset(struct mipi_dbi *mipi) +int mipi_dbi_poweron_reset(struct mipi_dbi_dev *dbidev) { - return mipi_dbi_poweron_reset_conditional(mipi, false); + return mipi_dbi_poweron_reset_conditional(dbidev, false); } EXPORT_SYMBOL(mipi_dbi_poweron_reset); /** * mipi_dbi_poweron_conditional_reset - MIPI DBI poweron and conditional reset - * @mipi: MIPI DBI structure + * @dbidev: MIPI DBI device structure * * This function enables the regulator if used and if the display is off, it * does a hardware and software reset. If mipi_dbi_display_is_on() determines @@ -603,9 +714,9 @@ EXPORT_SYMBOL(mipi_dbi_poweron_reset); * Zero if the controller was reset, 1 if the display was already on, or a * negative error code. */ -int mipi_dbi_poweron_conditional_reset(struct mipi_dbi *mipi) +int mipi_dbi_poweron_conditional_reset(struct mipi_dbi_dev *dbidev) { - return mipi_dbi_poweron_reset_conditional(mipi, true); + return mipi_dbi_poweron_reset_conditional(dbidev, true); } EXPORT_SYMBOL(mipi_dbi_poweron_conditional_reset); @@ -629,6 +740,15 @@ u32 mipi_dbi_spi_cmd_max_speed(struct spi_device *spi, size_t len) } EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed); +static bool mipi_dbi_machine_little_endian(void) +{ +#if defined(__LITTLE_ENDIAN) + return true; +#else + return false; +#endif +} + /* * MIPI DBI Type C Option 1 * @@ -647,15 +767,15 @@ EXPORT_SYMBOL(mipi_dbi_spi_cmd_max_speed); * 76543210 */ -static int mipi_dbi_spi1e_transfer(struct mipi_dbi *mipi, int dc, +static int mipi_dbi_spi1e_transfer(struct mipi_dbi *dbi, int dc, const void *buf, size_t len, unsigned int bpw) { - bool swap_bytes = (bpw == 16 && tinydrm_machine_little_endian()); - size_t chunk, max_chunk = mipi->tx_buf9_len; - struct spi_device *spi = mipi->spi; + bool swap_bytes = (bpw == 16 && mipi_dbi_machine_little_endian()); + size_t chunk, max_chunk = dbi->tx_buf9_len; + struct spi_device *spi = dbi->spi; struct spi_transfer tr = { - .tx_buf = mipi->tx_buf9, + .tx_buf = dbi->tx_buf9, .bits_per_word = 8, }; struct spi_message m; @@ -675,13 +795,11 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *mipi, int dc, return -EINVAL; /* Command: pad no-op's (zeroes) at beginning of block */ - dst = mipi->tx_buf9; + dst = dbi->tx_buf9; memset(dst, 0, 9); dst[8] = *src; tr.len = 9; - tinydrm_dbg_spi_message(spi, &m); - return spi_sync(spi, &m); } @@ -697,7 +815,7 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *mipi, int dc, chunk = min(len, max_chunk); len -= chunk; - dst = mipi->tx_buf9; + dst = dbi->tx_buf9; if (chunk < 8) { u8 val, carry = 0; @@ -759,7 +877,6 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *mipi, int dc, tr.len = chunk + added; - tinydrm_dbg_spi_message(spi, &m); ret = spi_sync(spi, &m); if (ret) return ret; @@ -768,11 +885,11 @@ static int mipi_dbi_spi1e_transfer(struct mipi_dbi *mipi, int dc, return 0; } -static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, int dc, +static int mipi_dbi_spi1_transfer(struct mipi_dbi *dbi, int dc, const void *buf, size_t len, unsigned int bpw) { - struct spi_device *spi = mipi->spi; + struct spi_device *spi = dbi->spi; struct spi_transfer tr = { .bits_per_word = 9, }; @@ -783,12 +900,12 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, int dc, u16 *dst16; int ret; - if (!tinydrm_spi_bpw_supported(spi, 9)) - return mipi_dbi_spi1e_transfer(mipi, dc, buf, len, bpw); + if (!spi_is_bpw_supported(spi, 9)) + return mipi_dbi_spi1e_transfer(dbi, dc, buf, len, bpw); tr.speed_hz = mipi_dbi_spi_cmd_max_speed(spi, len); - max_chunk = mipi->tx_buf9_len; - dst16 = mipi->tx_buf9; + max_chunk = dbi->tx_buf9_len; + dst16 = dbi->tx_buf9; if (drm_debug & DRM_UT_DRIVER) pr_debug("[drm:%s] dc=%d, max_chunk=%zu, transfers:\n", @@ -803,7 +920,7 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, int dc, size_t chunk = min(len, max_chunk); unsigned int i; - if (bpw == 16 && tinydrm_machine_little_endian()) { + if (bpw == 16 && mipi_dbi_machine_little_endian()) { for (i = 0; i < (chunk * 2); i += 2) { dst16[i] = *src16 >> 8; dst16[i + 1] = *src16++ & 0xFF; @@ -823,7 +940,6 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, int dc, tr.len = chunk; len -= chunk; - tinydrm_dbg_spi_message(spi, &m); ret = spi_sync(spi, &m); if (ret) return ret; @@ -832,30 +948,30 @@ static int mipi_dbi_spi1_transfer(struct mipi_dbi *mipi, int dc, return 0; } -static int mipi_dbi_typec1_command(struct mipi_dbi *mipi, u8 *cmd, +static int mipi_dbi_typec1_command(struct mipi_dbi *dbi, u8 *cmd, u8 *parameters, size_t num) { unsigned int bpw = (*cmd == MIPI_DCS_WRITE_MEMORY_START) ? 16 : 8; int ret; - if (mipi_dbi_command_is_read(mipi, *cmd)) + if (mipi_dbi_command_is_read(dbi, *cmd)) return -ENOTSUPP; MIPI_DBI_DEBUG_COMMAND(*cmd, parameters, num); - ret = mipi_dbi_spi1_transfer(mipi, 0, cmd, 1, 8); + ret = mipi_dbi_spi1_transfer(dbi, 0, cmd, 1, 8); if (ret || !num) return ret; - return mipi_dbi_spi1_transfer(mipi, 1, parameters, num, bpw); + return mipi_dbi_spi1_transfer(dbi, 1, parameters, num, bpw); } /* MIPI DBI Type C Option 3 */ -static int mipi_dbi_typec3_command_read(struct mipi_dbi *mipi, u8 *cmd, +static int mipi_dbi_typec3_command_read(struct mipi_dbi *dbi, u8 *cmd, u8 *data, size_t len) { - struct spi_device *spi = mipi->spi; + struct spi_device *spi = dbi->spi; u32 speed_hz = min_t(u32, MIPI_DBI_MAX_SPI_READ_SPEED, spi->max_speed_hz / 2); struct spi_transfer tr[2] = { @@ -892,15 +1008,13 @@ static int mipi_dbi_typec3_command_read(struct mipi_dbi *mipi, u8 *cmd, return -ENOMEM; tr[1].rx_buf = buf; - gpiod_set_value_cansleep(mipi->dc, 0); + gpiod_set_value_cansleep(dbi->dc, 0); spi_message_init_with_transfers(&m, tr, ARRAY_SIZE(tr)); ret = spi_sync(spi, &m); if (ret) goto err_free; - tinydrm_dbg_spi_message(spi, &m); - if (tr[1].len == len) { memcpy(data, buf, len); } else { @@ -918,42 +1032,42 @@ err_free: return ret; } -static int mipi_dbi_typec3_command(struct mipi_dbi *mipi, u8 *cmd, +static int mipi_dbi_typec3_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par, size_t num) { - struct spi_device *spi = mipi->spi; + struct spi_device *spi = dbi->spi; unsigned int bpw = 8; u32 speed_hz; int ret; - if (mipi_dbi_command_is_read(mipi, *cmd)) - return mipi_dbi_typec3_command_read(mipi, cmd, par, num); + if (mipi_dbi_command_is_read(dbi, *cmd)) + return mipi_dbi_typec3_command_read(dbi, cmd, par, num); MIPI_DBI_DEBUG_COMMAND(*cmd, par, num); - gpiod_set_value_cansleep(mipi->dc, 0); + gpiod_set_value_cansleep(dbi->dc, 0); speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1); - ret = tinydrm_spi_transfer(spi, speed_hz, NULL, 8, cmd, 1); + ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, cmd, 1); if (ret || !num) return ret; - if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !mipi->swap_bytes) + if (*cmd == MIPI_DCS_WRITE_MEMORY_START && !dbi->swap_bytes) bpw = 16; - gpiod_set_value_cansleep(mipi->dc, 1); + gpiod_set_value_cansleep(dbi->dc, 1); speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num); - return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num); + return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num); } /** - * mipi_dbi_spi_init - Initialize MIPI DBI SPI interfaced controller + * mipi_dbi_spi_init - Initialize MIPI DBI SPI interface * @spi: SPI device - * @mipi: &mipi_dbi structure to initialize + * @dbi: MIPI DBI structure to initialize * @dc: D/C gpio (optional) * - * This function sets &mipi_dbi->command, enables &mipi->read_commands for the - * usual read commands. It should be followed by a call to mipi_dbi_init() or + * This function sets &mipi_dbi->command, enables &mipi_dbi->read_commands for the + * usual read commands. It should be followed by a call to mipi_dbi_dev_init() or * a driver-specific init. * * If @dc is set, a Type C Option 3 interface is assumed, if not @@ -968,18 +1082,12 @@ static int mipi_dbi_typec3_command(struct mipi_dbi *mipi, u8 *cmd, * Returns: * Zero on success, negative error code on failure. */ -int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi, +int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi, struct gpio_desc *dc) { - size_t tx_size = tinydrm_spi_max_transfer_size(spi, 0); struct device *dev = &spi->dev; int ret; - if (tx_size < 16) { - DRM_ERROR("SPI transmit buffer too small: %zu\n", tx_size); - return -EINVAL; - } - /* * Even though it's not the SPI device that does DMA (the master does), * the dma mask is necessary for the dma_alloc_wc() in @@ -998,29 +1106,75 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *mipi, } } - mipi->spi = spi; - mipi->read_commands = mipi_dbi_dcs_read_commands; + dbi->spi = spi; + dbi->read_commands = mipi_dbi_dcs_read_commands; if (dc) { - mipi->command = mipi_dbi_typec3_command; - mipi->dc = dc; - if (tinydrm_machine_little_endian() && - !tinydrm_spi_bpw_supported(spi, 16)) - mipi->swap_bytes = true; + dbi->command = mipi_dbi_typec3_command; + dbi->dc = dc; + if (mipi_dbi_machine_little_endian() && !spi_is_bpw_supported(spi, 16)) + dbi->swap_bytes = true; } else { - mipi->command = mipi_dbi_typec1_command; - mipi->tx_buf9_len = tx_size; - mipi->tx_buf9 = devm_kmalloc(dev, tx_size, GFP_KERNEL); - if (!mipi->tx_buf9) + dbi->command = mipi_dbi_typec1_command; + dbi->tx_buf9_len = SZ_16K; + dbi->tx_buf9 = devm_kmalloc(dev, dbi->tx_buf9_len, GFP_KERNEL); + if (!dbi->tx_buf9) return -ENOMEM; } + mutex_init(&dbi->cmdlock); + DRM_DEBUG_DRIVER("SPI speed: %uMHz\n", spi->max_speed_hz / 1000000); return 0; } EXPORT_SYMBOL(mipi_dbi_spi_init); +/** + * mipi_dbi_spi_transfer - SPI transfer helper + * @spi: SPI device + * @speed_hz: Override speed (optional) + * @bpw: Bits per word + * @buf: Buffer to transfer + * @len: Buffer length + * + * This SPI transfer helper breaks up the transfer of @buf into chunks which + * the SPI controller driver can handle. + * + * Returns: + * Zero on success, negative error code on failure. + */ +int mipi_dbi_spi_transfer(struct spi_device *spi, u32 speed_hz, + u8 bpw, const void *buf, size_t len) +{ + size_t max_chunk = spi_max_transfer_size(spi); + struct spi_transfer tr = { + .bits_per_word = bpw, + .speed_hz = speed_hz, + }; + struct spi_message m; + size_t chunk; + int ret; + + spi_message_init_with_transfers(&m, &tr, 1); + + while (len) { + chunk = min(len, max_chunk); + + tr.tx_buf = buf; + tr.len = chunk; + buf += chunk; + len -= chunk; + + ret = spi_sync(spi, &m); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL(mipi_dbi_spi_transfer); + #endif /* CONFIG_SPI */ #ifdef CONFIG_DEBUG_FS @@ -1030,13 +1184,13 @@ static ssize_t mipi_dbi_debugfs_command_write(struct file *file, size_t count, loff_t *ppos) { struct seq_file *m = file->private_data; - struct mipi_dbi *mipi = m->private; + struct mipi_dbi_dev *dbidev = m->private; u8 val, cmd = 0, parameters[64]; char *buf, *pos, *token; unsigned int i; int ret, idx; - if (!drm_dev_enter(&mipi->drm, &idx)) + if (!drm_dev_enter(&dbidev->drm, &idx)) return -ENODEV; buf = memdup_user_nul(ubuf, count); @@ -1075,7 +1229,7 @@ static ssize_t mipi_dbi_debugfs_command_write(struct file *file, } } - ret = mipi_dbi_command_buf(mipi, cmd, parameters, i); + ret = mipi_dbi_command_buf(&dbidev->dbi, cmd, parameters, i); err_free: kfree(buf); @@ -1087,16 +1241,17 @@ err_exit: static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused) { - struct mipi_dbi *mipi = m->private; + struct mipi_dbi_dev *dbidev = m->private; + struct mipi_dbi *dbi = &dbidev->dbi; u8 cmd, val[4]; int ret, idx; size_t len; - if (!drm_dev_enter(&mipi->drm, &idx)) + if (!drm_dev_enter(&dbidev->drm, &idx)) return -ENODEV; for (cmd = 0; cmd < 255; cmd++) { - if (!mipi_dbi_command_is_read(mipi, cmd)) + if (!mipi_dbi_command_is_read(dbi, cmd)) continue; switch (cmd) { @@ -1116,7 +1271,7 @@ static int mipi_dbi_debugfs_command_show(struct seq_file *m, void *unused) } seq_printf(m, "%02x: ", cmd); - ret = mipi_dbi_command_buf(mipi, cmd, val, len); + ret = mipi_dbi_command_buf(dbi, cmd, val, len); if (ret) { seq_puts(m, "XX\n"); continue; @@ -1158,12 +1313,12 @@ static const struct file_operations mipi_dbi_debugfs_command_fops = { */ int mipi_dbi_debugfs_init(struct drm_minor *minor) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(minor->dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(minor->dev); umode_t mode = S_IFREG | S_IWUSR; - if (mipi->read_commands) + if (dbidev->dbi.read_commands) mode |= S_IRUGO; - debugfs_create_file("command", mode, minor->debugfs_root, mipi, + debugfs_create_file("command", mode, minor->debugfs_root, dbidev, &mipi_dbi_debugfs_command_fops); return 0; diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 9a59865ce574..4581c5387372 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c @@ -472,7 +472,7 @@ int drm_mm_insert_node_in_range(struct drm_mm * const mm, u64 remainder_mask; bool once; - DRM_MM_BUG_ON(range_start >= range_end); + DRM_MM_BUG_ON(range_start > range_end); if (unlikely(size == 0 || range_end - range_start < size)) return -ENOSPC; diff --git a/drivers/gpu/drm/drm_mode_object.c b/drivers/gpu/drm/drm_mode_object.c index 1c6e51135962..c355ba8e6d5d 100644 --- a/drivers/gpu/drm/drm_mode_object.c +++ b/drivers/gpu/drm/drm_mode_object.c @@ -42,6 +42,8 @@ int __drm_mode_object_add(struct drm_device *dev, struct drm_mode_object *obj, { int ret; + WARN_ON(dev->registered && !obj_free_cb); + mutex_lock(&dev->mode_config.idr_mutex); ret = idr_alloc(&dev->mode_config.object_idr, register_obj ? obj : NULL, 1, 0, GFP_KERNEL); @@ -102,6 +104,8 @@ void drm_mode_object_register(struct drm_device *dev, void drm_mode_object_unregister(struct drm_device *dev, struct drm_mode_object *object) { + WARN_ON(dev->registered && !object->free_cb); + mutex_lock(&dev->mode_config.idr_mutex); if (object->id) { idr_remove(&dev->mode_config.object_idr, object->id); diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c index 80fcd5dc1558..226a1d0720cf 100644 --- a/drivers/gpu/drm/drm_modes.c +++ b/drivers/gpu/drm/drm_modes.c @@ -1912,8 +1912,11 @@ void drm_mode_convert_to_umode(struct drm_mode_modeinfo *out, case HDMI_PICTURE_ASPECT_256_135: out->flags |= DRM_MODE_FLAG_PIC_AR_256_135; break; - case HDMI_PICTURE_ASPECT_RESERVED: default: + WARN(1, "Invalid aspect ratio (0%x) on mode\n", + in->picture_aspect_ratio); + /* fall through */ + case HDMI_PICTURE_ASPECT_NONE: out->flags |= DRM_MODE_FLAG_PIC_AR_NONE; break; } @@ -1972,20 +1975,22 @@ int drm_mode_convert_umode(struct drm_device *dev, switch (in->flags & DRM_MODE_FLAG_PIC_AR_MASK) { case DRM_MODE_FLAG_PIC_AR_4_3: - out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_4_3; + out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_4_3; break; case DRM_MODE_FLAG_PIC_AR_16_9: - out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_16_9; + out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_16_9; break; case DRM_MODE_FLAG_PIC_AR_64_27: - out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_64_27; + out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_64_27; break; case DRM_MODE_FLAG_PIC_AR_256_135: - out->picture_aspect_ratio |= HDMI_PICTURE_ASPECT_256_135; + out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_256_135; break; - default: + case DRM_MODE_FLAG_PIC_AR_NONE: out->picture_aspect_ratio = HDMI_PICTURE_ASPECT_NONE; break; + default: + return -EINVAL; } out->status = drm_mode_validate_driver(dev, out); diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c index d0c01318076b..0a2316e0e812 100644 --- a/drivers/gpu/drm/drm_prime.c +++ b/drivers/gpu/drm/drm_prime.c @@ -30,6 +30,7 @@ #include <linux/dma-buf.h> #include <linux/rbtree.h> +#include <drm/drm.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_framebuffer.h> @@ -38,47 +39,52 @@ #include "drm_internal.h" -/* - * DMA-BUF/GEM Object references and lifetime overview: - * - * On the export the dma_buf holds a reference to the exporting GEM - * object. It takes this reference in handle_to_fd_ioctl, when it - * first calls .prime_export and stores the exporting GEM object in - * the dma_buf priv. This reference needs to be released when the - * final reference to the &dma_buf itself is dropped and its - * &dma_buf_ops.release function is called. For GEM-based drivers, - * the dma_buf should be exported using drm_gem_dmabuf_export() and - * then released by drm_gem_dmabuf_release(). - * - * On the import the importing GEM object holds a reference to the - * dma_buf (which in turn holds a ref to the exporting GEM object). - * It takes that reference in the fd_to_handle ioctl. - * It calls dma_buf_get, creates an attachment to it and stores the - * attachment in the GEM object. When this attachment is destroyed - * when the imported object is destroyed, we remove the attachment - * and drop the reference to the dma_buf. - * - * When all the references to the &dma_buf are dropped, i.e. when - * userspace has closed both handles to the imported GEM object (through the - * FD_TO_HANDLE IOCTL) and closed the file descriptor of the exported - * (through the HANDLE_TO_FD IOCTL) dma_buf, and all kernel-internal references - * are also gone, then the dma_buf gets destroyed. This can also happen as a - * part of the clean up procedure in the drm_release() function if userspace - * fails to properly clean up. Note that both the kernel and userspace (by - * keeeping the PRIME file descriptors open) can hold references onto a - * &dma_buf. - * - * Thus the chain of references always flows in one direction - * (avoiding loops): importing_gem -> dmabuf -> exporting_gem - * - * Self-importing: if userspace is using PRIME as a replacement for flink - * then it will get a fd->handle request for a GEM object that it created. - * Drivers should detect this situation and return back the gem object - * from the dma-buf private. Prime will do this automatically for drivers that - * use the drm_gem_prime_{import,export} helpers. - * - * GEM struct &dma_buf_ops symbols are now exported. They can be resued by - * drivers which implement GEM interface. +/** + * DOC: overview and lifetime rules + * + * Similar to GEM global names, PRIME file descriptors are also used to share + * buffer objects across processes. They offer additional security: as file + * descriptors must be explicitly sent over UNIX domain sockets to be shared + * between applications, they can't be guessed like the globally unique GEM + * names. + * + * Drivers that support the PRIME API implement the + * &drm_driver.prime_handle_to_fd and &drm_driver.prime_fd_to_handle operations. + * GEM based drivers must use drm_gem_prime_handle_to_fd() and + * drm_gem_prime_fd_to_handle() to implement these. For GEM based drivers the + * actual driver interfaces is provided through the &drm_gem_object_funcs.export + * and &drm_driver.gem_prime_import hooks. + * + * &dma_buf_ops implementations for GEM drivers are all individually exported + * for drivers which need to overwrite or reimplement some of them. + * + * Reference Counting for GEM Drivers + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + * + * On the export the &dma_buf holds a reference to the exported buffer object, + * usually a &drm_gem_object. It takes this reference in the PRIME_HANDLE_TO_FD + * IOCTL, when it first calls &drm_gem_object_funcs.export + * and stores the exporting GEM object in the &dma_buf.priv field. This + * reference needs to be released when the final reference to the &dma_buf + * itself is dropped and its &dma_buf_ops.release function is called. For + * GEM-based drivers, the &dma_buf should be exported using + * drm_gem_dmabuf_export() and then released by drm_gem_dmabuf_release(). + * + * Thus the chain of references always flows in one direction, avoiding loops: + * importing GEM object -> dma-buf -> exported GEM bo. A further complication + * are the lookup caches for import and export. These are required to guarantee + * that any given object will always have only one uniqe userspace handle. This + * is required to allow userspace to detect duplicated imports, since some GEM + * drivers do fail command submissions if a given buffer object is listed more + * than once. These import and export caches in &drm_prime_file_private only + * retain a weak reference, which is cleaned up when the corresponding object is + * released. + * + * Self-importing: If userspace is using PRIME as a replacement for flink then + * it will get a fd->handle request for a GEM object that it created. Drivers + * should detect this situation and return back the underlying object from the + * dma-buf private. For GEM based drivers this is handled in + * drm_gem_prime_import() already. */ struct drm_prime_member { @@ -181,42 +187,6 @@ static int drm_prime_lookup_buf_handle(struct drm_prime_file_private *prime_fpri return -ENOENT; } -/** - * drm_gem_map_attach - dma_buf attach implementation for GEM - * @dma_buf: buffer to attach device to - * @attach: buffer attachment data - * - * Calls &drm_driver.gem_prime_pin for device specific handling. This can be - * used as the &dma_buf_ops.attach callback. - * - * Returns 0 on success, negative error code on failure. - */ -int drm_gem_map_attach(struct dma_buf *dma_buf, - struct dma_buf_attachment *attach) -{ - struct drm_gem_object *obj = dma_buf->priv; - - return drm_gem_pin(obj); -} -EXPORT_SYMBOL(drm_gem_map_attach); - -/** - * drm_gem_map_detach - dma_buf detach implementation for GEM - * @dma_buf: buffer to detach from - * @attach: attachment to be detached - * - * Cleans up &dma_buf_attachment. This can be used as the &dma_buf_ops.detach - * callback. - */ -void drm_gem_map_detach(struct dma_buf *dma_buf, - struct dma_buf_attachment *attach) -{ - struct drm_gem_object *obj = dma_buf->priv; - - drm_gem_unpin(obj); -} -EXPORT_SYMBOL(drm_gem_map_detach); - void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpriv, struct dma_buf *dma_buf) { @@ -242,67 +212,21 @@ void drm_prime_remove_buf_handle_locked(struct drm_prime_file_private *prime_fpr } } -/** - * drm_gem_map_dma_buf - map_dma_buf implementation for GEM - * @attach: attachment whose scatterlist is to be returned - * @dir: direction of DMA transfer - * - * Calls &drm_driver.gem_prime_get_sg_table and then maps the scatterlist. This - * can be used as the &dma_buf_ops.map_dma_buf callback. - * - * Returns sg_table containing the scatterlist to be returned; returns ERR_PTR - * on error. May return -EINTR if it is interrupted by a signal. - */ - -struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, - enum dma_data_direction dir) +void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) { - struct drm_gem_object *obj = attach->dmabuf->priv; - struct sg_table *sgt; - - if (WARN_ON(dir == DMA_NONE)) - return ERR_PTR(-EINVAL); - - if (obj->funcs) - sgt = obj->funcs->get_sg_table(obj); - else - sgt = obj->dev->driver->gem_prime_get_sg_table(obj); - - if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, - DMA_ATTR_SKIP_CPU_SYNC)) { - sg_free_table(sgt); - kfree(sgt); - sgt = ERR_PTR(-ENOMEM); - } - - return sgt; + mutex_init(&prime_fpriv->lock); + prime_fpriv->dmabufs = RB_ROOT; + prime_fpriv->handles = RB_ROOT; } -EXPORT_SYMBOL(drm_gem_map_dma_buf); -/** - * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM - * @attach: attachment to unmap buffer from - * @sgt: scatterlist info of the buffer to unmap - * @dir: direction of DMA transfer - * - * This can be used as the &dma_buf_ops.unmap_dma_buf callback. - */ -void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, - struct sg_table *sgt, - enum dma_data_direction dir) +void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) { - if (!sgt) - return; - - dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, - DMA_ATTR_SKIP_CPU_SYNC); - sg_free_table(sgt); - kfree(sgt); + /* by now drm_gem_release should've made sure the list is empty */ + WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs)); } -EXPORT_SYMBOL(drm_gem_unmap_dma_buf); /** - * drm_gem_dmabuf_export - dma_buf export implementation for GEM + * drm_gem_dmabuf_export - &dma_buf export implementation for GEM * @dev: parent device for the exported dmabuf * @exp_info: the export information used by dma_buf_export() * @@ -330,11 +254,11 @@ struct dma_buf *drm_gem_dmabuf_export(struct drm_device *dev, EXPORT_SYMBOL(drm_gem_dmabuf_export); /** - * drm_gem_dmabuf_release - dma_buf release implementation for GEM + * drm_gem_dmabuf_release - &dma_buf release implementation for GEM * @dma_buf: buffer to be released * * Generic release function for dma_bufs exported as PRIME buffers. GEM drivers - * must use this in their dma_buf ops structure as the release callback. + * must use this in their &dma_buf_ops structure as the release callback. * drm_gem_dmabuf_release() should be used in conjunction with * drm_gem_dmabuf_export(). */ @@ -351,128 +275,100 @@ void drm_gem_dmabuf_release(struct dma_buf *dma_buf) EXPORT_SYMBOL(drm_gem_dmabuf_release); /** - * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM - * @dma_buf: buffer to be mapped + * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers + * @dev: dev to export the buffer from + * @file_priv: drm file-private structure + * @prime_fd: fd id of the dma-buf which should be imported + * @handle: pointer to storage for the handle of the imported buffer object * - * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap - * callback. + * This is the PRIME import function which must be used mandatorily by GEM + * drivers to ensure correct lifetime management of the underlying GEM object. + * The actual importing of GEM object from the dma-buf is done through the + * &drm_driver.gem_prime_import driver callback. * - * Returns the kernel virtual address. + * Returns 0 on success or a negative error code on failure. */ -void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf) +int drm_gem_prime_fd_to_handle(struct drm_device *dev, + struct drm_file *file_priv, int prime_fd, + uint32_t *handle) { - struct drm_gem_object *obj = dma_buf->priv; - void *vaddr; + struct dma_buf *dma_buf; + struct drm_gem_object *obj; + int ret; - vaddr = drm_gem_vmap(obj); - if (IS_ERR(vaddr)) - vaddr = NULL; + dma_buf = dma_buf_get(prime_fd); + if (IS_ERR(dma_buf)) + return PTR_ERR(dma_buf); - return vaddr; -} -EXPORT_SYMBOL(drm_gem_dmabuf_vmap); + mutex_lock(&file_priv->prime.lock); -/** - * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM - * @dma_buf: buffer to be unmapped - * @vaddr: the virtual address of the buffer - * - * Releases a kernel virtual mapping. This can be used as the - * &dma_buf_ops.vunmap callback. - */ -void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) -{ - struct drm_gem_object *obj = dma_buf->priv; + ret = drm_prime_lookup_buf_handle(&file_priv->prime, + dma_buf, handle); + if (ret == 0) + goto out_put; - drm_gem_vunmap(obj, vaddr); -} -EXPORT_SYMBOL(drm_gem_dmabuf_vunmap); + /* never seen this one, need to import */ + mutex_lock(&dev->object_name_lock); + if (dev->driver->gem_prime_import) + obj = dev->driver->gem_prime_import(dev, dma_buf); + else + obj = drm_gem_prime_import(dev, dma_buf); + if (IS_ERR(obj)) { + ret = PTR_ERR(obj); + goto out_unlock; + } -/** - * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM - * @dma_buf: buffer to be mapped - * @vma: virtual address range - * - * Provides memory mapping for the buffer. This can be used as the - * &dma_buf_ops.mmap callback. - * - * Returns 0 on success or a negative error code on failure. - */ -int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) -{ - struct drm_gem_object *obj = dma_buf->priv; - struct drm_device *dev = obj->dev; + if (obj->dma_buf) { + WARN_ON(obj->dma_buf != dma_buf); + } else { + obj->dma_buf = dma_buf; + get_dma_buf(dma_buf); + } - if (!dev->driver->gem_prime_mmap) - return -ENOSYS; + /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */ + ret = drm_gem_handle_create_tail(file_priv, obj, handle); + drm_gem_object_put_unlocked(obj); + if (ret) + goto out_put; - return dev->driver->gem_prime_mmap(obj, vma); -} -EXPORT_SYMBOL(drm_gem_dmabuf_mmap); + ret = drm_prime_add_buf_handle(&file_priv->prime, + dma_buf, *handle); + mutex_unlock(&file_priv->prime.lock); + if (ret) + goto fail; -static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = { - .cache_sgt_mapping = true, - .attach = drm_gem_map_attach, - .detach = drm_gem_map_detach, - .map_dma_buf = drm_gem_map_dma_buf, - .unmap_dma_buf = drm_gem_unmap_dma_buf, - .release = drm_gem_dmabuf_release, - .mmap = drm_gem_dmabuf_mmap, - .vmap = drm_gem_dmabuf_vmap, - .vunmap = drm_gem_dmabuf_vunmap, -}; + dma_buf_put(dma_buf); -/** - * DOC: PRIME Helpers - * - * Drivers can implement @gem_prime_export and @gem_prime_import in terms of - * simpler APIs by using the helper functions @drm_gem_prime_export and - * @drm_gem_prime_import. These functions implement dma-buf support in terms of - * six lower-level driver callbacks: - * - * Export callbacks: - * - * * @gem_prime_pin (optional): prepare a GEM object for exporting - * * @gem_prime_get_sg_table: provide a scatter/gather table of pinned pages - * * @gem_prime_vmap: vmap a buffer exported by your driver - * * @gem_prime_vunmap: vunmap a buffer exported by your driver - * * @gem_prime_mmap (optional): mmap a buffer exported by your driver - * - * Import callback: - * - * * @gem_prime_import_sg_table (import): produce a GEM object from another - * driver's scatter/gather table - */ + return 0; -/** - * drm_gem_prime_export - helper library implementation of the export callback - * @dev: drm_device to export from - * @obj: GEM object to export - * @flags: flags like DRM_CLOEXEC and DRM_RDWR - * - * This is the implementation of the gem_prime_export functions for GEM drivers - * using the PRIME helpers. - */ -struct dma_buf *drm_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, - int flags) +fail: + /* hmm, if driver attached, we are relying on the free-object path + * to detach.. which seems ok.. + */ + drm_gem_handle_delete(file_priv, *handle); + dma_buf_put(dma_buf); + return ret; + +out_unlock: + mutex_unlock(&dev->object_name_lock); +out_put: + mutex_unlock(&file_priv->prime.lock); + dma_buf_put(dma_buf); + return ret; +} +EXPORT_SYMBOL(drm_gem_prime_fd_to_handle); + +int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct dma_buf_export_info exp_info = { - .exp_name = KBUILD_MODNAME, /* white lie for debug */ - .owner = dev->driver->fops->owner, - .ops = &drm_gem_prime_dmabuf_ops, - .size = obj->size, - .flags = flags, - .priv = obj, - .resv = obj->resv, - }; + struct drm_prime_handle *args = data; - if (dev->driver->gem_prime_res_obj) - exp_info.resv = dev->driver->gem_prime_res_obj(obj); + if (!dev->driver->prime_fd_to_handle) + return -ENOSYS; - return drm_gem_dmabuf_export(dev, &exp_info); + return dev->driver->prime_fd_to_handle(dev, file_priv, + args->fd, &args->handle); } -EXPORT_SYMBOL(drm_gem_prime_export); static struct dma_buf *export_and_register_object(struct drm_device *dev, struct drm_gem_object *obj, @@ -489,9 +385,9 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev, if (obj->funcs && obj->funcs->export) dmabuf = obj->funcs->export(obj, flags); else if (dev->driver->gem_prime_export) - dmabuf = dev->driver->gem_prime_export(dev, obj, flags); + dmabuf = dev->driver->gem_prime_export(obj, flags); else - dmabuf = drm_gem_prime_export(dev, obj, flags); + dmabuf = drm_gem_prime_export(obj, flags); if (IS_ERR(dmabuf)) { /* normally the created dma-buf takes ownership of the ref, * but if that fails then drop the ref @@ -521,7 +417,7 @@ static struct dma_buf *export_and_register_object(struct drm_device *dev, * This is the PRIME export function which must be used mandatorily by GEM * drivers to ensure correct lifetime management of the underlying GEM object. * The actual exporting from GEM object to a dma-buf is done through the - * gem_prime_export driver callback. + * &drm_driver.gem_prime_export driver callback. */ int drm_gem_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, @@ -610,6 +506,195 @@ out_unlock: } EXPORT_SYMBOL(drm_gem_prime_handle_to_fd); +int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_prime_handle *args = data; + + if (!dev->driver->prime_handle_to_fd) + return -ENOSYS; + + /* check flags are valid */ + if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR)) + return -EINVAL; + + return dev->driver->prime_handle_to_fd(dev, file_priv, + args->handle, args->flags, &args->fd); +} + +/** + * DOC: PRIME Helpers + * + * Drivers can implement &drm_gem_object_funcs.export and + * &drm_driver.gem_prime_import in terms of simpler APIs by using the helper + * functions drm_gem_prime_export() and drm_gem_prime_import(). These functions + * implement dma-buf support in terms of some lower-level helpers, which are + * again exported for drivers to use individually: + * + * Exporting buffers + * ~~~~~~~~~~~~~~~~~ + * + * Optional pinning of buffers is handled at dma-buf attach and detach time in + * drm_gem_map_attach() and drm_gem_map_detach(). Backing storage itself is + * handled by drm_gem_map_dma_buf() and drm_gem_unmap_dma_buf(), which relies on + * &drm_gem_object_funcs.get_sg_table. + * + * For kernel-internal access there's drm_gem_dmabuf_vmap() and + * drm_gem_dmabuf_vunmap(). Userspace mmap support is provided by + * drm_gem_dmabuf_mmap(). + * + * Note that these export helpers can only be used if the underlying backing + * storage is fully coherent and either permanently pinned, or it is safe to pin + * it indefinitely. + * + * FIXME: The underlying helper functions are named rather inconsistently. + * + * Exporting buffers + * ~~~~~~~~~~~~~~~~~ + * + * Importing dma-bufs using drm_gem_prime_import() relies on + * &drm_driver.gem_prime_import_sg_table. + * + * Note that similarly to the export helpers this permanently pins the + * underlying backing storage. Which is ok for scanout, but is not the best + * option for sharing lots of buffers for rendering. + */ + +/** + * drm_gem_map_attach - dma_buf attach implementation for GEM + * @dma_buf: buffer to attach device to + * @attach: buffer attachment data + * + * Calls &drm_gem_object_funcs.pin for device specific handling. This can be + * used as the &dma_buf_ops.attach callback. Must be used together with + * drm_gem_map_detach(). + * + * Returns 0 on success, negative error code on failure. + */ +int drm_gem_map_attach(struct dma_buf *dma_buf, + struct dma_buf_attachment *attach) +{ + struct drm_gem_object *obj = dma_buf->priv; + + return drm_gem_pin(obj); +} +EXPORT_SYMBOL(drm_gem_map_attach); + +/** + * drm_gem_map_detach - dma_buf detach implementation for GEM + * @dma_buf: buffer to detach from + * @attach: attachment to be detached + * + * Calls &drm_gem_object_funcs.pin for device specific handling. Cleans up + * &dma_buf_attachment from drm_gem_map_attach(). This can be used as the + * &dma_buf_ops.detach callback. + */ +void drm_gem_map_detach(struct dma_buf *dma_buf, + struct dma_buf_attachment *attach) +{ + struct drm_gem_object *obj = dma_buf->priv; + + drm_gem_unpin(obj); +} +EXPORT_SYMBOL(drm_gem_map_detach); + +/** + * drm_gem_map_dma_buf - map_dma_buf implementation for GEM + * @attach: attachment whose scatterlist is to be returned + * @dir: direction of DMA transfer + * + * Calls &drm_gem_object_funcs.get_sg_table and then maps the scatterlist. This + * can be used as the &dma_buf_ops.map_dma_buf callback. Should be used together + * with drm_gem_unmap_dma_buf(). + * + * Returns:sg_table containing the scatterlist to be returned; returns ERR_PTR + * on error. May return -EINTR if it is interrupted by a signal. + */ +struct sg_table *drm_gem_map_dma_buf(struct dma_buf_attachment *attach, + enum dma_data_direction dir) +{ + struct drm_gem_object *obj = attach->dmabuf->priv; + struct sg_table *sgt; + + if (WARN_ON(dir == DMA_NONE)) + return ERR_PTR(-EINVAL); + + if (obj->funcs) + sgt = obj->funcs->get_sg_table(obj); + else + sgt = obj->dev->driver->gem_prime_get_sg_table(obj); + + if (!dma_map_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, + DMA_ATTR_SKIP_CPU_SYNC)) { + sg_free_table(sgt); + kfree(sgt); + sgt = ERR_PTR(-ENOMEM); + } + + return sgt; +} +EXPORT_SYMBOL(drm_gem_map_dma_buf); + +/** + * drm_gem_unmap_dma_buf - unmap_dma_buf implementation for GEM + * @attach: attachment to unmap buffer from + * @sgt: scatterlist info of the buffer to unmap + * @dir: direction of DMA transfer + * + * This can be used as the &dma_buf_ops.unmap_dma_buf callback. + */ +void drm_gem_unmap_dma_buf(struct dma_buf_attachment *attach, + struct sg_table *sgt, + enum dma_data_direction dir) +{ + if (!sgt) + return; + + dma_unmap_sg_attrs(attach->dev, sgt->sgl, sgt->nents, dir, + DMA_ATTR_SKIP_CPU_SYNC); + sg_free_table(sgt); + kfree(sgt); +} +EXPORT_SYMBOL(drm_gem_unmap_dma_buf); + +/** + * drm_gem_dmabuf_vmap - dma_buf vmap implementation for GEM + * @dma_buf: buffer to be mapped + * + * Sets up a kernel virtual mapping. This can be used as the &dma_buf_ops.vmap + * callback. Calls into &drm_gem_object_funcs.vmap for device specific handling. + * + * Returns the kernel virtual address or NULL on failure. + */ +void *drm_gem_dmabuf_vmap(struct dma_buf *dma_buf) +{ + struct drm_gem_object *obj = dma_buf->priv; + void *vaddr; + + vaddr = drm_gem_vmap(obj); + if (IS_ERR(vaddr)) + vaddr = NULL; + + return vaddr; +} +EXPORT_SYMBOL(drm_gem_dmabuf_vmap); + +/** + * drm_gem_dmabuf_vunmap - dma_buf vunmap implementation for GEM + * @dma_buf: buffer to be unmapped + * @vaddr: the virtual address of the buffer + * + * Releases a kernel virtual mapping. This can be used as the + * &dma_buf_ops.vunmap callback. Calls into &drm_gem_object_funcs.vunmap for device specific handling. + */ +void drm_gem_dmabuf_vunmap(struct dma_buf *dma_buf, void *vaddr) +{ + struct drm_gem_object *obj = dma_buf->priv; + + drm_gem_vunmap(obj, vaddr); +} +EXPORT_SYMBOL(drm_gem_dmabuf_vunmap); + /** * drm_gem_prime_mmap - PRIME mmap function for GEM drivers * @obj: GEM object @@ -657,14 +742,117 @@ out: EXPORT_SYMBOL(drm_gem_prime_mmap); /** + * drm_gem_dmabuf_mmap - dma_buf mmap implementation for GEM + * @dma_buf: buffer to be mapped + * @vma: virtual address range + * + * Provides memory mapping for the buffer. This can be used as the + * &dma_buf_ops.mmap callback. It just forwards to &drm_driver.gem_prime_mmap, + * which should be set to drm_gem_prime_mmap(). + * + * FIXME: There's really no point to this wrapper, drivers which need anything + * else but drm_gem_prime_mmap can roll their own &dma_buf_ops.mmap callback. + * + * Returns 0 on success or a negative error code on failure. + */ +int drm_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struct *vma) +{ + struct drm_gem_object *obj = dma_buf->priv; + struct drm_device *dev = obj->dev; + + if (!dev->driver->gem_prime_mmap) + return -ENOSYS; + + return dev->driver->gem_prime_mmap(obj, vma); +} +EXPORT_SYMBOL(drm_gem_dmabuf_mmap); + +static const struct dma_buf_ops drm_gem_prime_dmabuf_ops = { + .cache_sgt_mapping = true, + .attach = drm_gem_map_attach, + .detach = drm_gem_map_detach, + .map_dma_buf = drm_gem_map_dma_buf, + .unmap_dma_buf = drm_gem_unmap_dma_buf, + .release = drm_gem_dmabuf_release, + .mmap = drm_gem_dmabuf_mmap, + .vmap = drm_gem_dmabuf_vmap, + .vunmap = drm_gem_dmabuf_vunmap, +}; + +/** + * drm_prime_pages_to_sg - converts a page array into an sg list + * @pages: pointer to the array of page pointers to convert + * @nr_pages: length of the page vector + * + * This helper creates an sg table object from a set of pages + * the driver is responsible for mapping the pages into the + * importers address space for use with dma_buf itself. + * + * This is useful for implementing &drm_gem_object_funcs.get_sg_table. + */ +struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages) +{ + struct sg_table *sg = NULL; + int ret; + + sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); + if (!sg) { + ret = -ENOMEM; + goto out; + } + + ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0, + nr_pages << PAGE_SHIFT, GFP_KERNEL); + if (ret) + goto out; + + return sg; +out: + kfree(sg); + return ERR_PTR(ret); +} +EXPORT_SYMBOL(drm_prime_pages_to_sg); + +/** + * drm_gem_prime_export - helper library implementation of the export callback + * @obj: GEM object to export + * @flags: flags like DRM_CLOEXEC and DRM_RDWR + * + * This is the implementation of the &drm_gem_object_funcs.export functions for GEM drivers + * using the PRIME helpers. It is used as the default in + * drm_gem_prime_handle_to_fd(). + */ +struct dma_buf *drm_gem_prime_export(struct drm_gem_object *obj, + int flags) +{ + struct drm_device *dev = obj->dev; + struct dma_buf_export_info exp_info = { + .exp_name = KBUILD_MODNAME, /* white lie for debug */ + .owner = dev->driver->fops->owner, + .ops = &drm_gem_prime_dmabuf_ops, + .size = obj->size, + .flags = flags, + .priv = obj, + .resv = obj->resv, + }; + + return drm_gem_dmabuf_export(dev, &exp_info); +} +EXPORT_SYMBOL(drm_gem_prime_export); + +/** * drm_gem_prime_import_dev - core implementation of the import callback * @dev: drm_device to import into * @dma_buf: dma-buf object to import * @attach_dev: struct device to dma_buf attach * - * This is the core of drm_gem_prime_import. It's designed to be called by - * drivers who want to use a different device structure than dev->dev for - * attaching via dma_buf. + * This is the core of drm_gem_prime_import(). It's designed to be called by + * drivers who want to use a different device structure than &drm_device.dev for + * attaching via dma_buf. This function calls + * &drm_driver.gem_prime_import_sg_table internally. + * + * Drivers must arrange to call drm_prime_gem_destroy() from their + * &drm_gem_object_funcs.free hook when using this function. */ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev, struct dma_buf *dma_buf, @@ -709,6 +897,7 @@ struct drm_gem_object *drm_gem_prime_import_dev(struct drm_device *dev, } obj->import_attach = attach; + obj->resv = dma_buf->resv; return obj; @@ -728,7 +917,12 @@ EXPORT_SYMBOL(drm_gem_prime_import_dev); * @dma_buf: dma-buf object to import * * This is the implementation of the gem_prime_import functions for GEM drivers - * using the PRIME helpers. + * using the PRIME helpers. Drivers can use this as their + * &drm_driver.gem_prime_import implementation. It is used as the default + * implementation in drm_gem_prime_fd_to_handle(). + * + * Drivers must arrange to call drm_prime_gem_destroy() from their + * &drm_gem_object_funcs.free hook when using this function. */ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf) @@ -738,154 +932,6 @@ struct drm_gem_object *drm_gem_prime_import(struct drm_device *dev, EXPORT_SYMBOL(drm_gem_prime_import); /** - * drm_gem_prime_fd_to_handle - PRIME import function for GEM drivers - * @dev: dev to export the buffer from - * @file_priv: drm file-private structure - * @prime_fd: fd id of the dma-buf which should be imported - * @handle: pointer to storage for the handle of the imported buffer object - * - * This is the PRIME import function which must be used mandatorily by GEM - * drivers to ensure correct lifetime management of the underlying GEM object. - * The actual importing of GEM object from the dma-buf is done through the - * gem_import_export driver callback. - */ -int drm_gem_prime_fd_to_handle(struct drm_device *dev, - struct drm_file *file_priv, int prime_fd, - uint32_t *handle) -{ - struct dma_buf *dma_buf; - struct drm_gem_object *obj; - int ret; - - dma_buf = dma_buf_get(prime_fd); - if (IS_ERR(dma_buf)) - return PTR_ERR(dma_buf); - - mutex_lock(&file_priv->prime.lock); - - ret = drm_prime_lookup_buf_handle(&file_priv->prime, - dma_buf, handle); - if (ret == 0) - goto out_put; - - /* never seen this one, need to import */ - mutex_lock(&dev->object_name_lock); - if (dev->driver->gem_prime_import) - obj = dev->driver->gem_prime_import(dev, dma_buf); - else - obj = drm_gem_prime_import(dev, dma_buf); - if (IS_ERR(obj)) { - ret = PTR_ERR(obj); - goto out_unlock; - } - - if (obj->dma_buf) { - WARN_ON(obj->dma_buf != dma_buf); - } else { - obj->dma_buf = dma_buf; - get_dma_buf(dma_buf); - } - - /* _handle_create_tail unconditionally unlocks dev->object_name_lock. */ - ret = drm_gem_handle_create_tail(file_priv, obj, handle); - drm_gem_object_put_unlocked(obj); - if (ret) - goto out_put; - - ret = drm_prime_add_buf_handle(&file_priv->prime, - dma_buf, *handle); - mutex_unlock(&file_priv->prime.lock); - if (ret) - goto fail; - - dma_buf_put(dma_buf); - - return 0; - -fail: - /* hmm, if driver attached, we are relying on the free-object path - * to detach.. which seems ok.. - */ - drm_gem_handle_delete(file_priv, *handle); - dma_buf_put(dma_buf); - return ret; - -out_unlock: - mutex_unlock(&dev->object_name_lock); -out_put: - mutex_unlock(&file_priv->prime.lock); - dma_buf_put(dma_buf); - return ret; -} -EXPORT_SYMBOL(drm_gem_prime_fd_to_handle); - -int drm_prime_handle_to_fd_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_prime_handle *args = data; - - if (!drm_core_check_feature(dev, DRIVER_PRIME)) - return -EOPNOTSUPP; - - if (!dev->driver->prime_handle_to_fd) - return -ENOSYS; - - /* check flags are valid */ - if (args->flags & ~(DRM_CLOEXEC | DRM_RDWR)) - return -EINVAL; - - return dev->driver->prime_handle_to_fd(dev, file_priv, - args->handle, args->flags, &args->fd); -} - -int drm_prime_fd_to_handle_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - struct drm_prime_handle *args = data; - - if (!drm_core_check_feature(dev, DRIVER_PRIME)) - return -EOPNOTSUPP; - - if (!dev->driver->prime_fd_to_handle) - return -ENOSYS; - - return dev->driver->prime_fd_to_handle(dev, file_priv, - args->fd, &args->handle); -} - -/** - * drm_prime_pages_to_sg - converts a page array into an sg list - * @pages: pointer to the array of page pointers to convert - * @nr_pages: length of the page vector - * - * This helper creates an sg table object from a set of pages - * the driver is responsible for mapping the pages into the - * importers address space for use with dma_buf itself. - */ -struct sg_table *drm_prime_pages_to_sg(struct page **pages, unsigned int nr_pages) -{ - struct sg_table *sg = NULL; - int ret; - - sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL); - if (!sg) { - ret = -ENOMEM; - goto out; - } - - ret = sg_alloc_table_from_pages(sg, pages, nr_pages, 0, - nr_pages << PAGE_SHIFT, GFP_KERNEL); - if (ret) - goto out; - - return sg; -out: - kfree(sg); - return ERR_PTR(ret); -} -EXPORT_SYMBOL(drm_prime_pages_to_sg); - -/** * drm_prime_sg_to_page_addr_arrays - convert an sg table into a page array * @sgt: scatter-gather table to convert * @pages: optional array of page pointers to store the page array in @@ -894,6 +940,9 @@ EXPORT_SYMBOL(drm_prime_pages_to_sg); * * Exports an sg table into an array of pages and addresses. This is currently * required by the TTM driver in order to do correct fault handling. + * + * Drivers can use this in their &drm_driver.gem_prime_import_sg_table + * implementation. */ int drm_prime_sg_to_page_addr_arrays(struct sg_table *sgt, struct page **pages, dma_addr_t *addrs, int max_entries) @@ -934,7 +983,7 @@ EXPORT_SYMBOL(drm_prime_sg_to_page_addr_arrays); * @sg: the sg-table which was pinned at import time * * This is the cleanup functions which GEM drivers need to call when they use - * @drm_gem_prime_import to import dma-bufs. + * drm_gem_prime_import() or drm_gem_prime_import_dev() to import dma-bufs. */ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) { @@ -949,16 +998,3 @@ void drm_prime_gem_destroy(struct drm_gem_object *obj, struct sg_table *sg) dma_buf_put(dma_buf); } EXPORT_SYMBOL(drm_prime_gem_destroy); - -void drm_prime_init_file_private(struct drm_prime_file_private *prime_fpriv) -{ - mutex_init(&prime_fpriv->lock); - prime_fpriv->dmabufs = RB_ROOT; - prime_fpriv->handles = RB_ROOT; -} - -void drm_prime_destroy_file_private(struct drm_prime_file_private *prime_fpriv) -{ - /* by now drm_gem_release should've made sure the list is empty */ - WARN_ON(!RB_EMPTY_ROOT(&prime_fpriv->dmabufs)); -} diff --git a/drivers/gpu/drm/drm_scatter.c b/drivers/gpu/drm/drm_scatter.c index 2d7790f14b0c..d5c386154246 100644 --- a/drivers/gpu/drm/drm_scatter.c +++ b/drivers/gpu/drm/drm_scatter.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_scatter.c * IOCTLs to manage scatter/gather memory * diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index a199c8d56b95..1438dcb3ebb1 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -53,6 +53,7 @@ #include <linux/sync_file.h> #include <linux/uaccess.h> +#include <drm/drm.h> #include <drm/drm_drv.h> #include <drm/drm_file.h> #include <drm/drm_gem.h> @@ -1297,14 +1298,14 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, struct dma_fence *iter, *last_signaled = NULL; dma_fence_chain_for_each(iter, fence) { - if (!iter) - break; - dma_fence_put(last_signaled); - last_signaled = dma_fence_get(iter); - if (!to_dma_fence_chain(last_signaled)->prev_seqno) + if (iter->context != fence->context) { + dma_fence_put(iter); /* It is most likely that timeline has * unorder points. */ break; + } + dma_fence_put(last_signaled); + last_signaled = dma_fence_get(iter); } point = dma_fence_is_signaled(last_signaled) ? last_signaled->seqno : diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index ad10810bc972..dd2bc85f43cc 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -14,6 +14,7 @@ #include <linux/err.h> #include <linux/export.h> #include <linux/gfp.h> +#include <linux/i2c.h> #include <linux/kdev_t.h> #include <linux/slab.h> @@ -26,6 +27,7 @@ #include <drm/drm_sysfs.h> #include "drm_internal.h" +#include "drm_crtc_internal.h" #define to_drm_minor(d) dev_get_drvdata(d) #define to_drm_connector(d) dev_get_drvdata(d) @@ -294,6 +296,9 @@ int drm_sysfs_connector_add(struct drm_connector *connector) /* Let userspace know we have a new connector */ drm_sysfs_hotplug_event(dev); + if (connector->ddc) + return sysfs_create_link(&connector->kdev->kobj, + &connector->ddc->dev.kobj, "ddc"); return 0; } @@ -301,6 +306,10 @@ void drm_sysfs_connector_remove(struct drm_connector *connector) { if (!connector->kdev) return; + + if (connector->ddc) + sysfs_remove_link(&connector->kdev->kobj, "ddc"); + DRM_DEBUG("removing \"%s\" from sysfs\n", connector->name); @@ -325,6 +334,9 @@ void drm_sysfs_lease_event(struct drm_device *dev) * Send a uevent for the DRM device specified by @dev. Currently we only * set HOTPLUG=1 in the uevent environment, but this could be expanded to * deal with other types of events. + * + * Any new uapi should be using the drm_sysfs_connector_status_event() + * for uevents on connector status change. */ void drm_sysfs_hotplug_event(struct drm_device *dev) { @@ -337,6 +349,37 @@ void drm_sysfs_hotplug_event(struct drm_device *dev) } EXPORT_SYMBOL(drm_sysfs_hotplug_event); +/** + * drm_sysfs_connector_status_event - generate a DRM uevent for connector + * property status change + * @connector: connector on which property status changed + * @property: connector property whose status changed. + * + * Send a uevent for the DRM device specified by @dev. Currently we + * set HOTPLUG=1 and connector id along with the attached property id + * related to the status change. + */ +void drm_sysfs_connector_status_event(struct drm_connector *connector, + struct drm_property *property) +{ + struct drm_device *dev = connector->dev; + char hotplug_str[] = "HOTPLUG=1", conn_id[21], prop_id[21]; + char *envp[4] = { hotplug_str, conn_id, prop_id, NULL }; + + WARN_ON(!drm_mode_obj_find_prop_id(&connector->base, + property->base.id)); + + snprintf(conn_id, ARRAY_SIZE(conn_id), + "CONNECTOR=%u", connector->base.id); + snprintf(prop_id, ARRAY_SIZE(prop_id), + "PROPERTY=%u", property->base.id); + + DRM_DEBUG("generating connector status event\n"); + + kobject_uevent_env(&dev->primary->kdev->kobj, KOBJ_CHANGE, envp); +} +EXPORT_SYMBOL(drm_sysfs_connector_status_event); + static void drm_sysfs_release(struct device *dev) { kfree(dev); diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 603ab105125d..fd1fbc77871f 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -31,7 +31,6 @@ #include <drm/drm_drv.h> #include <drm/drm_framebuffer.h> #include <drm/drm_print.h> -#include <drm/drm_os_linux.h> #include <drm/drm_vblank.h> #include "drm_internal.h" @@ -1670,12 +1669,28 @@ int drm_wait_vblank_ioctl(struct drm_device *dev, void *data, } if (req_seq != seq) { + int wait; + DRM_DEBUG("waiting on vblank count %llu, crtc %u\n", req_seq, pipe); - DRM_WAIT_ON(ret, vblank->queue, 3 * HZ, - vblank_passed(drm_vblank_count(dev, pipe), - req_seq) || - !READ_ONCE(vblank->enabled)); + wait = wait_event_interruptible_timeout(vblank->queue, + vblank_passed(drm_vblank_count(dev, pipe), req_seq) || + !READ_ONCE(vblank->enabled), + msecs_to_jiffies(3000)); + + switch (wait) { + case 0: + /* timeout */ + ret = -EBUSY; + break; + case -ERESTARTSYS: + /* interrupted by signal */ + ret = -EINTR; + break; + default: + ret = 0; + break; + } } if (ret != -EINTR) { diff --git a/drivers/gpu/drm/drm_vm.c b/drivers/gpu/drm/drm_vm.c index 05f7c5833946..52e87e4869a5 100644 --- a/drivers/gpu/drm/drm_vm.c +++ b/drivers/gpu/drm/drm_vm.c @@ -1,4 +1,4 @@ -/** +/* * \file drm_vm.c * Memory mapping for DRM * diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 7eb7cf9c3fa8..08e033c1758d 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -430,17 +430,17 @@ static int etnaviv_ioctl_pm_query_sig(struct drm_device *dev, void *data, static const struct drm_ioctl_desc etnaviv_ioctls[] = { #define ETNA_IOCTL(n, func, flags) \ DRM_IOCTL_DEF_DRV(ETNAVIV_##n, etnaviv_ioctl_##func, flags) - ETNA_IOCTL(GET_PARAM, get_param, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(GEM_NEW, gem_new, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(GEM_INFO, gem_info, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(GEM_SUBMIT, gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_AUTH|DRM_RENDER_ALLOW), - ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_AUTH|DRM_RENDER_ALLOW), + ETNA_IOCTL(GET_PARAM, get_param, DRM_RENDER_ALLOW), + ETNA_IOCTL(GEM_NEW, gem_new, DRM_RENDER_ALLOW), + ETNA_IOCTL(GEM_INFO, gem_info, DRM_RENDER_ALLOW), + ETNA_IOCTL(GEM_CPU_PREP, gem_cpu_prep, DRM_RENDER_ALLOW), + ETNA_IOCTL(GEM_CPU_FINI, gem_cpu_fini, DRM_RENDER_ALLOW), + ETNA_IOCTL(GEM_SUBMIT, gem_submit, DRM_RENDER_ALLOW), + ETNA_IOCTL(WAIT_FENCE, wait_fence, DRM_RENDER_ALLOW), + ETNA_IOCTL(GEM_USERPTR, gem_userptr, DRM_RENDER_ALLOW), + ETNA_IOCTL(GEM_WAIT, gem_wait, DRM_RENDER_ALLOW), + ETNA_IOCTL(PM_QUERY_DOM, pm_query_dom, DRM_RENDER_ALLOW), + ETNA_IOCTL(PM_QUERY_SIG, pm_query_sig, DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { @@ -462,17 +462,13 @@ static const struct file_operations fops = { }; static struct drm_driver etnaviv_drm_driver = { - .driver_features = DRIVER_GEM | - DRIVER_PRIME | - DRIVER_RENDER, + .driver_features = DRIVER_GEM | DRIVER_RENDER, .open = etnaviv_open, .postclose = etnaviv_postclose, .gem_free_object_unlocked = etnaviv_gem_free_object, .gem_vm_ops = &vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = etnaviv_gem_prime_pin, .gem_prime_unpin = etnaviv_gem_prime_unpin, .gem_prime_get_sg_table = etnaviv_gem_prime_get_sg_table, diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index e8778ebb72e6..17ca602db60a 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -565,8 +565,7 @@ void etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj) } static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags, - struct reservation_object *robj, const struct etnaviv_gem_ops *ops, - struct drm_gem_object **obj) + const struct etnaviv_gem_ops *ops, struct drm_gem_object **obj) { struct etnaviv_gem_object *etnaviv_obj; unsigned sz = sizeof(*etnaviv_obj); @@ -594,8 +593,6 @@ static int etnaviv_gem_new_impl(struct drm_device *dev, u32 size, u32 flags, etnaviv_obj->flags = flags; etnaviv_obj->ops = ops; - if (robj) - etnaviv_obj->base.resv = robj; mutex_init(&etnaviv_obj->lock); INIT_LIST_HEAD(&etnaviv_obj->vram_list); @@ -614,7 +611,7 @@ int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, size = PAGE_ALIGN(size); - ret = etnaviv_gem_new_impl(dev, size, flags, NULL, + ret = etnaviv_gem_new_impl(dev, size, flags, &etnaviv_gem_shmem_ops, &obj); if (ret) goto fail; @@ -646,13 +643,12 @@ fail: } int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags, - struct reservation_object *robj, const struct etnaviv_gem_ops *ops, - struct etnaviv_gem_object **res) + const struct etnaviv_gem_ops *ops, struct etnaviv_gem_object **res) { struct drm_gem_object *obj; int ret; - ret = etnaviv_gem_new_impl(dev, size, flags, robj, ops, &obj); + ret = etnaviv_gem_new_impl(dev, size, flags, ops, &obj); if (ret) return ret; @@ -734,7 +730,7 @@ int etnaviv_gem_new_userptr(struct drm_device *dev, struct drm_file *file, struct etnaviv_gem_object *etnaviv_obj; int ret; - ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED, NULL, + ret = etnaviv_gem_new_private(dev, size, ETNA_BO_CACHED, &etnaviv_gem_userptr_ops, &etnaviv_obj); if (ret) return ret; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.h b/drivers/gpu/drm/etnaviv/etnaviv_gem.h index 753c458497d0..fcd5d71b502f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.h @@ -112,8 +112,7 @@ void etnaviv_submit_put(struct etnaviv_gem_submit * submit); int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj, struct timespec *timeout); int etnaviv_gem_new_private(struct drm_device *dev, size_t size, u32 flags, - struct reservation_object *robj, const struct etnaviv_gem_ops *ops, - struct etnaviv_gem_object **res); + const struct etnaviv_gem_ops *ops, struct etnaviv_gem_object **res); void etnaviv_gem_obj_add(struct drm_device *dev, struct drm_gem_object *obj); struct page **etnaviv_gem_get_pages(struct etnaviv_gem_object *obj); void etnaviv_gem_put_pages(struct etnaviv_gem_object *obj); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c index 00e8b6a817e3..a05292e8ed6f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c @@ -109,7 +109,6 @@ struct drm_gem_object *etnaviv_gem_prime_import_sg_table(struct drm_device *dev, int ret, npages; ret = etnaviv_gem_new_private(dev, size, ETNA_BO_WC, - attach->dmabuf->resv, &etnaviv_gem_prime_ops, &etnaviv_obj); if (ret < 0) return ERR_PTR(ret); diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c index 58baf49d9926..cc53dcad25e4 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.c +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c @@ -75,29 +75,29 @@ static const struct vm_operations_struct exynos_drm_gem_vm_ops = { static const struct drm_ioctl_desc exynos_ioctls[] = { DRM_IOCTL_DEF_DRV(EXYNOS_GEM_CREATE, exynos_drm_gem_create_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_MAP, exynos_drm_gem_map_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_GEM_GET, exynos_drm_gem_get_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_VIDI_CONNECTION, vidi_connection_ioctl, DRM_AUTH), DRM_IOCTL_DEF_DRV(EXYNOS_G2D_GET_VER, exynos_g2d_get_ver_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_G2D_SET_CMDLIST, exynos_g2d_set_cmdlist_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_G2D_EXEC, exynos_g2d_exec_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_RESOURCES, exynos_drm_ipp_get_res_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_CAPS, exynos_drm_ipp_get_caps_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_IPP_GET_LIMITS, exynos_drm_ipp_get_limits_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(EXYNOS_IPP_COMMIT, exynos_drm_ipp_commit_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), }; static const struct file_operations exynos_drm_driver_fops = { @@ -112,7 +112,7 @@ static const struct file_operations exynos_drm_driver_fops = { }; static struct drm_driver exynos_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_RENDER, .open = exynos_drm_open, .lastclose = drm_fb_helper_lastclose, @@ -122,7 +122,6 @@ static struct drm_driver exynos_drm_driver = { .dumb_create = exynos_drm_gem_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, .gem_prime_import = exynos_drm_gem_prime_import, .gem_prime_get_sg_table = exynos_drm_gem_prime_get_sg_table, .gem_prime_import_sg_table = exynos_drm_gem_prime_import_sg_table, diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c index f4635bea0265..b9ca81a6f80f 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_crtc.c @@ -8,12 +8,13 @@ #include <linux/clk.h> #include <linux/regmap.h> -#include <drm/drmP.h> +#include <video/videomode.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_probe_helper.h> -#include <video/videomode.h> +#include <drm/drm_vblank.h> #include "fsl_dcu_drm_crtc.h" #include "fsl_dcu_drm_drv.h" diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c index e81daaaa5965..f15d2e7967a3 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c @@ -18,13 +18,15 @@ #include <linux/pm_runtime.h> #include <linux/regmap.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_irq.h> #include <drm/drm_modeset_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "fsl_dcu_drm_crtc.h" #include "fsl_dcu_drm_drv.h" @@ -133,8 +135,7 @@ static irqreturn_t fsl_dcu_drm_irq(int irq, void *arg) DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops); static struct drm_driver fsl_dcu_drm_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET - | DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .load = fsl_dcu_load, .unload = fsl_dcu_unload, .irq_handler = fsl_dcu_drm_irq, @@ -144,8 +145,6 @@ static struct drm_driver fsl_dcu_drm_driver = { .gem_vm_ops = &drm_gem_cma_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c index 2467c8934405..d763f53f480c 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_kms.c @@ -5,7 +5,6 @@ * Freescale DCU drm device driver */ -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c index 6f2f65030dd1..86fac677fe69 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_plane.c @@ -7,10 +7,10 @@ #include <linux/regmap.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c index c49e9e3740f8..279d83eaffc0 100644 --- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c +++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_rgb.c @@ -8,7 +8,6 @@ #include <linux/backlight.h> #include <linux/of_graph.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index 08657a3627f3..cc4c41748cfb 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -11,10 +11,16 @@ * Jianhua Li <lijianhua@huawei.com> */ +#include <linux/delay.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_vram_helper.h> #include <drm/drm_plane_helper.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "hibmc_drm_drv.h" #include "hibmc_drm_regs.h" diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index ce89e56937b0..2ae538835781 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -13,9 +13,16 @@ #include <linux/console.h> #include <linux/module.h> +#include <linux/pci.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_gem_vram_helper.h> +#include <drm/drm_irq.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> +#include <drm/drm_vram_mm_helper.h> #include "hibmc_drm_drv.h" #include "hibmc_drm_regs.h" @@ -51,10 +58,9 @@ static struct drm_driver hibmc_driver = { .desc = "hibmc drm driver", .major = 1, .minor = 0, - .gem_free_object_unlocked = - drm_gem_vram_driver_gem_free_object_unlocked, .dumb_create = hibmc_dumb_create, .dumb_map_offset = drm_gem_vram_driver_dumb_mmap_offset, + .gem_prime_mmap = drm_gem_prime_mmap, .irq_handler = hibmc_drm_interrupt, }; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index 69348bf54a84..e58ecd7edcf8 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -14,12 +14,11 @@ #ifndef HIBMC_DRM_DRV_H #define HIBMC_DRM_DRV_H -#include <drm/drmP.h> -#include <drm/drm_atomic.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_gem.h> -#include <drm/drm_gem_vram_helper.h> -#include <drm/drm_vram_mm_helper.h> +#include <drm/drm_framebuffer.h> + +struct drm_device; +struct drm_gem_object; struct hibmc_framebuffer { struct drm_framebuffer fb; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c index af1ea4cceffa..b4c1cea051e8 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_fbdev.c @@ -13,6 +13,8 @@ #include <drm/drm_crtc.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_vram_helper.h> #include <drm/drm_probe_helper.h> #include "hibmc_drm_drv.h" diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index 634a3bf018b2..6d98fdc06f6c 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -13,6 +13,7 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_print.h> #include "hibmc_drm_drv.h" #include "hibmc_drm_regs.h" diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index 5d4a03cd7d50..9f6e473e6295 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -11,7 +11,13 @@ * Jianhua Li <lijianhua@huawei.com> */ +#include <linux/pci.h> + #include <drm/drm_atomic_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_vram_helper.h> +#include <drm/drm_print.h> +#include <drm/drm_vram_mm_helper.h> #include "hibmc_drm_drv.h" @@ -60,7 +66,7 @@ int hibmc_gem_create(struct drm_device *dev, u32 size, bool iskernel, DRM_ERROR("failed to allocate GEM object: %d\n", ret); return ret; } - *obj = &gbo->gem; + *obj = &gbo->bo.base; return 0; } diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c index ad7042ae2241..0df1afdf319d 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_ade.c @@ -13,19 +13,23 @@ #include <linux/bitops.h> #include <linux/clk.h> -#include <video/display_timing.h> #include <linux/mfd/syscon.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/reset.h> -#include <drm/drmP.h> +#include <video/display_timing.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "kirin_drm_drv.h" #include "kirin_ade_reg.h" diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c index 4a7fe10a37cb..204c94c01e3d 100644 --- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c @@ -13,16 +13,19 @@ #include <linux/of_platform.h> #include <linux/component.h> +#include <linux/module.h> #include <linux/of_graph.h> +#include <linux/platform_device.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "kirin_drm_drv.h" @@ -113,8 +116,7 @@ static int kirin_gem_cma_dumb_create(struct drm_file *file, } static struct drm_driver kirin_drm_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &kirin_drm_fops, .gem_free_object_unlocked = drm_gem_cma_free_object, @@ -123,8 +125,6 @@ static struct drm_driver kirin_drm_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/i2c/ch7006_priv.h b/drivers/gpu/drm/i2c/ch7006_priv.h index b6e091935977..986b04599906 100644 --- a/drivers/gpu/drm/i2c/ch7006_priv.h +++ b/drivers/gpu/drm/i2c/ch7006_priv.h @@ -27,7 +27,6 @@ #ifndef __DRM_I2C_CH7006_PRIV_H__ #define __DRM_I2C_CH7006_PRIV_H__ -#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_encoder_slave.h> #include <drm/drm_probe_helper.h> diff --git a/drivers/gpu/drm/i2c/sil164_drv.c b/drivers/gpu/drm/i2c/sil164_drv.c index 878ba8d06ce2..8bcf0d199145 100644 --- a/drivers/gpu/drm/i2c/sil164_drv.c +++ b/drivers/gpu/drm/i2c/sil164_drv.c @@ -26,8 +26,9 @@ #include <linux/module.h> -#include <drm/drmP.h> +#include <drm/drm_drv.h> #include <drm/drm_encoder_slave.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include <drm/i2c/sil164.h> diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c index 3b378936f575..2a77823b8e9a 100644 --- a/drivers/gpu/drm/i810/i810_dma.c +++ b/drivers/gpu/drm/i810/i810_dma.c @@ -30,13 +30,20 @@ * */ -#include <drm/drmP.h> +#include <linux/delay.h> +#include <linux/mman.h> + +#include <drm/drm_agpsupport.h> +#include <drm/drm_device.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_irq.h> +#include <drm/drm_pci.h> +#include <drm/drm_print.h> #include <drm/i810_drm.h> + #include "i810_drv.h" -#include <linux/interrupt.h> /* For task queue support */ -#include <linux/delay.h> -#include <linux/slab.h> -#include <linux/pagemap.h> #define I810_BUF_FREE 2 #define I810_BUF_CLIENT 1 diff --git a/drivers/gpu/drm/i810/i810_drv.c b/drivers/gpu/drm/i810/i810_drv.c index c69d5c487f51..5dd26a06ee0e 100644 --- a/drivers/gpu/drm/i810/i810_drv.c +++ b/drivers/gpu/drm/i810/i810_drv.c @@ -30,13 +30,15 @@ * Gareth Hughes <gareth@valinux.com> */ +#include "i810_drv.h" #include <linux/module.h> -#include <drm/drmP.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_pci.h> +#include <drm/drm_pciids.h> #include <drm/i810_drm.h> -#include "i810_drv.h" -#include <drm/drm_pciids.h> static struct pci_device_id pciidlist[] = { i810_PCI_IDS diff --git a/drivers/gpu/drm/i810/i810_drv.h b/drivers/gpu/drm/i810/i810_drv.h index c73d2f2da57b..9df3981ffc66 100644 --- a/drivers/gpu/drm/i810/i810_drv.h +++ b/drivers/gpu/drm/i810/i810_drv.h @@ -32,7 +32,9 @@ #ifndef _I810_DRV_H_ #define _I810_DRV_H_ +#include <drm/drm_ioctl.h> #include <drm/drm_legacy.h> +#include <drm/i810_drm.h> /* General customization: */ diff --git a/drivers/gpu/drm/i915/display/intel_ddi.c b/drivers/gpu/drm/i915/display/intel_ddi.c index c6f38c7b397d..cf3c3fd7089f 100644 --- a/drivers/gpu/drm/i915/display/intel_ddi.c +++ b/drivers/gpu/drm/i915/display/intel_ddi.c @@ -3562,7 +3562,8 @@ static void intel_enable_ddi(struct intel_encoder *encoder, /* Enable hdcp if it's desired */ if (conn_state->content_protection == DRM_MODE_CONTENT_PROTECTION_DESIRED) - intel_hdcp_enable(to_intel_connector(conn_state->connector)); + intel_hdcp_enable(to_intel_connector(conn_state->connector), + (u8)conn_state->hdcp_content_type); } static void intel_disable_ddi_dp(struct intel_encoder *encoder, @@ -3631,15 +3632,41 @@ static void intel_ddi_update_pipe(struct intel_encoder *encoder, const struct intel_crtc_state *crtc_state, const struct drm_connector_state *conn_state) { + struct intel_connector *connector = + to_intel_connector(conn_state->connector); + struct intel_hdcp *hdcp = &connector->hdcp; + bool content_protection_type_changed = + (conn_state->hdcp_content_type != hdcp->content_type && + conn_state->content_protection != + DRM_MODE_CONTENT_PROTECTION_UNDESIRED); + if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_HDMI)) intel_ddi_update_pipe_dp(encoder, crtc_state, conn_state); + /* + * During the HDCP encryption session if Type change is requested, + * disable the HDCP and reenable it with new TYPE value. + */ if (conn_state->content_protection == - DRM_MODE_CONTENT_PROTECTION_DESIRED) - intel_hdcp_enable(to_intel_connector(conn_state->connector)); - else if (conn_state->content_protection == - DRM_MODE_CONTENT_PROTECTION_UNDESIRED) - intel_hdcp_disable(to_intel_connector(conn_state->connector)); + DRM_MODE_CONTENT_PROTECTION_UNDESIRED || + content_protection_type_changed) + intel_hdcp_disable(connector); + + /* + * Mark the hdcp state as DESIRED after the hdcp disable of type + * change procedure. + */ + if (content_protection_type_changed) { + mutex_lock(&hdcp->mutex); + hdcp->value = DRM_MODE_CONTENT_PROTECTION_DESIRED; + schedule_work(&hdcp->prop_work); + mutex_unlock(&hdcp->mutex); + } + + if (conn_state->content_protection == + DRM_MODE_CONTENT_PROTECTION_DESIRED || + content_protection_type_changed) + intel_hdcp_enable(connector, (u8)conn_state->hdcp_content_type); } static void diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c index a78139f9e847..845eb8f29b58 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.c +++ b/drivers/gpu/drm/i915/display/intel_hdcp.c @@ -869,7 +869,6 @@ static void intel_hdcp_prop_work(struct work_struct *work) prop_work); struct intel_connector *connector = intel_hdcp_to_connector(hdcp); struct drm_device *dev = connector->base.dev; - struct drm_connector_state *state; drm_modeset_lock(&dev->mode_config.connection_mutex, NULL); mutex_lock(&hdcp->mutex); @@ -879,10 +878,9 @@ static void intel_hdcp_prop_work(struct work_struct *work) * those to UNDESIRED is handled by core. If value == UNDESIRED, * we're running just after hdcp has been disabled, so just exit */ - if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) { - state = connector->base.state; - state->content_protection = hdcp->value; - } + if (hdcp->value != DRM_MODE_CONTENT_PROTECTION_UNDESIRED) + drm_hdcp_update_content_protection(&connector->base, + hdcp->value); mutex_unlock(&hdcp->mutex); drm_modeset_unlock(&dev->mode_config.connection_mutex); @@ -1754,14 +1752,15 @@ static const struct component_ops i915_hdcp_component_ops = { .unbind = i915_hdcp_component_unbind, }; -static inline int initialize_hdcp_port_data(struct intel_connector *connector) +static inline int initialize_hdcp_port_data(struct intel_connector *connector, + const struct intel_hdcp_shim *shim) { struct intel_hdcp *hdcp = &connector->hdcp; struct hdcp_port_data *data = &hdcp->port_data; data->port = connector->encoder->port; data->port_type = (u8)HDCP_PORT_TYPE_INTEGRATED; - data->protocol = (u8)hdcp->shim->protocol; + data->protocol = (u8)shim->protocol; data->k = 1; if (!data->streams) @@ -1811,12 +1810,13 @@ void intel_hdcp_component_init(struct drm_i915_private *dev_priv) } } -static void intel_hdcp2_init(struct intel_connector *connector) +static void intel_hdcp2_init(struct intel_connector *connector, + const struct intel_hdcp_shim *shim) { struct intel_hdcp *hdcp = &connector->hdcp; int ret; - ret = initialize_hdcp_port_data(connector); + ret = initialize_hdcp_port_data(connector, shim); if (ret) { DRM_DEBUG_KMS("Mei hdcp data init failed\n"); return; @@ -1835,23 +1835,28 @@ int intel_hdcp_init(struct intel_connector *connector, if (!shim) return -EINVAL; - ret = drm_connector_attach_content_protection_property(&connector->base); - if (ret) + if (is_hdcp2_supported(dev_priv)) + intel_hdcp2_init(connector, shim); + + ret = + drm_connector_attach_content_protection_property(&connector->base, + hdcp->hdcp2_supported); + if (ret) { + hdcp->hdcp2_supported = false; + kfree(hdcp->port_data.streams); return ret; + } hdcp->shim = shim; mutex_init(&hdcp->mutex); INIT_DELAYED_WORK(&hdcp->check_work, intel_hdcp_check_work); INIT_WORK(&hdcp->prop_work, intel_hdcp_prop_work); - - if (is_hdcp2_supported(dev_priv)) - intel_hdcp2_init(connector); init_waitqueue_head(&hdcp->cp_irq_queue); return 0; } -int intel_hdcp_enable(struct intel_connector *connector) +int intel_hdcp_enable(struct intel_connector *connector, u8 content_type) { struct intel_hdcp *hdcp = &connector->hdcp; unsigned long check_link_interval = DRM_HDCP_CHECK_PERIOD_MS; @@ -1862,6 +1867,7 @@ int intel_hdcp_enable(struct intel_connector *connector) mutex_lock(&hdcp->mutex); WARN_ON(hdcp->value == DRM_MODE_CONTENT_PROTECTION_ENABLED); + hdcp->content_type = content_type; /* * Considering that HDCP2.2 is more secure than HDCP1.4, If the setup @@ -1873,8 +1879,12 @@ int intel_hdcp_enable(struct intel_connector *connector) check_link_interval = DRM_HDCP2_CHECK_PERIOD_MS; } - /* When HDCP2.2 fails, HDCP1.4 will be attempted */ - if (ret && intel_hdcp_capable(connector)) { + /* + * When HDCP2.2 fails and Content Type is not Type1, HDCP1.4 will + * be attempted. + */ + if (ret && intel_hdcp_capable(connector) && + hdcp->content_type != DRM_MODE_HDCP_CONTENT_TYPE1) { ret = _intel_hdcp_enable(connector); } @@ -1956,12 +1966,15 @@ void intel_hdcp_atomic_check(struct drm_connector *connector, /* * Nothing to do if the state didn't change, or HDCP was activated since - * the last commit + * the last commit. And also no change in hdcp content type. */ if (old_cp == new_cp || (old_cp == DRM_MODE_CONTENT_PROTECTION_DESIRED && - new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) - return; + new_cp == DRM_MODE_CONTENT_PROTECTION_ENABLED)) { + if (old_state->hdcp_content_type == + new_state->hdcp_content_type) + return; + } crtc_state = drm_atomic_get_new_crtc_state(new_state->state, new_state->crtc); diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.h b/drivers/gpu/drm/i915/display/intel_hdcp.h index be8da85c866a..13555b054930 100644 --- a/drivers/gpu/drm/i915/display/intel_hdcp.h +++ b/drivers/gpu/drm/i915/display/intel_hdcp.h @@ -21,7 +21,7 @@ void intel_hdcp_atomic_check(struct drm_connector *connector, struct drm_connector_state *new_state); int intel_hdcp_init(struct intel_connector *connector, const struct intel_hdcp_shim *hdcp_shim); -int intel_hdcp_enable(struct intel_connector *connector); +int intel_hdcp_enable(struct intel_connector *connector, u8 content_type); int intel_hdcp_disable(struct intel_connector *connector); bool is_hdcp_supported(struct drm_i915_private *dev_priv, enum port port); bool intel_hdcp_capable(struct intel_connector *connector); diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c index cbf1701d3acc..570b20ad9e58 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c @@ -204,8 +204,7 @@ static const struct dma_buf_ops i915_dmabuf_ops = { .end_cpu_access = i915_gem_end_cpu_access, }; -struct dma_buf *i915_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *gem_obj, int flags) +struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags) { struct drm_i915_gem_object *obj = to_intel_bo(gem_obj); DEFINE_DMA_BUF_EXPORT_INFO(exp_info); @@ -222,7 +221,7 @@ struct dma_buf *i915_gem_prime_export(struct drm_device *dev, return ERR_PTR(ret); } - return drm_gem_dmabuf_export(dev, &exp_info); + return drm_gem_dmabuf_export(gem_obj->dev, &exp_info); } static int i915_gem_object_get_pages_dmabuf(struct drm_i915_gem_object *obj) diff --git a/drivers/gpu/drm/i915/gem/i915_gem_wait.c b/drivers/gpu/drm/i915/gem/i915_gem_wait.c index 26ec6579b7cd..fa46a54bcbe7 100644 --- a/drivers/gpu/drm/i915/gem/i915_gem_wait.c +++ b/drivers/gpu/drm/i915/gem/i915_gem_wait.c @@ -35,7 +35,6 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, unsigned int flags, long timeout) { - unsigned int seq = __read_seqcount_begin(&resv->seq); struct dma_fence *excl; bool prune_fences = false; @@ -83,15 +82,12 @@ i915_gem_object_wait_reservation(struct reservation_object *resv, /* * Opportunistically prune the fences iff we know they have *all* been - * signaled and that the reservation object has not been changed (i.e. - * no new fences have been added). + * signaled. */ - if (prune_fences && !__read_seqcount_retry(&resv->seq, seq)) { - if (reservation_object_trylock(resv)) { - if (!__read_seqcount_retry(&resv->seq, seq)) - reservation_object_add_excl_fence(resv, NULL); - reservation_object_unlock(resv); - } + if (prune_fences && reservation_object_trylock(resv)) { + if (reservation_object_test_signaled_rcu(resv, true)) + reservation_object_add_excl_fence(resv, NULL); + reservation_object_unlock(resv); } return timeout; diff --git a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c index e3a64edef918..d85d1ce273ca 100644 --- a/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c +++ b/drivers/gpu/drm/i915/gem/selftests/i915_gem_dmabuf.c @@ -20,7 +20,7 @@ static int igt_dmabuf_export(void *arg) if (IS_ERR(obj)) return PTR_ERR(obj); - dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); + dmabuf = i915_gem_prime_export(&obj->base, 0); i915_gem_object_put(obj); if (IS_ERR(dmabuf)) { pr_err("i915_gem_prime_export failed with err=%d\n", @@ -44,7 +44,7 @@ static int igt_dmabuf_import_self(void *arg) if (IS_ERR(obj)) return PTR_ERR(obj); - dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); + dmabuf = i915_gem_prime_export(&obj->base, 0); if (IS_ERR(dmabuf)) { pr_err("i915_gem_prime_export failed with err=%d\n", (int)PTR_ERR(dmabuf)); @@ -219,7 +219,7 @@ static int igt_dmabuf_export_vmap(void *arg) if (IS_ERR(obj)) return PTR_ERR(obj); - dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); + dmabuf = i915_gem_prime_export(&obj->base, 0); if (IS_ERR(dmabuf)) { pr_err("i915_gem_prime_export failed with err=%d\n", (int)PTR_ERR(dmabuf)); @@ -266,7 +266,7 @@ static int igt_dmabuf_export_kmap(void *arg) if (IS_ERR(obj)) return PTR_ERR(obj); - dmabuf = i915_gem_prime_export(&i915->drm, &obj->base, 0); + dmabuf = i915_gem_prime_export(&obj->base, 0); i915_gem_object_put(obj); if (IS_ERR(dmabuf)) { err = PTR_ERR(dmabuf); diff --git a/drivers/gpu/drm/i915/gvt/dmabuf.c b/drivers/gpu/drm/i915/gvt/dmabuf.c index 41c8ebc60c63..13044c027f27 100644 --- a/drivers/gpu/drm/i915/gvt/dmabuf.c +++ b/drivers/gpu/drm/i915/gvt/dmabuf.c @@ -491,7 +491,7 @@ int intel_vgpu_get_dmabuf(struct intel_vgpu *vgpu, unsigned int dmabuf_id) obj->gvt_info = dmabuf_obj->info; - dmabuf = i915_gem_prime_export(dev, &obj->base, DRM_CLOEXEC | DRM_RDWR); + dmabuf = i915_gem_prime_export(&obj->base, DRM_CLOEXEC | DRM_RDWR); if (IS_ERR(dmabuf)) { gvt_vgpu_err("export dma-buf failed\n"); ret = PTR_ERR(dmabuf); diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 7d0813150146..f2d3d754af37 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c @@ -3195,9 +3195,9 @@ static const struct drm_ioctl_desc i915_ioctls[] = { DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_GETPARAM, i915_gem_context_getparam_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_SETPARAM, i915_gem_context_setparam_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_PERF_OPEN, i915_perf_open_ioctl, DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_PERF_ADD_CONFIG, i915_perf_add_config_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_PERF_REMOVE_CONFIG, i915_perf_remove_config_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(I915_QUERY, i915_query_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_VM_CREATE, i915_gem_vm_create_ioctl, DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(I915_GEM_VM_DESTROY, i915_gem_vm_destroy_ioctl, DRM_RENDER_ALLOW), }; @@ -3207,7 +3207,7 @@ static struct drm_driver driver = { * deal with them for Intel hardware. */ .driver_features = - DRIVER_GEM | DRIVER_PRIME | + DRIVER_GEM | DRIVER_RENDER | DRIVER_MODESET | DRIVER_ATOMIC | DRIVER_SYNCOBJ, .release = i915_driver_release, .open = i915_driver_open, diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 991eaeac9994..2e13ecc9cbb6 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -2495,8 +2495,7 @@ int i915_gem_object_set_cache_level(struct drm_i915_gem_object *obj, struct drm_gem_object *i915_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); -struct dma_buf *i915_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *gem_obj, int flags); +struct dma_buf *i915_gem_prime_export(struct drm_gem_object *gem_obj, int flags); static inline struct i915_gem_context * __i915_gem_context_lookup_rcu(struct drm_i915_file_private *file_priv, u32 id) diff --git a/drivers/gpu/drm/imx/dw_hdmi-imx.c b/drivers/gpu/drm/imx/dw_hdmi-imx.c index 06393cd1067d..5a3ad6fc8ea7 100644 --- a/drivers/gpu/drm/imx/dw_hdmi-imx.c +++ b/drivers/gpu/drm/imx/dw_hdmi-imx.c @@ -3,19 +3,21 @@ * * derived from imx-hdmi.c(renamed to bridge/dw_hdmi.c now) */ -#include <linux/module.h> -#include <linux/platform_device.h> + #include <linux/component.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> -#include <drm/bridge/dw_hdmi.h> -#include <video/imx-ipu-v3.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/regmap.h> -#include <drm/drm_of.h> -#include <drm/drmP.h> + +#include <video/imx-ipu-v3.h> + +#include <drm/bridge/dw_hdmi.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_edid.h> #include <drm/drm_encoder_slave.h> +#include <drm/drm_of.h> #include "imx-drm.h" diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index 3e8bece620df..da87c70e413b 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -4,14 +4,18 @@ * * Copyright (C) 2011 Sascha Hauer, Pengutronix */ + #include <linux/component.h> #include <linux/device.h> #include <linux/dma-buf.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <drm/drmP.h> + +#include <video/imx-ipu-v3.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -19,7 +23,7 @@ #include <drm/drm_of.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <video/imx-ipu-v3.h> +#include <drm/drm_vblank.h> #include "imx-drm.h" #include "ipuv3-plane.h" @@ -147,16 +151,13 @@ static const struct drm_ioctl_desc imx_drm_ioctls[] = { }; static struct drm_driver imx_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index 383733302280..db461b6a257f 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -5,25 +5,27 @@ * Copyright (C) 2012 Sascha Hauer, Pengutronix */ -#include <linux/module.h> #include <linux/clk.h> #include <linux/component.h> -#include <drm/drmP.h> -#include <drm/drm_atomic.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_of.h> -#include <drm/drm_panel.h> -#include <drm/drm_probe_helper.h> #include <linux/mfd/syscon.h> #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h> +#include <linux/module.h> #include <linux/of_device.h> #include <linux/of_graph.h> -#include <video/of_display_timing.h> -#include <video/of_videomode.h> #include <linux/regmap.h> #include <linux/videodev2.h> +#include <video/of_display_timing.h> +#include <video/of_videomode.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + #include "imx-drm.h" #define DRIVER_NAME "imx-ldb" @@ -460,9 +462,10 @@ static int imx_ldb_register(struct drm_device *drm, */ drm_connector_helper_add(&imx_ldb_ch->connector, &imx_ldb_connector_helper_funcs); - drm_connector_init(drm, &imx_ldb_ch->connector, - &imx_ldb_connector_funcs, - DRM_MODE_CONNECTOR_LVDS); + drm_connector_init_with_ddc(drm, &imx_ldb_ch->connector, + &imx_ldb_connector_funcs, + DRM_MODE_CONNECTOR_LVDS, + imx_ldb_ch->ddc); drm_connector_attach_encoder(&imx_ldb_ch->connector, encoder); } diff --git a/drivers/gpu/drm/imx/imx-tve.c b/drivers/gpu/drm/imx/imx-tve.c index e725af8a0025..5bbfaa2cd0f4 100644 --- a/drivers/gpu/drm/imx/imx-tve.c +++ b/drivers/gpu/drm/imx/imx-tve.c @@ -5,20 +5,22 @@ * Copyright (C) 2013 Philipp Zabel, Pengutronix */ -#include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/clk.h> #include <linux/component.h> -#include <linux/module.h> #include <linux/i2c.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/regulator/consumer.h> #include <linux/spinlock.h> #include <linux/videodev2.h> -#include <drm/drmP.h> + +#include <video/imx-ipu-v3.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_probe_helper.h> -#include <video/imx-ipu-v3.h> #include "imx-drm.h" @@ -482,8 +484,10 @@ static int imx_tve_register(struct drm_device *drm, struct imx_tve *tve) drm_connector_helper_add(&tve->connector, &imx_tve_connector_helper_funcs); - drm_connector_init(drm, &tve->connector, &imx_tve_connector_funcs, - DRM_MODE_CONNECTOR_VGA); + drm_connector_init_with_ddc(drm, &tve->connector, + &imx_tve_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + tve->ddc); drm_connector_attach_encoder(&tve->connector, &tve->encoder); diff --git a/drivers/gpu/drm/imx/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3-crtc.c index c436a28d50e4..63c0284f8b3c 100644 --- a/drivers/gpu/drm/imx/ipuv3-crtc.c +++ b/drivers/gpu/drm/imx/ipuv3-crtc.c @@ -4,21 +4,25 @@ * * Copyright (C) 2011 Sascha Hauer, Pengutronix */ + #include <linux/clk.h> #include <linux/component.h> #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/errno.h> #include <linux/export.h> #include <linux/module.h> #include <linux/platform_device.h> -#include <drm/drmP.h> + +#include <video/imx-ipu-v3.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> -#include <video/imx-ipu-v3.h> #include "imx-drm.h" #include "ipuv3-plane.h" diff --git a/drivers/gpu/drm/imx/ipuv3-plane.c b/drivers/gpu/drm/imx/ipuv3-plane.c index 2a1e071d39ee..28826c0aa24a 100644 --- a/drivers/gpu/drm/imx/ipuv3-plane.c +++ b/drivers/gpu/drm/imx/ipuv3-plane.c @@ -5,15 +5,16 @@ * Copyright (C) 2013 Philipp Zabel, Pengutronix */ -#include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> -#include "video/imx-ipu-v3.h" +#include <video/imx-ipu-v3.h> + #include "imx-drm.h" #include "ipuv3-plane.h" diff --git a/drivers/gpu/drm/imx/parallel-display.c b/drivers/gpu/drm/imx/parallel-display.c index 1a76de1e8e7b..2e51b2fade75 100644 --- a/drivers/gpu/drm/imx/parallel-display.c +++ b/drivers/gpu/drm/imx/parallel-display.c @@ -7,14 +7,16 @@ #include <linux/component.h> #include <linux/module.h> -#include <drm/drmP.h> +#include <linux/platform_device.h> +#include <linux/videodev2.h> + +#include <video/of_display_timing.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> -#include <linux/videodev2.h> -#include <video/of_display_timing.h> #include "imx-drm.h" diff --git a/drivers/gpu/drm/ingenic/ingenic-drm.c b/drivers/gpu/drm/ingenic/ingenic-drm.c index e9f9e9fb9b17..ce1fae3a78a9 100644 --- a/drivers/gpu/drm/ingenic/ingenic-drm.c +++ b/drivers/gpu/drm/ingenic/ingenic-drm.c @@ -166,6 +166,8 @@ struct ingenic_drm { struct ingenic_dma_hwdesc *dma_hwdesc; dma_addr_t dma_hwdesc_phys; + + bool panel_is_sharp; }; static const u32 ingenic_drm_primary_formats[] = { @@ -283,6 +285,13 @@ static void ingenic_drm_crtc_update_timings(struct ingenic_drm *priv, regmap_write(priv->map, JZ_REG_LCD_DAV, vds << JZ_LCD_DAV_VDS_OFFSET | vde << JZ_LCD_DAV_VDE_OFFSET); + + if (priv->panel_is_sharp) { + regmap_write(priv->map, JZ_REG_LCD_PS, hde << 16 | (hde + 1)); + regmap_write(priv->map, JZ_REG_LCD_CLS, hde << 16 | (hde + 1)); + regmap_write(priv->map, JZ_REG_LCD_SPL, hpe << 16 | (hpe + 1)); + regmap_write(priv->map, JZ_REG_LCD_REV, mode->htotal << 16); + } } static void ingenic_drm_crtc_update_ctrl(struct ingenic_drm *priv, @@ -378,11 +387,18 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, { struct ingenic_drm *priv = drm_encoder_get_priv(encoder); struct drm_display_mode *mode = &crtc_state->adjusted_mode; - struct drm_display_info *info = &conn_state->connector->display_info; - unsigned int cfg = JZ_LCD_CFG_PS_DISABLE - | JZ_LCD_CFG_CLS_DISABLE - | JZ_LCD_CFG_SPL_DISABLE - | JZ_LCD_CFG_REV_DISABLE; + struct drm_connector *conn = conn_state->connector; + struct drm_display_info *info = &conn->display_info; + unsigned int cfg; + + priv->panel_is_sharp = info->bus_flags & DRM_BUS_FLAG_SHARP_SIGNALS; + + if (priv->panel_is_sharp) { + cfg = JZ_LCD_CFG_MODE_SPECIAL_TFT_1 | JZ_LCD_CFG_REV_POLARITY; + } else { + cfg = JZ_LCD_CFG_PS_DISABLE | JZ_LCD_CFG_CLS_DISABLE + | JZ_LCD_CFG_SPL_DISABLE | JZ_LCD_CFG_REV_DISABLE; + } if (mode->flags & DRM_MODE_FLAG_NHSYNC) cfg |= JZ_LCD_CFG_HSYNC_ACTIVE_LOW; @@ -393,24 +409,29 @@ static void ingenic_drm_encoder_atomic_mode_set(struct drm_encoder *encoder, if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_NEGEDGE) cfg |= JZ_LCD_CFG_PCLK_FALLING_EDGE; - if (conn_state->connector->connector_type == DRM_MODE_CONNECTOR_TV) { - if (mode->flags & DRM_MODE_FLAG_INTERLACE) - cfg |= JZ_LCD_CFG_MODE_TV_OUT_I; - else - cfg |= JZ_LCD_CFG_MODE_TV_OUT_P; - } else { - switch (*info->bus_formats) { - case MEDIA_BUS_FMT_RGB565_1X16: - cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT; - break; - case MEDIA_BUS_FMT_RGB666_1X18: - cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT; - break; - case MEDIA_BUS_FMT_RGB888_1X24: - cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT; - break; - default: - break; + if (!priv->panel_is_sharp) { + if (conn->connector_type == DRM_MODE_CONNECTOR_TV) { + if (mode->flags & DRM_MODE_FLAG_INTERLACE) + cfg |= JZ_LCD_CFG_MODE_TV_OUT_I; + else + cfg |= JZ_LCD_CFG_MODE_TV_OUT_P; + } else { + switch (*info->bus_formats) { + case MEDIA_BUS_FMT_RGB565_1X16: + cfg |= JZ_LCD_CFG_MODE_GENERIC_16BIT; + break; + case MEDIA_BUS_FMT_RGB666_1X18: + cfg |= JZ_LCD_CFG_MODE_GENERIC_18BIT; + break; + case MEDIA_BUS_FMT_RGB888_1X24: + cfg |= JZ_LCD_CFG_MODE_GENERIC_24BIT; + break; + case MEDIA_BUS_FMT_RGB888_3X8: + cfg |= JZ_LCD_CFG_MODE_8BIT_SERIAL; + break; + default: + break; + } } } @@ -433,6 +454,7 @@ static int ingenic_drm_encoder_atomic_check(struct drm_encoder *encoder, case MEDIA_BUS_FMT_RGB565_1X16: case MEDIA_BUS_FMT_RGB666_1X18: case MEDIA_BUS_FMT_RGB888_1X24: + case MEDIA_BUS_FMT_RGB888_3X8: return 0; default: return -EINVAL; @@ -484,8 +506,7 @@ static void ingenic_drm_disable_vblank(struct drm_crtc *crtc) DEFINE_DRM_GEM_CMA_FOPS(ingenic_drm_fops); static struct drm_driver ingenic_drm_driver_data = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME - | DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .name = "ingenic-drm", .desc = "DRM module for Ingenic SoCs", .date = "20190422", @@ -581,7 +602,6 @@ static int ingenic_drm_probe(struct platform_device *pdev) struct drm_bridge *bridge; struct drm_panel *panel; struct drm_device *drm; - struct resource *mem; void __iomem *base; long parent_rate; int ret, irq; @@ -615,8 +635,7 @@ static int ingenic_drm_probe(struct platform_device *pdev) drm->mode_config.max_height = 600; drm->mode_config.funcs = &ingenic_drm_mode_config_funcs; - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - base = devm_ioremap_resource(dev, mem); + base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(base)) { dev_err(dev, "Failed to get memory resource"); return PTR_ERR(base); diff --git a/drivers/gpu/drm/lima/lima_device.c b/drivers/gpu/drm/lima/lima_device.c index 570d0e93f9a9..d86b8d81a483 100644 --- a/drivers/gpu/drm/lima/lima_device.c +++ b/drivers/gpu/drm/lima/lima_device.c @@ -80,26 +80,23 @@ const char *lima_ip_name(struct lima_ip *ip) static int lima_clk_init(struct lima_device *dev) { int err; - unsigned long bus_rate, gpu_rate; dev->clk_bus = devm_clk_get(dev->dev, "bus"); if (IS_ERR(dev->clk_bus)) { - dev_err(dev->dev, "get bus clk failed %ld\n", PTR_ERR(dev->clk_bus)); - return PTR_ERR(dev->clk_bus); + err = PTR_ERR(dev->clk_bus); + if (err != -EPROBE_DEFER) + dev_err(dev->dev, "get bus clk failed %d\n", err); + return err; } dev->clk_gpu = devm_clk_get(dev->dev, "core"); if (IS_ERR(dev->clk_gpu)) { - dev_err(dev->dev, "get core clk failed %ld\n", PTR_ERR(dev->clk_gpu)); - return PTR_ERR(dev->clk_gpu); + err = PTR_ERR(dev->clk_gpu); + if (err != -EPROBE_DEFER) + dev_err(dev->dev, "get core clk failed %d\n", err); + return err; } - bus_rate = clk_get_rate(dev->clk_bus); - dev_info(dev->dev, "bus rate = %lu\n", bus_rate); - - gpu_rate = clk_get_rate(dev->clk_gpu); - dev_info(dev->dev, "mod rate = %lu", gpu_rate); - err = clk_prepare_enable(dev->clk_bus); if (err) return err; @@ -111,11 +108,17 @@ static int lima_clk_init(struct lima_device *dev) dev->reset = devm_reset_control_get_optional(dev->dev, NULL); if (IS_ERR(dev->reset)) { err = PTR_ERR(dev->reset); + if (err != -EPROBE_DEFER) + dev_err(dev->dev, "get reset controller failed %d\n", + err); goto error_out1; } else if (dev->reset != NULL) { err = reset_control_deassert(dev->reset); - if (err) + if (err) { + dev_err(dev->dev, + "reset controller deassert failed %d\n", err); goto error_out1; + } } return 0; @@ -145,7 +148,8 @@ static int lima_regulator_init(struct lima_device *dev) dev->regulator = NULL; if (ret == -ENODEV) return 0; - dev_err(dev->dev, "failed to get regulator: %d\n", ret); + if (ret != -EPROBE_DEFER) + dev_err(dev->dev, "failed to get regulator: %d\n", ret); return ret; } @@ -291,16 +295,12 @@ int lima_device_init(struct lima_device *ldev) dma_set_coherent_mask(ldev->dev, DMA_BIT_MASK(32)); err = lima_clk_init(ldev); - if (err) { - dev_err(ldev->dev, "clk init fail %d\n", err); + if (err) return err; - } err = lima_regulator_init(ldev); - if (err) { - dev_err(ldev->dev, "regulator init fail %d\n", err); + if (err) goto err_out0; - } ldev->empty_vm = lima_vm_create(ldev); if (!ldev->empty_vm) { @@ -343,6 +343,9 @@ int lima_device_init(struct lima_device *ldev) if (err) goto err_out5; + dev_info(ldev->dev, "bus rate = %lu\n", clk_get_rate(ldev->clk_bus)); + dev_info(ldev->dev, "mod rate = %lu", clk_get_rate(ldev->clk_gpu)); + return 0; err_out5: diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c index b29c26cd13b2..75ec703d22e0 100644 --- a/drivers/gpu/drm/lima/lima_drv.c +++ b/drivers/gpu/drm/lima/lima_drv.c @@ -231,13 +231,13 @@ static void lima_drm_driver_postclose(struct drm_device *dev, struct drm_file *f } static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = { - DRM_IOCTL_DEF_DRV(LIMA_GET_PARAM, lima_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(LIMA_GEM_CREATE, lima_ioctl_gem_create, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(LIMA_GEM_INFO, lima_ioctl_gem_info, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(LIMA_GEM_SUBMIT, lima_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT, lima_ioctl_gem_wait, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(LIMA_CTX_CREATE, lima_ioctl_ctx_create, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(LIMA_CTX_FREE, lima_ioctl_ctx_free, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_GET_PARAM, lima_ioctl_get_param, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_GEM_CREATE, lima_ioctl_gem_create, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_GEM_INFO, lima_ioctl_gem_info, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_GEM_SUBMIT, lima_ioctl_gem_submit, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT, lima_ioctl_gem_wait, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_CTX_CREATE, lima_ioctl_ctx_create, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(LIMA_CTX_FREE, lima_ioctl_ctx_free, DRM_RENDER_ALLOW), }; static const struct file_operations lima_drm_driver_fops = { @@ -252,7 +252,7 @@ static const struct file_operations lima_drm_driver_fops = { }; static struct drm_driver lima_drm_driver = { - .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_PRIME | DRIVER_SYNCOBJ, + .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ, .open = lima_drm_driver_open, .postclose = lima_drm_driver_postclose, .ioctls = lima_drm_driver_ioctls, @@ -307,10 +307,8 @@ static int lima_pdev_probe(struct platform_device *pdev) ldev->ddev = ddev; err = lima_device_init(ldev); - if (err) { - dev_err(&pdev->dev, "Fatal error during GPU init\n"); + if (err) goto err_out1; - } /* * Register the DRM device with the core and the connectors with diff --git a/drivers/gpu/drm/lima/lima_gem.c b/drivers/gpu/drm/lima/lima_gem.c index 477c0f766663..fd1a024703d2 100644 --- a/drivers/gpu/drm/lima/lima_gem.c +++ b/drivers/gpu/drm/lima/lima_gem.c @@ -24,7 +24,7 @@ int lima_gem_create_handle(struct drm_device *dev, struct drm_file *file, struct lima_bo *bo; struct lima_device *ldev = to_lima_dev(dev); - bo = lima_bo_create(ldev, size, flags, NULL, NULL); + bo = lima_bo_create(ldev, size, flags, NULL); if (IS_ERR(bo)) return PTR_ERR(bo); diff --git a/drivers/gpu/drm/lima/lima_gem_prime.c b/drivers/gpu/drm/lima/lima_gem_prime.c index 9c6d9f1dba55..e3eb251e0a12 100644 --- a/drivers/gpu/drm/lima/lima_gem_prime.c +++ b/drivers/gpu/drm/lima/lima_gem_prime.c @@ -18,8 +18,7 @@ struct drm_gem_object *lima_gem_prime_import_sg_table( struct lima_device *ldev = to_lima_dev(dev); struct lima_bo *bo; - bo = lima_bo_create(ldev, attach->dmabuf->size, 0, sgt, - attach->dmabuf->resv); + bo = lima_bo_create(ldev, attach->dmabuf->size, 0, sgt); if (IS_ERR(bo)) return ERR_CAST(bo); diff --git a/drivers/gpu/drm/lima/lima_object.c b/drivers/gpu/drm/lima/lima_object.c index 5c41f859a72f..87123b1d083c 100644 --- a/drivers/gpu/drm/lima/lima_object.c +++ b/drivers/gpu/drm/lima/lima_object.c @@ -33,8 +33,7 @@ void lima_bo_destroy(struct lima_bo *bo) kfree(bo); } -static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size, u32 flags, - struct reservation_object *resv) +static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size, u32 flags) { struct lima_bo *bo; int err; @@ -47,7 +46,6 @@ static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size, mutex_init(&bo->lock); INIT_LIST_HEAD(&bo->va); - bo->gem.resv = resv; err = drm_gem_object_init(dev->ddev, &bo->gem, size); if (err) { @@ -59,14 +57,13 @@ static struct lima_bo *lima_bo_create_struct(struct lima_device *dev, u32 size, } struct lima_bo *lima_bo_create(struct lima_device *dev, u32 size, - u32 flags, struct sg_table *sgt, - struct reservation_object *resv) + u32 flags, struct sg_table *sgt) { int i, err; size_t npages; struct lima_bo *bo, *ret; - bo = lima_bo_create_struct(dev, size, flags, resv); + bo = lima_bo_create_struct(dev, size, flags); if (IS_ERR(bo)) return bo; diff --git a/drivers/gpu/drm/lima/lima_object.h b/drivers/gpu/drm/lima/lima_object.h index 6738724afb7b..31ca2d8dc0a1 100644 --- a/drivers/gpu/drm/lima/lima_object.h +++ b/drivers/gpu/drm/lima/lima_object.h @@ -27,8 +27,7 @@ to_lima_bo(struct drm_gem_object *obj) } struct lima_bo *lima_bo_create(struct lima_device *dev, u32 size, - u32 flags, struct sg_table *sgt, - struct reservation_object *resv); + u32 flags, struct sg_table *sgt); void lima_bo_destroy(struct lima_bo *bo); void *lima_bo_vmap(struct lima_bo *bo); void lima_bo_vunmap(struct lima_bo *bo); diff --git a/drivers/gpu/drm/lima/lima_vm.h b/drivers/gpu/drm/lima/lima_vm.h index caee2f8a29b4..e0bdedcf14dd 100644 --- a/drivers/gpu/drm/lima/lima_vm.h +++ b/drivers/gpu/drm/lima/lima_vm.h @@ -15,9 +15,9 @@ #define LIMA_VM_NUM_PT_PER_BT (1 << LIMA_VM_NUM_PT_PER_BT_SHIFT) #define LIMA_VM_NUM_BT (LIMA_PAGE_ENT_NUM >> LIMA_VM_NUM_PT_PER_BT_SHIFT) -#define LIMA_VA_RESERVE_START 0xFFF00000 +#define LIMA_VA_RESERVE_START 0x0FFF00000ULL #define LIMA_VA_RESERVE_DLBU LIMA_VA_RESERVE_START -#define LIMA_VA_RESERVE_END 0x100000000 +#define LIMA_VA_RESERVE_END 0x100000000ULL struct lima_device; diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c index baf63fb6850a..982fe8485a61 100644 --- a/drivers/gpu/drm/mcde/mcde_drv.c +++ b/drivers/gpu/drm/mcde/mcde_drv.c @@ -237,7 +237,7 @@ DEFINE_DRM_GEM_CMA_FOPS(drm_fops); static struct drm_driver mcde_drm_driver = { .driver_features = - DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, + DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .release = mcde_release, .lastclose = drm_fb_helper_lastclose, .ioctls = NULL, @@ -254,8 +254,6 @@ static struct drm_driver mcde_drm_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, @@ -319,7 +317,7 @@ static int mcde_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct drm_device *drm; struct mcde *mcde; - struct component_match *match; + struct component_match *match = NULL; struct resource *res; u32 pid; u32 val; @@ -485,6 +483,10 @@ static int mcde_probe(struct platform_device *pdev) } put_device(p); } + if (!match) { + dev_err(dev, "no matching components\n"); + return -ENODEV; + } if (IS_ERR(match)) { dev_err(dev, "could not create component match\n"); ret = PTR_ERR(match); diff --git a/drivers/gpu/drm/mediatek/mtk_disp_color.c b/drivers/gpu/drm/mediatek/mtk_disp_color.c index f33d98b356d6..59de2a46aa49 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_color.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_color.c @@ -3,9 +3,9 @@ * Copyright (c) 2017 MediaTek Inc. */ -#include <drm/drmP.h> #include <linux/clk.h> #include <linux/component.h> +#include <linux/module.h> #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c index c4f07c28c74f..21851756c579 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c @@ -3,9 +3,9 @@ * Copyright (c) 2015 MediaTek Inc. */ -#include <drm/drmP.h> #include <linux/clk.h> #include <linux/component.h> +#include <linux/module.h> #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c index 9a6f0a29e43c..405afef31407 100644 --- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c +++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c @@ -3,9 +3,9 @@ * Copyright (c) 2015 MediaTek Inc. */ -#include <drm/drmP.h> #include <linux/clk.h> #include <linux/component.h> +#include <linux/module.h> #include <linux/of_device.h> #include <linux/of_irq.h> #include <linux/platform_device.h> diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c index bacd989cc9aa..be6d95c5ff25 100644 --- a/drivers/gpu/drm/mediatek/mtk_dpi.c +++ b/drivers/gpu/drm/mediatek/mtk_dpi.c @@ -3,21 +3,23 @@ * Copyright (c) 2014 MediaTek Inc. * Author: Jie Qiu <jie.qiu@mediatek.com> */ -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_of.h> -#include <linux/kernel.h> + +#include <linux/clk.h> #include <linux/component.h> -#include <linux/platform_device.h> +#include <linux/interrupt.h> +#include <linux/kernel.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_graph.h> -#include <linux/interrupt.h> +#include <linux/platform_device.h> #include <linux/types.h> -#include <linux/clk.h> + #include <video/videomode.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_of.h> + #include "mtk_dpi_regs.h" #include "mtk_drm_ddp_comp.h" diff --git a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c index a9007210dda1..34a731755791 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_crtc.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_crtc.c @@ -3,14 +3,16 @@ * Copyright (c) 2015 MediaTek Inc. */ +#include <linux/clk.h> +#include <linux/pm_runtime.h> + #include <asm/barrier.h> -#include <drm/drmP.h> +#include <soc/mediatek/smi.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <linux/clk.h> -#include <linux/pm_runtime.h> -#include <soc/mediatek/smi.h> +#include <drm/drm_vblank.h> #include "mtk_drm_drv.h" #include "mtk_drm_crtc.h" diff --git a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c index b38963f1f2ec..efa85973e46b 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_ddp_comp.c @@ -12,7 +12,7 @@ #include <linux/of_irq.h> #include <linux/of_platform.h> #include <linux/platform_device.h> -#include <drm/drmP.h> + #include "mtk_drm_drv.h" #include "mtk_drm_plane.h" #include "mtk_drm_ddp_comp.h" diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c index 95fdbd0fbcac..2ee809a6f3dc 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c @@ -4,22 +4,26 @@ * Author: YT SHEN <yt.shen@mediatek.com> */ -#include <drm/drmP.h> +#include <linux/component.h> +#include <linux/iommu.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_platform.h> +#include <linux/pm_runtime.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> -#include <linux/component.h> -#include <linux/iommu.h> -#include <linux/of_address.h> -#include <linux/of_platform.h> -#include <linux/pm_runtime.h> +#include <drm/drm_vblank.h> #include "mtk_drm_crtc.h" #include "mtk_drm_ddp.h" +#include "mtk_drm_ddp.h" #include "mtk_drm_ddp_comp.h" #include "mtk_drm_drv.h" #include "mtk_drm_fb.h" @@ -38,22 +42,12 @@ static void mtk_atomic_schedule(struct mtk_drm_private *private, schedule_work(&private->commit.work); } -static void mtk_atomic_wait_for_fences(struct drm_atomic_state *state) -{ - struct drm_plane *plane; - struct drm_plane_state *new_plane_state; - int i; - - for_each_new_plane_in_state(state, plane, new_plane_state, i) - mtk_fb_wait(new_plane_state->fb); -} - static void mtk_atomic_complete(struct mtk_drm_private *private, struct drm_atomic_state *state) { struct drm_device *drm = private->drm; - mtk_atomic_wait_for_fences(state); + drm_atomic_helper_wait_for_fences(drm, state, false); /* * Mediatek drm supports runtime PM, so plane registers cannot be @@ -321,8 +315,7 @@ static const struct file_operations mtk_drm_fops = { }; static struct drm_driver mtk_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .gem_free_object_unlocked = mtk_drm_gem_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, @@ -330,8 +323,6 @@ static struct drm_driver mtk_drm_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = mtk_gem_prime_get_sg_table, .gem_prime_import_sg_table = mtk_gem_prime_import_sg_table, .gem_prime_mmap = mtk_drm_gem_mmap_buf, diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.c b/drivers/gpu/drm/mediatek/mtk_drm_fb.c index 4c3ad7de2d3b..ae40b080ae47 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.c @@ -3,13 +3,14 @@ * Copyright (c) 2015 MediaTek Inc. */ -#include <drm/drmP.h> +#include <linux/dma-buf.h> +#include <linux/reservation.h> + #include <drm/drm_modeset_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <linux/dma-buf.h> -#include <linux/reservation.h> #include "mtk_drm_drv.h" #include "mtk_drm_fb.h" @@ -49,34 +50,6 @@ static struct drm_framebuffer *mtk_drm_framebuffer_init(struct drm_device *dev, return fb; } -/* - * Wait for any exclusive fence in fb's gem object's reservation object. - * - * Returns -ERESTARTSYS if interrupted, else 0. - */ -int mtk_fb_wait(struct drm_framebuffer *fb) -{ - struct drm_gem_object *gem; - struct reservation_object *resv; - long ret; - - if (!fb) - return 0; - - gem = fb->obj[0]; - if (!gem || !gem->dma_buf || !gem->dma_buf->resv) - return 0; - - resv = gem->dma_buf->resv; - ret = reservation_object_wait_timeout_rcu(resv, false, true, - MAX_SCHEDULE_TIMEOUT); - /* MAX_SCHEDULE_TIMEOUT on success, -ERESTARTSYS if interrupted */ - if (WARN_ON(ret < 0)) - return ret; - - return 0; -} - struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *cmd) diff --git a/drivers/gpu/drm/mediatek/mtk_drm_fb.h b/drivers/gpu/drm/mediatek/mtk_drm_fb.h index 6b80c28e33cf..eb64d26001c6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_fb.h +++ b/drivers/gpu/drm/mediatek/mtk_drm_fb.h @@ -6,7 +6,6 @@ #ifndef MTK_DRM_FB_H #define MTK_DRM_FB_H -int mtk_fb_wait(struct drm_framebuffer *fb); struct drm_framebuffer *mtk_drm_mode_fb_create(struct drm_device *dev, struct drm_file *file, const struct drm_mode_fb_cmd2 *cmd); diff --git a/drivers/gpu/drm/mediatek/mtk_drm_gem.c b/drivers/gpu/drm/mediatek/mtk_drm_gem.c index 0d69698f8173..ca672f1d140d 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_gem.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_gem.c @@ -3,10 +3,13 @@ * Copyright (c) 2015 MediaTek Inc. */ -#include <drm/drmP.h> -#include <drm/drm_gem.h> #include <linux/dma-buf.h> +#include <drm/drm.h> +#include <drm/drm_device.h> +#include <drm/drm_gem.h> +#include <drm/drm_prime.h> + #include "mtk_drm_drv.h" #include "mtk_drm_gem.h" diff --git a/drivers/gpu/drm/mediatek/mtk_drm_plane.c b/drivers/gpu/drm/mediatek/mtk_drm_plane.c index f2ef83aed6f9..584a9ecadce6 100644 --- a/drivers/gpu/drm/mediatek/mtk_drm_plane.c +++ b/drivers/gpu/drm/mediatek/mtk_drm_plane.c @@ -4,10 +4,11 @@ * Author: CK Hu <ck.hu@mediatek.com> */ -#include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include "mtk_drm_crtc.h" #include "mtk_drm_ddp_comp.h" @@ -146,6 +147,7 @@ static void mtk_plane_atomic_disable(struct drm_plane *plane, } static const struct drm_plane_helper_funcs mtk_plane_helper_funcs = { + .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = mtk_plane_atomic_check, .atomic_update = mtk_plane_atomic_update, .atomic_disable = mtk_plane_atomic_disable, diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c index b91c4616644a..224afb666881 100644 --- a/drivers/gpu/drm/mediatek/mtk_dsi.c +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c @@ -3,12 +3,6 @@ * Copyright (c) 2015 MediaTek Inc. */ -#include <drm/drmP.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_mipi_dsi.h> -#include <drm/drm_panel.h> -#include <drm/drm_of.h> -#include <drm/drm_probe_helper.h> #include <linux/clk.h> #include <linux/component.h> #include <linux/iopoll.h> @@ -17,9 +11,17 @@ #include <linux/of_platform.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> + #include <video/mipi_display.h> #include <video/videomode.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + #include "mtk_drm_ddp_comp.h" #define DSI_START 0x00 diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c index 5d6a9f094df5..ce91b61364eb 100644 --- a/drivers/gpu/drm/mediatek/mtk_hdmi.c +++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c @@ -3,11 +3,7 @@ * Copyright (c) 2014 MediaTek Inc. * Author: Jie Qiu <jie.qiu@mediatek.com> */ -#include <drm/drmP.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_crtc.h> -#include <drm/drm_probe_helper.h> -#include <drm/drm_edid.h> + #include <linux/arm-smccc.h> #include <linux/clk.h> #include <linux/delay.h> @@ -23,7 +19,15 @@ #include <linux/phy/phy.h> #include <linux/platform_device.h> #include <linux/regmap.h> + #include <sound/hdmi-codec.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_edid.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + #include "mtk_cec.h" #include "mtk_hdmi.h" #include "mtk_hdmi_regs.h" diff --git a/drivers/gpu/drm/meson/meson_crtc.c b/drivers/gpu/drm/meson/meson_crtc.c index aa8ea107524e..3320a74e67fa 100644 --- a/drivers/gpu/drm/meson/meson_crtc.c +++ b/drivers/gpu/drm/meson/meson_crtc.c @@ -9,23 +9,21 @@ * Jasper St. Pierre <jstpierre@mecheye.net> */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/platform_device.h> #include <linux/bitfield.h> -#include <drm/drmP.h> -#include <drm/drm_atomic.h> +#include <linux/soc/amlogic/meson-canvas.h> + #include <drm/drm_atomic_helper.h> -#include <drm/drm_flip_work.h> +#include <drm/drm_device.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "meson_crtc.h" #include "meson_plane.h" +#include "meson_registers.h" #include "meson_venc.h" -#include "meson_vpp.h" #include "meson_viu.h" -#include "meson_registers.h" +#include "meson_vpp.h" #define MESON_G12A_VIU_OFFSET 0x5ec0 diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c index 2310c96fff46..42af49afdd75 100644 --- a/drivers/gpu/drm/meson/meson_drv.c +++ b/drivers/gpu/drm/meson/meson_drv.c @@ -8,35 +8,30 @@ * Jasper St. Pierre <jstpierre@mecheye.net> */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> -#include <linux/platform_device.h> #include <linux/component.h> +#include <linux/module.h> #include <linux/of_graph.h> +#include <linux/platform_device.h> +#include <linux/soc/amlogic/meson-canvas.h> -#include <drm/drmP.h> -#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_flip_work.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_plane_helper.h> +#include <drm/drm_irq.h> +#include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_rect.h> +#include <drm/drm_vblank.h> +#include "meson_crtc.h" #include "meson_drv.h" -#include "meson_plane.h" #include "meson_overlay.h" -#include "meson_crtc.h" +#include "meson_plane.h" +#include "meson_registers.h" #include "meson_venc_cvbs.h" - -#include "meson_vpp.h" #include "meson_viu.h" -#include "meson_venc.h" -#include "meson_registers.h" +#include "meson_vpp.h" #define DRIVER_NAME "meson" #define DRIVER_DESC "Amlogic Meson DRM driver" @@ -93,9 +88,7 @@ static int meson_dumb_create(struct drm_file *file, struct drm_device *dev, DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver meson_driver = { - .driver_features = DRIVER_GEM | - DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, /* IRQ */ .irq_handler = meson_irq, @@ -103,8 +96,6 @@ static struct drm_driver meson_driver = { /* PRIME Ops */ .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/meson/meson_drv.h b/drivers/gpu/drm/meson/meson_drv.h index 7b6593f33dfe..c9aaec1a846e 100644 --- a/drivers/gpu/drm/meson/meson_drv.h +++ b/drivers/gpu/drm/meson/meson_drv.h @@ -7,11 +7,14 @@ #ifndef __MESON_DRV_H #define __MESON_DRV_H -#include <linux/platform_device.h> -#include <linux/regmap.h> +#include <linux/device.h> #include <linux/of.h> -#include <linux/soc/amlogic/meson-canvas.h> -#include <drm/drmP.h> +#include <linux/regmap.h> + +struct drm_crtc; +struct drm_device; +struct drm_plane; +struct meson_drm; struct meson_drm { struct device *dev; diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c index df3f9ddd2234..9f0b08eaf003 100644 --- a/drivers/gpu/drm/meson/meson_dw_hdmi.c +++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c @@ -5,29 +5,30 @@ * Copyright (C) 2015 Amlogic, Inc. All rights reserved. */ +#include <linux/clk.h> +#include <linux/component.h> #include <linux/kernel.h> #include <linux/module.h> -#include <linux/component.h> #include <linux/of_device.h> #include <linux/of_graph.h> -#include <linux/reset.h> -#include <linux/clk.h> #include <linux/regulator/consumer.h> +#include <linux/reset.h> -#include <drm/drmP.h> +#include <drm/bridge/dw_hdmi.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_device.h> #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> -#include <drm/bridge/dw_hdmi.h> +#include <drm/drm_print.h> -#include <uapi/linux/media-bus-format.h> -#include <uapi/linux/videodev2.h> +#include <linux/media-bus-format.h> +#include <linux/videodev2.h> #include "meson_drv.h" -#include "meson_venc.h" -#include "meson_vclk.h" #include "meson_dw_hdmi.h" #include "meson_registers.h" +#include "meson_vclk.h" +#include "meson_venc.h" #define DRIVER_NAME "meson-dw-hdmi" #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver" diff --git a/drivers/gpu/drm/meson/meson_overlay.c b/drivers/gpu/drm/meson/meson_overlay.c index cc7c6ae3013d..5aa9dcb4b35e 100644 --- a/drivers/gpu/drm/meson/meson_overlay.c +++ b/drivers/gpu/drm/meson/meson_overlay.c @@ -5,24 +5,21 @@ * Copyright (C) 2015 Amlogic, Inc. All rights reserved. */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> #include <linux/bitfield.h> -#include <linux/platform_device.h> -#include <drm/drmP.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_device.h> +#include <drm/drm_fourcc.h> #include <drm/drm_plane_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_rect.h> #include "meson_overlay.h" -#include "meson_vpp.h" -#include "meson_viu.h" #include "meson_registers.h" +#include "meson_viu.h" +#include "meson_vpp.h" /* VD1_IF0_GEN_REG */ #define VD_URGENT_CHROMA BIT(28) diff --git a/drivers/gpu/drm/meson/meson_plane.c b/drivers/gpu/drm/meson/meson_plane.c index 7a7e88dadd0b..80b8d70c4d75 100644 --- a/drivers/gpu/drm/meson/meson_plane.c +++ b/drivers/gpu/drm/meson/meson_plane.c @@ -9,24 +9,20 @@ * Jasper St. Pierre <jstpierre@mecheye.net> */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/mutex.h> #include <linux/bitfield.h> -#include <linux/platform_device.h> -#include <drm/drmP.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_device.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_rect.h> +#include <drm/drm_plane_helper.h> #include "meson_plane.h" -#include "meson_vpp.h" -#include "meson_viu.h" #include "meson_registers.h" +#include "meson_viu.h" /* OSD_SCI_WH_M1 */ #define SCI_WH_M1_W(w) FIELD_PREP(GENMASK(28, 16), w) diff --git a/drivers/gpu/drm/meson/meson_registers.h b/drivers/gpu/drm/meson/meson_registers.h index 410e324d6f93..057453ce027c 100644 --- a/drivers/gpu/drm/meson/meson_registers.h +++ b/drivers/gpu/drm/meson/meson_registers.h @@ -6,6 +6,8 @@ #ifndef __MESON_REGISTERS_H #define __MESON_REGISTERS_H +#include <linux/io.h> + /* Shift all registers by 2 */ #define _REG(reg) ((reg) << 2) diff --git a/drivers/gpu/drm/meson/meson_vclk.c b/drivers/gpu/drm/meson/meson_vclk.c index 26732f038d19..8abff51f937d 100644 --- a/drivers/gpu/drm/meson/meson_vclk.c +++ b/drivers/gpu/drm/meson/meson_vclk.c @@ -5,9 +5,10 @@ * Copyright (C) 2015 Amlogic, Inc. All rights reserved. */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <drm/drmP.h> +#include <linux/export.h> + +#include <drm/drm_print.h> + #include "meson_drv.h" #include "meson_vclk.h" diff --git a/drivers/gpu/drm/meson/meson_vclk.h b/drivers/gpu/drm/meson/meson_vclk.h index ed993d20abda..b62125540aef 100644 --- a/drivers/gpu/drm/meson/meson_vclk.h +++ b/drivers/gpu/drm/meson/meson_vclk.h @@ -9,6 +9,10 @@ #ifndef __MESON_VCLK_H #define __MESON_VCLK_H +#include <drm/drm_modes.h> + +struct meson_drm; + enum { MESON_VCLK_TARGET_CVBS = 0, MESON_VCLK_TARGET_HDMI = 1, diff --git a/drivers/gpu/drm/meson/meson_venc.c b/drivers/gpu/drm/meson/meson_venc.c index 7b7a0d8d737c..3d4791798ae0 100644 --- a/drivers/gpu/drm/meson/meson_venc.c +++ b/drivers/gpu/drm/meson/meson_venc.c @@ -5,14 +5,14 @@ * Copyright (C) 2015 Amlogic, Inc. All rights reserved. */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <drm/drmP.h> +#include <linux/export.h> + +#include <drm/drm_modes.h> + #include "meson_drv.h" +#include "meson_registers.h" #include "meson_venc.h" #include "meson_vpp.h" -#include "meson_vclk.h" -#include "meson_registers.h" /** * DOC: Video Encoder diff --git a/drivers/gpu/drm/meson/meson_venc.h b/drivers/gpu/drm/meson/meson_venc.h index 985642a1678e..576768bdd08d 100644 --- a/drivers/gpu/drm/meson/meson_venc.h +++ b/drivers/gpu/drm/meson/meson_venc.h @@ -14,6 +14,8 @@ #ifndef __MESON_VENC_H #define __MESON_VENC_H +struct drm_display_mode; + enum { MESON_VENC_MODE_NONE = 0, MESON_VENC_MODE_CVBS_PAL, diff --git a/drivers/gpu/drm/meson/meson_venc_cvbs.c b/drivers/gpu/drm/meson/meson_venc_cvbs.c index 6313a519f257..45a467f10b9b 100644 --- a/drivers/gpu/drm/meson/meson_venc_cvbs.c +++ b/drivers/gpu/drm/meson/meson_venc_cvbs.c @@ -9,19 +9,18 @@ * Jasper St. Pierre <jstpierre@mecheye.net> */ -#include <linux/kernel.h> -#include <linux/module.h> +#include <linux/export.h> #include <linux/of_graph.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_device.h> #include <drm/drm_edid.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_print.h> -#include "meson_venc_cvbs.h" -#include "meson_venc.h" -#include "meson_vclk.h" #include "meson_registers.h" +#include "meson_vclk.h" +#include "meson_venc_cvbs.h" /* HHI VDAC Registers */ #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */ diff --git a/drivers/gpu/drm/meson/meson_viu.c b/drivers/gpu/drm/meson/meson_viu.c index 4b2b3024d371..9f8a450d50d5 100644 --- a/drivers/gpu/drm/meson/meson_viu.c +++ b/drivers/gpu/drm/meson/meson_viu.c @@ -6,13 +6,10 @@ * Copyright (C) 2014 Endless Mobile */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <drm/drmP.h> +#include <linux/export.h> + #include "meson_drv.h" #include "meson_viu.h" -#include "meson_vpp.h" -#include "meson_venc.h" #include "meson_registers.h" /** diff --git a/drivers/gpu/drm/meson/meson_vpp.c b/drivers/gpu/drm/meson/meson_vpp.c index bfee30fa6e34..cbe6cf46e541 100644 --- a/drivers/gpu/drm/meson/meson_vpp.c +++ b/drivers/gpu/drm/meson/meson_vpp.c @@ -6,12 +6,11 @@ * Copyright (C) 2014 Endless Mobile */ -#include <linux/kernel.h> -#include <linux/module.h> -#include <drm/drmP.h> +#include <linux/export.h> + #include "meson_drv.h" -#include "meson_vpp.h" #include "meson_registers.h" +#include "meson_vpp.h" /** * DOC: Video Post Processing diff --git a/drivers/gpu/drm/meson/meson_vpp.h b/drivers/gpu/drm/meson/meson_vpp.h index 9fc82db8a12d..afc9553ed8d3 100644 --- a/drivers/gpu/drm/meson/meson_vpp.h +++ b/drivers/gpu/drm/meson/meson_vpp.h @@ -9,6 +9,9 @@ #ifndef __MESON_VPP_H #define __MESON_VPP_H +struct drm_rect; +struct meson_drm; + /* Mux VIU/VPP to ENCI */ #define MESON_VIU_VPP_MUX_ENCI 0x5 /* Mux VIU/VPP to ENCP */ diff --git a/drivers/gpu/drm/mga/mga_dma.c b/drivers/gpu/drm/mga/mga_dma.c index 1ffdafea27e4..85c74364ce24 100644 --- a/drivers/gpu/drm/mga/mga_dma.c +++ b/drivers/gpu/drm/mga/mga_dma.c @@ -35,8 +35,8 @@ * \author Gareth Hughes <gareth@valinux.com> */ -#include <drm/drmP.h> -#include <drm/mga_drm.h> +#include <linux/delay.h> + #include "mga_drv.h" #define MGA_DEFAULT_USEC_TIMEOUT 10000 @@ -62,7 +62,7 @@ int mga_do_wait_for_idle(drm_mga_private_t *dev_priv) MGA_WRITE8(MGA_CRTC_INDEX, 0); return 0; } - DRM_UDELAY(1); + udelay(1); } #if MGA_DMA_DEBUG @@ -114,7 +114,7 @@ void mga_do_dma_flush(drm_mga_private_t *dev_priv) status = MGA_READ(MGA_STATUS) & MGA_ENGINE_IDLE_MASK; if (status == MGA_ENDPRDMASTS) break; - DRM_UDELAY(1); + udelay(1); } if (primary->tail == primary->last_flush) { @@ -1120,7 +1120,7 @@ int mga_dma_buffers(struct drm_device *dev, void *data, */ if (d->send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - DRM_CURRENTPID, d->send_count); + task_pid_nr(current), d->send_count); return -EINVAL; } @@ -1128,7 +1128,8 @@ int mga_dma_buffers(struct drm_device *dev, void *data, */ if (d->request_count < 0 || d->request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - DRM_CURRENTPID, d->request_count, dma->buf_count); + task_pid_nr(current), d->request_count, + dma->buf_count); return -EINVAL; } diff --git a/drivers/gpu/drm/mga/mga_drv.c b/drivers/gpu/drm/mga/mga_drv.c index 6e1d1054ad06..71128e6f6ae9 100644 --- a/drivers/gpu/drm/mga/mga_drv.c +++ b/drivers/gpu/drm/mga/mga_drv.c @@ -31,12 +31,11 @@ #include <linux/module.h> -#include <drm/drmP.h> -#include <drm/mga_drm.h> -#include "mga_drv.h" - +#include <drm/drm_drv.h> #include <drm/drm_pciids.h> +#include "mga_drv.h" + static struct pci_device_id pciidlist[] = { mga_PCI_IDS }; diff --git a/drivers/gpu/drm/mga/mga_drv.h b/drivers/gpu/drm/mga/mga_drv.h index a45bb22275a7..d5deecb93975 100644 --- a/drivers/gpu/drm/mga/mga_drv.h +++ b/drivers/gpu/drm/mga/mga_drv.h @@ -31,7 +31,20 @@ #ifndef __MGA_DRV_H__ #define __MGA_DRV_H__ +#include <linux/irqreturn.h> +#include <linux/slab.h> + +#include <drm/drm_agpsupport.h> +#include <drm/drm_device.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_irq.h> #include <drm/drm_legacy.h> +#include <drm/drm_pci.h> +#include <drm/drm_print.h> +#include <drm/drm_sarea.h> +#include <drm/drm_vblank.h> +#include <drm/mga_drm.h> /* General customization: */ @@ -188,7 +201,7 @@ extern int mga_warp_init(drm_mga_private_t *dev_priv); extern int mga_enable_vblank(struct drm_device *dev, unsigned int pipe); extern void mga_disable_vblank(struct drm_device *dev, unsigned int pipe); extern u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe); -extern int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence); +extern void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence); extern int mga_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence); extern irqreturn_t mga_driver_irq_handler(int irq, void *arg); extern void mga_driver_irq_preinstall(struct drm_device *dev); @@ -199,10 +212,14 @@ extern long mga_compat_ioctl(struct file *filp, unsigned int cmd, #define mga_flush_write_combine() wmb() -#define MGA_READ8(reg) DRM_READ8(dev_priv->mmio, (reg)) -#define MGA_READ(reg) DRM_READ32(dev_priv->mmio, (reg)) -#define MGA_WRITE8(reg, val) DRM_WRITE8(dev_priv->mmio, (reg), (val)) -#define MGA_WRITE(reg, val) DRM_WRITE32(dev_priv->mmio, (reg), (val)) +#define MGA_READ8(reg) \ + readb(((void __iomem *)dev_priv->mmio->handle) + (reg)) +#define MGA_READ(reg) \ + readl(((void __iomem *)dev_priv->mmio->handle) + (reg)) +#define MGA_WRITE8(reg, val) \ + writeb(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) +#define MGA_WRITE(reg, val) \ + writel(val, ((void __iomem *)dev_priv->mmio->handle) + (reg)) #define DWGREG0 0x1c00 #define DWGREG0_END 0x1dff diff --git a/drivers/gpu/drm/mga/mga_ioc32.c b/drivers/gpu/drm/mga/mga_ioc32.c index 245fb2e359cf..6ccd270789c6 100644 --- a/drivers/gpu/drm/mga/mga_ioc32.c +++ b/drivers/gpu/drm/mga/mga_ioc32.c @@ -30,10 +30,9 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ + #include <linux/compat.h> -#include <drm/drmP.h> -#include <drm/mga_drm.h> #include "mga_drv.h" typedef struct drm32_mga_init { diff --git a/drivers/gpu/drm/mga/mga_irq.c b/drivers/gpu/drm/mga/mga_irq.c index 693ba708cfed..a7e6ffc80a78 100644 --- a/drivers/gpu/drm/mga/mga_irq.c +++ b/drivers/gpu/drm/mga/mga_irq.c @@ -31,8 +31,6 @@ * Eric Anholt <anholt@FreeBSD.org> */ -#include <drm/drmP.h> -#include <drm/mga_drm.h> #include "mga_drv.h" u32 mga_get_vblank_counter(struct drm_device *dev, unsigned int pipe) @@ -118,23 +116,21 @@ void mga_disable_vblank(struct drm_device *dev, unsigned int pipe) /* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */ } -int mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence) +void mga_driver_fence_wait(struct drm_device *dev, unsigned int *sequence) { drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; unsigned int cur_fence; - int ret = 0; /* Assume that the user has missed the current sequence number * by about a day rather than she wants to wait for years * using fences. */ - DRM_WAIT_ON(ret, dev_priv->fence_queue, 3 * HZ, + wait_event_timeout(dev_priv->fence_queue, (((cur_fence = atomic_read(&dev_priv->last_fence_retired)) - - *sequence) <= (1 << 23))); + - *sequence) <= (1 << 23)), + msecs_to_jiffies(3000)); *sequence = cur_fence; - - return ret; } void mga_driver_irq_preinstall(struct drm_device *dev) diff --git a/drivers/gpu/drm/mga/mga_state.c b/drivers/gpu/drm/mga/mga_state.c index e5f6b735f575..77a0b006f066 100644 --- a/drivers/gpu/drm/mga/mga_state.c +++ b/drivers/gpu/drm/mga/mga_state.c @@ -32,8 +32,6 @@ * Gareth Hughes <gareth@valinux.com> */ -#include <drm/drmP.h> -#include <drm/mga_drm.h> #include "mga_drv.h" /* ================================================================ @@ -1016,7 +1014,7 @@ int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) return -EINVAL; } - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); + DRM_DEBUG("pid=%d\n", task_pid_nr(current)); switch (param->param) { case MGA_PARAM_IRQ_NR: @@ -1048,7 +1046,7 @@ static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *fi return -EINVAL; } - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); + DRM_DEBUG("pid=%d\n", task_pid_nr(current)); /* I would normal do this assignment in the declaration of fence, * but dev_priv may be NULL. @@ -1077,7 +1075,7 @@ file_priv) return -EINVAL; } - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); + DRM_DEBUG("pid=%d\n", task_pid_nr(current)); mga_driver_fence_wait(dev, fence); return 0; diff --git a/drivers/gpu/drm/mga/mga_warp.c b/drivers/gpu/drm/mga/mga_warp.c index 0b76352260a9..b5ef1d2c8b1c 100644 --- a/drivers/gpu/drm/mga/mga_warp.c +++ b/drivers/gpu/drm/mga/mga_warp.c @@ -29,11 +29,9 @@ #include <linux/firmware.h> #include <linux/ihex.h> -#include <linux/platform_device.h> #include <linux/module.h> +#include <linux/platform_device.h> -#include <drm/drmP.h> -#include <drm/mga_drm.h> #include "mga_drv.h" #define FIRMWARE_G200 "matrox/g200_warp.fw" diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile index 98d204408bd0..04b281bcf655 100644 --- a/drivers/gpu/drm/mgag200/Makefile +++ b/drivers/gpu/drm/mgag200/Makefile @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only mgag200-y := mgag200_main.o mgag200_mode.o mgag200_cursor.o \ - mgag200_drv.o mgag200_fb.o mgag200_i2c.o mgag200_ttm.o + mgag200_drv.o mgag200_i2c.o mgag200_ttm.o obj-$(CONFIG_DRM_MGAG200) += mgag200.o diff --git a/drivers/gpu/drm/mgag200/mgag200_cursor.c b/drivers/gpu/drm/mgag200/mgag200_cursor.c index f0c61a92351c..289ce3e29032 100644 --- a/drivers/gpu/drm/mgag200/mgag200_cursor.c +++ b/drivers/gpu/drm/mgag200/mgag200_cursor.c @@ -5,7 +5,8 @@ * Author: Christopher Harvey <charvey@matrox.com> */ -#include <drm/drmP.h> +#include <drm/drm_pci.h> + #include "mgag200_drv.h" static bool warn_transparent = true; @@ -98,11 +99,12 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, } /* Pin and map up-coming buffer to write colour indices */ - ret = drm_gem_vram_pin(pixels_next, 0); - if (ret) + ret = drm_gem_vram_pin(pixels_next, DRM_GEM_VRAM_PL_FLAG_VRAM); + if (ret) { dev_err(&dev->pdev->dev, "failed to pin cursor buffer: %d\n", ret); goto err_drm_gem_vram_kunmap_src; + } dst = drm_gem_vram_kmap(pixels_next, true, NULL); if (IS_ERR(dst)) { ret = PTR_ERR(dst); @@ -110,7 +112,7 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, "failed to kmap cursor updates: %d\n", ret); goto err_drm_gem_vram_unpin_dst; } - gpu_addr = drm_gem_vram_offset(pixels_2); + gpu_addr = drm_gem_vram_offset(pixels_next); if (gpu_addr < 0) { ret = (int)gpu_addr; dev_err(&dev->pdev->dev, @@ -211,7 +213,6 @@ int mga_crtc_cursor_set(struct drm_crtc *crtc, mdev->cursor.pixels_current = pixels_next; drm_gem_vram_kunmap(pixels_next); - drm_gem_vram_unpin(pixels_next); drm_gem_vram_kunmap(gbo); drm_gem_vram_unpin(gbo); drm_gem_object_put_unlocked(obj); diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c index aafa1cb31f50..afd9119b6cf1 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.c +++ b/drivers/gpu/drm/mgag200/mgag200_drv.c @@ -5,14 +5,18 @@ * Authors: Matthew Garrett * Dave Airlie */ + #include <linux/module.h> #include <linux/console.h> -#include <drm/drmP.h> - -#include "mgag200_drv.h" +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_pci.h> #include <drm/drm_pciids.h> +#include "mgag200_drv.h" + /* * This is the generic driver code. This binds the driver to the drm core, * which then performs further device association and calls our graphics init diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index c47671ce6c48..1c93f8dc08c7 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h @@ -10,19 +10,17 @@ #ifndef __MGAG200_DRV_H__ #define __MGAG200_DRV_H__ +#include <linux/i2c-algo-bit.h> +#include <linux/i2c.h> + #include <video/vga.h> #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> - #include <drm/drm_gem.h> #include <drm/drm_gem_vram_helper.h> - #include <drm/drm_vram_mm_helper.h> -#include <linux/i2c.h> -#include <linux/i2c-algo-bit.h> - #include "mgag200_reg.h" #define DRIVER_AUTHOR "Matthew Garrett" @@ -100,21 +98,6 @@ #define to_mga_crtc(x) container_of(x, struct mga_crtc, base) #define to_mga_encoder(x) container_of(x, struct mga_encoder, base) #define to_mga_connector(x) container_of(x, struct mga_connector, base) -#define to_mga_framebuffer(x) container_of(x, struct mga_framebuffer, base) - -struct mga_framebuffer { - struct drm_framebuffer base; - struct drm_gem_object *obj; -}; - -struct mga_fbdev { - struct drm_fb_helper helper; /* must be first */ - struct mga_framebuffer mfb; - void *sysram; - int size; - int x1, y1, x2, y2; /* dirty rect */ - spinlock_t dirty_lock; -}; struct mga_crtc { struct drm_crtc base; @@ -189,7 +172,6 @@ struct mga_device { struct mga_mc mc; struct mga_mode_info mode_info; - struct mga_fbdev *mfbdev; struct mga_cursor cursor; bool suspended; @@ -210,25 +192,9 @@ struct mga_device { int mgag200_modeset_init(struct mga_device *mdev); void mgag200_modeset_fini(struct mga_device *mdev); - /* mgag200_fb.c */ -int mgag200_fbdev_init(struct mga_device *mdev); -void mgag200_fbdev_fini(struct mga_device *mdev); - /* mgag200_main.c */ -int mgag200_framebuffer_init(struct drm_device *dev, - struct mga_framebuffer *mfb, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object *obj); - - int mgag200_driver_load(struct drm_device *dev, unsigned long flags); void mgag200_driver_unload(struct drm_device *dev); -int mgag200_gem_create(struct drm_device *dev, - u32 size, bool iskernel, - struct drm_gem_object **obj); -int mgag200_dumb_create(struct drm_file *file, - struct drm_device *dev, - struct drm_mode_create_dumb *args); /* mgag200_i2c.c */ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev); diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c deleted file mode 100644 index 8adb33228732..000000000000 --- a/drivers/gpu/drm/mgag200/mgag200_fb.c +++ /dev/null @@ -1,315 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright 2010 Matt Turner. - * Copyright 2012 Red Hat - * - * Authors: Matthew Garrett - * Matt Turner - * Dave Airlie - */ -#include <linux/module.h> -#include <drm/drmP.h> -#include <drm/drm_util.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_crtc_helper.h> - -#include "mgag200_drv.h" - -static void mga_dirty_update(struct mga_fbdev *mfbdev, - int x, int y, int width, int height) -{ - int i; - struct drm_gem_object *obj; - struct drm_gem_vram_object *gbo; - int src_offset, dst_offset; - int bpp = mfbdev->mfb.base.format->cpp[0]; - int ret; - u8 *dst; - bool unmap = false; - bool store_for_later = false; - int x2, y2; - unsigned long flags; - - obj = mfbdev->mfb.obj; - gbo = drm_gem_vram_of_gem(obj); - - if (drm_can_sleep()) { - /* We pin the BO so it won't be moved during the - * update. The actual location, video RAM or system - * memory, is not important. - */ - ret = drm_gem_vram_pin(gbo, 0); - if (ret) { - if (ret != -EBUSY) - return; - store_for_later = true; - } - } else { - store_for_later = true; - } - - x2 = x + width - 1; - y2 = y + height - 1; - spin_lock_irqsave(&mfbdev->dirty_lock, flags); - - if (mfbdev->y1 < y) - y = mfbdev->y1; - if (mfbdev->y2 > y2) - y2 = mfbdev->y2; - if (mfbdev->x1 < x) - x = mfbdev->x1; - if (mfbdev->x2 > x2) - x2 = mfbdev->x2; - - if (store_for_later) { - mfbdev->x1 = x; - mfbdev->x2 = x2; - mfbdev->y1 = y; - mfbdev->y2 = y2; - spin_unlock_irqrestore(&mfbdev->dirty_lock, flags); - return; - } - - mfbdev->x1 = mfbdev->y1 = INT_MAX; - mfbdev->x2 = mfbdev->y2 = 0; - spin_unlock_irqrestore(&mfbdev->dirty_lock, flags); - - dst = drm_gem_vram_kmap(gbo, false, NULL); - if (IS_ERR(dst)) { - DRM_ERROR("failed to kmap fb updates\n"); - goto out; - } else if (!dst) { - dst = drm_gem_vram_kmap(gbo, true, NULL); - if (IS_ERR(dst)) { - DRM_ERROR("failed to kmap fb updates\n"); - goto out; - } - unmap = true; - } - - for (i = y; i <= y2; i++) { - /* assume equal stride for now */ - src_offset = dst_offset = - i * mfbdev->mfb.base.pitches[0] + (x * bpp); - memcpy_toio(dst + dst_offset, mfbdev->sysram + src_offset, - (x2 - x + 1) * bpp); - } - - if (unmap) - drm_gem_vram_kunmap(gbo); - -out: - drm_gem_vram_unpin(gbo); -} - -static void mga_fillrect(struct fb_info *info, - const struct fb_fillrect *rect) -{ - struct mga_fbdev *mfbdev = info->par; - drm_fb_helper_sys_fillrect(info, rect); - mga_dirty_update(mfbdev, rect->dx, rect->dy, rect->width, - rect->height); -} - -static void mga_copyarea(struct fb_info *info, - const struct fb_copyarea *area) -{ - struct mga_fbdev *mfbdev = info->par; - drm_fb_helper_sys_copyarea(info, area); - mga_dirty_update(mfbdev, area->dx, area->dy, area->width, - area->height); -} - -static void mga_imageblit(struct fb_info *info, - const struct fb_image *image) -{ - struct mga_fbdev *mfbdev = info->par; - drm_fb_helper_sys_imageblit(info, image); - mga_dirty_update(mfbdev, image->dx, image->dy, image->width, - image->height); -} - - -static struct fb_ops mgag200fb_ops = { - .owner = THIS_MODULE, - .fb_check_var = drm_fb_helper_check_var, - .fb_set_par = drm_fb_helper_set_par, - .fb_fillrect = mga_fillrect, - .fb_copyarea = mga_copyarea, - .fb_imageblit = mga_imageblit, - .fb_pan_display = drm_fb_helper_pan_display, - .fb_blank = drm_fb_helper_blank, - .fb_setcmap = drm_fb_helper_setcmap, -}; - -static int mgag200fb_create_object(struct mga_fbdev *afbdev, - const struct drm_mode_fb_cmd2 *mode_cmd, - struct drm_gem_object **gobj_p) -{ - struct drm_device *dev = afbdev->helper.dev; - u32 size; - struct drm_gem_object *gobj; - int ret = 0; - - size = mode_cmd->pitches[0] * mode_cmd->height; - ret = mgag200_gem_create(dev, size, true, &gobj); - if (ret) - return ret; - - *gobj_p = gobj; - return ret; -} - -static int mgag200fb_create(struct drm_fb_helper *helper, - struct drm_fb_helper_surface_size *sizes) -{ - struct mga_fbdev *mfbdev = - container_of(helper, struct mga_fbdev, helper); - struct drm_device *dev = mfbdev->helper.dev; - struct drm_mode_fb_cmd2 mode_cmd; - struct mga_device *mdev = dev->dev_private; - struct fb_info *info; - struct drm_framebuffer *fb; - struct drm_gem_object *gobj = NULL; - int ret; - void *sysram; - int size; - - mode_cmd.width = sizes->surface_width; - mode_cmd.height = sizes->surface_height; - mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8); - - mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp, - sizes->surface_depth); - size = mode_cmd.pitches[0] * mode_cmd.height; - - ret = mgag200fb_create_object(mfbdev, &mode_cmd, &gobj); - if (ret) { - DRM_ERROR("failed to create fbcon backing object %d\n", ret); - return ret; - } - - sysram = vmalloc(size); - if (!sysram) { - ret = -ENOMEM; - goto err_sysram; - } - - info = drm_fb_helper_alloc_fbi(helper); - if (IS_ERR(info)) { - ret = PTR_ERR(info); - goto err_alloc_fbi; - } - - ret = mgag200_framebuffer_init(dev, &mfbdev->mfb, &mode_cmd, gobj); - if (ret) - goto err_alloc_fbi; - - mfbdev->sysram = sysram; - mfbdev->size = size; - - fb = &mfbdev->mfb.base; - - /* setup helper */ - mfbdev->helper.fb = fb; - - info->fbops = &mgag200fb_ops; - - /* setup aperture base/size for vesafb takeover */ - info->apertures->ranges[0].base = mdev->dev->mode_config.fb_base; - info->apertures->ranges[0].size = mdev->mc.vram_size; - - drm_fb_helper_fill_info(info, &mfbdev->helper, sizes); - - info->screen_base = sysram; - info->screen_size = size; - info->pixmap.flags = FB_PIXMAP_SYSTEM; - - DRM_DEBUG_KMS("allocated %dx%d\n", - fb->width, fb->height); - - return 0; - -err_alloc_fbi: - vfree(sysram); -err_sysram: - drm_gem_object_put_unlocked(gobj); - - return ret; -} - -static int mga_fbdev_destroy(struct drm_device *dev, - struct mga_fbdev *mfbdev) -{ - struct mga_framebuffer *mfb = &mfbdev->mfb; - - drm_fb_helper_unregister_fbi(&mfbdev->helper); - - if (mfb->obj) { - drm_gem_object_put_unlocked(mfb->obj); - mfb->obj = NULL; - } - drm_fb_helper_fini(&mfbdev->helper); - vfree(mfbdev->sysram); - drm_framebuffer_unregister_private(&mfb->base); - drm_framebuffer_cleanup(&mfb->base); - - return 0; -} - -static const struct drm_fb_helper_funcs mga_fb_helper_funcs = { - .fb_probe = mgag200fb_create, -}; - -int mgag200_fbdev_init(struct mga_device *mdev) -{ - struct mga_fbdev *mfbdev; - int ret; - int bpp_sel = 32; - - /* prefer 16bpp on low end gpus with limited VRAM */ - if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024)) - bpp_sel = 16; - - mfbdev = devm_kzalloc(mdev->dev->dev, sizeof(struct mga_fbdev), GFP_KERNEL); - if (!mfbdev) - return -ENOMEM; - - mdev->mfbdev = mfbdev; - spin_lock_init(&mfbdev->dirty_lock); - - drm_fb_helper_prepare(mdev->dev, &mfbdev->helper, &mga_fb_helper_funcs); - - ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper, - MGAG200FB_CONN_LIMIT); - if (ret) - goto err_fb_helper; - - ret = drm_fb_helper_single_add_all_connectors(&mfbdev->helper); - if (ret) - goto err_fb_setup; - - /* disable all the possible outputs/crtcs before entering KMS mode */ - drm_helper_disable_unused_functions(mdev->dev); - - ret = drm_fb_helper_initial_config(&mfbdev->helper, bpp_sel); - if (ret) - goto err_fb_setup; - - return 0; - -err_fb_setup: - drm_fb_helper_fini(&mfbdev->helper); -err_fb_helper: - mdev->mfbdev = NULL; - - return ret; -} - -void mgag200_fbdev_fini(struct mga_device *mdev) -{ - if (!mdev->mfbdev) - return; - - mga_fbdev_destroy(mdev->dev, mdev->mfbdev); -} diff --git a/drivers/gpu/drm/mgag200/mgag200_i2c.c b/drivers/gpu/drm/mgag200/mgag200_i2c.c index 77d1c4771786..51d4037f00d4 100644 --- a/drivers/gpu/drm/mgag200/mgag200_i2c.c +++ b/drivers/gpu/drm/mgag200/mgag200_i2c.c @@ -25,10 +25,12 @@ /* * Authors: Dave Airlie <airlied@redhat.com> */ + #include <linux/export.h> -#include <linux/i2c.h> #include <linux/i2c-algo-bit.h> -#include <drm/drmP.h> +#include <linux/i2c.h> + +#include <drm/drm_pci.h> #include "mgag200_drv.h" diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c index dd61ccc5af5c..a9773334dedf 100644 --- a/drivers/gpu/drm/mgag200/mgag200_main.c +++ b/drivers/gpu/drm/mgag200/mgag200_main.c @@ -7,70 +7,15 @@ * Matt Turner * Dave Airlie */ -#include <drm/drmP.h> -#include <drm/drm_crtc_helper.h> -#include "mgag200_drv.h" -static void mga_user_framebuffer_destroy(struct drm_framebuffer *fb) -{ - struct mga_framebuffer *mga_fb = to_mga_framebuffer(fb); - - drm_gem_object_put_unlocked(mga_fb->obj); - drm_framebuffer_cleanup(fb); - kfree(fb); -} - -static const struct drm_framebuffer_funcs mga_fb_funcs = { - .destroy = mga_user_framebuffer_destroy, -}; - -int mgag200_framebuffer_init(struct drm_device *dev, - struct mga_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, &mga_fb_funcs); - if (ret) { - DRM_ERROR("drm_framebuffer_init failed: %d\n", ret); - return ret; - } - return 0; -} - -static struct drm_framebuffer * -mgag200_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 mga_framebuffer *mga_fb; - int ret; - - obj = drm_gem_object_lookup(filp, mode_cmd->handles[0]); - if (obj == NULL) - return ERR_PTR(-ENOENT); - - mga_fb = kzalloc(sizeof(*mga_fb), GFP_KERNEL); - if (!mga_fb) { - drm_gem_object_put_unlocked(obj); - return ERR_PTR(-ENOMEM); - } +#include <drm/drm_crtc_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_pci.h> - ret = mgag200_framebuffer_init(dev, mga_fb, mode_cmd, obj); - if (ret) { - drm_gem_object_put_unlocked(obj); - kfree(mga_fb); - return ERR_PTR(ret); - } - return &mga_fb->base; -} +#include "mgag200_drv.h" static const struct drm_mode_config_funcs mga_mode_funcs = { - .fb_create = mgag200_user_framebuffer_create, + .fb_create = drm_gem_fb_create }; static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem) @@ -217,7 +162,7 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) if (IS_G200_SE(mdev) && mdev->mc.vram_size < (2048*1024)) dev->mode_config.preferred_depth = 16; else - dev->mode_config.preferred_depth = 24; + dev->mode_config.preferred_depth = 32; dev->mode_config.prefer_shadow = 1; r = mgag200_modeset_init(mdev); @@ -241,6 +186,10 @@ int mgag200_driver_load(struct drm_device *dev, unsigned long flags) } mdev->cursor.pixels_current = NULL; + r = drm_fbdev_generic_setup(mdev->dev, 0); + if (r) + goto err_modeset; + return 0; err_modeset: @@ -259,32 +208,7 @@ void mgag200_driver_unload(struct drm_device *dev) if (mdev == NULL) return; mgag200_modeset_fini(mdev); - mgag200_fbdev_fini(mdev); drm_mode_config_cleanup(dev); mgag200_mm_fini(mdev); dev->dev_private = NULL; } - -int mgag200_gem_create(struct drm_device *dev, - u32 size, bool iskernel, - struct drm_gem_object **obj) -{ - struct drm_gem_vram_object *gbo; - int ret; - - *obj = NULL; - - size = roundup(size, PAGE_SIZE); - if (size == 0) - return -EINVAL; - - gbo = drm_gem_vram_create(dev, &dev->vram_mm->bdev, size, 0, false); - if (IS_ERR(gbo)) { - ret = PTR_ERR(gbo); - if (ret != -ERESTARTSYS) - DRM_ERROR("failed to allocate GEM object\n"); - return ret; - } - *obj = &gbo->gem; - return 0; -} diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index a25054015e8c..5e778b5f1a10 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c @@ -10,8 +10,9 @@ #include <linux/delay.h> -#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_pci.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> @@ -859,28 +860,16 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, struct drm_framebuffer *fb, int x, int y, int atomic) { - struct mga_device *mdev = crtc->dev->dev_private; - struct drm_gem_object *obj; - struct mga_framebuffer *mga_fb; struct drm_gem_vram_object *gbo; int ret; s64 gpu_addr; - void *base; if (!atomic && fb) { - mga_fb = to_mga_framebuffer(fb); - obj = mga_fb->obj; - gbo = drm_gem_vram_of_gem(obj); - - /* unmap if console */ - if (&mdev->mfbdev->mfb == mga_fb) - drm_gem_vram_kunmap(gbo); + gbo = drm_gem_vram_of_gem(fb->obj[0]); drm_gem_vram_unpin(gbo); } - mga_fb = to_mga_framebuffer(crtc->primary->fb); - obj = mga_fb->obj; - gbo = drm_gem_vram_of_gem(obj); + gbo = drm_gem_vram_of_gem(crtc->primary->fb->obj[0]); ret = drm_gem_vram_pin(gbo, DRM_GEM_VRAM_PL_FLAG_VRAM); if (ret) @@ -891,15 +880,6 @@ static int mga_crtc_do_set_base(struct drm_crtc *crtc, goto err_drm_gem_vram_unpin; } - if (&mdev->mfbdev->mfb == mga_fb) { - /* if pushing console in kmap it */ - base = drm_gem_vram_kmap(gbo, true, NULL); - if (IS_ERR(base)) { - ret = PTR_ERR(base); - DRM_ERROR("failed to kmap fbcon\n"); - } - } - mga_set_start_address(crtc, (u32)gpu_addr); return 0; @@ -1423,14 +1403,9 @@ static void mga_crtc_disable(struct drm_crtc *crtc) DRM_DEBUG_KMS("\n"); mga_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); if (crtc->primary->fb) { - struct mga_device *mdev = crtc->dev->dev_private; - struct mga_framebuffer *mga_fb = to_mga_framebuffer(crtc->primary->fb); - struct drm_gem_object *obj = mga_fb->obj; - struct drm_gem_vram_object *gbo = drm_gem_vram_of_gem(obj); - - /* unmap if console */ - if (&mdev->mfbdev->mfb == mga_fb) - drm_gem_vram_kunmap(gbo); + struct drm_framebuffer *fb = crtc->primary->fb; + struct drm_gem_vram_object *gbo = + drm_gem_vram_of_gem(fb->obj[0]); drm_gem_vram_unpin(gbo); } crtc->primary->fb = NULL; @@ -1703,18 +1678,19 @@ static struct drm_connector *mga_vga_init(struct drm_device *dev) return NULL; connector = &mga_connector->base; + mga_connector->i2c = mgag200_i2c_create(dev); + if (!mga_connector->i2c) + DRM_ERROR("failed to add ddc bus\n"); - drm_connector_init(dev, connector, - &mga_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA); + drm_connector_init_with_ddc(dev, connector, + &mga_vga_connector_funcs, + DRM_MODE_CONNECTOR_VGA, + &mga_connector->i2c->adapter); drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs); drm_connector_register(connector); - mga_connector->i2c = mgag200_i2c_create(dev); - if (!mga_connector->i2c) - DRM_ERROR("failed to add ddc bus\n"); - return connector; } @@ -1723,7 +1699,6 @@ int mgag200_modeset_init(struct mga_device *mdev) { struct drm_encoder *encoder; struct drm_connector *connector; - int ret; mdev->mode_info.mode_config_initialized = true; @@ -1748,12 +1723,6 @@ int mgag200_modeset_init(struct mga_device *mdev) drm_connector_attach_encoder(connector, encoder); - ret = mgag200_fbdev_init(mdev); - if (ret) { - DRM_ERROR("mga_fbdev_init failed\n"); - return ret; - } - return 0; } diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c index 59294c0fd24a..73a6b848601c 100644 --- a/drivers/gpu/drm/mgag200/mgag200_ttm.c +++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c @@ -25,7 +25,8 @@ /* * Authors: Dave Airlie <airlied@redhat.com> */ -#include <drm/drmP.h> + +#include <drm/drm_pci.h> #include "mgag200_drv.h" diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c index 45bfac9e3af7..8cf0b8a4ed03 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c @@ -12,6 +12,7 @@ #include <drm/drm_damage_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_gem_framebuffer_helper.h> #include "msm_drv.h" #include "dpu_kms.h" @@ -764,8 +765,6 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, struct dpu_plane *pdpu = to_dpu_plane(plane); struct dpu_plane_state *pstate = to_dpu_plane_state(new_state); struct dpu_hw_fmt_layout layout; - struct drm_gem_object *obj; - struct dma_fence *fence; struct dpu_kms *kms = _dpu_plane_get_kms(&pdpu->base); int ret; @@ -782,10 +781,7 @@ static int dpu_plane_prepare_fb(struct drm_plane *plane, * we can use msm_atomic_prepare_fb() instead of doing the * implicit fence and fb prepare by hand here. */ - obj = msm_framebuffer_bo(new_state->fb, 0); - fence = reservation_object_get_excl_rcu(obj->resv); - if (fence) - drm_atomic_set_fence_for_plane(new_state, fence); + drm_gem_fb_prepare_fb(plane, new_state); if (pstate->aspace) { ret = msm_framebuffer_prepare(new_state->fb, diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c index dd16babdd8c0..169d5f915e68 100644 --- a/drivers/gpu/drm/msm/msm_atomic.c +++ b/drivers/gpu/drm/msm/msm_atomic.c @@ -5,6 +5,7 @@ */ #include <drm/drm_atomic_uapi.h> +#include <drm/drm_gem_framebuffer_helper.h> #include "msm_drv.h" #include "msm_gem.h" @@ -37,16 +38,11 @@ int msm_atomic_prepare_fb(struct drm_plane *plane, { struct msm_drm_private *priv = plane->dev->dev_private; struct msm_kms *kms = priv->kms; - struct drm_gem_object *obj; - struct dma_fence *fence; if (!new_state->fb) return 0; - obj = msm_framebuffer_bo(new_state->fb, 0); - fence = reservation_object_get_excl_rcu(obj->resv); - - drm_atomic_set_fence_for_plane(new_state, fence); + drm_gem_fb_prepare_fb(plane, new_state); return msm_framebuffer_prepare(new_state->fb, kms->aspace); } diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index c356f5ccf253..ee031c086805 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -984,17 +984,17 @@ static int msm_ioctl_submitqueue_close(struct drm_device *dev, void *data, } static const struct drm_ioctl_desc msm_ioctls[] = { - DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_INFO, msm_ioctl_gem_info, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GET_PARAM, msm_ioctl_get_param, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_NEW, msm_ioctl_gem_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_INFO, msm_ioctl_gem_info, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_PREP, msm_ioctl_gem_cpu_prep, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_CPU_FINI, msm_ioctl_gem_cpu_fini, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_SUBMIT, msm_ioctl_gem_submit, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_WAIT_FENCE, msm_ioctl_wait_fence, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_GEM_MADVISE, msm_ioctl_gem_madvise, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_NEW, msm_ioctl_submitqueue_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_CLOSE, msm_ioctl_submitqueue_close, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(MSM_SUBMITQUEUE_QUERY, msm_ioctl_submitqueue_query, DRM_RENDER_ALLOW), }; static const struct vm_operations_struct vm_ops = { @@ -1017,7 +1017,6 @@ static const struct file_operations fops = { static struct drm_driver msm_driver = { .driver_features = DRIVER_GEM | - DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC | DRIVER_MODESET, @@ -1036,8 +1035,6 @@ static struct drm_driver msm_driver = { .dumb_map_offset = msm_gem_dumb_map_offset, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = msm_gem_prime_pin, .gem_prime_unpin = msm_gem_prime_unpin, .gem_prime_get_sg_table = msm_gem_prime_get_sg_table, diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c index 8cf6362e64bf..8cc70026c358 100644 --- a/drivers/gpu/drm/msm/msm_gem.c +++ b/drivers/gpu/drm/msm/msm_gem.c @@ -975,7 +975,6 @@ int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file, static int msm_gem_new_impl(struct drm_device *dev, uint32_t size, uint32_t flags, - struct reservation_object *resv, struct drm_gem_object **obj, bool struct_mutex_locked) { @@ -1002,9 +1001,6 @@ static int msm_gem_new_impl(struct drm_device *dev, msm_obj->flags = flags; msm_obj->madv = MSM_MADV_WILLNEED; - if (resv) - msm_obj->base.resv = resv; - INIT_LIST_HEAD(&msm_obj->submit_entry); INIT_LIST_HEAD(&msm_obj->vmas); @@ -1046,7 +1042,7 @@ static struct drm_gem_object *_msm_gem_new(struct drm_device *dev, if (size == 0) return ERR_PTR(-EINVAL); - ret = msm_gem_new_impl(dev, size, flags, NULL, &obj, struct_mutex_locked); + ret = msm_gem_new_impl(dev, size, flags, &obj, struct_mutex_locked); if (ret) goto fail; @@ -1123,7 +1119,7 @@ struct drm_gem_object *msm_gem_import(struct drm_device *dev, size = PAGE_ALIGN(dmabuf->size); - ret = msm_gem_new_impl(dev, size, MSM_BO_WC, dmabuf->resv, &obj, false); + ret = msm_gem_new_impl(dev, size, MSM_BO_WC, &obj, false); if (ret) goto fail; diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c index 4edb874548b3..f7308d68c5ed 100644 --- a/drivers/gpu/drm/msm/msm_gpu.c +++ b/drivers/gpu/drm/msm/msm_gpu.c @@ -95,7 +95,8 @@ static void msm_devfreq_init(struct msm_gpu *gpu) */ gpu->devfreq.devfreq = devm_devfreq_add_device(&gpu->pdev->dev, - &msm_devfreq_profile, "simple_ondemand", NULL); + &msm_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND, + NULL); if (IS_ERR(gpu->devfreq.devfreq)) { DRM_DEV_ERROR(&gpu->pdev->dev, "Couldn't initialize GPU devfreq\n"); diff --git a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c index 93f413345e0d..12421567af89 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_crtc.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_crtc.c @@ -8,21 +8,23 @@ * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved. */ -#include <drm/drmP.h> +#include <linux/clk.h> +#include <linux/iopoll.h> +#include <linux/of_graph.h> +#include <linux/platform_data/simplefb.h> + +#include <video/videomode.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> -#include <linux/clk.h> -#include <linux/iopoll.h> -#include <linux/of_graph.h> -#include <linux/platform_data/simplefb.h> -#include <video/videomode.h> +#include <drm/drm_vblank.h> #include "mxsfb_drv.h" #include "mxsfb_regs.h" diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c index 6fafc90da4ec..878ef6822812 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c @@ -8,29 +8,32 @@ * Copyright (C) 2008 Embedded Alley Solutions, Inc All Rights Reserved. */ -#include <linux/module.h> -#include <linux/spinlock.h> #include <linux/clk.h> #include <linux/component.h> +#include <linux/dma-mapping.h> #include <linux/list.h> +#include <linux/module.h> #include <linux/of_device.h> #include <linux/of_graph.h> #include <linux/of_reserved_mem.h> #include <linux/pm_runtime.h> #include <linux/reservation.h> +#include <linux/spinlock.h> -#include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_fb_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_irq.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> +#include <drm/drm_vblank.h> #include "mxsfb_drv.h" #include "mxsfb_regs.h" @@ -313,8 +316,7 @@ static irqreturn_t mxsfb_irq_handler(int irq, void *data) DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver mxsfb_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | - DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .irq_handler = mxsfb_irq_handler, .irq_preinstall = mxsfb_irq_preinstall, .irq_uninstall = mxsfb_irq_preinstall, @@ -323,8 +325,6 @@ static struct drm_driver mxsfb_driver = { .dumb_create = drm_gem_cma_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/mxsfb/mxsfb_out.c b/drivers/gpu/drm/mxsfb/mxsfb_out.c index 91e76f9cead6..231d016c6f47 100644 --- a/drivers/gpu/drm/mxsfb/mxsfb_out.c +++ b/drivers/gpu/drm/mxsfb/mxsfb_out.c @@ -15,7 +15,6 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> -#include <drm/drmP.h> #include "mxsfb_drv.h" diff --git a/drivers/gpu/drm/nouveau/dispnv50/wndw.c b/drivers/gpu/drm/nouveau/dispnv50/wndw.c index 283ff690350e..89f8e76a2d7d 100644 --- a/drivers/gpu/drm/nouveau/dispnv50/wndw.c +++ b/drivers/gpu/drm/nouveau/dispnv50/wndw.c @@ -457,7 +457,7 @@ nv50_wndw_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) asyw->image.handle[0] = ctxdma->object.handle; } - asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.resv); + asyw->state.fence = reservation_object_get_excl_rcu(fb->nvbo->bo.base.resv); asyw->image.offset[0] = fb->nvbo->bo.offset; if (wndw->func->prepare) { diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index c3fd5dd39ed9..e2bae1424502 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c @@ -139,7 +139,7 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, if (chan->ntfy) { nouveau_vma_del(&chan->ntfy_vma); nouveau_bo_unpin(chan->ntfy); - drm_gem_object_put_unlocked(&chan->ntfy->gem); + drm_gem_object_put_unlocked(&chan->ntfy->bo.base); } if (chan->heap.block_size) @@ -245,12 +245,6 @@ nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS) } int -nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS) -{ - return -EINVAL; -} - -int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) { struct drm_nouveau_channel_alloc *init = data; @@ -345,7 +339,7 @@ nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS) goto done; } - ret = drm_gem_handle_create(file_priv, &chan->ntfy->gem, + ret = drm_gem_handle_create(file_priv, &chan->ntfy->bo.base, &init->notifier_handle); if (ret) goto done; diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.h b/drivers/gpu/drm/nouveau/nouveau_abi16.h index 195546719bfe..70f6aa5c9dd1 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.h +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.h @@ -6,7 +6,6 @@ struct drm_device *dev, void *data, struct drm_file *file_priv int nouveau_abi16_ioctl_getparam(ABI16_IOCTL_ARGS); -int nouveau_abi16_ioctl_setparam(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_channel_alloc(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_channel_free(ABI16_IOCTL_ARGS); int nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 34a998012bf6..99e391be9370 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c @@ -136,7 +136,7 @@ nouveau_bo_del_ttm(struct ttm_buffer_object *bo) struct drm_device *dev = drm->dev; struct nouveau_bo *nvbo = nouveau_bo(bo); - if (unlikely(nvbo->gem.filp)) + if (unlikely(nvbo->bo.base.filp)) DRM_ERROR("bo %p still attached to GEM object\n", bo); WARN_ON(nvbo->pin_refcnt > 0); nv10_bo_put_tile_region(dev, nvbo->tile, NULL); @@ -299,6 +299,7 @@ nouveau_bo_new(struct nouveau_cli *cli, u64 size, int align, type, &nvbo->placement, align >> PAGE_SHIFT, false, acc_size, sg, robj, nouveau_bo_del_ttm); + if (ret) { /* ttm will call nouveau_bo_del_ttm if it fails.. */ return ret; @@ -1323,7 +1324,7 @@ nouveau_bo_vm_cleanup(struct ttm_buffer_object *bo, { struct nouveau_drm *drm = nouveau_bdev(bo->bdev); struct drm_device *dev = drm->dev; - struct dma_fence *fence = reservation_object_get_excl(bo->resv); + struct dma_fence *fence = reservation_object_get_excl(bo->base.resv); nv10_bo_put_tile_region(dev, *old_tile, fence); *old_tile = new_tile; @@ -1400,7 +1401,7 @@ nouveau_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp) { struct nouveau_bo *nvbo = nouveau_bo(bo); - return drm_vma_node_verify_access(&nvbo->gem.vma_node, + return drm_vma_node_verify_access(&nvbo->bo.base.vma_node, filp->private_data); } @@ -1654,7 +1655,7 @@ nouveau_ttm_tt_unpopulate(struct ttm_tt *ttm) void nouveau_bo_fence(struct nouveau_bo *nvbo, struct nouveau_fence *fence, bool exclusive) { - struct reservation_object *resv = nvbo->bo.resv; + struct reservation_object *resv = nvbo->bo.base.resv; if (exclusive) reservation_object_add_excl_fence(resv, &fence->base); diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.h b/drivers/gpu/drm/nouveau/nouveau_bo.h index 383ac36d5869..d675efe8e7f9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.h +++ b/drivers/gpu/drm/nouveau/nouveau_bo.h @@ -35,11 +35,6 @@ struct nouveau_bo { struct nouveau_drm_tile *tile; - /* Only valid if allocated via nouveau_gem_new() and iff you hold a - * gem reference to it! For debugging, use gem.filp != NULL to test - * whether it is valid. */ - struct drm_gem_object gem; - /* protect by the ttm reservation lock */ int pin_refcnt; diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 8f15281faa79..330d7d29a6e3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c @@ -1349,7 +1349,7 @@ nouveau_connector_create(struct drm_device *dev, break; case DRM_MODE_CONNECTOR_DisplayPort: case DRM_MODE_CONNECTOR_eDP: - nv_connector->aux.dev = dev->dev; + nv_connector->aux.dev = connector->kdev; nv_connector->aux.transfer = nouveau_connector_aux_xfer; snprintf(aux_name, sizeof(aux_name), "sor-%04x-%04x", dcbe->hasht, dcbe->hashm); diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 832da8e0020d..98afc50162e9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -201,7 +201,7 @@ nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb) struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); if (fb->nvbo) - drm_gem_object_put_unlocked(&fb->nvbo->gem); + drm_gem_object_put_unlocked(&fb->nvbo->bo.base); drm_framebuffer_cleanup(drm_fb); kfree(fb); @@ -214,7 +214,7 @@ nouveau_user_framebuffer_create_handle(struct drm_framebuffer *drm_fb, { struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb); - return drm_gem_handle_create(file_priv, &fb->nvbo->gem, handle); + return drm_gem_handle_create(file_priv, &fb->nvbo->bo.base, handle); } static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = { @@ -660,8 +660,8 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev, if (ret) return ret; - ret = drm_gem_handle_create(file_priv, &bo->gem, &args->handle); - drm_gem_object_put_unlocked(&bo->gem); + ret = drm_gem_handle_create(file_priv, &bo->bo.base, &args->handle); + drm_gem_object_put_unlocked(&bo->bo.base); return ret; } @@ -675,7 +675,7 @@ nouveau_display_dumb_map_offset(struct drm_file *file_priv, gem = drm_gem_object_lookup(file_priv, handle); if (gem) { struct nouveau_bo *bo = nouveau_gem_object(gem); - *poffset = drm_vma_node_offset_addr(&bo->bo.vma_node); + *poffset = drm_vma_node_offset_addr(&bo->bo.base.vma_node); drm_gem_object_put_unlocked(gem); return 0; } diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 7c2fcaba42d6..7e045580a3a4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c @@ -1046,20 +1046,20 @@ nouveau_drm_postclose(struct drm_device *dev, struct drm_file *fpriv) static const struct drm_ioctl_desc nouveau_ioctls[] = { - DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, nouveau_abi16_ioctl_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_INIT, nouveau_svmm_init, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_BIND, nouveau_svmm_bind, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GETPARAM, nouveau_abi16_ioctl_getparam, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_SETPARAM, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_ALLOC, nouveau_abi16_ioctl_channel_alloc, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_CHANNEL_FREE, nouveau_abi16_ioctl_channel_free, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GROBJ_ALLOC, nouveau_abi16_ioctl_grobj_alloc, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_NOTIFIEROBJ_ALLOC, nouveau_abi16_ioctl_notifierobj_alloc, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GPUOBJ_FREE, nouveau_abi16_ioctl_gpuobj_free, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_INIT, nouveau_svmm_init, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_SVM_BIND, nouveau_svmm_bind, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_NEW, nouveau_gem_ioctl_new, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_PUSHBUF, nouveau_gem_ioctl_pushbuf, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_PREP, nouveau_gem_ioctl_cpu_prep, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_CPU_FINI, nouveau_gem_ioctl_cpu_fini, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(NOUVEAU_GEM_INFO, nouveau_gem_ioctl_info, DRM_RENDER_ALLOW), }; long @@ -1105,7 +1105,7 @@ nouveau_driver_fops = { static struct drm_driver driver_stub = { .driver_features = - DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER + DRIVER_GEM | DRIVER_MODESET | DRIVER_RENDER #if defined(CONFIG_NOUVEAU_LEGACY_CTX_SUPPORT) | DRIVER_KMS_LEGACY_CONTEXT #endif @@ -1130,10 +1130,7 @@ driver_stub = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = nouveau_gem_prime_pin, - .gem_prime_res_obj = nouveau_gem_prime_res_obj, .gem_prime_unpin = nouveau_gem_prime_unpin, .gem_prime_get_sg_table = nouveau_gem_prime_get_sg_table, .gem_prime_import_sg_table = nouveau_gem_prime_import_sg_table, diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index d4964f3397a1..e5f249ab216a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -335,7 +335,7 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, bool e { struct nouveau_fence_chan *fctx = chan->fence; struct dma_fence *fence; - struct reservation_object *resv = nvbo->bo.resv; + struct reservation_object *resv = nvbo->bo.base.resv; struct reservation_object_list *fobj; struct nouveau_fence *f; int ret = 0, i; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index b4bda716564d..c7368aa0bdec 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -205,13 +205,13 @@ nouveau_gem_new(struct nouveau_cli *cli, u64 size, int align, uint32_t domain, /* Initialize the embedded gem-object. We return a single gem-reference * to the caller, instead of a normal nouveau_bo ttm reference. */ - ret = drm_gem_object_init(drm->dev, &nvbo->gem, nvbo->bo.mem.size); + ret = drm_gem_object_init(drm->dev, &nvbo->bo.base, nvbo->bo.mem.size); if (ret) { nouveau_bo_ref(NULL, pnvbo); return -ENOMEM; } - nvbo->bo.persistent_swap_storage = nvbo->gem.filp; + nvbo->bo.persistent_swap_storage = nvbo->bo.base.filp; return 0; } @@ -240,7 +240,7 @@ nouveau_gem_info(struct drm_file *file_priv, struct drm_gem_object *gem, } rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT; - rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.vma_node); + rep->map_handle = drm_vma_node_offset_addr(&nvbo->bo.base.vma_node); rep->tile_mode = nvbo->mode; rep->tile_flags = nvbo->contig ? 0 : NOUVEAU_GEM_TILE_NONCONTIG; if (cli->device.info.family >= NV_DEVICE_INFO_V0_FERMI) @@ -268,15 +268,16 @@ nouveau_gem_ioctl_new(struct drm_device *dev, void *data, if (ret) return ret; - ret = drm_gem_handle_create(file_priv, &nvbo->gem, &req->info.handle); + ret = drm_gem_handle_create(file_priv, &nvbo->bo.base, + &req->info.handle); if (ret == 0) { - ret = nouveau_gem_info(file_priv, &nvbo->gem, &req->info); + ret = nouveau_gem_info(file_priv, &nvbo->bo.base, &req->info); if (ret) drm_gem_handle_delete(file_priv, req->info.handle); } /* drop reference from allocate - handle holds it now */ - drm_gem_object_put_unlocked(&nvbo->gem); + drm_gem_object_put_unlocked(&nvbo->bo.base); return ret; } @@ -355,7 +356,7 @@ validate_fini_no_ticket(struct validate_op *op, struct nouveau_channel *chan, list_del(&nvbo->entry); nvbo->reserved_by = NULL; ttm_bo_unreserve(&nvbo->bo); - drm_gem_object_put_unlocked(&nvbo->gem); + drm_gem_object_put_unlocked(&nvbo->bo.base); } } @@ -493,7 +494,7 @@ validate_list(struct nouveau_channel *chan, struct nouveau_cli *cli, list_for_each_entry(nvbo, list, entry) { struct drm_nouveau_gem_pushbuf_bo *b = &pbbo[nvbo->pbbo_index]; - ret = nouveau_gem_set_domain(&nvbo->gem, b->read_domains, + ret = nouveau_gem_set_domain(&nvbo->bo.base, b->read_domains, b->write_domains, b->valid_domains); if (unlikely(ret)) { @@ -886,7 +887,7 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, return -ENOENT; nvbo = nouveau_gem_object(gem); - lret = reservation_object_wait_timeout_rcu(nvbo->bo.resv, write, true, + lret = reservation_object_wait_timeout_rcu(nvbo->bo.base.resv, write, true, no_wait ? 0 : 30 * HZ); if (!lret) ret = -EBUSY; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.h b/drivers/gpu/drm/nouveau/nouveau_gem.h index 03371204a47c..40ba0f1ba5aa 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.h +++ b/drivers/gpu/drm/nouveau/nouveau_gem.h @@ -10,7 +10,7 @@ static inline struct nouveau_bo * nouveau_gem_object(struct drm_gem_object *gem) { - return gem ? container_of(gem, struct nouveau_bo, gem) : NULL; + return gem ? container_of(gem, struct nouveau_bo, bo.base) : NULL; } /* nouveau_gem.c */ @@ -33,7 +33,6 @@ extern int nouveau_gem_ioctl_info(struct drm_device *, void *, struct drm_file *); extern int nouveau_gem_prime_pin(struct drm_gem_object *); -struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *); extern void nouveau_gem_prime_unpin(struct drm_gem_object *); extern struct sg_table *nouveau_gem_prime_get_sg_table(struct drm_gem_object *); extern struct drm_gem_object *nouveau_gem_prime_import_sg_table( diff --git a/drivers/gpu/drm/nouveau/nouveau_prime.c b/drivers/gpu/drm/nouveau/nouveau_prime.c index 1fefc93af1d7..e86ad7ae622b 100644 --- a/drivers/gpu/drm/nouveau/nouveau_prime.c +++ b/drivers/gpu/drm/nouveau/nouveau_prime.c @@ -68,10 +68,10 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, flags = TTM_PL_FLAG_TT; - ww_mutex_lock(&robj->lock, NULL); + reservation_object_lock(robj, NULL); ret = nouveau_bo_new(&drm->client, attach->dmabuf->size, 0, flags, 0, 0, sg, robj, &nvbo); - ww_mutex_unlock(&robj->lock); + reservation_object_unlock(robj); if (ret) return ERR_PTR(ret); @@ -79,13 +79,13 @@ struct drm_gem_object *nouveau_gem_prime_import_sg_table(struct drm_device *dev, /* Initialize the embedded gem-object. We return a single gem-reference * to the caller, instead of a normal nouveau_bo ttm reference. */ - ret = drm_gem_object_init(dev, &nvbo->gem, nvbo->bo.mem.size); + ret = drm_gem_object_init(dev, &nvbo->bo.base, nvbo->bo.mem.size); if (ret) { nouveau_bo_ref(NULL, &nvbo); return ERR_PTR(-ENOMEM); } - return &nvbo->gem; + return &nvbo->bo.base; } int nouveau_gem_prime_pin(struct drm_gem_object *obj) @@ -107,10 +107,3 @@ void nouveau_gem_prime_unpin(struct drm_gem_object *obj) nouveau_bo_unpin(nvbo); } - -struct reservation_object *nouveau_gem_prime_res_obj(struct drm_gem_object *obj) -{ - struct nouveau_bo *nvbo = nouveau_gem_object(obj); - - return nvbo->bo.resv; -} diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index f9ac9afc5641..3c5ddbf30e97 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -4,12 +4,14 @@ * Author: Rob Clark <rob@ti.com> */ +#include <linux/math64.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_mode.h> #include <drm/drm_plane_helper.h> -#include <linux/math64.h> +#include <drm/drm_vblank.h> #include "omap_drv.h" diff --git a/drivers/gpu/drm/omapdrm/omap_debugfs.c b/drivers/gpu/drm/omapdrm/omap_debugfs.c index 2b283f68fab7..34dfb33145b4 100644 --- a/drivers/gpu/drm/omapdrm/omap_debugfs.c +++ b/drivers/gpu/drm/omapdrm/omap_debugfs.c @@ -7,6 +7,8 @@ #include <linux/seq_file.h> #include <drm/drm_crtc.h> +#include <drm/drm_debugfs.h> +#include <drm/drm_file.h> #include <drm/drm_fb_helper.h> #include "omap_drv.h" diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 288c59dae56a..9f652d2e7af1 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -4,15 +4,21 @@ * Author: Rob Clark <rob@ti.com> */ -#include <linux/of.h> +#include <linux/dma-mapping.h> +#include <linux/platform_device.h> #include <linux/sort.h> #include <linux/sys_soc.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_probe_helper.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> #include <drm/drm_panel.h> +#include <drm/drm_prime.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "omap_dmm_tiler.h" #include "omap_drv.h" @@ -466,19 +472,19 @@ static int ioctl_gem_info(struct drm_device *dev, void *data, static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = { DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, drm_invalid_op, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), /* Deprecated, to be removed. */ DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, drm_noop, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), /* Deprecated, to be removed. */ DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, drm_noop, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), }; /* @@ -513,7 +519,7 @@ static const struct file_operations omapdriver_fops = { }; static struct drm_driver omap_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_RENDER, .open = dev_open, .lastclose = drm_fb_helper_lastclose, diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 025bd57081d5..7c4b66efcaa7 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -11,12 +11,11 @@ #include <linux/types.h> #include <linux/workqueue.h> -#include <drm/drmP.h> +#include "dss/omapdss.h" + #include <drm/drm_gem.h> #include <drm/omap_drm.h> -#include "dss/omapdss.h" - #include "omap_connector.h" #include "omap_crtc.h" #include "omap_encoder.h" diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c index 7e89e5cb4068..1b8b5108caf8 100644 --- a/drivers/gpu/drm/omapdrm/omap_fb.c +++ b/drivers/gpu/drm/omapdrm/omap_fb.c @@ -4,10 +4,10 @@ * Author: Rob Clark <rob@ti.com> */ -#include <linux/seq_file.h> +#include <linux/dma-mapping.h> -#include <drm/drm_crtc.h> #include <drm/drm_modeset_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include "omap_dmm_tiler.h" diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 561c4812545b..58f53946ee4d 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -7,6 +7,8 @@ #include <drm/drm_crtc.h> #include <drm/drm_util.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_file.h> +#include <drm/drm_fourcc.h> #include "omap_drv.h" @@ -76,8 +78,6 @@ static struct fb_ops omap_fb_ops = { .fb_setcmap = drm_fb_helper_setcmap, .fb_blank = drm_fb_helper_blank, .fb_pan_display = omap_fbdev_pan_display, - .fb_debug_enter = drm_fb_helper_debug_enter, - .fb_debug_leave = drm_fb_helper_debug_leave, .fb_ioctl = drm_fb_helper_ioctl, .fb_read = drm_fb_helper_sys_read, diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 37378dbc50d0..08f539efddfb 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -4,11 +4,13 @@ * Author: Rob Clark <rob.clark@linaro.org> */ +#include <linux/dma-mapping.h> #include <linux/seq_file.h> #include <linux/shmem_fs.h> #include <linux/spinlock.h> #include <linux/pfn_t.h> +#include <drm/drm_prime.h> #include <drm/drm_vma_manager.h> #include "omap_drv.h" diff --git a/drivers/gpu/drm/omapdrm/omap_gem.h b/drivers/gpu/drm/omapdrm/omap_gem.h index 31cf345bf8ae..729b7812a815 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.h +++ b/drivers/gpu/drm/omapdrm/omap_gem.h @@ -65,8 +65,7 @@ u64 omap_gem_mmap_offset(struct drm_gem_object *obj); size_t omap_gem_mmap_size(struct drm_gem_object *obj); /* PRIME Interface */ -struct dma_buf *omap_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, int flags); +struct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags); struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, struct dma_buf *buffer); diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index 07c0b1b486f7..e8c3ae7ac77e 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -5,6 +5,9 @@ */ #include <linux/dma-buf.h> +#include <linux/highmem.h> + +#include <drm/drm_prime.h> #include "omap_drv.h" @@ -125,8 +128,7 @@ static const struct dma_buf_ops omap_dmabuf_ops = { .mmap = omap_gem_dmabuf_mmap, }; -struct dma_buf *omap_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, int flags) +struct dma_buf *omap_gem_prime_export(struct drm_gem_object *obj, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); @@ -135,7 +137,7 @@ struct dma_buf *omap_gem_prime_export(struct drm_device *dev, exp_info.flags = flags; exp_info.priv = obj; - return drm_gem_dmabuf_export(dev, &exp_info); + return drm_gem_dmabuf_export(obj->dev, &exp_info); } /* ----------------------------------------------------------------------------- diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index 726a013e7988..382bcdc72ac0 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c @@ -4,6 +4,8 @@ * Author: Rob Clark <rob.clark@linaro.org> */ +#include <drm/drm_vblank.h> + #include "omap_drv.h" struct omap_irq_wait { diff --git a/drivers/gpu/drm/panel/Kconfig b/drivers/gpu/drm/panel/Kconfig index d9d931aa6e26..eaecd40cc32e 100644 --- a/drivers/gpu/drm/panel/Kconfig +++ b/drivers/gpu/drm/panel/Kconfig @@ -111,6 +111,15 @@ config DRM_PANEL_LG_LG4573 Say Y here if you want to enable support for LG4573 RGB panel. To compile this driver as a module, choose M here. +config DRM_PANEL_NOVATEK_NT39016 + tristate "Novatek NT39016 RGB/SPI panel" + depends on OF && SPI + depends on BACKLIGHT_CLASS_DEVICE + select REGMAP_SPI + help + Say Y here if you want to enable support for the panels built + around the Novatek NT39016 display controller. + config DRM_PANEL_OLIMEX_LCD_OLINUXINO tristate "Olimex LCD-OLinuXino panel" depends on OF @@ -159,6 +168,15 @@ config DRM_PANEL_RASPBERRYPI_TOUCHSCREEN Pi 7" Touchscreen. To compile this driver as a module, choose M here. +config DRM_PANEL_RAYDIUM_RM67191 + tristate "Raydium RM67191 FHD 1080x1920 DSI video mode panel" + depends on OF + depends on DRM_MIPI_DSI + depends on BACKLIGHT_CLASS_DEVICE + help + Say Y here if you want to enable support for Raydium RM67191 FHD + (1080x1920) DSI panel. + config DRM_PANEL_RAYDIUM_RM68200 tristate "Raydium RM68200 720x1280 DSI video mode panel" depends on OF diff --git a/drivers/gpu/drm/panel/Makefile b/drivers/gpu/drm/panel/Makefile index fb0cb3aaa9e6..62dae45f8f74 100644 --- a/drivers/gpu/drm/panel/Makefile +++ b/drivers/gpu/drm/panel/Makefile @@ -9,11 +9,13 @@ obj-$(CONFIG_DRM_PANEL_INNOLUX_P079ZCA) += panel-innolux-p079zca.o obj-$(CONFIG_DRM_PANEL_JDI_LT070ME05000) += panel-jdi-lt070me05000.o obj-$(CONFIG_DRM_PANEL_KINGDISPLAY_KD097D04) += panel-kingdisplay-kd097d04.o obj-$(CONFIG_DRM_PANEL_LG_LG4573) += panel-lg-lg4573.o +obj-$(CONFIG_DRM_PANEL_NOVATEK_NT39016) += panel-novatek-nt39016.o obj-$(CONFIG_DRM_PANEL_OLIMEX_LCD_OLINUXINO) += panel-olimex-lcd-olinuxino.o obj-$(CONFIG_DRM_PANEL_ORISETECH_OTM8009A) += panel-orisetech-otm8009a.o obj-$(CONFIG_DRM_PANEL_OSD_OSD101T2587_53TS) += panel-osd-osd101t2587-53ts.o obj-$(CONFIG_DRM_PANEL_PANASONIC_VVX10F034N00) += panel-panasonic-vvx10f034n00.o obj-$(CONFIG_DRM_PANEL_RASPBERRYPI_TOUCHSCREEN) += panel-raspberrypi-touchscreen.o +obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM67191) += panel-raydium-rm67191.o obj-$(CONFIG_DRM_PANEL_RAYDIUM_RM68200) += panel-raydium-rm68200.o obj-$(CONFIG_DRM_PANEL_ROCKTECH_JH057N00900) += panel-rocktech-jh057n00900.o obj-$(CONFIG_DRM_PANEL_RONBO_RB070D30) += panel-ronbo-rb070d30.o diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c index 1ec57d0806a8..ad47cc95459e 100644 --- a/drivers/gpu/drm/panel/panel-lvds.c +++ b/drivers/gpu/drm/panel/panel-lvds.c @@ -147,8 +147,11 @@ static int panel_lvds_parse_dt(struct panel_lvds *lvds) int ret; ret = of_get_display_timing(np, "panel-timing", &timing); - if (ret < 0) + if (ret < 0) { + dev_err(lvds->dev, "%pOF: problems parsing panel-timing (%d)\n", + np, ret); return ret; + } videomode_from_timing(&timing, &lvds->video_mode); diff --git a/drivers/gpu/drm/panel/panel-novatek-nt39016.c b/drivers/gpu/drm/panel/panel-novatek-nt39016.c new file mode 100644 index 000000000000..2ad1063b068d --- /dev/null +++ b/drivers/gpu/drm/panel/panel-novatek-nt39016.c @@ -0,0 +1,359 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Novatek NT39016 TFT LCD panel driver + * + * Copyright (C) 2017, Maarten ter Huurne <maarten@treewalker.org> + * Copyright (C) 2019, Paul Cercueil <paul@crapouillou.net> + */ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/device.h> +#include <linux/gpio/consumer.h> +#include <linux/media-bus-format.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/regmap.h> +#include <linux/regulator/consumer.h> +#include <linux/spi/spi.h> + +#include <drm/drm_modes.h> +#include <drm/drm_panel.h> + +enum nt39016_regs { + NT39016_REG_SYSTEM, + NT39016_REG_TIMING, + NT39016_REG_OP, + NT39016_REG_DATA_IN, + NT39016_REG_SRC_TIMING_DELAY, + NT39016_REG_GATE_TIMING_DELAY, + NT39016_REG_RESERVED, + NT39016_REG_INITIAL_FUNC, + NT39016_REG_CONTRAST, + NT39016_REG_BRIGHTNESS, + NT39016_REG_HUE_SATURATION, + NT39016_REG_RB_SUBCONTRAST, + NT39016_REG_R_SUBBRIGHTNESS, + NT39016_REG_B_SUBBRIGHTNESS, + NT39016_REG_VCOMDC, + NT39016_REG_VCOMAC, + NT39016_REG_VGAM2, + NT39016_REG_VGAM34, + NT39016_REG_VGAM56, + NT39016_REG_VCOMDC_TRIM = 0x1e, + NT39016_REG_DISPLAY_MODE = 0x20, +}; + +#define NT39016_SYSTEM_RESET_N BIT(0) +#define NT39016_SYSTEM_STANDBY BIT(1) + +struct nt39016_panel_info { + struct drm_display_mode display_mode; + u16 width_mm, height_mm; + u32 bus_format, bus_flags; +}; + +struct nt39016 { + struct drm_panel drm_panel; + struct device *dev; + struct regmap *map; + struct regulator *supply; + const struct nt39016_panel_info *panel_info; + + struct gpio_desc *reset_gpio; + + struct backlight_device *backlight; +}; + +static inline struct nt39016 *to_nt39016(struct drm_panel *panel) +{ + return container_of(panel, struct nt39016, drm_panel); +} + +#define RV(REG, VAL) { .reg = (REG), .def = (VAL), .delay_us = 2 } +static const struct reg_sequence nt39016_panel_regs[] = { + RV(NT39016_REG_SYSTEM, 0x00), + RV(NT39016_REG_TIMING, 0x00), + RV(NT39016_REG_OP, 0x03), + RV(NT39016_REG_DATA_IN, 0xCC), + RV(NT39016_REG_SRC_TIMING_DELAY, 0x46), + RV(NT39016_REG_GATE_TIMING_DELAY, 0x05), + RV(NT39016_REG_RESERVED, 0x00), + RV(NT39016_REG_INITIAL_FUNC, 0x00), + RV(NT39016_REG_CONTRAST, 0x08), + RV(NT39016_REG_BRIGHTNESS, 0x40), + RV(NT39016_REG_HUE_SATURATION, 0x88), + RV(NT39016_REG_RB_SUBCONTRAST, 0x88), + RV(NT39016_REG_R_SUBBRIGHTNESS, 0x20), + RV(NT39016_REG_B_SUBBRIGHTNESS, 0x20), + RV(NT39016_REG_VCOMDC, 0x67), + RV(NT39016_REG_VCOMAC, 0xA4), + RV(NT39016_REG_VGAM2, 0x04), + RV(NT39016_REG_VGAM34, 0x24), + RV(NT39016_REG_VGAM56, 0x24), + RV(NT39016_REG_DISPLAY_MODE, 0x00), +}; + +#undef RV + +static const struct regmap_range nt39016_regmap_no_ranges[] = { + regmap_reg_range(0x13, 0x1D), + regmap_reg_range(0x1F, 0x1F), +}; + +static const struct regmap_access_table nt39016_regmap_access_table = { + .no_ranges = nt39016_regmap_no_ranges, + .n_no_ranges = ARRAY_SIZE(nt39016_regmap_no_ranges), +}; + +static const struct regmap_config nt39016_regmap_config = { + .reg_bits = 6, + .pad_bits = 2, + .val_bits = 8, + + .max_register = NT39016_REG_DISPLAY_MODE, + .wr_table = &nt39016_regmap_access_table, + .write_flag_mask = 0x02, + + .cache_type = REGCACHE_FLAT, +}; + +static int nt39016_prepare(struct drm_panel *drm_panel) +{ + struct nt39016 *panel = to_nt39016(drm_panel); + int err; + + err = regulator_enable(panel->supply); + if (err) { + dev_err(panel->dev, "Failed to enable power supply: %d", err); + return err; + } + + /* + * Reset the NT39016. + * The documentation says the reset pulse should be at least 40 us to + * pass the glitch filter, but when testing I see some resets fail and + * some succeed when using a 70 us delay, so we use 100 us instead. + */ + gpiod_set_value_cansleep(panel->reset_gpio, 1); + usleep_range(100, 1000); + gpiod_set_value_cansleep(panel->reset_gpio, 0); + udelay(2); + + /* Init all registers. */ + err = regmap_multi_reg_write(panel->map, nt39016_panel_regs, + ARRAY_SIZE(nt39016_panel_regs)); + if (err) { + dev_err(panel->dev, "Failed to init registers: %d", err); + goto err_disable_regulator; + } + + return 0; + +err_disable_regulator: + regulator_disable(panel->supply); + return err; +} + +static int nt39016_unprepare(struct drm_panel *drm_panel) +{ + struct nt39016 *panel = to_nt39016(drm_panel); + + gpiod_set_value_cansleep(panel->reset_gpio, 1); + + regulator_disable(panel->supply); + + return 0; +} + +static int nt39016_enable(struct drm_panel *drm_panel) +{ + struct nt39016 *panel = to_nt39016(drm_panel); + int ret; + + ret = regmap_write(panel->map, NT39016_REG_SYSTEM, + NT39016_SYSTEM_RESET_N | NT39016_SYSTEM_STANDBY); + if (ret) { + dev_err(panel->dev, "Unable to enable panel: %d", ret); + return ret; + } + + if (panel->backlight) { + /* Wait for the picture to be ready before enabling backlight */ + msleep(150); + + ret = backlight_enable(panel->backlight); + } + + return ret; +} + +static int nt39016_disable(struct drm_panel *drm_panel) +{ + struct nt39016 *panel = to_nt39016(drm_panel); + int err; + + backlight_disable(panel->backlight); + + err = regmap_write(panel->map, NT39016_REG_SYSTEM, + NT39016_SYSTEM_RESET_N); + if (err) { + dev_err(panel->dev, "Unable to disable panel: %d", err); + return err; + } + + return 0; +} + +static int nt39016_get_modes(struct drm_panel *drm_panel) +{ + struct nt39016 *panel = to_nt39016(drm_panel); + const struct nt39016_panel_info *panel_info = panel->panel_info; + struct drm_connector *connector = drm_panel->connector; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(drm_panel->drm, &panel_info->display_mode); + if (!mode) + return -ENOMEM; + + drm_mode_set_name(mode); + + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + connector->display_info.bpc = 8; + connector->display_info.width_mm = panel_info->width_mm; + connector->display_info.height_mm = panel_info->height_mm; + + drm_display_info_set_bus_formats(&connector->display_info, + &panel_info->bus_format, 1); + connector->display_info.bus_flags = panel_info->bus_flags; + + return 1; +} + +static const struct drm_panel_funcs nt39016_funcs = { + .prepare = nt39016_prepare, + .unprepare = nt39016_unprepare, + .enable = nt39016_enable, + .disable = nt39016_disable, + .get_modes = nt39016_get_modes, +}; + +static int nt39016_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct nt39016 *panel; + int err; + + panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); + if (!panel) + return -ENOMEM; + + panel->dev = dev; + spi_set_drvdata(spi, panel); + + panel->panel_info = of_device_get_match_data(dev); + if (!panel->panel_info) + return -EINVAL; + + panel->supply = devm_regulator_get(dev, "power"); + if (IS_ERR(panel->supply)) { + dev_err(dev, "Failed to get power supply"); + return PTR_ERR(panel->supply); + } + + panel->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(panel->reset_gpio)) { + dev_err(dev, "Failed to get reset GPIO"); + return PTR_ERR(panel->reset_gpio); + } + + spi->bits_per_word = 8; + spi->mode = SPI_MODE_3 | SPI_3WIRE; + err = spi_setup(spi); + if (err) { + dev_err(dev, "Failed to setup SPI"); + return err; + } + + panel->map = devm_regmap_init_spi(spi, &nt39016_regmap_config); + if (IS_ERR(panel->map)) { + dev_err(dev, "Failed to init regmap"); + return PTR_ERR(panel->map); + } + + panel->backlight = devm_of_find_backlight(dev); + if (IS_ERR(panel->backlight)) { + err = PTR_ERR(panel->backlight); + if (err != -EPROBE_DEFER) + dev_err(dev, "Failed to get backlight handle"); + return err; + } + + drm_panel_init(&panel->drm_panel); + panel->drm_panel.dev = dev; + panel->drm_panel.funcs = &nt39016_funcs; + + err = drm_panel_add(&panel->drm_panel); + if (err < 0) { + dev_err(dev, "Failed to register panel"); + return err; + } + + return 0; +} + +static int nt39016_remove(struct spi_device *spi) +{ + struct nt39016 *panel = spi_get_drvdata(spi); + + drm_panel_remove(&panel->drm_panel); + + nt39016_disable(&panel->drm_panel); + nt39016_unprepare(&panel->drm_panel); + + return 0; +} + +static const struct nt39016_panel_info kd035g6_info = { + .display_mode = { + .clock = 6000, + .hdisplay = 320, + .hsync_start = 320 + 10, + .hsync_end = 320 + 10 + 50, + .htotal = 320 + 10 + 50 + 20, + .vdisplay = 240, + .vsync_start = 240 + 5, + .vsync_end = 240 + 5 + 1, + .vtotal = 240 + 5 + 1 + 4, + .vrefresh = 60, + .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, + }, + .width_mm = 71, + .height_mm = 53, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_PIXDATA_NEGEDGE, +}; + +static const struct of_device_id nt39016_of_match[] = { + { .compatible = "kingdisplay,kd035g6-54nt", .data = &kd035g6_info }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, nt39016_of_match); + +static struct spi_driver nt39016_driver = { + .driver = { + .name = "nt39016", + .of_match_table = nt39016_of_match, + }, + .probe = nt39016_probe, + .remove = nt39016_remove, +}; + +module_spi_driver(nt39016_driver); + +MODULE_AUTHOR("Maarten ter Huurne <maarten@treewalker.org>"); +MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c index 28c0620dfe0f..b5b14aa059ea 100644 --- a/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c +++ b/drivers/gpu/drm/panel/panel-raspberrypi-touchscreen.c @@ -399,7 +399,13 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c, /* Look up the DSI host. It needs to probe before we do. */ endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); + if (!endpoint) + return -ENODEV; + dsi_host_node = of_graph_get_remote_port_parent(endpoint); + if (!dsi_host_node) + goto error; + host = of_find_mipi_dsi_host_by_node(dsi_host_node); of_node_put(dsi_host_node); if (!host) { @@ -408,6 +414,9 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c, } info.node = of_graph_get_remote_port(endpoint); + if (!info.node) + goto error; + of_node_put(endpoint); ts->dsi = mipi_dsi_device_register_full(host, &info); @@ -428,6 +437,10 @@ static int rpi_touchscreen_probe(struct i2c_client *i2c, return ret; return 0; + +error: + of_node_put(endpoint); + return -ENODEV; } static int rpi_touchscreen_remove(struct i2c_client *i2c) diff --git a/drivers/gpu/drm/panel/panel-raydium-rm67191.c b/drivers/gpu/drm/panel/panel-raydium-rm67191.c new file mode 100644 index 000000000000..6a5d37006103 --- /dev/null +++ b/drivers/gpu/drm/panel/panel-raydium-rm67191.c @@ -0,0 +1,668 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Raydium RM67191 MIPI-DSI panel driver + * + * Copyright 2019 NXP + */ + +#include <linux/backlight.h> +#include <linux/delay.h> +#include <linux/gpio/consumer.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/regulator/consumer.h> + +#include <video/mipi_display.h> +#include <video/of_videomode.h> +#include <video/videomode.h> + +#include <drm/drm_crtc.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> + +/* Panel specific color-format bits */ +#define COL_FMT_16BPP 0x55 +#define COL_FMT_18BPP 0x66 +#define COL_FMT_24BPP 0x77 + +/* Write Manufacture Command Set Control */ +#define WRMAUCCTR 0xFE + +/* Manufacturer Command Set pages (CMD2) */ +struct cmd_set_entry { + u8 cmd; + u8 param; +}; + +/* + * There is no description in the Reference Manual about these commands. + * We received them from vendor, so just use them as is. + */ +static const struct cmd_set_entry manufacturer_cmd_set[] = { + {0xFE, 0x0B}, + {0x28, 0x40}, + {0x29, 0x4F}, + {0xFE, 0x0E}, + {0x4B, 0x00}, + {0x4C, 0x0F}, + {0x4D, 0x20}, + {0x4E, 0x40}, + {0x4F, 0x60}, + {0x50, 0xA0}, + {0x51, 0xC0}, + {0x52, 0xE0}, + {0x53, 0xFF}, + {0xFE, 0x0D}, + {0x18, 0x08}, + {0x42, 0x00}, + {0x08, 0x41}, + {0x46, 0x02}, + {0x72, 0x09}, + {0xFE, 0x0A}, + {0x24, 0x17}, + {0x04, 0x07}, + {0x1A, 0x0C}, + {0x0F, 0x44}, + {0xFE, 0x04}, + {0x00, 0x0C}, + {0x05, 0x08}, + {0x06, 0x08}, + {0x08, 0x08}, + {0x09, 0x08}, + {0x0A, 0xE6}, + {0x0B, 0x8C}, + {0x1A, 0x12}, + {0x1E, 0xE0}, + {0x29, 0x93}, + {0x2A, 0x93}, + {0x2F, 0x02}, + {0x31, 0x02}, + {0x33, 0x05}, + {0x37, 0x2D}, + {0x38, 0x2D}, + {0x3A, 0x1E}, + {0x3B, 0x1E}, + {0x3D, 0x27}, + {0x3F, 0x80}, + {0x40, 0x40}, + {0x41, 0xE0}, + {0x4F, 0x2F}, + {0x50, 0x1E}, + {0xFE, 0x06}, + {0x00, 0xCC}, + {0x05, 0x05}, + {0x07, 0xA2}, + {0x08, 0xCC}, + {0x0D, 0x03}, + {0x0F, 0xA2}, + {0x32, 0xCC}, + {0x37, 0x05}, + {0x39, 0x83}, + {0x3A, 0xCC}, + {0x41, 0x04}, + {0x43, 0x83}, + {0x44, 0xCC}, + {0x49, 0x05}, + {0x4B, 0xA2}, + {0x4C, 0xCC}, + {0x51, 0x03}, + {0x53, 0xA2}, + {0x75, 0xCC}, + {0x7A, 0x03}, + {0x7C, 0x83}, + {0x7D, 0xCC}, + {0x82, 0x02}, + {0x84, 0x83}, + {0x85, 0xEC}, + {0x86, 0x0F}, + {0x87, 0xFF}, + {0x88, 0x00}, + {0x8A, 0x02}, + {0x8C, 0xA2}, + {0x8D, 0xEA}, + {0x8E, 0x01}, + {0x8F, 0xE8}, + {0xFE, 0x06}, + {0x90, 0x0A}, + {0x92, 0x06}, + {0x93, 0xA0}, + {0x94, 0xA8}, + {0x95, 0xEC}, + {0x96, 0x0F}, + {0x97, 0xFF}, + {0x98, 0x00}, + {0x9A, 0x02}, + {0x9C, 0xA2}, + {0xAC, 0x04}, + {0xFE, 0x06}, + {0xB1, 0x12}, + {0xB2, 0x17}, + {0xB3, 0x17}, + {0xB4, 0x17}, + {0xB5, 0x17}, + {0xB6, 0x11}, + {0xB7, 0x08}, + {0xB8, 0x09}, + {0xB9, 0x06}, + {0xBA, 0x07}, + {0xBB, 0x17}, + {0xBC, 0x17}, + {0xBD, 0x17}, + {0xBE, 0x17}, + {0xBF, 0x17}, + {0xC0, 0x17}, + {0xC1, 0x17}, + {0xC2, 0x17}, + {0xC3, 0x17}, + {0xC4, 0x0F}, + {0xC5, 0x0E}, + {0xC6, 0x00}, + {0xC7, 0x01}, + {0xC8, 0x10}, + {0xFE, 0x06}, + {0x95, 0xEC}, + {0x8D, 0xEE}, + {0x44, 0xEC}, + {0x4C, 0xEC}, + {0x32, 0xEC}, + {0x3A, 0xEC}, + {0x7D, 0xEC}, + {0x75, 0xEC}, + {0x00, 0xEC}, + {0x08, 0xEC}, + {0x85, 0xEC}, + {0xA6, 0x21}, + {0xA7, 0x05}, + {0xA9, 0x06}, + {0x82, 0x06}, + {0x41, 0x06}, + {0x7A, 0x07}, + {0x37, 0x07}, + {0x05, 0x06}, + {0x49, 0x06}, + {0x0D, 0x04}, + {0x51, 0x04}, +}; + +static const u32 rad_bus_formats[] = { + MEDIA_BUS_FMT_RGB888_1X24, + MEDIA_BUS_FMT_RGB666_1X18, + MEDIA_BUS_FMT_RGB565_1X16, +}; + +static const u32 rad_bus_flags = DRM_BUS_FLAG_DE_LOW | + DRM_BUS_FLAG_PIXDATA_NEGEDGE; + +struct rad_panel { + struct drm_panel panel; + struct mipi_dsi_device *dsi; + + struct gpio_desc *reset; + struct backlight_device *backlight; + + struct regulator_bulk_data *supplies; + unsigned int num_supplies; + + bool prepared; + bool enabled; +}; + +static const struct drm_display_mode default_mode = { + .clock = 132000, + .hdisplay = 1080, + .hsync_start = 1080 + 20, + .hsync_end = 1080 + 20 + 2, + .htotal = 1080 + 20 + 2 + 34, + .vdisplay = 1920, + .vsync_start = 1920 + 10, + .vsync_end = 1920 + 10 + 2, + .vtotal = 1920 + 10 + 2 + 4, + .vrefresh = 60, + .width_mm = 68, + .height_mm = 121, + .flags = DRM_MODE_FLAG_NHSYNC | + DRM_MODE_FLAG_NVSYNC, +}; + +static inline struct rad_panel *to_rad_panel(struct drm_panel *panel) +{ + return container_of(panel, struct rad_panel, panel); +} + +static int rad_panel_push_cmd_list(struct mipi_dsi_device *dsi) +{ + size_t i; + size_t count = ARRAY_SIZE(manufacturer_cmd_set); + int ret = 0; + + for (i = 0; i < count; i++) { + const struct cmd_set_entry *entry = &manufacturer_cmd_set[i]; + u8 buffer[2] = { entry->cmd, entry->param }; + + ret = mipi_dsi_generic_write(dsi, &buffer, sizeof(buffer)); + if (ret < 0) + return ret; + } + + return ret; +}; + +static int color_format_from_dsi_format(enum mipi_dsi_pixel_format format) +{ + switch (format) { + case MIPI_DSI_FMT_RGB565: + return COL_FMT_16BPP; + case MIPI_DSI_FMT_RGB666: + case MIPI_DSI_FMT_RGB666_PACKED: + return COL_FMT_18BPP; + case MIPI_DSI_FMT_RGB888: + return COL_FMT_24BPP; + default: + return COL_FMT_24BPP; /* for backward compatibility */ + } +}; + +static int rad_panel_prepare(struct drm_panel *panel) +{ + struct rad_panel *rad = to_rad_panel(panel); + int ret; + + if (rad->prepared) + return 0; + + ret = regulator_bulk_enable(rad->num_supplies, rad->supplies); + if (ret) + return ret; + + if (rad->reset) { + gpiod_set_value_cansleep(rad->reset, 1); + usleep_range(3000, 5000); + gpiod_set_value_cansleep(rad->reset, 0); + usleep_range(18000, 20000); + } + + rad->prepared = true; + + return 0; +} + +static int rad_panel_unprepare(struct drm_panel *panel) +{ + struct rad_panel *rad = to_rad_panel(panel); + int ret; + + if (!rad->prepared) + return 0; + + /* + * Right after asserting the reset, we need to release it, so that the + * touch driver can have an active connection with the touch controller + * even after the display is turned off. + */ + if (rad->reset) { + gpiod_set_value_cansleep(rad->reset, 1); + usleep_range(15000, 17000); + gpiod_set_value_cansleep(rad->reset, 0); + } + + ret = regulator_bulk_disable(rad->num_supplies, rad->supplies); + if (ret) + return ret; + + rad->prepared = false; + + return 0; +} + +static int rad_panel_enable(struct drm_panel *panel) +{ + struct rad_panel *rad = to_rad_panel(panel); + struct mipi_dsi_device *dsi = rad->dsi; + struct device *dev = &dsi->dev; + int color_format = color_format_from_dsi_format(dsi->format); + int ret; + + if (rad->enabled) + return 0; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + ret = rad_panel_push_cmd_list(dsi); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to send MCS (%d)\n", ret); + goto fail; + } + + /* Select User Command Set table (CMD1) */ + ret = mipi_dsi_generic_write(dsi, (u8[]){ WRMAUCCTR, 0x00 }, 2); + if (ret < 0) + goto fail; + + /* Software reset */ + ret = mipi_dsi_dcs_soft_reset(dsi); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to do Software Reset (%d)\n", ret); + goto fail; + } + + usleep_range(15000, 17000); + + /* Set DSI mode */ + ret = mipi_dsi_generic_write(dsi, (u8[]){ 0xC2, 0x0B }, 2); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to set DSI mode (%d)\n", ret); + goto fail; + } + /* Set tear ON */ + ret = mipi_dsi_dcs_set_tear_on(dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to set tear ON (%d)\n", ret); + goto fail; + } + /* Set tear scanline */ + ret = mipi_dsi_dcs_set_tear_scanline(dsi, 0x380); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to set tear scanline (%d)\n", ret); + goto fail; + } + /* Set pixel format */ + ret = mipi_dsi_dcs_set_pixel_format(dsi, color_format); + DRM_DEV_DEBUG_DRIVER(dev, "Interface color format set to 0x%x\n", + color_format); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to set pixel format (%d)\n", ret); + goto fail; + } + /* Exit sleep mode */ + ret = mipi_dsi_dcs_exit_sleep_mode(dsi); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to exit sleep mode (%d)\n", ret); + goto fail; + } + + usleep_range(5000, 7000); + + ret = mipi_dsi_dcs_set_display_on(dsi); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to set display ON (%d)\n", ret); + goto fail; + } + + backlight_enable(rad->backlight); + + rad->enabled = true; + + return 0; + +fail: + gpiod_set_value_cansleep(rad->reset, 1); + + return ret; +} + +static int rad_panel_disable(struct drm_panel *panel) +{ + struct rad_panel *rad = to_rad_panel(panel); + struct mipi_dsi_device *dsi = rad->dsi; + struct device *dev = &dsi->dev; + int ret; + + if (!rad->enabled) + return 0; + + dsi->mode_flags |= MIPI_DSI_MODE_LPM; + + backlight_disable(rad->backlight); + + usleep_range(10000, 12000); + + ret = mipi_dsi_dcs_set_display_off(dsi); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to set display OFF (%d)\n", ret); + return ret; + } + + usleep_range(5000, 10000); + + ret = mipi_dsi_dcs_enter_sleep_mode(dsi); + if (ret < 0) { + DRM_DEV_ERROR(dev, "Failed to enter sleep mode (%d)\n", ret); + return ret; + } + + rad->enabled = false; + + return 0; +} + +static int rad_panel_get_modes(struct drm_panel *panel) +{ + struct drm_connector *connector = panel->connector; + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(panel->drm, &default_mode); + if (!mode) { + DRM_DEV_ERROR(panel->dev, "failed to add mode %ux%ux@%u\n", + default_mode.hdisplay, default_mode.vdisplay, + default_mode.vrefresh); + return -ENOMEM; + } + + drm_mode_set_name(mode); + mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(panel->connector, mode); + + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + connector->display_info.bus_flags = rad_bus_flags; + + drm_display_info_set_bus_formats(&connector->display_info, + rad_bus_formats, + ARRAY_SIZE(rad_bus_formats)); + return 1; +} + +static int rad_bl_get_brightness(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + struct rad_panel *rad = mipi_dsi_get_drvdata(dsi); + u16 brightness; + int ret; + + if (!rad->prepared) + return 0; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_get_display_brightness(dsi, &brightness); + if (ret < 0) + return ret; + + bl->props.brightness = brightness; + + return brightness & 0xff; +} + +static int rad_bl_update_status(struct backlight_device *bl) +{ + struct mipi_dsi_device *dsi = bl_get_data(bl); + struct rad_panel *rad = mipi_dsi_get_drvdata(dsi); + int ret = 0; + + if (!rad->prepared) + return 0; + + dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; + + ret = mipi_dsi_dcs_set_display_brightness(dsi, bl->props.brightness); + if (ret < 0) + return ret; + + return 0; +} + +static const struct backlight_ops rad_bl_ops = { + .update_status = rad_bl_update_status, + .get_brightness = rad_bl_get_brightness, +}; + +static const struct drm_panel_funcs rad_panel_funcs = { + .prepare = rad_panel_prepare, + .unprepare = rad_panel_unprepare, + .enable = rad_panel_enable, + .disable = rad_panel_disable, + .get_modes = rad_panel_get_modes, +}; + +static const char * const rad_supply_names[] = { + "v3p3", + "v1p8", +}; + +static int rad_init_regulators(struct rad_panel *rad) +{ + struct device *dev = &rad->dsi->dev; + int i; + + rad->num_supplies = ARRAY_SIZE(rad_supply_names); + rad->supplies = devm_kcalloc(dev, rad->num_supplies, + sizeof(*rad->supplies), GFP_KERNEL); + if (!rad->supplies) + return -ENOMEM; + + for (i = 0; i < rad->num_supplies; i++) + rad->supplies[i].supply = rad_supply_names[i]; + + return devm_regulator_bulk_get(dev, rad->num_supplies, rad->supplies); +}; + +static int rad_panel_probe(struct mipi_dsi_device *dsi) +{ + struct device *dev = &dsi->dev; + struct device_node *np = dev->of_node; + struct rad_panel *panel; + struct backlight_properties bl_props; + int ret; + u32 video_mode; + + panel = devm_kzalloc(&dsi->dev, sizeof(*panel), GFP_KERNEL); + if (!panel) + return -ENOMEM; + + mipi_dsi_set_drvdata(dsi, panel); + + panel->dsi = dsi; + + dsi->format = MIPI_DSI_FMT_RGB888; + dsi->mode_flags = MIPI_DSI_MODE_VIDEO_HSE | MIPI_DSI_MODE_VIDEO | + MIPI_DSI_CLOCK_NON_CONTINUOUS; + + ret = of_property_read_u32(np, "video-mode", &video_mode); + if (!ret) { + switch (video_mode) { + case 0: + /* burst mode */ + dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_BURST; + break; + case 1: + /* non-burst mode with sync event */ + break; + case 2: + /* non-burst mode with sync pulse */ + dsi->mode_flags |= MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + break; + default: + dev_warn(dev, "invalid video mode %d\n", video_mode); + break; + } + } + + ret = of_property_read_u32(np, "dsi-lanes", &dsi->lanes); + if (ret) { + dev_err(dev, "Failed to get dsi-lanes property (%d)\n", ret); + return ret; + } + + panel->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW); + if (IS_ERR(panel->reset)) + return PTR_ERR(panel->reset); + + memset(&bl_props, 0, sizeof(bl_props)); + bl_props.type = BACKLIGHT_RAW; + bl_props.brightness = 255; + bl_props.max_brightness = 255; + + panel->backlight = devm_backlight_device_register(dev, dev_name(dev), + dev, dsi, &rad_bl_ops, + &bl_props); + if (IS_ERR(panel->backlight)) { + ret = PTR_ERR(panel->backlight); + dev_err(dev, "Failed to register backlight (%d)\n", ret); + return ret; + } + + ret = rad_init_regulators(panel); + if (ret) + return ret; + + drm_panel_init(&panel->panel); + panel->panel.funcs = &rad_panel_funcs; + panel->panel.dev = dev; + dev_set_drvdata(dev, panel); + + ret = drm_panel_add(&panel->panel); + if (ret) + return ret; + + ret = mipi_dsi_attach(dsi); + if (ret) + drm_panel_remove(&panel->panel); + + return ret; +} + +static int rad_panel_remove(struct mipi_dsi_device *dsi) +{ + struct rad_panel *rad = mipi_dsi_get_drvdata(dsi); + struct device *dev = &dsi->dev; + int ret; + + ret = mipi_dsi_detach(dsi); + if (ret) + DRM_DEV_ERROR(dev, "Failed to detach from host (%d)\n", + ret); + + drm_panel_remove(&rad->panel); + + return 0; +} + +static void rad_panel_shutdown(struct mipi_dsi_device *dsi) +{ + struct rad_panel *rad = mipi_dsi_get_drvdata(dsi); + + rad_panel_disable(&rad->panel); + rad_panel_unprepare(&rad->panel); +} + +static const struct of_device_id rad_of_match[] = { + { .compatible = "raydium,rm67191", }, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, rad_of_match); + +static struct mipi_dsi_driver rad_panel_driver = { + .driver = { + .name = "panel-raydium-rm67191", + .of_match_table = rad_of_match, + }, + .probe = rad_panel_probe, + .remove = rad_panel_remove, + .shutdown = rad_panel_shutdown, +}; +module_mipi_dsi_driver(rad_panel_driver); + +MODULE_AUTHOR("Robert Chiras <robert.chiras@nxp.com>"); +MODULE_DESCRIPTION("DRM Driver for Raydium RM67191 MIPI DSI panel"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c b/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c index 6dcb692c4701..b9109922397f 100644 --- a/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c +++ b/drivers/gpu/drm/panel/panel-rocktech-jh057n00900.c @@ -15,6 +15,7 @@ #include <linux/gpio/consumer.h> #include <linux/media-bus-format.h> #include <linux/module.h> +#include <linux/regulator/consumer.h> #include <video/display_timing.h> #include <video/mipi_display.h> @@ -33,6 +34,7 @@ #define ST7703_CMD_SETEXTC 0xB9 #define ST7703_CMD_SETMIPI 0xBA #define ST7703_CMD_SETVDC 0xBC +#define ST7703_CMD_UNKNOWN0 0xBF #define ST7703_CMD_SETSCR 0xC0 #define ST7703_CMD_SETPOWER 0xC1 #define ST7703_CMD_SETPANEL 0xCC @@ -46,6 +48,8 @@ struct jh057n { struct drm_panel panel; struct gpio_desc *reset_gpio; struct backlight_device *backlight; + struct regulator *vcc; + struct regulator *iovcc; bool prepared; struct dentry *debugfs; @@ -94,7 +98,7 @@ static int jh057n_init_sequence(struct jh057n *ctx) msleep(20); dsi_generic_write_seq(dsi, ST7703_CMD_SETVCOM, 0x3F, 0x3F); - dsi_generic_write_seq(dsi, 0xBF, 0x02, 0x11, 0x00); + dsi_generic_write_seq(dsi, ST7703_CMD_UNKNOWN0, 0x02, 0x11, 0x00); dsi_generic_write_seq(dsi, ST7703_CMD_SETGIP1, 0x82, 0x10, 0x06, 0x05, 0x9E, 0x0A, 0xA5, 0x12, 0x31, 0x23, 0x37, 0x83, 0x04, 0xBC, 0x27, 0x38, @@ -123,7 +127,7 @@ static int jh057n_init_sequence(struct jh057n *ctx) ret = mipi_dsi_dcs_exit_sleep_mode(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "Failed to exit sleep mode\n"); + DRM_DEV_ERROR(dev, "Failed to exit sleep mode: %d\n", ret); return ret; } /* Panel is operational 120 msec after reset */ @@ -139,6 +143,14 @@ static int jh057n_init_sequence(struct jh057n *ctx) static int jh057n_enable(struct drm_panel *panel) { struct jh057n *ctx = panel_to_jh057n(panel); + int ret; + + ret = jh057n_init_sequence(ctx); + if (ret < 0) { + DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", + ret); + return ret; + } return backlight_enable(ctx->backlight); } @@ -146,19 +158,21 @@ static int jh057n_enable(struct drm_panel *panel) static int jh057n_disable(struct drm_panel *panel) { struct jh057n *ctx = panel_to_jh057n(panel); + struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); - return backlight_disable(ctx->backlight); + backlight_disable(ctx->backlight); + return mipi_dsi_dcs_set_display_off(dsi); } static int jh057n_unprepare(struct drm_panel *panel) { struct jh057n *ctx = panel_to_jh057n(panel); - struct mipi_dsi_device *dsi = to_mipi_dsi_device(ctx->dev); if (!ctx->prepared) return 0; - mipi_dsi_dcs_set_display_off(dsi); + regulator_disable(ctx->iovcc); + regulator_disable(ctx->vcc); ctx->prepared = false; return 0; @@ -173,21 +187,31 @@ static int jh057n_prepare(struct drm_panel *panel) return 0; DRM_DEV_DEBUG_DRIVER(ctx->dev, "Resetting the panel\n"); + ret = regulator_enable(ctx->vcc); + if (ret < 0) { + DRM_DEV_ERROR(ctx->dev, + "Failed to enable vcc supply: %d\n", ret); + return ret; + } + ret = regulator_enable(ctx->iovcc); + if (ret < 0) { + DRM_DEV_ERROR(ctx->dev, + "Failed to enable iovcc supply: %d\n", ret); + goto disable_vcc; + } + gpiod_set_value_cansleep(ctx->reset_gpio, 1); usleep_range(20, 40); gpiod_set_value_cansleep(ctx->reset_gpio, 0); msleep(20); - ret = jh057n_init_sequence(ctx); - if (ret < 0) { - DRM_DEV_ERROR(ctx->dev, "Panel init sequence failed: %d\n", - ret); - return ret; - } - ctx->prepared = true; return 0; + +disable_vcc: + regulator_disable(ctx->vcc); + return ret; } static const struct drm_display_mode default_mode = { @@ -300,6 +324,25 @@ static int jh057n_probe(struct mipi_dsi_device *dsi) if (IS_ERR(ctx->backlight)) return PTR_ERR(ctx->backlight); + ctx->vcc = devm_regulator_get(dev, "vcc"); + if (IS_ERR(ctx->vcc)) { + ret = PTR_ERR(ctx->vcc); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "Failed to request vcc regulator: %d\n", + ret); + return ret; + } + ctx->iovcc = devm_regulator_get(dev, "iovcc"); + if (IS_ERR(ctx->iovcc)) { + ret = PTR_ERR(ctx->iovcc); + if (ret != -EPROBE_DEFER) + DRM_DEV_ERROR(dev, + "Failed to request iovcc regulator: %d\n", + ret); + return ret; + } + drm_panel_init(&ctx->panel); ctx->panel.dev = dev; ctx->panel.funcs = &jh057n_drm_funcs; @@ -308,7 +351,9 @@ static int jh057n_probe(struct mipi_dsi_device *dsi) ret = mipi_dsi_attach(dsi); if (ret < 0) { - DRM_DEV_ERROR(dev, "mipi_dsi_attach failed. Is host ready?\n"); + DRM_DEV_ERROR(dev, + "mipi_dsi_attach failed (%d). Is host ready?\n", + ret); drm_panel_remove(&ctx->panel); return ret; } @@ -327,12 +372,12 @@ static void jh057n_shutdown(struct mipi_dsi_device *dsi) struct jh057n *ctx = mipi_dsi_get_drvdata(dsi); int ret; - ret = jh057n_unprepare(&ctx->panel); + ret = drm_panel_unprepare(&ctx->panel); if (ret < 0) DRM_DEV_ERROR(&dsi->dev, "Failed to unprepare panel: %d\n", ret); - ret = jh057n_disable(&ctx->panel); + ret = drm_panel_disable(&ctx->panel); if (ret < 0) DRM_DEV_ERROR(&dsi->dev, "Failed to disable panel: %d\n", ret); diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index 5a93c4edf1e4..bff7578f84dd 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c @@ -30,6 +30,7 @@ #include <linux/regulator/consumer.h> #include <video/display_timing.h> +#include <video/of_display_timing.h> #include <video/videomode.h> #include <drm/drm_crtc.h> @@ -37,6 +38,22 @@ #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> +/** + * @modes: Pointer to array of fixed modes appropriate for this panel. If + * only one mode then this can just be the address of this the mode. + * NOTE: cannot be used with "timings" and also if this is specified + * then you cannot override the mode in the device tree. + * @num_modes: Number of elements in modes array. + * @timings: Pointer to array of display timings. NOTE: cannot be used with + * "modes" and also these will be used to validate a device tree + * override if one is present. + * @num_timings: Number of elements in timings array. + * @bpc: Bits per color. + * @size: Structure containing the physical size of this panel. + * @delay: Structure containing various delay values for this panel. + * @bus_format: See MEDIA_BUS_FMT_... defines. + * @bus_flags: See DRM_BUS_FLAG_... defines. + */ struct panel_desc { const struct drm_display_mode *modes; unsigned int num_modes; @@ -92,6 +109,8 @@ struct panel_simple { struct i2c_adapter *ddc; struct gpio_desc *enable_gpio; + + struct drm_display_mode override_mode; }; static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) @@ -99,16 +118,13 @@ static inline struct panel_simple *to_panel_simple(struct drm_panel *panel) return container_of(panel, struct panel_simple, base); } -static int panel_simple_get_fixed_modes(struct panel_simple *panel) +static unsigned int panel_simple_get_timings_modes(struct panel_simple *panel) { struct drm_connector *connector = panel->base.connector; struct drm_device *drm = panel->base.drm; struct drm_display_mode *mode; unsigned int i, num = 0; - if (!panel->desc) - return 0; - for (i = 0; i < panel->desc->num_timings; i++) { const struct display_timing *dt = &panel->desc->timings[i]; struct videomode vm; @@ -132,6 +148,16 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel) num++; } + return num; +} + +static unsigned int panel_simple_get_display_modes(struct panel_simple *panel) +{ + struct drm_connector *connector = panel->base.connector; + struct drm_device *drm = panel->base.drm; + struct drm_display_mode *mode; + unsigned int i, num = 0; + for (i = 0; i < panel->desc->num_modes; i++) { const struct drm_display_mode *m = &panel->desc->modes[i]; @@ -153,6 +179,44 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel) num++; } + return num; +} + +static int panel_simple_get_non_edid_modes(struct panel_simple *panel) +{ + struct drm_connector *connector = panel->base.connector; + struct drm_device *drm = panel->base.drm; + struct drm_display_mode *mode; + bool has_override = panel->override_mode.type; + unsigned int num = 0; + + if (!panel->desc) + return 0; + + if (has_override) { + mode = drm_mode_duplicate(drm, &panel->override_mode); + if (mode) { + drm_mode_probed_add(connector, mode); + num = 1; + } else { + dev_err(drm->dev, "failed to add override mode\n"); + } + } + + /* Only add timings if override was not there or failed to validate */ + if (num == 0 && panel->desc->num_timings) + num = panel_simple_get_timings_modes(panel); + + /* + * Only add fixed modes if timings/override added no mode. + * + * We should only ever have either the display timings specified + * or a fixed mode. Anything else is rather bogus. + */ + WARN_ON(panel->desc->num_timings && panel->desc->num_modes); + if (num == 0) + num = panel_simple_get_display_modes(panel); + connector->display_info.bpc = panel->desc->bpc; connector->display_info.width_mm = panel->desc->size.width; connector->display_info.height_mm = panel->desc->size.height; @@ -269,7 +333,7 @@ static int panel_simple_get_modes(struct drm_panel *panel) } /* add hard-coded panel modes */ - num += panel_simple_get_fixed_modes(p); + num += panel_simple_get_non_edid_modes(p); return num; } @@ -300,10 +364,58 @@ static const struct drm_panel_funcs panel_simple_funcs = { .get_timings = panel_simple_get_timings, }; +#define PANEL_SIMPLE_BOUNDS_CHECK(to_check, bounds, field) \ + (to_check->field.typ >= bounds->field.min && \ + to_check->field.typ <= bounds->field.max) +static void panel_simple_parse_panel_timing_node(struct device *dev, + struct panel_simple *panel, + const struct display_timing *ot) +{ + const struct panel_desc *desc = panel->desc; + struct videomode vm; + unsigned int i; + + if (WARN_ON(desc->num_modes)) { + dev_err(dev, "Reject override mode: panel has a fixed mode\n"); + return; + } + if (WARN_ON(!desc->num_timings)) { + dev_err(dev, "Reject override mode: no timings specified\n"); + return; + } + + for (i = 0; i < panel->desc->num_timings; i++) { + const struct display_timing *dt = &panel->desc->timings[i]; + + if (!PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hactive) || + !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hfront_porch) || + !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hback_porch) || + !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, hsync_len) || + !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vactive) || + !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vfront_porch) || + !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vback_porch) || + !PANEL_SIMPLE_BOUNDS_CHECK(ot, dt, vsync_len)) + continue; + + if (ot->flags != dt->flags) + continue; + + videomode_from_timing(ot, &vm); + drm_display_mode_from_videomode(&vm, &panel->override_mode); + panel->override_mode.type |= DRM_MODE_TYPE_DRIVER | + DRM_MODE_TYPE_PREFERRED; + break; + } + + if (WARN_ON(!panel->override_mode.type)) + dev_err(dev, "Reject override mode: No display_timing found\n"); +} + static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) { struct device_node *backlight, *ddc; struct panel_simple *panel; + struct display_timing dt; int err; panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL); @@ -349,6 +461,9 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) } } + if (!of_get_display_timing(dev->of_node, "panel-timing", &dt)) + panel_simple_parse_panel_timing_node(dev, panel, &dt); + drm_panel_init(&panel->base); panel->base.dev = dev; panel->base.funcs = &panel_simple_funcs; @@ -496,22 +611,21 @@ static const struct panel_desc auo_b101aw03 = { }, }; -static const struct drm_display_mode auo_b101ean01_mode = { - .clock = 72500, - .hdisplay = 1280, - .hsync_start = 1280 + 119, - .hsync_end = 1280 + 119 + 32, - .htotal = 1280 + 119 + 32 + 21, - .vdisplay = 800, - .vsync_start = 800 + 4, - .vsync_end = 800 + 4 + 20, - .vtotal = 800 + 4 + 20 + 8, - .vrefresh = 60, +static const struct display_timing auo_b101ean01_timing = { + .pixelclock = { 65300000, 72500000, 75000000 }, + .hactive = { 1280, 1280, 1280 }, + .hfront_porch = { 18, 119, 119 }, + .hback_porch = { 21, 21, 21 }, + .hsync_len = { 32, 32, 32 }, + .vactive = { 800, 800, 800 }, + .vfront_porch = { 4, 4, 4 }, + .vback_porch = { 8, 8, 8 }, + .vsync_len = { 18, 20, 20 }, }; static const struct panel_desc auo_b101ean01 = { - .modes = &auo_b101ean01_mode, - .num_modes = 1, + .timings = &auo_b101ean01_timing, + .num_timings = 1, .bpc = 6, .size = { .width = 217, @@ -724,9 +838,9 @@ static const struct panel_desc auo_g133han01 = { static const struct display_timing auo_g185han01_timings = { .pixelclock = { 120000000, 144000000, 175000000 }, .hactive = { 1920, 1920, 1920 }, - .hfront_porch = { 18, 60, 74 }, - .hback_porch = { 12, 44, 54 }, - .hsync_len = { 10, 24, 32 }, + .hfront_porch = { 36, 120, 148 }, + .hback_porch = { 24, 88, 108 }, + .hsync_len = { 20, 48, 64 }, .vactive = { 1080, 1080, 1080 }, .vfront_porch = { 6, 10, 40 }, .vback_porch = { 2, 5, 20 }, @@ -1335,6 +1449,31 @@ static const struct panel_desc giantplus_gpg482739qs5 = { .bus_format = MEDIA_BUS_FMT_RGB888_1X24, }; +static const struct display_timing giantplus_gpm940b0_timing = { + .pixelclock = { 13500000, 27000000, 27500000 }, + .hactive = { 320, 320, 320 }, + .hfront_porch = { 14, 686, 718 }, + .hback_porch = { 50, 70, 255 }, + .hsync_len = { 1, 1, 1 }, + .vactive = { 240, 240, 240 }, + .vfront_porch = { 1, 1, 179 }, + .vback_porch = { 1, 21, 31 }, + .vsync_len = { 1, 1, 6 }, + .flags = DISPLAY_FLAGS_HSYNC_LOW | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc giantplus_gpm940b0 = { + .timings = &giantplus_gpm940b0_timing, + .num_timings = 1, + .bpc = 8, + .size = { + .width = 60, + .height = 45, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_3X8, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_NEGEDGE, +}; + static const struct display_timing hannstar_hsd070pww1_timing = { .pixelclock = { 64300000, 71100000, 82000000 }, .hactive = { 1280, 1280, 1280 }, @@ -1578,23 +1717,32 @@ static const struct panel_desc innolux_g121x1_l03 = { }, }; -static const struct drm_display_mode innolux_n116bge_mode = { - .clock = 76420, - .hdisplay = 1366, - .hsync_start = 1366 + 136, - .hsync_end = 1366 + 136 + 30, - .htotal = 1366 + 136 + 30 + 60, - .vdisplay = 768, - .vsync_start = 768 + 8, - .vsync_end = 768 + 8 + 12, - .vtotal = 768 + 8 + 12 + 12, - .vrefresh = 60, - .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, +/* + * Datasheet specifies that at 60 Hz refresh rate: + * - total horizontal time: { 1506, 1592, 1716 } + * - total vertical time: { 788, 800, 868 } + * + * ...but doesn't go into exactly how that should be split into a front + * porch, back porch, or sync length. For now we'll leave a single setting + * here which allows a bit of tweaking of the pixel clock at the expense of + * refresh rate. + */ +static const struct display_timing innolux_n116bge_timing = { + .pixelclock = { 72600000, 76420000, 80240000 }, + .hactive = { 1366, 1366, 1366 }, + .hfront_porch = { 136, 136, 136 }, + .hback_porch = { 60, 60, 60 }, + .hsync_len = { 30, 30, 30 }, + .vactive = { 768, 768, 768 }, + .vfront_porch = { 8, 8, 8 }, + .vback_porch = { 12, 12, 12 }, + .vsync_len = { 12, 12, 12 }, + .flags = DISPLAY_FLAGS_VSYNC_LOW | DISPLAY_FLAGS_HSYNC_LOW, }; static const struct panel_desc innolux_n116bge = { - .modes = &innolux_n116bge_mode, - .num_modes = 1, + .timings = &innolux_n116bge_timing, + .num_timings = 1, .bpc = 6, .size = { .width = 256, @@ -2157,6 +2305,33 @@ static const struct panel_desc ontat_yx700wv03 = { .bus_format = MEDIA_BUS_FMT_RGB666_1X18, }; +static const struct drm_display_mode ortustech_com37h3m_mode = { + .clock = 22153, + .hdisplay = 480, + .hsync_start = 480 + 8, + .hsync_end = 480 + 8 + 10, + .htotal = 480 + 8 + 10 + 10, + .vdisplay = 640, + .vsync_start = 640 + 4, + .vsync_end = 640 + 4 + 3, + .vtotal = 640 + 4 + 3 + 4, + .vrefresh = 60, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, +}; + +static const struct panel_desc ortustech_com37h3m = { + .modes = &ortustech_com37h3m_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 56, /* 56.16mm */ + .height = 75, /* 74.88mm */ + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_POSEDGE | + DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE, +}; + static const struct drm_display_mode ortustech_com43h4m85ulc_mode = { .clock = 25000, .hdisplay = 480, @@ -2354,6 +2529,59 @@ static const struct panel_desc samsung_ltn140at29_301 = { }, }; +static const struct drm_display_mode sharp_ld_d5116z01b_mode = { + .clock = 168480, + .hdisplay = 1920, + .hsync_start = 1920 + 48, + .hsync_end = 1920 + 48 + 32, + .htotal = 1920 + 48 + 32 + 80, + .vdisplay = 1280, + .vsync_start = 1280 + 3, + .vsync_end = 1280 + 3 + 10, + .vtotal = 1280 + 3 + 10 + 57, + .vrefresh = 60, + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC, +}; + +static const struct panel_desc sharp_ld_d5116z01b = { + .modes = &sharp_ld_d5116z01b_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 260, + .height = 120, + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DATA_MSB_TO_LSB, +}; + +static const struct drm_display_mode sharp_lq070y3dg3b_mode = { + .clock = 33260, + .hdisplay = 800, + .hsync_start = 800 + 64, + .hsync_end = 800 + 64 + 128, + .htotal = 800 + 64 + 128 + 64, + .vdisplay = 480, + .vsync_start = 480 + 8, + .vsync_end = 480 + 8 + 2, + .vtotal = 480 + 8 + 2 + 35, + .vrefresh = 60, + .flags = DISPLAY_FLAGS_PIXDATA_POSEDGE, +}; + +static const struct panel_desc sharp_lq070y3dg3b = { + .modes = &sharp_lq070y3dg3b_mode, + .num_modes = 1, + .bpc = 8, + .size = { + .width = 152, /* 152.4mm */ + .height = 91, /* 91.4mm */ + }, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_POSEDGE | + DRM_BUS_FLAG_SYNC_DRIVE_POSEDGE, +}; + static const struct drm_display_mode sharp_lq035q7db03_mode = { .clock = 5500, .hdisplay = 240, @@ -2454,6 +2682,33 @@ static const struct panel_desc sharp_lq150x1lg11 = { .bus_format = MEDIA_BUS_FMT_RGB565_1X16, }; +static const struct display_timing sharp_ls020b1dd01d_timing = { + .pixelclock = { 2000000, 4200000, 5000000 }, + .hactive = { 240, 240, 240 }, + .hfront_porch = { 66, 66, 66 }, + .hback_porch = { 1, 1, 1 }, + .hsync_len = { 1, 1, 1 }, + .vactive = { 160, 160, 160 }, + .vfront_porch = { 52, 52, 52 }, + .vback_porch = { 6, 6, 6 }, + .vsync_len = { 10, 10, 10 }, + .flags = DISPLAY_FLAGS_HSYNC_HIGH | DISPLAY_FLAGS_VSYNC_LOW, +}; + +static const struct panel_desc sharp_ls020b1dd01d = { + .timings = &sharp_ls020b1dd01d_timing, + .num_timings = 1, + .bpc = 6, + .size = { + .width = 42, + .height = 28, + }, + .bus_format = MEDIA_BUS_FMT_RGB565_1X16, + .bus_flags = DRM_BUS_FLAG_DE_HIGH + | DRM_BUS_FLAG_PIXDATA_NEGEDGE + | DRM_BUS_FLAG_SHARP_SIGNALS, +}; + static const struct drm_display_mode shelly_sca07010_bfn_lnn_mode = { .clock = 33300, .hdisplay = 800, @@ -2883,6 +3138,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "giantplus,gpg482739qs5", .data = &giantplus_gpg482739qs5 }, { + .compatible = "giantplus,gpm940b0", + .data = &giantplus_gpm940b0, + }, { .compatible = "hannstar,hsd070pww1", .data = &hannstar_hsd070pww1, }, { @@ -2979,6 +3237,12 @@ static const struct of_device_id platform_of_match[] = { .compatible = "ontat,yx700wv03", .data = &ontat_yx700wv03, }, { + .compatible = "ortustech,com37h3m05dtc", + .data = &ortustech_com37h3m, + }, { + .compatible = "ortustech,com37h3m99dtc", + .data = &ortustech_com37h3m, + }, { .compatible = "ortustech,com43h4m85ulc", .data = &ortustech_com43h4m85ulc, }, { @@ -3003,9 +3267,15 @@ static const struct of_device_id platform_of_match[] = { .compatible = "samsung,ltn140at29-301", .data = &samsung_ltn140at29_301, }, { + .compatible = "sharp,ld-d5116z01b", + .data = &sharp_ld_d5116z01b, + }, { .compatible = "sharp,lq035q7db03", .data = &sharp_lq035q7db03, }, { + .compatible = "sharp,lq070y3dg3b", + .data = &sharp_lq070y3dg3b, + }, { .compatible = "sharp,lq101k1ly04", .data = &sharp_lq101k1ly04, }, { @@ -3015,6 +3285,9 @@ static const struct of_device_id platform_of_match[] = { .compatible = "sharp,lq150x1lg11", .data = &sharp_lq150x1lg11, }, { + .compatible = "sharp,ls020b1dd01d", + .data = &sharp_ls020b1dd01d, + }, { .compatible = "shelly,sca07010-bfn-lnn", .data = &shelly_sca07010_bfn_lnn, }, { diff --git a/drivers/gpu/drm/panfrost/panfrost_devfreq.c b/drivers/gpu/drm/panfrost/panfrost_devfreq.c index db798532b0b6..a7c18bceb7fd 100644 --- a/drivers/gpu/drm/panfrost/panfrost_devfreq.c +++ b/drivers/gpu/drm/panfrost/panfrost_devfreq.c @@ -157,7 +157,8 @@ int panfrost_devfreq_init(struct panfrost_device *pfdev) dev_pm_opp_put(opp); pfdev->devfreq.devfreq = devm_devfreq_add_device(&pfdev->pdev->dev, - &panfrost_devfreq_profile, "simple_ondemand", NULL); + &panfrost_devfreq_profile, DEVFREQ_GOV_SIMPLE_ONDEMAND, + NULL); if (IS_ERR(pfdev->devfreq.devfreq)) { DRM_DEV_ERROR(&pfdev->pdev->dev, "Couldn't initialize GPU devfreq\n"); ret = PTR_ERR(pfdev->devfreq.devfreq); diff --git a/drivers/gpu/drm/panfrost/panfrost_device.h b/drivers/gpu/drm/panfrost/panfrost_device.h index 83cc01cafde1..ea5948ff3647 100644 --- a/drivers/gpu/drm/panfrost/panfrost_device.h +++ b/drivers/gpu/drm/panfrost/panfrost_device.h @@ -43,6 +43,7 @@ struct panfrost_features { u32 js_features[16]; u32 nr_core_groups; + u32 thread_tls_alloc; unsigned long hw_features[64 / BITS_PER_LONG]; unsigned long hw_issues[64 / BITS_PER_LONG]; diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c index 85b4b51b6a0d..b187daa4da85 100644 --- a/drivers/gpu/drm/panfrost/panfrost_drv.c +++ b/drivers/gpu/drm/panfrost/panfrost_drv.c @@ -32,10 +32,42 @@ static int panfrost_ioctl_get_param(struct drm_device *ddev, void *data, struct if (param->pad != 0) return -EINVAL; +#define PANFROST_FEATURE(name, member) \ + case DRM_PANFROST_PARAM_ ## name: \ + param->value = pfdev->features.member; \ + break +#define PANFROST_FEATURE_ARRAY(name, member, max) \ + case DRM_PANFROST_PARAM_ ## name ## 0 ... \ + DRM_PANFROST_PARAM_ ## name ## max: \ + param->value = pfdev->features.member[param->param - \ + DRM_PANFROST_PARAM_ ## name ## 0]; \ + break + switch (param->param) { - case DRM_PANFROST_PARAM_GPU_PROD_ID: - param->value = pfdev->features.id; - break; + PANFROST_FEATURE(GPU_PROD_ID, id); + PANFROST_FEATURE(GPU_REVISION, revision); + PANFROST_FEATURE(SHADER_PRESENT, shader_present); + PANFROST_FEATURE(TILER_PRESENT, tiler_present); + PANFROST_FEATURE(L2_PRESENT, l2_present); + PANFROST_FEATURE(STACK_PRESENT, stack_present); + PANFROST_FEATURE(AS_PRESENT, as_present); + PANFROST_FEATURE(JS_PRESENT, js_present); + PANFROST_FEATURE(L2_FEATURES, l2_features); + PANFROST_FEATURE(CORE_FEATURES, core_features); + PANFROST_FEATURE(TILER_FEATURES, tiler_features); + PANFROST_FEATURE(MEM_FEATURES, mem_features); + PANFROST_FEATURE(MMU_FEATURES, mmu_features); + PANFROST_FEATURE(THREAD_FEATURES, thread_features); + PANFROST_FEATURE(MAX_THREADS, max_threads); + PANFROST_FEATURE(THREAD_MAX_WORKGROUP_SZ, + thread_max_workgroup_sz); + PANFROST_FEATURE(THREAD_MAX_BARRIER_SZ, + thread_max_barrier_sz); + PANFROST_FEATURE(COHERENCY_FEATURES, coherency_features); + PANFROST_FEATURE_ARRAY(TEXTURE_FEATURES, texture_features, 3); + PANFROST_FEATURE_ARRAY(JS_FEATURES, js_features, 15); + PANFROST_FEATURE(NR_CORE_GROUPS, nr_core_groups); + PANFROST_FEATURE(THREAD_TLS_ALLOC, thread_tls_alloc); default: return -EINVAL; } @@ -357,8 +389,7 @@ static const struct drm_ioctl_desc panfrost_drm_driver_ioctls[] = { DEFINE_DRM_GEM_SHMEM_FOPS(panfrost_drm_driver_fops); static struct drm_driver panfrost_drm_driver = { - .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_PRIME | - DRIVER_SYNCOBJ, + .driver_features = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ, .open = panfrost_open, .postclose = panfrost_postclose, .ioctls = panfrost_drm_driver_ioctls, diff --git a/drivers/gpu/drm/panfrost/panfrost_gem.c b/drivers/gpu/drm/panfrost/panfrost_gem.c index b46416be5a54..543ab1b81bd5 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gem.c +++ b/drivers/gpu/drm/panfrost/panfrost_gem.c @@ -92,8 +92,6 @@ panfrost_gem_prime_import_sg_table(struct drm_device *dev, pobj = to_panfrost_bo(obj); - obj->resv = attach->dmabuf->resv; - panfrost_mmu_map(pobj); return obj; diff --git a/drivers/gpu/drm/panfrost/panfrost_gpu.c b/drivers/gpu/drm/panfrost/panfrost_gpu.c index 20ab333fc925..f67ed925c0ef 100644 --- a/drivers/gpu/drm/panfrost/panfrost_gpu.c +++ b/drivers/gpu/drm/panfrost/panfrost_gpu.c @@ -232,6 +232,8 @@ static void panfrost_gpu_init_features(struct panfrost_device *pfdev) pfdev->features.stack_present = gpu_read(pfdev, GPU_STACK_PRESENT_LO); pfdev->features.stack_present |= (u64)gpu_read(pfdev, GPU_STACK_PRESENT_HI) << 32; + pfdev->features.thread_tls_alloc = gpu_read(pfdev, GPU_THREAD_TLS_ALLOC); + gpu_id = gpu_read(pfdev, GPU_ID); pfdev->features.revision = gpu_id & 0xffff; pfdev->features.id = gpu_id >> 16; diff --git a/drivers/gpu/drm/pl111/pl111_debugfs.c b/drivers/gpu/drm/pl111/pl111_debugfs.c index 8d6a40469f0b..3c8e82016854 100644 --- a/drivers/gpu/drm/pl111/pl111_debugfs.c +++ b/drivers/gpu/drm/pl111/pl111_debugfs.c @@ -5,8 +5,10 @@ #include <linux/amba/clcd-regs.h> #include <linux/seq_file.h> + #include <drm/drm_debugfs.h> -#include <drm/drmP.h> +#include <drm/drm_file.h> + #include "pl111_drm.h" #define REGDEF(reg) { reg, #reg } diff --git a/drivers/gpu/drm/pl111/pl111_display.c b/drivers/gpu/drm/pl111/pl111_display.c index 15d2755fdba4..9a153125e5d2 100644 --- a/drivers/gpu/drm/pl111/pl111_display.c +++ b/drivers/gpu/drm/pl111/pl111_display.c @@ -11,14 +11,16 @@ #include <linux/amba/clcd-regs.h> #include <linux/clk.h> +#include <linux/delay.h> #include <linux/version.h> #include <linux/dma-buf.h> #include <linux/of_graph.h> -#include <drm/drmP.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_vblank.h> #include "pl111_drm.h" @@ -546,25 +548,8 @@ pl111_init_clock_divider(struct drm_device *drm) int pl111_display_init(struct drm_device *drm) { struct pl111_drm_dev_private *priv = drm->dev_private; - struct device *dev = drm->dev; - struct device_node *endpoint; - u32 tft_r0b0g0[3]; int ret; - endpoint = of_graph_get_next_endpoint(dev->of_node, NULL); - if (!endpoint) - return -ENODEV; - - if (of_property_read_u32_array(endpoint, - "arm,pl11x,tft-r0g0b0-pads", - tft_r0b0g0, - ARRAY_SIZE(tft_r0b0g0)) != 0) { - dev_err(dev, "arm,pl11x,tft-r0g0b0-pads should be 3 ints\n"); - of_node_put(endpoint); - return -ENOENT; - } - of_node_put(endpoint); - ret = pl111_init_clock_divider(drm); if (ret) return ret; diff --git a/drivers/gpu/drm/pl111/pl111_drm.h b/drivers/gpu/drm/pl111/pl111_drm.h index b2c5e9f34051..77d2da9a8a7c 100644 --- a/drivers/gpu/drm/pl111/pl111_drm.h +++ b/drivers/gpu/drm/pl111/pl111_drm.h @@ -13,14 +13,15 @@ #ifndef _PL111_DRM_H_ #define _PL111_DRM_H_ -#include <drm/drm_gem.h> -#include <drm/drm_simple_kms_helper.h> +#include <linux/clk-provider.h> +#include <linux/interrupt.h> + +#include <drm/drm_bridge.h> #include <drm/drm_connector.h> #include <drm/drm_encoder.h> +#include <drm/drm_gem.h> #include <drm/drm_panel.h> -#include <drm/drm_bridge.h> -#include <linux/clk-provider.h> -#include <linux/interrupt.h> +#include <drm/drm_simple_kms_helper.h> #define CLCD_IRQ_NEXTBASE_UPDATE BIT(2) diff --git a/drivers/gpu/drm/pl111/pl111_drv.c b/drivers/gpu/drm/pl111/pl111_drv.c index 01f8462aa2db..276b53473a84 100644 --- a/drivers/gpu/drm/pl111/pl111_drv.c +++ b/drivers/gpu/drm/pl111/pl111_drv.c @@ -48,18 +48,18 @@ #include <linux/amba/bus.h> #include <linux/amba/clcd-regs.h> -#include <linux/version.h> -#include <linux/shmem_fs.h> #include <linux/dma-buf.h> #include <linux/module.h> -#include <linux/slab.h> #include <linux/of.h> #include <linux/of_graph.h> #include <linux/of_reserved_mem.h> +#include <linux/shmem_fs.h> +#include <linux/slab.h> +#include <linux/version.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -67,6 +67,7 @@ #include <drm/drm_of.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "pl111_drm.h" #include "pl111_versatile.h" @@ -224,7 +225,7 @@ DEFINE_DRM_GEM_CMA_FOPS(drm_fops); static struct drm_driver pl111_drm_driver = { .driver_features = - DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, + DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .ioctls = NULL, .fops = &drm_fops, .name = "pl111", @@ -238,9 +239,7 @@ static struct drm_driver pl111_drm_driver = { .gem_vm_ops = &drm_gem_cma_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, .gem_prime_import_sg_table = pl111_gem_import_sg_table, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_mmap = drm_gem_cma_prime_mmap, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/pl111/pl111_nomadik.h b/drivers/gpu/drm/pl111/pl111_nomadik.h index 19d663d46353..47ccf5c839fc 100644 --- a/drivers/gpu/drm/pl111/pl111_nomadik.h +++ b/drivers/gpu/drm/pl111/pl111_nomadik.h @@ -1,10 +1,11 @@ // SPDX-License-Identifier: GPL-2.0+ -#include <linux/device.h> #ifndef PL111_NOMADIK_H #define PL111_NOMADIK_H #endif +struct device; + #ifdef CONFIG_ARCH_NOMADIK void pl111_nomadik_init(struct device *dev); diff --git a/drivers/gpu/drm/pl111/pl111_versatile.c b/drivers/gpu/drm/pl111/pl111_versatile.c index 38f4ee05285e..09aeaffb7660 100644 --- a/drivers/gpu/drm/pl111/pl111_versatile.c +++ b/drivers/gpu/drm/pl111/pl111_versatile.c @@ -1,13 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-only + #include <linux/amba/clcd-regs.h> +#include <linux/bitops.h> #include <linux/device.h> +#include <linux/mfd/syscon.h> +#include <linux/module.h> #include <linux/of.h> #include <linux/of_platform.h> #include <linux/regmap.h> -#include <linux/mfd/syscon.h> -#include <linux/bitops.h> -#include <linux/module.h> -#include <drm/drmP.h> + #include "pl111_versatile.h" #include "pl111_vexpress.h" #include "pl111_drm.h" diff --git a/drivers/gpu/drm/pl111/pl111_versatile.h b/drivers/gpu/drm/pl111/pl111_versatile.h index 41aa6d969dc6..143877010042 100644 --- a/drivers/gpu/drm/pl111/pl111_versatile.h +++ b/drivers/gpu/drm/pl111/pl111_versatile.h @@ -4,6 +4,9 @@ #ifndef PL111_VERSATILE_H #define PL111_VERSATILE_H +struct device; +struct pl111_drm_dev_private; + int pl111_versatile_init(struct device *dev, struct pl111_drm_dev_private *priv); #endif diff --git a/drivers/gpu/drm/pl111/pl111_vexpress.c b/drivers/gpu/drm/pl111/pl111_vexpress.c index 38c938c9adda..350570fe06b5 100644 --- a/drivers/gpu/drm/pl111/pl111_vexpress.c +++ b/drivers/gpu/drm/pl111/pl111_vexpress.c @@ -51,6 +51,7 @@ int pl111_vexpress_clcd_init(struct device *dev, } if (of_device_is_compatible(child, "arm,hdlcd")) { has_coretile_hdlcd = true; + of_node_put(child); break; } } diff --git a/drivers/gpu/drm/qxl/qxl_cmd.c b/drivers/gpu/drm/qxl/qxl_cmd.c index 0a2e51af1230..ef09dc6bc635 100644 --- a/drivers/gpu/drm/qxl/qxl_cmd.c +++ b/drivers/gpu/drm/qxl/qxl_cmd.c @@ -25,6 +25,8 @@ /* QXL cmd/ring handling */ +#include <linux/delay.h> + #include <drm/drm_util.h> #include "qxl_drv.h" @@ -375,7 +377,7 @@ void qxl_io_destroy_primary(struct qxl_device *qdev) { wait_for_io_cmd(qdev, 0, QXL_IO_DESTROY_PRIMARY_ASYNC); qdev->primary_bo->is_primary = false; - drm_gem_object_put_unlocked(&qdev->primary_bo->gem_base); + drm_gem_object_put_unlocked(&qdev->primary_bo->tbo.base); qdev->primary_bo = NULL; } @@ -402,7 +404,7 @@ void qxl_io_create_primary(struct qxl_device *qdev, struct qxl_bo *bo) wait_for_io_cmd(qdev, 0, QXL_IO_CREATE_PRIMARY_ASYNC); qdev->primary_bo = bo; qdev->primary_bo->is_primary = true; - drm_gem_object_get(&qdev->primary_bo->gem_base); + drm_gem_object_get(&qdev->primary_bo->tbo.base); } void qxl_io_memslot_add(struct qxl_device *qdev, uint8_t id) diff --git a/drivers/gpu/drm/qxl/qxl_debugfs.c b/drivers/gpu/drm/qxl/qxl_debugfs.c index 118422549828..94439212a5c5 100644 --- a/drivers/gpu/drm/qxl/qxl_debugfs.c +++ b/drivers/gpu/drm/qxl/qxl_debugfs.c @@ -28,9 +28,9 @@ * Alon Levy <alevy@redhat.com> */ -#include <linux/debugfs.h> +#include <drm/drm_debugfs.h> +#include <drm/drm_file.h> -#include <drm/drmP.h> #include "qxl_drv.h" #include "qxl_object.h" @@ -61,12 +61,12 @@ qxl_debugfs_buffers_info(struct seq_file *m, void *data) int rel; rcu_read_lock(); - fobj = rcu_dereference(bo->tbo.resv->fence); + fobj = rcu_dereference(bo->tbo.base.resv->fence); rel = fobj ? fobj->shared_count : 0; rcu_read_unlock(); seq_printf(m, "size %ld, pc %d, num releases %d\n", - (unsigned long)bo->gem_base.size, + (unsigned long)bo->tbo.base.size, bo->pin_count, rel); } return 0; diff --git a/drivers/gpu/drm/qxl/qxl_display.c b/drivers/gpu/drm/qxl/qxl_display.c index 8b319ebbb0fb..16d73b22f3f5 100644 --- a/drivers/gpu/drm/qxl/qxl_display.c +++ b/drivers/gpu/drm/qxl/qxl_display.c @@ -24,11 +24,14 @@ */ #include <linux/crc32.h> +#include <linux/delay.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "qxl_drv.h" #include "qxl_object.h" @@ -794,7 +797,7 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane, qdev->dumb_shadow_bo->surf.height != surf.height) { if (qdev->dumb_shadow_bo) { drm_gem_object_put_unlocked - (&qdev->dumb_shadow_bo->gem_base); + (&qdev->dumb_shadow_bo->tbo.base); qdev->dumb_shadow_bo = NULL; } qxl_bo_create(qdev, surf.height * surf.stride, @@ -804,10 +807,10 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane, if (user_bo->shadow != qdev->dumb_shadow_bo) { if (user_bo->shadow) { drm_gem_object_put_unlocked - (&user_bo->shadow->gem_base); + (&user_bo->shadow->tbo.base); user_bo->shadow = NULL; } - drm_gem_object_get(&qdev->dumb_shadow_bo->gem_base); + drm_gem_object_get(&qdev->dumb_shadow_bo->tbo.base); user_bo->shadow = qdev->dumb_shadow_bo; } } @@ -838,7 +841,7 @@ static void qxl_plane_cleanup_fb(struct drm_plane *plane, qxl_bo_unpin(user_bo); if (old_state->fb != plane->state->fb && user_bo->shadow) { - drm_gem_object_put_unlocked(&user_bo->shadow->gem_base); + drm_gem_object_put_unlocked(&user_bo->shadow->tbo.base); user_bo->shadow = NULL; } } diff --git a/drivers/gpu/drm/qxl/qxl_draw.c b/drivers/gpu/drm/qxl/qxl_draw.c index 97c3f1a95a32..5bebf1ea1c5d 100644 --- a/drivers/gpu/drm/qxl/qxl_draw.c +++ b/drivers/gpu/drm/qxl/qxl_draw.c @@ -20,6 +20,8 @@ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#include <drm/drm_fourcc.h> + #include "qxl_drv.h" #include "qxl_object.h" diff --git a/drivers/gpu/drm/qxl/qxl_drv.c b/drivers/gpu/drm/qxl/qxl_drv.c index f33e349c4ec5..c1802e01d9f6 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.c +++ b/drivers/gpu/drm/qxl/qxl_drv.c @@ -28,14 +28,18 @@ * Alon Levy <alevy@redhat.com> */ -#include <linux/module.h> +#include "qxl_drv.h" #include <linux/console.h> +#include <linux/module.h> +#include <linux/pci.h> -#include <drm/drmP.h> #include <drm/drm.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> #include <drm/drm_modeset_helper.h> +#include <drm/drm_prime.h> #include <drm/drm_probe_helper.h> -#include "qxl_drv.h" + #include "qxl_object.h" static const struct pci_device_id pciidlist[] = { @@ -206,16 +210,14 @@ static int qxl_pm_resume(struct device *dev) static int qxl_pm_thaw(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct drm_device *drm_dev = dev_get_drvdata(dev); return qxl_drm_resume(drm_dev, true); } static int qxl_pm_freeze(struct device *dev) { - struct pci_dev *pdev = to_pci_dev(dev); - struct drm_device *drm_dev = pci_get_drvdata(pdev); + struct drm_device *drm_dev = dev_get_drvdata(dev); return qxl_drm_freeze(drm_dev); } @@ -247,8 +249,7 @@ static struct pci_driver qxl_pci_driver = { }; static struct drm_driver qxl_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .dumb_create = qxl_mode_dumb_create, .dumb_map_offset = qxl_mode_dumb_mmap, @@ -257,8 +258,6 @@ static struct drm_driver qxl_driver = { #endif .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = qxl_gem_prime_pin, .gem_prime_unpin = qxl_gem_prime_unpin, .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table, diff --git a/drivers/gpu/drm/qxl/qxl_drv.h b/drivers/gpu/drm/qxl/qxl_drv.h index 2896bb6fdbf4..9e034c5fa87d 100644 --- a/drivers/gpu/drm/qxl/qxl_drv.h +++ b/drivers/gpu/drm/qxl/qxl_drv.h @@ -31,22 +31,21 @@ */ #include <linux/dma-fence.h> -#include <linux/workqueue.h> #include <linux/firmware.h> #include <linux/platform_device.h> +#include <linux/workqueue.h> #include <drm/drm_crtc.h> #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_ioctl.h> #include <drm/drm_gem.h> -#include <drm/drmP.h> +#include <drm/qxl_drm.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> -/* just for ttm_validate_buffer */ #include <drm/ttm/ttm_execbuf_util.h> #include <drm/ttm/ttm_module.h> #include <drm/ttm/ttm_placement.h> -#include <drm/qxl_drm.h> #include "qxl_dev.h" @@ -72,12 +71,13 @@ extern int qxl_max_ioctls; QXL_INTERRUPT_CLIENT_MONITORS_CONFIG) struct qxl_bo { + struct ttm_buffer_object tbo; + /* Protected by gem.mutex */ struct list_head list; /* Protected by tbo.reserved */ struct ttm_place placements[3]; struct ttm_placement placement; - struct ttm_buffer_object tbo; struct ttm_bo_kmap_obj kmap; unsigned int pin_count; void *kptr; @@ -85,7 +85,6 @@ struct qxl_bo { int type; /* Constant after initialization */ - struct drm_gem_object gem_base; unsigned int is_primary:1; /* is this now a primary surface */ unsigned int is_dumb:1; struct qxl_bo *shadow; @@ -94,7 +93,7 @@ struct qxl_bo { uint32_t surface_id; struct qxl_release *surf_create; }; -#define gem_to_qxl_bo(gobj) container_of((gobj), struct qxl_bo, gem_base) +#define gem_to_qxl_bo(gobj) container_of((gobj), struct qxl_bo, tbo.base) #define to_qxl_bo(tobj) container_of((tobj), struct qxl_bo, tbo) struct qxl_gem { diff --git a/drivers/gpu/drm/qxl/qxl_gem.c b/drivers/gpu/drm/qxl/qxl_gem.c index 89606c819d82..69f37db1027a 100644 --- a/drivers/gpu/drm/qxl/qxl_gem.c +++ b/drivers/gpu/drm/qxl/qxl_gem.c @@ -23,7 +23,6 @@ * Alon Levy */ -#include <drm/drmP.h> #include <drm/drm.h> #include "qxl_drv.h" @@ -64,7 +63,7 @@ int qxl_gem_object_create(struct qxl_device *qdev, int size, size, initial_domain, alignment, r); return r; } - *obj = &qbo->gem_base; + *obj = &qbo->tbo.base; mutex_lock(&qdev->gem.mutex); list_add_tail(&qbo->list, &qdev->gem.objects); diff --git a/drivers/gpu/drm/qxl/qxl_ioctl.c b/drivers/gpu/drm/qxl/qxl_ioctl.c index d410e2925162..8117a45b3610 100644 --- a/drivers/gpu/drm/qxl/qxl_ioctl.c +++ b/drivers/gpu/drm/qxl/qxl_ioctl.c @@ -23,6 +23,9 @@ * Alon Levy */ +#include <linux/pci.h> +#include <linux/uaccess.h> + #include "qxl_drv.h" #include "qxl_object.h" diff --git a/drivers/gpu/drm/qxl/qxl_irq.c b/drivers/gpu/drm/qxl/qxl_irq.c index 3bb31add6350..8435af108632 100644 --- a/drivers/gpu/drm/qxl/qxl_irq.c +++ b/drivers/gpu/drm/qxl/qxl_irq.c @@ -23,6 +23,10 @@ * Alon Levy */ +#include <linux/pci.h> + +#include <drm/drm_irq.h> + #include "qxl_drv.h" irqreturn_t qxl_irq_handler(int irq, void *arg) diff --git a/drivers/gpu/drm/qxl/qxl_kms.c b/drivers/gpu/drm/qxl/qxl_kms.c index bee61fa2c9bc..611cbe7aee69 100644 --- a/drivers/gpu/drm/qxl/qxl_kms.c +++ b/drivers/gpu/drm/qxl/qxl_kms.c @@ -23,11 +23,14 @@ * Alon Levy */ -#include "qxl_drv.h" -#include "qxl_object.h" +#include <linux/io-mapping.h> +#include <linux/pci.h> +#include <drm/drm_drv.h> #include <drm/drm_probe_helper.h> -#include <linux/io-mapping.h> + +#include "qxl_drv.h" +#include "qxl_object.h" int qxl_log_level; diff --git a/drivers/gpu/drm/qxl/qxl_object.c b/drivers/gpu/drm/qxl/qxl_object.c index 4928fa602944..548dfe6f3b26 100644 --- a/drivers/gpu/drm/qxl/qxl_object.c +++ b/drivers/gpu/drm/qxl/qxl_object.c @@ -33,14 +33,14 @@ static void qxl_ttm_bo_destroy(struct ttm_buffer_object *tbo) struct qxl_device *qdev; bo = to_qxl_bo(tbo); - qdev = (struct qxl_device *)bo->gem_base.dev->dev_private; + qdev = (struct qxl_device *)bo->tbo.base.dev->dev_private; qxl_surface_evict(qdev, bo, false); WARN_ON_ONCE(bo->map_count > 0); mutex_lock(&qdev->gem.mutex); list_del_init(&bo->list); mutex_unlock(&qdev->gem.mutex); - drm_gem_object_release(&bo->gem_base); + drm_gem_object_release(&bo->tbo.base); kfree(bo); } @@ -95,7 +95,7 @@ int qxl_bo_create(struct qxl_device *qdev, if (bo == NULL) return -ENOMEM; size = roundup(size, PAGE_SIZE); - r = drm_gem_object_init(&qdev->ddev, &bo->gem_base, size); + r = drm_gem_object_init(&qdev->ddev, &bo->tbo.base, size); if (unlikely(r)) { kfree(bo); return r; @@ -214,20 +214,20 @@ void qxl_bo_unref(struct qxl_bo **bo) if ((*bo) == NULL) return; - drm_gem_object_put_unlocked(&(*bo)->gem_base); + drm_gem_object_put_unlocked(&(*bo)->tbo.base); *bo = NULL; } struct qxl_bo *qxl_bo_ref(struct qxl_bo *bo) { - drm_gem_object_get(&bo->gem_base); + drm_gem_object_get(&bo->tbo.base); return bo; } static int __qxl_bo_pin(struct qxl_bo *bo) { struct ttm_operation_ctx ctx = { false, false }; - struct drm_device *ddev = bo->gem_base.dev; + struct drm_device *ddev = bo->tbo.base.dev; int r; if (bo->pin_count) { @@ -247,7 +247,7 @@ static int __qxl_bo_pin(struct qxl_bo *bo) static int __qxl_bo_unpin(struct qxl_bo *bo) { struct ttm_operation_ctx ctx = { false, false }; - struct drm_device *ddev = bo->gem_base.dev; + struct drm_device *ddev = bo->tbo.base.dev; int r, i; if (!bo->pin_count) { @@ -310,13 +310,13 @@ void qxl_bo_force_delete(struct qxl_device *qdev) dev_err(qdev->ddev.dev, "Userspace still has active objects !\n"); list_for_each_entry_safe(bo, n, &qdev->gem.objects, list) { dev_err(qdev->ddev.dev, "%p %p %lu %lu force free\n", - &bo->gem_base, bo, (unsigned long)bo->gem_base.size, - *((unsigned long *)&bo->gem_base.refcount)); + &bo->tbo.base, bo, (unsigned long)bo->tbo.base.size, + *((unsigned long *)&bo->tbo.base.refcount)); mutex_lock(&qdev->gem.mutex); list_del_init(&bo->list); mutex_unlock(&qdev->gem.mutex); /* this should unref the ttm bo */ - drm_gem_object_put_unlocked(&bo->gem_base); + drm_gem_object_put_unlocked(&bo->tbo.base); } } diff --git a/drivers/gpu/drm/qxl/qxl_object.h b/drivers/gpu/drm/qxl/qxl_object.h index 255b914e2a7b..8ae54ba7857c 100644 --- a/drivers/gpu/drm/qxl/qxl_object.h +++ b/drivers/gpu/drm/qxl/qxl_object.h @@ -34,7 +34,7 @@ static inline int qxl_bo_reserve(struct qxl_bo *bo, bool no_wait) r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) { - struct drm_device *ddev = bo->gem_base.dev; + struct drm_device *ddev = bo->tbo.base.dev; dev_err(ddev->dev, "%p reserve failed\n", bo); } @@ -60,7 +60,7 @@ static inline unsigned long qxl_bo_size(struct qxl_bo *bo) static inline u64 qxl_bo_mmap_offset(struct qxl_bo *bo) { - return drm_vma_node_offset_addr(&bo->tbo.vma_node); + return drm_vma_node_offset_addr(&bo->tbo.base.vma_node); } static inline int qxl_bo_wait(struct qxl_bo *bo, u32 *mem_type, @@ -71,7 +71,7 @@ static inline int qxl_bo_wait(struct qxl_bo *bo, u32 *mem_type, r = ttm_bo_reserve(&bo->tbo, true, no_wait, NULL); if (unlikely(r != 0)) { if (r != -ERESTARTSYS) { - struct drm_device *ddev = bo->gem_base.dev; + struct drm_device *ddev = bo->tbo.base.dev; dev_err(ddev->dev, "%p reserve failed for wait\n", bo); diff --git a/drivers/gpu/drm/qxl/qxl_release.c b/drivers/gpu/drm/qxl/qxl_release.c index 49f9a9385393..df55b83e0a55 100644 --- a/drivers/gpu/drm/qxl/qxl_release.c +++ b/drivers/gpu/drm/qxl/qxl_release.c @@ -19,9 +19,13 @@ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +#include <linux/delay.h> + +#include <trace/events/dma_fence.h> + #include "qxl_drv.h" #include "qxl_object.h" -#include <trace/events/dma_fence.h> /* * drawable cmd cache - allocate a bunch of VRAM pages, suballocate @@ -234,12 +238,12 @@ static int qxl_release_validate_bo(struct qxl_bo *bo) return ret; } - ret = reservation_object_reserve_shared(bo->tbo.resv, 1); + ret = reservation_object_reserve_shared(bo->tbo.base.resv, 1); if (ret) return ret; /* allocate a surface for reserved + validated buffers */ - ret = qxl_bo_check_id(bo->gem_base.dev->dev_private, bo); + ret = qxl_bo_check_id(bo->tbo.base.dev->dev_private, bo); if (ret) return ret; return 0; @@ -454,9 +458,9 @@ void qxl_release_fence_buffer_objects(struct qxl_release *release) list_for_each_entry(entry, &release->bos, head) { bo = entry->bo; - reservation_object_add_shared_fence(bo->resv, &release->base); + reservation_object_add_shared_fence(bo->base.resv, &release->base); ttm_bo_add_to_lru(bo); - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); } spin_unlock(&glob->lru_lock); ww_acquire_fini(&release->ticket); diff --git a/drivers/gpu/drm/qxl/qxl_ttm.c b/drivers/gpu/drm/qxl/qxl_ttm.c index 0234f8556ada..9b24514c75aa 100644 --- a/drivers/gpu/drm/qxl/qxl_ttm.c +++ b/drivers/gpu/drm/qxl/qxl_ttm.c @@ -23,19 +23,21 @@ * Alon Levy */ +#include <linux/delay.h> + +#include <drm/drm.h> +#include <drm/drm_file.h> +#include <drm/drm_debugfs.h> +#include <drm/qxl_drm.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> -#include <drm/ttm/ttm_page_alloc.h> #include <drm/ttm/ttm_module.h> -#include <drm/drmP.h> -#include <drm/drm.h> -#include <drm/qxl_drm.h> +#include <drm/ttm/ttm_page_alloc.h> +#include <drm/ttm/ttm_placement.h> + #include "qxl_drv.h" #include "qxl_object.h" -#include <linux/delay.h> - static struct qxl_device *qxl_get_qdev(struct ttm_bo_device *bdev) { struct qxl_mman *mman; @@ -153,7 +155,7 @@ static int qxl_verify_access(struct ttm_buffer_object *bo, struct file *filp) { struct qxl_bo *qbo = to_qxl_bo(bo); - return drm_vma_node_verify_access(&qbo->gem_base.vma_node, + return drm_vma_node_verify_access(&qbo->tbo.base.vma_node, filp->private_data); } @@ -295,7 +297,7 @@ static void qxl_bo_move_notify(struct ttm_buffer_object *bo, if (!qxl_ttm_bo_is_qxl_bo(bo)) return; qbo = to_qxl_bo(bo); - qdev = qbo->gem_base.dev->dev_private; + qdev = qbo->tbo.base.dev->dev_private; if (bo->mem.mem_type == TTM_PL_PRIV && qbo->surface_id) qxl_surface_evict(qdev, qbo, new_mem ? true : false); diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c index 6589f9e0310e..6ac71755c22d 100644 --- a/drivers/gpu/drm/r128/r128_ioc32.c +++ b/drivers/gpu/drm/r128/r128_ioc32.c @@ -29,10 +29,11 @@ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ + #include <linux/compat.h> -#include <drm/drmP.h> #include <drm/r128_drm.h> + #include "r128_drv.h" typedef struct drm_r128_init32 { diff --git a/drivers/gpu/drm/r128/r128_irq.c b/drivers/gpu/drm/r128/r128_irq.c index 9730f4918944..d84e9c96e20a 100644 --- a/drivers/gpu/drm/r128/r128_irq.c +++ b/drivers/gpu/drm/r128/r128_irq.c @@ -30,8 +30,11 @@ * Eric Anholt <anholt@FreeBSD.org> */ -#include <drm/drmP.h> +#include <drm/drm_device.h> +#include <drm/drm_print.h> +#include <drm/drm_vblank.h> #include <drm/r128_drm.h> + #include "r128_drv.h" u32 r128_get_vblank_counter(struct drm_device *dev, unsigned int pipe) diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 32808e50be12..3f7701321d21 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -505,7 +505,6 @@ struct radeon_bo { struct list_head va; /* Constant after initialization */ struct radeon_device *rdev; - struct drm_gem_object gem_base; struct ttm_bo_kmap_obj dma_buf_vmap; pid_t pid; @@ -513,7 +512,7 @@ struct radeon_bo { struct radeon_mn *mn; struct list_head mn_list; }; -#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base) +#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, tbo.base) int radeon_gem_debugfs_init(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index 7ce5064a59f6..1ea50ce16312 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c @@ -122,7 +122,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, if (rdev->asic->copy.dma) { time = radeon_benchmark_do_move(rdev, size, saddr, daddr, RADEON_BENCHMARK_COPY_DMA, n, - dobj->tbo.resv); + dobj->tbo.base.resv); if (time < 0) goto out_cleanup; if (time > 0) @@ -133,7 +133,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, if (rdev->asic->copy.blit) { time = radeon_benchmark_do_move(rdev, size, saddr, daddr, RADEON_BENCHMARK_COPY_BLIT, n, - dobj->tbo.resv); + dobj->tbo.base.resv); if (time < 0) goto out_cleanup; if (time > 0) diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index cef0e697a2ea..7e5254a34e84 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c @@ -257,7 +257,7 @@ static int radeon_cs_sync_rings(struct radeon_cs_parser *p) list_for_each_entry(reloc, &p->validated, tv.head) { struct reservation_object *resv; - resv = reloc->robj->tbo.resv; + resv = reloc->robj->tbo.base.resv; r = radeon_sync_resv(p->rdev, &p->ib.sync, resv, reloc->tv.num_shared); if (r) @@ -443,7 +443,7 @@ static void radeon_cs_parser_fini(struct radeon_cs_parser *parser, int error, bo if (bo == NULL) continue; - drm_gem_object_put_unlocked(&bo->gem_base); + drm_gem_object_put_unlocked(&bo->tbo.base); } } kfree(parser->track); diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index bd52f15e6330..7bf73230ac0b 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -275,7 +275,7 @@ static void radeon_unpin_work_func(struct work_struct *__work) } else DRM_ERROR("failed to reserve buffer after flip\n"); - drm_gem_object_put_unlocked(&work->old_rbo->gem_base); + drm_gem_object_put_unlocked(&work->old_rbo->tbo.base); kfree(work); } @@ -533,7 +533,7 @@ static int radeon_crtc_page_flip_target(struct drm_crtc *crtc, DRM_ERROR("failed to pin new rbo buffer before flip\n"); goto cleanup; } - work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.resv)); + work->fence = dma_fence_get(reservation_object_get_excl(new_rbo->tbo.base.resv)); radeon_bo_get_tiling_flags(new_rbo, &tiling_flags, NULL); radeon_bo_unreserve(new_rbo); @@ -607,7 +607,7 @@ pflip_cleanup: radeon_bo_unreserve(new_rbo); cleanup: - drm_gem_object_put_unlocked(&work->old_rbo->gem_base); + drm_gem_object_put_unlocked(&work->old_rbo->tbo.base); dma_fence_put(work->fence); kfree(work); return r; diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index a6cbe11f79c6..a4a78dfdef37 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -130,8 +130,7 @@ int radeon_gem_object_open(struct drm_gem_object *obj, struct drm_file *file_priv); void radeon_gem_object_close(struct drm_gem_object *obj, struct drm_file *file_priv); -struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *gobj, +struct dma_buf *radeon_gem_prime_export(struct drm_gem_object *gobj, int flags); extern int radeon_get_crtc_scanoutpos(struct drm_device *dev, unsigned int crtc, unsigned int flags, int *vpos, int *hpos, @@ -153,7 +152,6 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev, struct sg_table *sg); int radeon_gem_prime_pin(struct drm_gem_object *obj); void radeon_gem_prime_unpin(struct drm_gem_object *obj); -struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *); void *radeon_gem_prime_vmap(struct drm_gem_object *obj); void radeon_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); @@ -539,7 +537,7 @@ radeon_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe, static struct drm_driver kms_driver = { .driver_features = - DRIVER_USE_AGP | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER, + DRIVER_USE_AGP | DRIVER_GEM | DRIVER_RENDER, .load = radeon_driver_load_kms, .open = radeon_driver_open_kms, .postclose = radeon_driver_postclose_kms, @@ -565,10 +563,8 @@ static struct drm_driver kms_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_prime_export = radeon_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_pin = radeon_gem_prime_pin, .gem_prime_unpin = radeon_gem_prime_unpin, - .gem_prime_res_obj = radeon_gem_prime_res_obj, .gem_prime_get_sg_table = radeon_gem_prime_get_sg_table, .gem_prime_import_sg_table = radeon_gem_prime_import_sg_table, .gem_prime_vmap = radeon_gem_prime_vmap, diff --git a/drivers/gpu/drm/radeon/radeon_gem.c b/drivers/gpu/drm/radeon/radeon_gem.c index d8bc5d2dfd61..03873f21a734 100644 --- a/drivers/gpu/drm/radeon/radeon_gem.c +++ b/drivers/gpu/drm/radeon/radeon_gem.c @@ -83,7 +83,7 @@ retry: } return r; } - *obj = &robj->gem_base; + *obj = &robj->tbo.base; robj->pid = task_pid_nr(current); mutex_lock(&rdev->gem.mutex); @@ -114,7 +114,7 @@ static int radeon_gem_set_domain(struct drm_gem_object *gobj, } if (domain == RADEON_GEM_DOMAIN_CPU) { /* Asking for cpu access wait for object idle */ - r = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, 30 * HZ); + r = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ); if (!r) r = -EBUSY; @@ -449,7 +449,7 @@ int radeon_gem_busy_ioctl(struct drm_device *dev, void *data, } robj = gem_to_radeon_bo(gobj); - r = reservation_object_test_signaled_rcu(robj->tbo.resv, true); + r = reservation_object_test_signaled_rcu(robj->tbo.base.resv, true); if (r == 0) r = -EBUSY; else @@ -478,7 +478,7 @@ int radeon_gem_wait_idle_ioctl(struct drm_device *dev, void *data, } robj = gem_to_radeon_bo(gobj); - ret = reservation_object_wait_timeout_rcu(robj->tbo.resv, true, true, 30 * HZ); + ret = reservation_object_wait_timeout_rcu(robj->tbo.base.resv, true, true, 30 * HZ); if (ret == 0) r = -EBUSY; else if (ret < 0) diff --git a/drivers/gpu/drm/radeon/radeon_mn.c b/drivers/gpu/drm/radeon/radeon_mn.c index 8c3871ed23a9..0d64ace0e6c1 100644 --- a/drivers/gpu/drm/radeon/radeon_mn.c +++ b/drivers/gpu/drm/radeon/radeon_mn.c @@ -163,7 +163,7 @@ static int radeon_mn_invalidate_range_start(struct mmu_notifier *mn, continue; } - r = reservation_object_wait_timeout_rcu(bo->tbo.resv, + r = reservation_object_wait_timeout_rcu(bo->tbo.base.resv, true, false, MAX_SCHEDULE_TIMEOUT); if (r <= 0) DRM_ERROR("(%ld) failed to wait for user bo\n", r); diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 21f73fc86f38..9db8ba29ef68 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c @@ -85,9 +85,9 @@ static void radeon_ttm_bo_destroy(struct ttm_buffer_object *tbo) mutex_unlock(&bo->rdev->gem.mutex); radeon_bo_clear_surface_reg(bo); WARN_ON_ONCE(!list_empty(&bo->va)); - if (bo->gem_base.import_attach) - drm_prime_gem_destroy(&bo->gem_base, bo->tbo.sg); - drm_gem_object_release(&bo->gem_base); + if (bo->tbo.base.import_attach) + drm_prime_gem_destroy(&bo->tbo.base, bo->tbo.sg); + drm_gem_object_release(&bo->tbo.base); kfree(bo); } @@ -209,7 +209,7 @@ int radeon_bo_create(struct radeon_device *rdev, bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL); if (bo == NULL) return -ENOMEM; - drm_gem_private_object_init(rdev->ddev, &bo->gem_base, size); + drm_gem_private_object_init(rdev->ddev, &bo->tbo.base, size); bo->rdev = rdev; bo->surface_reg = -1; INIT_LIST_HEAD(&bo->list); @@ -442,13 +442,13 @@ void radeon_bo_force_delete(struct radeon_device *rdev) dev_err(rdev->dev, "Userspace still has active objects !\n"); list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) { dev_err(rdev->dev, "%p %p %lu %lu force free\n", - &bo->gem_base, bo, (unsigned long)bo->gem_base.size, - *((unsigned long *)&bo->gem_base.refcount)); + &bo->tbo.base, bo, (unsigned long)bo->tbo.base.size, + *((unsigned long *)&bo->tbo.base.refcount)); mutex_lock(&bo->rdev->gem.mutex); list_del_init(&bo->list); mutex_unlock(&bo->rdev->gem.mutex); /* this should unref the ttm bo */ - drm_gem_object_put_unlocked(&bo->gem_base); + drm_gem_object_put_unlocked(&bo->tbo.base); } } @@ -610,7 +610,7 @@ int radeon_bo_get_surface_reg(struct radeon_bo *bo) int steal; int i; - lockdep_assert_held(&bo->tbo.resv->lock.base); + reservation_object_assert_held(bo->tbo.base.resv); if (!bo->tiling_flags) return 0; @@ -736,7 +736,7 @@ void radeon_bo_get_tiling_flags(struct radeon_bo *bo, uint32_t *tiling_flags, uint32_t *pitch) { - lockdep_assert_held(&bo->tbo.resv->lock.base); + reservation_object_assert_held(bo->tbo.base.resv); if (tiling_flags) *tiling_flags = bo->tiling_flags; @@ -748,7 +748,7 @@ int radeon_bo_check_tiling(struct radeon_bo *bo, bool has_moved, bool force_drop) { if (!force_drop) - lockdep_assert_held(&bo->tbo.resv->lock.base); + reservation_object_assert_held(bo->tbo.base.resv); if (!(bo->tiling_flags & RADEON_TILING_SURFACE)) return 0; @@ -870,7 +870,7 @@ int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, bool no_wait) void radeon_bo_fence(struct radeon_bo *bo, struct radeon_fence *fence, bool shared) { - struct reservation_object *resv = bo->tbo.resv; + struct reservation_object *resv = bo->tbo.base.resv; if (shared) reservation_object_add_shared_fence(resv, &fence->base); diff --git a/drivers/gpu/drm/radeon/radeon_object.h b/drivers/gpu/drm/radeon/radeon_object.h index 9ffd8215d38a..e5554bf9140e 100644 --- a/drivers/gpu/drm/radeon/radeon_object.h +++ b/drivers/gpu/drm/radeon/radeon_object.h @@ -116,7 +116,7 @@ static inline unsigned radeon_bo_gpu_page_alignment(struct radeon_bo *bo) */ static inline u64 radeon_bo_mmap_offset(struct radeon_bo *bo) { - return drm_vma_node_offset_addr(&bo->tbo.vma_node); + return drm_vma_node_offset_addr(&bo->tbo.base.vma_node); } extern int radeon_bo_wait(struct radeon_bo *bo, u32 *mem_type, diff --git a/drivers/gpu/drm/radeon/radeon_prime.c b/drivers/gpu/drm/radeon/radeon_prime.c index d3a5bea9a2c5..52b0d0cd8cbe 100644 --- a/drivers/gpu/drm/radeon/radeon_prime.c +++ b/drivers/gpu/drm/radeon/radeon_prime.c @@ -68,10 +68,10 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev, struct radeon_bo *bo; int ret; - ww_mutex_lock(&resv->lock, NULL); + reservation_object_lock(resv, NULL); ret = radeon_bo_create(rdev, attach->dmabuf->size, PAGE_SIZE, false, RADEON_GEM_DOMAIN_GTT, 0, sg, resv, &bo); - ww_mutex_unlock(&resv->lock); + reservation_object_unlock(resv); if (ret) return ERR_PTR(ret); @@ -80,7 +80,7 @@ struct drm_gem_object *radeon_gem_prime_import_sg_table(struct drm_device *dev, mutex_unlock(&rdev->gem.mutex); bo->prime_shared_count = 1; - return &bo->gem_base; + return &bo->tbo.base; } int radeon_gem_prime_pin(struct drm_gem_object *obj) @@ -117,19 +117,11 @@ void radeon_gem_prime_unpin(struct drm_gem_object *obj) } -struct reservation_object *radeon_gem_prime_res_obj(struct drm_gem_object *obj) -{ - struct radeon_bo *bo = gem_to_radeon_bo(obj); - - return bo->tbo.resv; -} - -struct dma_buf *radeon_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *gobj, +struct dma_buf *radeon_gem_prime_export(struct drm_gem_object *gobj, int flags) { struct radeon_bo *bo = gem_to_radeon_bo(gobj); if (radeon_ttm_tt_has_userptr(bo->tbo.ttm)) return ERR_PTR(-EPERM); - return drm_gem_prime_export(dev, gobj, flags); + return drm_gem_prime_export(gobj, flags); } diff --git a/drivers/gpu/drm/radeon/radeon_test.c b/drivers/gpu/drm/radeon/radeon_test.c index 0f6ba81a1669..a5e1d2139e80 100644 --- a/drivers/gpu/drm/radeon/radeon_test.c +++ b/drivers/gpu/drm/radeon/radeon_test.c @@ -120,11 +120,11 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) if (ring == R600_RING_TYPE_DMA_INDEX) fence = radeon_copy_dma(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, - vram_obj->tbo.resv); + vram_obj->tbo.base.resv); else fence = radeon_copy_blit(rdev, gtt_addr, vram_addr, size / RADEON_GPU_PAGE_SIZE, - vram_obj->tbo.resv); + vram_obj->tbo.base.resv); if (IS_ERR(fence)) { DRM_ERROR("Failed GTT->VRAM copy %d\n", i); r = PTR_ERR(fence); @@ -171,11 +171,11 @@ static void radeon_do_test_moves(struct radeon_device *rdev, int flag) if (ring == R600_RING_TYPE_DMA_INDEX) fence = radeon_copy_dma(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, - vram_obj->tbo.resv); + vram_obj->tbo.base.resv); else fence = radeon_copy_blit(rdev, vram_addr, gtt_addr, size / RADEON_GPU_PAGE_SIZE, - vram_obj->tbo.resv); + vram_obj->tbo.base.resv); if (IS_ERR(fence)) { DRM_ERROR("Failed VRAM->GTT copy %d\n", i); r = PTR_ERR(fence); diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index fb3696bc616d..35ac75a11d38 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -184,7 +184,7 @@ static int radeon_verify_access(struct ttm_buffer_object *bo, struct file *filp) if (radeon_ttm_tt_has_userptr(bo->ttm)) return -EPERM; - return drm_vma_node_verify_access(&rbo->gem_base.vma_node, + return drm_vma_node_verify_access(&rbo->tbo.base.vma_node, filp->private_data); } @@ -244,7 +244,7 @@ static int radeon_move_blit(struct ttm_buffer_object *bo, BUILD_BUG_ON((PAGE_SIZE % RADEON_GPU_PAGE_SIZE) != 0); num_pages = new_mem->num_pages * (PAGE_SIZE / RADEON_GPU_PAGE_SIZE); - fence = radeon_copy(rdev, old_start, new_start, num_pages, bo->resv); + fence = radeon_copy(rdev, old_start, new_start, num_pages, bo->base.resv); if (IS_ERR(fence)) return PTR_ERR(fence); diff --git a/drivers/gpu/drm/radeon/radeon_uvd.c b/drivers/gpu/drm/radeon/radeon_uvd.c index ff4f794d1c86..311e69c2ed7f 100644 --- a/drivers/gpu/drm/radeon/radeon_uvd.c +++ b/drivers/gpu/drm/radeon/radeon_uvd.c @@ -477,7 +477,7 @@ static int radeon_uvd_cs_msg(struct radeon_cs_parser *p, struct radeon_bo *bo, return -EINVAL; } - f = reservation_object_get_excl(bo->tbo.resv); + f = reservation_object_get_excl(bo->tbo.base.resv); if (f) { r = radeon_fence_wait((struct radeon_fence *)f, false); if (r) { diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index 8512b02e9583..e48a05533126 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -702,7 +702,7 @@ int radeon_vm_update_page_directory(struct radeon_device *rdev, if (ib.length_dw != 0) { radeon_asic_vm_pad_ib(rdev, &ib); - radeon_sync_resv(rdev, &ib.sync, pd->tbo.resv, true); + radeon_sync_resv(rdev, &ib.sync, pd->tbo.base.resv, true); WARN_ON(ib.length_dw > ndw); r = radeon_ib_schedule(rdev, &ib, NULL, false); if (r) { @@ -830,8 +830,8 @@ static int radeon_vm_update_ptes(struct radeon_device *rdev, uint64_t pte; int r; - radeon_sync_resv(rdev, &ib->sync, pt->tbo.resv, true); - r = reservation_object_reserve_shared(pt->tbo.resv, 1); + radeon_sync_resv(rdev, &ib->sync, pt->tbo.base.resv, true); + r = reservation_object_reserve_shared(pt->tbo.base.resv, 1); if (r) return r; diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c index 6df37c2a9678..9c93eb4fad8b 100644 --- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c +++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c @@ -441,14 +441,11 @@ MODULE_DEVICE_TABLE(of, rcar_du_of_table); DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops); static struct drm_driver rcar_du_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME - | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/rockchip/Makefile b/drivers/gpu/drm/rockchip/Makefile index 524684ba7f6a..17a9e7eb2130 100644 --- a/drivers/gpu/drm/rockchip/Makefile +++ b/drivers/gpu/drm/rockchip/Makefile @@ -4,8 +4,7 @@ # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o \ - rockchip_drm_gem.o rockchip_drm_psr.o \ - rockchip_drm_vop.o rockchip_vop_reg.o + rockchip_drm_gem.o rockchip_drm_vop.o rockchip_vop_reg.o rockchipdrm-$(CONFIG_DRM_FBDEV_EMULATION) += rockchip_drm_fbdev.o rockchipdrm-$(CONFIG_ROCKCHIP_ANALOGIX_DP) += analogix_dp-rockchip.o diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c index 95e5c517a15f..7d7cb57410fc 100644 --- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c +++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c @@ -16,19 +16,18 @@ #include <linux/reset.h> #include <linux/clk.h> -#include <drm/drmP.h> -#include <drm/drm_dp_helper.h> -#include <drm/drm_of.h> -#include <drm/drm_panel.h> -#include <drm/drm_probe_helper.h> - #include <video/of_videomode.h> #include <video/videomode.h> +#include <drm/drm_atomic.h> +#include <drm/drm_atomic_helper.h> #include <drm/bridge/analogix_dp.h> +#include <drm/drm_dp_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> #include "rockchip_drm_drv.h" -#include "rockchip_drm_psr.h" #include "rockchip_drm_vop.h" #define RK3288_GRF_SOC_CON6 0x25c @@ -73,29 +72,6 @@ struct rockchip_dp_device { struct analogix_dp_plat_data plat_data; }; -static int analogix_dp_psr_set(struct drm_encoder *encoder, bool enabled) -{ - struct rockchip_dp_device *dp = to_dp(encoder); - int ret; - - if (!analogix_dp_psr_enabled(dp->adp)) - return 0; - - DRM_DEV_DEBUG(dp->dev, "%s PSR...\n", enabled ? "Entry" : "Exit"); - - ret = rockchip_drm_wait_vact_end(dp->encoder.crtc, - PSR_WAIT_LINE_FLAG_TIMEOUT_MS); - if (ret) { - DRM_DEV_ERROR(dp->dev, "line flag interrupt did not arrive\n"); - return -ETIMEDOUT; - } - - if (enabled) - return analogix_dp_enable_psr(dp->adp); - else - return analogix_dp_disable_psr(dp->adp); -} - static int rockchip_dp_pre_init(struct rockchip_dp_device *dp) { reset_control_assert(dp->rst); @@ -126,21 +102,9 @@ static int rockchip_dp_poweron_start(struct analogix_dp_plat_data *plat_data) return ret; } -static int rockchip_dp_poweron_end(struct analogix_dp_plat_data *plat_data) -{ - struct rockchip_dp_device *dp = to_dp(plat_data); - - return rockchip_drm_psr_inhibit_put(&dp->encoder); -} - static int rockchip_dp_powerdown(struct analogix_dp_plat_data *plat_data) { struct rockchip_dp_device *dp = to_dp(plat_data); - int ret; - - ret = rockchip_drm_psr_inhibit_get(&dp->encoder); - if (ret != 0) - return ret; clk_disable_unprepare(dp->pclk); @@ -180,12 +144,42 @@ static void rockchip_dp_drm_encoder_mode_set(struct drm_encoder *encoder, /* do nothing */ } -static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder) +static +struct drm_crtc *rockchip_dp_drm_get_new_crtc(struct drm_encoder *encoder, + struct drm_atomic_state *state) +{ + struct drm_connector *connector; + struct drm_connector_state *conn_state; + + connector = drm_atomic_get_new_connector_for_encoder(state, encoder); + if (!connector) + return NULL; + + conn_state = drm_atomic_get_new_connector_state(state, connector); + if (!conn_state) + return NULL; + + return conn_state->crtc; +} + +static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { struct rockchip_dp_device *dp = to_dp(encoder); + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; int ret; u32 val; + crtc = rockchip_dp_drm_get_new_crtc(encoder, state); + if (!crtc) + return; + + old_crtc_state = drm_atomic_get_old_crtc_state(state, crtc); + /* Coming back from self refresh, nothing to do */ + if (old_crtc_state && old_crtc_state->self_refresh_active) + return; + ret = drm_of_encoder_active_endpoint_id(dp->dev->of_node, encoder); if (ret < 0) return; @@ -210,9 +204,27 @@ static void rockchip_dp_drm_encoder_enable(struct drm_encoder *encoder) clk_disable_unprepare(dp->grfclk); } -static void rockchip_dp_drm_encoder_nop(struct drm_encoder *encoder) +static void rockchip_dp_drm_encoder_disable(struct drm_encoder *encoder, + struct drm_atomic_state *state) { - /* do nothing */ + struct rockchip_dp_device *dp = to_dp(encoder); + struct drm_crtc *crtc; + struct drm_crtc_state *new_crtc_state = NULL; + int ret; + + crtc = rockchip_dp_drm_get_new_crtc(encoder, state); + /* No crtc means we're doing a full shutdown */ + if (!crtc) + return; + + new_crtc_state = drm_atomic_get_new_crtc_state(state, crtc); + /* If we're not entering self-refresh, no need to wait for vact */ + if (!new_crtc_state || !new_crtc_state->self_refresh_active) + return; + + ret = rockchip_drm_wait_vact_end(crtc, PSR_WAIT_LINE_FLAG_TIMEOUT_MS); + if (ret) + DRM_DEV_ERROR(dp->dev, "line flag irq timed out\n"); } static int @@ -241,8 +253,8 @@ rockchip_dp_drm_encoder_atomic_check(struct drm_encoder *encoder, static struct drm_encoder_helper_funcs rockchip_dp_encoder_helper_funcs = { .mode_fixup = rockchip_dp_drm_encoder_mode_fixup, .mode_set = rockchip_dp_drm_encoder_mode_set, - .enable = rockchip_dp_drm_encoder_enable, - .disable = rockchip_dp_drm_encoder_nop, + .atomic_enable = rockchip_dp_drm_encoder_enable, + .atomic_disable = rockchip_dp_drm_encoder_disable, .atomic_check = rockchip_dp_drm_encoder_atomic_check, }; @@ -334,23 +346,16 @@ static int rockchip_dp_bind(struct device *dev, struct device *master, dp->plat_data.dev_type = dp->data->chip_type; dp->plat_data.power_on_start = rockchip_dp_poweron_start; - dp->plat_data.power_on_end = rockchip_dp_poweron_end; dp->plat_data.power_off = rockchip_dp_powerdown; dp->plat_data.get_modes = rockchip_dp_get_modes; - ret = rockchip_drm_psr_register(&dp->encoder, analogix_dp_psr_set); - if (ret < 0) - goto err_cleanup_encoder; - dp->adp = analogix_dp_bind(dev, dp->drm_dev, &dp->plat_data); if (IS_ERR(dp->adp)) { ret = PTR_ERR(dp->adp); - goto err_unreg_psr; + goto err_cleanup_encoder; } return 0; -err_unreg_psr: - rockchip_drm_psr_unregister(&dp->encoder); err_cleanup_encoder: dp->encoder.funcs->destroy(&dp->encoder); return ret; @@ -362,7 +367,6 @@ static void rockchip_dp_unbind(struct device *dev, struct device *master, struct rockchip_dp_device *dp = dev_get_drvdata(dev); analogix_dp_unbind(dp->adp); - rockchip_drm_psr_unregister(&dp->encoder); dp->encoder.funcs->destroy(&dp->encoder); dp->adp = ERR_PTR(-ENODEV); diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c index 8c32c32be85c..d505ea7d5384 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.c +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c @@ -4,24 +4,23 @@ * Author: Chris Zhong <zyw@rock-chips.com> */ -#include <drm/drmP.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_dp_helper.h> -#include <drm/drm_edid.h> -#include <drm/drm_of.h> -#include <drm/drm_probe_helper.h> - #include <linux/clk.h> #include <linux/component.h> #include <linux/extcon.h> #include <linux/firmware.h> -#include <linux/regmap.h> -#include <linux/reset.h> #include <linux/mfd/syscon.h> #include <linux/phy/phy.h> +#include <linux/regmap.h> +#include <linux/reset.h> #include <sound/hdmi-codec.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_dp_helper.h> +#include <drm/drm_edid.h> +#include <drm/drm_of.h> +#include <drm/drm_probe_helper.h> + #include "cdn-dp-core.h" #include "cdn-dp-reg.h" #include "rockchip_drm_vop.h" diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.h b/drivers/gpu/drm/rockchip/cdn-dp-core.h index f18a01e6cbc2..b85ea89eb60b 100644 --- a/drivers/gpu/drm/rockchip/cdn-dp-core.h +++ b/drivers/gpu/drm/rockchip/cdn-dp-core.h @@ -7,10 +7,10 @@ #ifndef _CDN_DP_CORE_H #define _CDN_DP_CORE_H -#include <drm/drmP.h> #include <drm/drm_dp_helper.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> + #include "rockchip_drm_drv.h" #define MAX_PHY 2 diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c index ef8486e5e2cd..bc073ec5c183 100644 --- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c @@ -6,10 +6,6 @@ * Nickey Yang <nickey.yang@rock-chips.com> */ -#include <drm/drmP.h> -#include <drm/drm_mipi_dsi.h> -#include <drm/bridge/dw_mipi_dsi.h> -#include <drm/drm_of.h> #include <linux/clk.h> #include <linux/iopoll.h> #include <linux/math64.h> @@ -18,8 +14,13 @@ #include <linux/of_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> + #include <video/mipi_display.h> +#include <drm/bridge/dw_mipi_dsi.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_of.h> + #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c index cdc304d4cd02..906891b03a38 100644 --- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c +++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c @@ -10,11 +10,10 @@ #include <linux/phy/phy.h> #include <linux/regmap.h> -#include <drm/drm_of.h> -#include <drm/drmP.h> +#include <drm/bridge/dw_hdmi.h> #include <drm/drm_edid.h> +#include <drm/drm_of.h> #include <drm/drm_probe_helper.h> -#include <drm/bridge/dw_hdmi.h> #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c index f8ca98d294d0..ed344a795b4d 100644 --- a/drivers/gpu/drm/rockchip/inno_hdmi.c +++ b/drivers/gpu/drm/rockchip/inno_hdmi.c @@ -15,10 +15,9 @@ #include <linux/mutex.h> #include <linux/of_device.h> -#include <drm/drm_of.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_edid.h> +#include <drm/drm_of.h> #include <drm/drm_probe_helper.h> #include "rockchip_drm_drv.h" diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c index 53d2c5bd61dc..30c177eb3022 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c @@ -6,11 +6,6 @@ * based on exynos_drm_drv.c */ -#include <drm/drmP.h> -#include <drm/drm_fb_helper.h> -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_of.h> -#include <drm/drm_probe_helper.h> #include <linux/dma-mapping.h> #include <linux/dma-iommu.h> #include <linux/pm_runtime.h> @@ -21,6 +16,13 @@ #include <linux/console.h> #include <linux/iommu.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + #include "rockchip_drm_drv.h" #include "rockchip_drm_fb.h" #include "rockchip_drm_fbdev.h" @@ -212,16 +214,13 @@ static const struct file_operations rockchip_drm_driver_fops = { }; static struct drm_driver rockchip_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | - DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .lastclose = drm_fb_helper_lastclose, .gem_vm_ops = &drm_gem_cma_vm_ops, .gem_free_object_unlocked = rockchip_gem_free_object, .dumb_create = rockchip_gem_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = rockchip_gem_prime_get_sg_table, .gem_prime_import_sg_table = rockchip_gem_prime_import_sg_table, .gem_prime_vmap = rockchip_gem_prime_vmap, diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c index 64ca87cf6d50..ca01234c037c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c @@ -5,18 +5,18 @@ */ #include <linux/kernel.h> + #include <drm/drm.h> -#include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_damage_helper.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> #include "rockchip_drm_drv.h" #include "rockchip_drm_fb.h" #include "rockchip_drm_gem.h" -#include "rockchip_drm_psr.h" static const struct drm_framebuffer_funcs rockchip_drm_fb_funcs = { .destroy = drm_gem_fb_destroy, @@ -105,31 +105,8 @@ err_gem_object_unreference: return ERR_PTR(ret); } -static void -rockchip_atomic_helper_commit_tail_rpm(struct drm_atomic_state *old_state) -{ - struct drm_device *dev = old_state->dev; - - rockchip_drm_psr_inhibit_get_state(old_state); - - drm_atomic_helper_commit_modeset_disables(dev, old_state); - - drm_atomic_helper_commit_modeset_enables(dev, old_state); - - drm_atomic_helper_commit_planes(dev, old_state, - DRM_PLANE_COMMIT_ACTIVE_ONLY); - - rockchip_drm_psr_inhibit_put_state(old_state); - - drm_atomic_helper_commit_hw_done(old_state); - - drm_atomic_helper_wait_for_vblanks(dev, old_state); - - drm_atomic_helper_cleanup_planes(dev, old_state); -} - static const struct drm_mode_config_helper_funcs rockchip_mode_config_helpers = { - .atomic_commit_tail = rockchip_atomic_helper_commit_tail_rpm, + .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm, }; static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = { diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c index bb8ac18298f6..02be6c5ff857 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fbdev.c @@ -5,8 +5,8 @@ */ #include <drm/drm.h> -#include <drm/drmP.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_probe_helper.h> #include "rockchip_drm_drv.h" diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c index ba9e77acbe16..291e89b4045f 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_gem.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_gem.c @@ -4,14 +4,14 @@ * Author:Mark Yao <mark.yao@rock-chips.com> */ +#include <linux/dma-buf.h> +#include <linux/iommu.h> + #include <drm/drm.h> -#include <drm/drmP.h> #include <drm/drm_gem.h> +#include <drm/drm_prime.h> #include <drm/drm_vma_manager.h> -#include <linux/dma-buf.h> -#include <linux/iommu.h> - #include "rockchip_drm_drv.h" #include "rockchip_drm_gem.h" diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c deleted file mode 100644 index b604747fe453..000000000000 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c +++ /dev/null @@ -1,282 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * Author: Yakir Yang <ykk@rock-chips.com> - */ - -#include <drm/drmP.h> -#include <drm/drm_atomic.h> -#include <drm/drm_probe_helper.h> - -#include "rockchip_drm_drv.h" -#include "rockchip_drm_psr.h" - -#define PSR_FLUSH_TIMEOUT_MS 100 - -struct psr_drv { - struct list_head list; - struct drm_encoder *encoder; - - struct mutex lock; - int inhibit_count; - bool enabled; - - struct delayed_work flush_work; - - int (*set)(struct drm_encoder *encoder, bool enable); -}; - -static struct psr_drv *find_psr_by_encoder(struct drm_encoder *encoder) -{ - struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; - struct psr_drv *psr; - - mutex_lock(&drm_drv->psr_list_lock); - list_for_each_entry(psr, &drm_drv->psr_list, list) { - if (psr->encoder == encoder) - goto out; - } - psr = ERR_PTR(-ENODEV); - -out: - mutex_unlock(&drm_drv->psr_list_lock); - return psr; -} - -static int psr_set_state_locked(struct psr_drv *psr, bool enable) -{ - int ret; - - if (psr->inhibit_count > 0) - return -EINVAL; - - if (enable == psr->enabled) - return 0; - - ret = psr->set(psr->encoder, enable); - if (ret) - return ret; - - psr->enabled = enable; - return 0; -} - -static void psr_flush_handler(struct work_struct *work) -{ - struct psr_drv *psr = container_of(to_delayed_work(work), - struct psr_drv, flush_work); - - mutex_lock(&psr->lock); - psr_set_state_locked(psr, true); - mutex_unlock(&psr->lock); -} - -/** - * rockchip_drm_psr_inhibit_put - release PSR inhibit on given encoder - * @encoder: encoder to obtain the PSR encoder - * - * Decrements PSR inhibit count on given encoder. Should be called only - * for a PSR inhibit count increment done before. If PSR inhibit counter - * reaches zero, PSR flush work is scheduled to make the hardware enter - * PSR mode in PSR_FLUSH_TIMEOUT_MS. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder) -{ - struct psr_drv *psr = find_psr_by_encoder(encoder); - - if (IS_ERR(psr)) - return PTR_ERR(psr); - - mutex_lock(&psr->lock); - --psr->inhibit_count; - WARN_ON(psr->inhibit_count < 0); - if (!psr->inhibit_count) - mod_delayed_work(system_wq, &psr->flush_work, - PSR_FLUSH_TIMEOUT_MS); - mutex_unlock(&psr->lock); - - return 0; -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put); - -void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state) -{ - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; - struct drm_encoder *encoder; - u32 encoder_mask = 0; - int i; - - for_each_old_crtc_in_state(state, crtc, crtc_state, i) { - encoder_mask |= crtc_state->encoder_mask; - encoder_mask |= crtc->state->encoder_mask; - } - - drm_for_each_encoder_mask(encoder, state->dev, encoder_mask) - rockchip_drm_psr_inhibit_get(encoder); -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get_state); - -void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state) -{ - struct drm_crtc *crtc; - struct drm_crtc_state *crtc_state; - struct drm_encoder *encoder; - u32 encoder_mask = 0; - int i; - - for_each_old_crtc_in_state(state, crtc, crtc_state, i) { - encoder_mask |= crtc_state->encoder_mask; - encoder_mask |= crtc->state->encoder_mask; - } - - drm_for_each_encoder_mask(encoder, state->dev, encoder_mask) - rockchip_drm_psr_inhibit_put(encoder); -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_put_state); - -/** - * rockchip_drm_psr_inhibit_get - acquire PSR inhibit on given encoder - * @encoder: encoder to obtain the PSR encoder - * - * Increments PSR inhibit count on given encoder. This function guarantees - * that after it returns PSR is turned off on given encoder and no PSR-related - * hardware state change occurs at least until a matching call to - * rockchip_drm_psr_inhibit_put() is done. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder) -{ - struct psr_drv *psr = find_psr_by_encoder(encoder); - - if (IS_ERR(psr)) - return PTR_ERR(psr); - - mutex_lock(&psr->lock); - psr_set_state_locked(psr, false); - ++psr->inhibit_count; - mutex_unlock(&psr->lock); - cancel_delayed_work_sync(&psr->flush_work); - - return 0; -} -EXPORT_SYMBOL(rockchip_drm_psr_inhibit_get); - -static void rockchip_drm_do_flush(struct psr_drv *psr) -{ - cancel_delayed_work_sync(&psr->flush_work); - - mutex_lock(&psr->lock); - if (!psr_set_state_locked(psr, false)) - mod_delayed_work(system_wq, &psr->flush_work, - PSR_FLUSH_TIMEOUT_MS); - mutex_unlock(&psr->lock); -} - -/** - * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders - * @dev: drm device - * - * Disable the PSR function for all registered encoders, and then enable the - * PSR function back after PSR_FLUSH_TIMEOUT. If encoder PSR state have been - * changed during flush time, then keep the state no change after flush - * timeout. - * - * Returns: - * Zero on success, negative errno on failure. - */ -void rockchip_drm_psr_flush_all(struct drm_device *dev) -{ - struct rockchip_drm_private *drm_drv = dev->dev_private; - struct psr_drv *psr; - - mutex_lock(&drm_drv->psr_list_lock); - list_for_each_entry(psr, &drm_drv->psr_list, list) - rockchip_drm_do_flush(psr); - mutex_unlock(&drm_drv->psr_list_lock); -} -EXPORT_SYMBOL(rockchip_drm_psr_flush_all); - -/** - * rockchip_drm_psr_register - register encoder to psr driver - * @encoder: encoder that obtain the PSR function - * @psr_set: call back to set PSR state - * - * The function returns with PSR inhibit counter initialized with one - * and the caller (typically encoder driver) needs to call - * rockchip_drm_psr_inhibit_put() when it becomes ready to accept PSR - * enable request. - * - * Returns: - * Zero on success, negative errno on failure. - */ -int rockchip_drm_psr_register(struct drm_encoder *encoder, - int (*psr_set)(struct drm_encoder *, bool enable)) -{ - struct rockchip_drm_private *drm_drv; - struct psr_drv *psr; - - if (!encoder || !psr_set) - return -EINVAL; - - drm_drv = encoder->dev->dev_private; - - psr = kzalloc(sizeof(struct psr_drv), GFP_KERNEL); - if (!psr) - return -ENOMEM; - - INIT_DELAYED_WORK(&psr->flush_work, psr_flush_handler); - mutex_init(&psr->lock); - - psr->inhibit_count = 1; - psr->enabled = false; - psr->encoder = encoder; - psr->set = psr_set; - - mutex_lock(&drm_drv->psr_list_lock); - list_add_tail(&psr->list, &drm_drv->psr_list); - mutex_unlock(&drm_drv->psr_list_lock); - - return 0; -} -EXPORT_SYMBOL(rockchip_drm_psr_register); - -/** - * rockchip_drm_psr_unregister - unregister encoder to psr driver - * @encoder: encoder that obtain the PSR function - * @psr_set: call back to set PSR state - * - * It is expected that the PSR inhibit counter is 1 when this function is - * called, which corresponds to a state when related encoder has been - * disconnected from any CRTCs and its driver called - * rockchip_drm_psr_inhibit_get() to stop the PSR logic. - * - * Returns: - * Zero on success, negative errno on failure. - */ -void rockchip_drm_psr_unregister(struct drm_encoder *encoder) -{ - struct rockchip_drm_private *drm_drv = encoder->dev->dev_private; - struct psr_drv *psr, *n; - - mutex_lock(&drm_drv->psr_list_lock); - list_for_each_entry_safe(psr, n, &drm_drv->psr_list, list) { - if (psr->encoder == encoder) { - /* - * Any other value would mean that the encoder - * is still in use. - */ - WARN_ON(psr->inhibit_count != 1); - - list_del(&psr->list); - kfree(psr); - } - } - mutex_unlock(&drm_drv->psr_list_lock); -} -EXPORT_SYMBOL(rockchip_drm_psr_unregister); diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h deleted file mode 100644 index 28a9c399114e..000000000000 --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h +++ /dev/null @@ -1,22 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd - * Author: Yakir Yang <ykk@rock-chips.com> - */ - -#ifndef __ROCKCHIP_DRM_PSR___ -#define __ROCKCHIP_DRM_PSR___ - -void rockchip_drm_psr_flush_all(struct drm_device *dev); - -int rockchip_drm_psr_inhibit_put(struct drm_encoder *encoder); -int rockchip_drm_psr_inhibit_get(struct drm_encoder *encoder); - -void rockchip_drm_psr_inhibit_get_state(struct drm_atomic_state *state); -void rockchip_drm_psr_inhibit_put_state(struct drm_atomic_state *state); - -int rockchip_drm_psr_register(struct drm_encoder *encoder, - int (*psr_set)(struct drm_encoder *, bool enable)); -void rockchip_drm_psr_unregister(struct drm_encoder *encoder); - -#endif /* __ROCKCHIP_DRM_PSR__ */ diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c index 09a790c2f3a1..2f821c58007c 100644 --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c @@ -4,40 +4,43 @@ * Author:Mark Yao <mark.yao@rock-chips.com> */ +#include <linux/clk.h> +#include <linux/component.h> +#include <linux/delay.h> +#include <linux/iopoll.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/overflow.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> +#include <linux/reset.h> + #include <drm/drm.h> -#include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_uapi.h> #include <drm/drm_crtc.h> #include <drm/drm_flip_work.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_self_refresh_helper.h> +#include <drm/drm_vblank.h> + #ifdef CONFIG_DRM_ANALOGIX_DP #include <drm/bridge/analogix_dp.h> #endif -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/clk.h> -#include <linux/iopoll.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/pm_runtime.h> -#include <linux/component.h> -#include <linux/overflow.h> - -#include <linux/reset.h> -#include <linux/delay.h> - #include "rockchip_drm_drv.h" #include "rockchip_drm_gem.h" #include "rockchip_drm_fb.h" -#include "rockchip_drm_psr.h" #include "rockchip_drm_vop.h" #include "rockchip_rgb.h" +#define VOP_SELF_REFRESH_ENTRY_DELAY_MS 100 + #define VOP_WIN_SET(vop, win, name, v) \ vop_reg_set(vop, &win->phy->name, win->base, ~0, v, #name) #define VOP_SCL_SET(vop, win, name, v) \ @@ -79,7 +82,7 @@ vop_get_intr_type(vop, &vop->data->intr->name, type) #define VOP_WIN_GET(vop, win, name) \ - vop_read_reg(vop, win->offset, win->phy->name) + vop_read_reg(vop, win->base, &win->phy->name) #define VOP_WIN_HAS_REG(win, name) \ (!!(win->phy->name.mask)) @@ -124,6 +127,7 @@ struct vop { bool is_enabled; struct completion dsp_hold_completion; + unsigned int win_enabled; /* protected by dev->event_lock */ struct drm_pending_vblank_event *event; @@ -528,8 +532,10 @@ static void vop_core_clks_disable(struct vop *vop) clk_disable(vop->hclk); } -static void vop_win_disable(struct vop *vop, const struct vop_win_data *win) +static void vop_win_disable(struct vop *vop, const struct vop_win *vop_win) { + const struct vop_win_data *win = vop_win->data; + if (win->phy->scl && win->phy->scl->ext) { VOP_SCL_SET_EXT(vop, win, yrgb_hor_scl_mode, SCALE_NONE); VOP_SCL_SET_EXT(vop, win, yrgb_ver_scl_mode, SCALE_NONE); @@ -538,9 +544,10 @@ static void vop_win_disable(struct vop *vop, const struct vop_win_data *win) } VOP_WIN_SET(vop, win, enable, 0); + vop->win_enabled &= ~BIT(VOP_WIN_TO_INDEX(vop_win)); } -static int vop_enable(struct drm_crtc *crtc) +static int vop_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { struct vop *vop = to_vop(crtc); int ret, i; @@ -580,12 +587,17 @@ static int vop_enable(struct drm_crtc *crtc) * We need to make sure that all windows are disabled before we * enable the crtc. Otherwise we might try to scan from a destroyed * buffer later. + * + * In the case of enable-after-PSR, we don't need to worry about this + * case since the buffer is guaranteed to be valid and disabling the + * window will result in screen glitches on PSR exit. */ - for (i = 0; i < vop->data->win_size; i++) { - struct vop_win *vop_win = &vop->win[i]; - const struct vop_win_data *win = vop_win->data; + if (!old_state || !old_state->self_refresh_active) { + for (i = 0; i < vop->data->win_size; i++) { + struct vop_win *vop_win = &vop->win[i]; - vop_win_disable(vop, win); + vop_win_disable(vop, vop_win); + } } spin_unlock(&vop->reg_lock); @@ -615,6 +627,25 @@ err_put_pm_runtime: return ret; } +static void rockchip_drm_set_win_enabled(struct drm_crtc *crtc, bool enabled) +{ + struct vop *vop = to_vop(crtc); + int i; + + spin_lock(&vop->reg_lock); + + for (i = 0; i < vop->data->win_size; i++) { + struct vop_win *vop_win = &vop->win[i]; + const struct vop_win_data *win = vop_win->data; + + VOP_WIN_SET(vop, win, enable, + enabled && (vop->win_enabled & BIT(i))); + } + vop_cfg_done(vop); + + spin_unlock(&vop->reg_lock); +} + static void vop_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -622,9 +653,16 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, WARN_ON(vop->event); + if (crtc->state->self_refresh_active) + rockchip_drm_set_win_enabled(crtc, false); + mutex_lock(&vop->vop_lock); + drm_crtc_vblank_off(crtc); + if (crtc->state->self_refresh_active) + goto out; + /* * Vop standby will take effect at end of current frame, * if dsp hold valid irq happen, it means standby complete. @@ -655,6 +693,8 @@ static void vop_crtc_atomic_disable(struct drm_crtc *crtc, clk_disable(vop->dclk); vop_core_clks_disable(vop); pm_runtime_put(vop->dev); + +out: mutex_unlock(&vop->vop_lock); if (crtc->state->event && !crtc->state->active) { @@ -726,7 +766,6 @@ static void vop_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_state *old_state) { struct vop_win *vop_win = to_vop_win(plane); - const struct vop_win_data *win = vop_win->data; struct vop *vop = to_vop(old_state->crtc); if (!old_state->crtc) @@ -734,7 +773,7 @@ static void vop_plane_atomic_disable(struct drm_plane *plane, spin_lock(&vop->reg_lock); - vop_win_disable(vop, win); + vop_win_disable(vop, vop_win); spin_unlock(&vop->reg_lock); } @@ -873,6 +912,7 @@ static void vop_plane_atomic_update(struct drm_plane *plane, } VOP_WIN_SET(vop, win, enable, 1); + vop->win_enabled |= BIT(win_index); spin_unlock(&vop->reg_lock); } @@ -924,12 +964,10 @@ static void vop_plane_atomic_async_update(struct drm_plane *plane, swap(plane->state->fb, new_state->fb); if (vop->is_enabled) { - rockchip_drm_psr_inhibit_get_state(new_state->state); vop_plane_atomic_update(plane, plane->state); spin_lock(&vop->reg_lock); vop_cfg_done(vop); spin_unlock(&vop->reg_lock); - rockchip_drm_psr_inhibit_put_state(new_state->state); /* * A scanout can still be occurring, so we can't drop the @@ -1033,11 +1071,17 @@ static void vop_crtc_atomic_enable(struct drm_crtc *crtc, int dither_bpc = s->output_bpc ? s->output_bpc : 10; int ret; + if (old_state && old_state->self_refresh_active) { + drm_crtc_vblank_on(crtc); + rockchip_drm_set_win_enabled(crtc, true); + return; + } + mutex_lock(&vop->vop_lock); WARN_ON(vop->event); - ret = vop_enable(crtc); + ret = vop_enable(crtc, old_state); if (ret) { mutex_unlock(&vop->vop_lock); DRM_DEV_ERROR(vop->dev, "Failed to enable vop (%d)\n", ret); @@ -1519,6 +1563,13 @@ static int vop_create_crtc(struct vop *vop) init_completion(&vop->line_flag_completion); crtc->port = port; + ret = drm_self_refresh_helper_init(crtc, + VOP_SELF_REFRESH_ENTRY_DELAY_MS); + if (ret) + DRM_DEV_DEBUG_KMS(vop->dev, + "Failed to init %s with SR helpers %d, ignoring\n", + crtc->name, ret); + return 0; err_cleanup_crtc: @@ -1536,6 +1587,8 @@ static void vop_destroy_crtc(struct vop *vop) struct drm_device *drm_dev = vop->drm_dev; struct drm_plane *plane, *tmp; + drm_self_refresh_helper_cleanup(crtc); + of_node_put(crtc->port); /* @@ -1560,7 +1613,6 @@ static void vop_destroy_crtc(struct vop *vop) static int vop_initial(struct vop *vop) { - const struct vop_data *vop_data = vop->data; struct reset_control *ahb_rst; int i, ret; @@ -1627,12 +1679,13 @@ static int vop_initial(struct vop *vop) VOP_REG_SET(vop, misc, global_regdone_en, 1); VOP_REG_SET(vop, common, dsp_blank, 0); - for (i = 0; i < vop_data->win_size; i++) { - const struct vop_win_data *win = &vop_data->win[i]; + for (i = 0; i < vop->data->win_size; i++) { + struct vop_win *vop_win = &vop->win[i]; + const struct vop_win_data *win = vop_win->data; int channel = i * 2 + 1; VOP_WIN_SET(vop, win, channel, (channel + 1) << 4 | channel); - vop_win_disable(vop, win); + vop_win_disable(vop, vop_win); VOP_WIN_SET(vop, win, gate, 1); } diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c index 830858a809e5..64aefa856896 100644 --- a/drivers/gpu/drm/rockchip/rockchip_lvds.c +++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c @@ -6,21 +6,21 @@ * Sandy Huang <hjc@rock-chips.com> */ -#include <drm/drmP.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_dp_helper.h> -#include <drm/drm_panel.h> -#include <drm/drm_of.h> -#include <drm/drm_probe_helper.h> - -#include <linux/component.h> #include <linux/clk.h> +#include <linux/component.h> #include <linux/mfd/syscon.h> #include <linux/of_graph.h> #include <linux/pinctrl/devinfo.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/reset.h> +#include <drm/drm_atomic_helper.h> + +#include <drm/drm_dp_helper.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" diff --git a/drivers/gpu/drm/rockchip/rockchip_rgb.c b/drivers/gpu/drm/rockchip/rockchip_rgb.c index ce4d82d293e4..89e0bb0fe0ab 100644 --- a/drivers/gpu/drm/rockchip/rockchip_rgb.c +++ b/drivers/gpu/drm/rockchip/rockchip_rgb.c @@ -5,16 +5,15 @@ * Sandy Huang <hjc@rock-chips.com> */ -#include <drm/drmP.h> +#include <linux/component.h> +#include <linux/of_graph.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_dp_helper.h> -#include <drm/drm_panel.h> #include <drm/drm_of.h> +#include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> -#include <linux/component.h> -#include <linux/of_graph.h> - #include "rockchip_drm_drv.h" #include "rockchip_drm_vop.h" diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c index 7b9c74750f6d..d1494be14471 100644 --- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c +++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c @@ -4,10 +4,15 @@ * Author:Mark Yao <mark.yao@rock-chips.com> */ -#include <drm/drmP.h> - -#include <linux/kernel.h> #include <linux/component.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> + +#include <drm/drm_fourcc.h> +#include <drm/drm_plane.h> +#include <drm/drm_print.h> #include "rockchip_drm_vop.h" #include "rockchip_vop_reg.h" diff --git a/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h b/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h index 1626f3967130..d79086498aff 100644 --- a/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h +++ b/drivers/gpu/drm/scheduler/gpu_scheduler_trace.h @@ -28,8 +28,6 @@ #include <linux/types.h> #include <linux/tracepoint.h> -#include <drm/drmP.h> - #undef TRACE_SYSTEM #define TRACE_SYSTEM gpu_scheduler #define TRACE_INCLUDE_FILE gpu_scheduler_trace diff --git a/drivers/gpu/drm/scheduler/sched_entity.c b/drivers/gpu/drm/scheduler/sched_entity.c index 35ddbec1375a..d5a6a946f486 100644 --- a/drivers/gpu/drm/scheduler/sched_entity.c +++ b/drivers/gpu/drm/scheduler/sched_entity.c @@ -22,6 +22,9 @@ */ #include <linux/kthread.h> +#include <linux/slab.h> + +#include <drm/drm_print.h> #include <drm/gpu_scheduler.h> #include "gpu_scheduler_trace.h" diff --git a/drivers/gpu/drm/scheduler/sched_fence.c b/drivers/gpu/drm/scheduler/sched_fence.c index d8d2dff9ea2f..54977408f574 100644 --- a/drivers/gpu/drm/scheduler/sched_fence.c +++ b/drivers/gpu/drm/scheduler/sched_fence.c @@ -22,9 +22,11 @@ */ #include <linux/kthread.h> -#include <linux/wait.h> +#include <linux/module.h> #include <linux/sched.h> -#include <drm/drmP.h> +#include <linux/slab.h> +#include <linux/wait.h> + #include <drm/gpu_scheduler.h> static struct kmem_cache *sched_fence_slab; diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c index c1058eece16b..9a0ee74d82dc 100644 --- a/drivers/gpu/drm/scheduler/sched_main.c +++ b/drivers/gpu/drm/scheduler/sched_main.c @@ -48,7 +48,8 @@ #include <linux/wait.h> #include <linux/sched.h> #include <uapi/linux/sched/types.h> -#include <drm/drmP.h> + +#include <drm/drm_print.h> #include <drm/gpu_scheduler.h> #include <drm/spsc_queue.h> diff --git a/drivers/gpu/drm/selftests/test-drm_framebuffer.c b/drivers/gpu/drm/selftests/test-drm_framebuffer.c index a04d02dacce2..74d5561a862b 100644 --- a/drivers/gpu/drm/selftests/test-drm_framebuffer.c +++ b/drivers/gpu/drm/selftests/test-drm_framebuffer.c @@ -3,7 +3,12 @@ * Test cases for the drm_framebuffer functions */ -#include <drm/drmP.h> +#include <linux/kernel.h> + +#include <drm/drm_device.h> +#include <drm/drm_mode.h> +#include <drm/drm_fourcc.h> + #include "../drm_crtc_internal.h" #include "test-drm_modeset_common.h" diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c index b6988a6d698e..75a752d59ef1 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.c @@ -10,13 +10,14 @@ #include <linux/backlight.h> #include <linux/clk.h> -#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "shmob_drm_backlight.h" #include "shmob_drm_crtc.h" diff --git a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h index 9ca6920641d8..21718843f46d 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_crtc.h +++ b/drivers/gpu/drm/shmobile/shmob_drm_crtc.h @@ -10,12 +10,14 @@ #ifndef __SHMOB_DRM_CRTC_H__ #define __SHMOB_DRM_CRTC_H__ -#include <drm/drmP.h> #include <drm/drm_crtc.h> +#include <drm/drm_connector.h> #include <drm/drm_encoder.h> struct backlight_device; +struct drm_pending_vblank_event; struct shmob_drm_device; +struct shmob_drm_format_info; struct shmob_drm_crtc { struct drm_crtc crtc; diff --git a/drivers/gpu/drm/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/shmobile/shmob_drm_drv.c index cb821adfc321..b8c0930959c7 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_drv.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_drv.c @@ -15,10 +15,12 @@ #include <linux/pm.h> #include <linux/slab.h> -#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_irq.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "shmob_drm_drv.h" #include "shmob_drm_kms.h" @@ -127,15 +129,12 @@ static irqreturn_t shmob_drm_irq(int irq, void *arg) DEFINE_DRM_GEM_CMA_FOPS(shmob_drm_fops); static struct drm_driver shmob_drm_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET - | DRIVER_PRIME, + .driver_features = DRIVER_GEM | DRIVER_MODESET, .irq_handler = shmob_drm_irq, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/shmobile/shmob_drm_kms.c b/drivers/gpu/drm/shmobile/shmob_drm_kms.c index 2e08bc203bf9..c51197b6fd85 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_kms.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_kms.c @@ -7,7 +7,6 @@ * Laurent Pinchart (laurent.pinchart@ideasonboard.com) */ -#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.c b/drivers/gpu/drm/shmobile/shmob_drm_plane.c index 1d1ee5e51351..cbc464f006b4 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.c +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.c @@ -7,10 +7,10 @@ * Laurent Pinchart (laurent.pinchart@ideasonboard.com) */ -#include <drm/drmP.h> #include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include "shmob_drm_drv.h" diff --git a/drivers/gpu/drm/shmobile/shmob_drm_plane.h b/drivers/gpu/drm/shmobile/shmob_drm_plane.h index bae67cc8c628..e72b21a4288f 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_plane.h +++ b/drivers/gpu/drm/shmobile/shmob_drm_plane.h @@ -10,6 +10,7 @@ #ifndef __SHMOB_DRM_PLANE_H__ #define __SHMOB_DRM_PLANE_H__ +struct drm_plane; struct shmob_drm_device; int shmob_drm_plane_create(struct shmob_drm_device *sdev, unsigned int index); diff --git a/drivers/gpu/drm/shmobile/shmob_drm_regs.h b/drivers/gpu/drm/shmobile/shmob_drm_regs.h index 9eb0b3d01df8..058533685c4c 100644 --- a/drivers/gpu/drm/shmobile/shmob_drm_regs.h +++ b/drivers/gpu/drm/shmobile/shmob_drm_regs.h @@ -11,6 +11,9 @@ #define __SHMOB_DRM_REGS_H__ #include <linux/io.h> +#include <linux/jiffies.h> + +#include "shmob_drm_drv.h" /* Register definitions */ #define LDDCKPAT1R 0x400 diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c index bb6ae6dd66c9..a39fc36f815b 100644 --- a/drivers/gpu/drm/sti/sti_drv.c +++ b/drivers/gpu/drm/sti/sti_drv.c @@ -23,7 +23,6 @@ #include "sti_crtc.h" #include "sti_drv.h" -#include "sti_drv.h" #include "sti_plane.h" #define DRIVER_NAME "sti" @@ -141,8 +140,7 @@ static void sti_mode_config_init(struct drm_device *dev) DEFINE_DRM_GEM_CMA_FOPS(sti_driver_fops); static struct drm_driver sti_driver = { - .driver_features = DRIVER_MODESET | - DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, @@ -153,8 +151,6 @@ static struct drm_driver sti_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c index 9e6d5d8b7030..e55870190bf5 100644 --- a/drivers/gpu/drm/sti/sti_dvo.c +++ b/drivers/gpu/drm/sti/sti_dvo.c @@ -221,8 +221,7 @@ static void sti_dvo_disable(struct drm_bridge *bridge) writel(0x00000000, dvo->regs + DVO_DOF_CFG); - if (dvo->panel) - dvo->panel->funcs->disable(dvo->panel); + drm_panel_disable(dvo->panel); /* Disable/unprepare dvo clock */ clk_disable_unprepare(dvo->clk_pix); @@ -262,8 +261,7 @@ static void sti_dvo_pre_enable(struct drm_bridge *bridge) if (clk_prepare_enable(dvo->clk)) DRM_ERROR("Failed to prepare/enable dvo clk\n"); - if (dvo->panel) - dvo->panel->funcs->enable(dvo->panel); + drm_panel_enable(dvo->panel); /* Set LUT */ writel(config->lowbyte, dvo->regs + DVO_LUT_PROG_LOW); @@ -340,7 +338,7 @@ static int sti_dvo_connector_get_modes(struct drm_connector *connector) struct sti_dvo *dvo = dvo_connector->dvo; if (dvo->panel) - return dvo->panel->funcs->get_modes(dvo->panel); + return drm_panel_get_modes(dvo->panel); return 0; } diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index f03d617edc4c..9862c322f0c4 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -849,10 +849,13 @@ static int hdmi_audio_configure(struct sti_hdmi *hdmi) switch (info->channels) { case 8: audio_cfg |= HDMI_AUD_CFG_CH78_VALID; + /* fall through */ case 6: audio_cfg |= HDMI_AUD_CFG_CH56_VALID; + /* fall through */ case 4: audio_cfg |= HDMI_AUD_CFG_CH34_VALID | HDMI_AUD_CFG_8CH; + /* fall through */ case 2: audio_cfg |= HDMI_AUD_CFG_CH12_VALID; break; @@ -1284,8 +1287,10 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data) drm_connector->polled = DRM_CONNECTOR_POLL_HPD; - drm_connector_init(drm_dev, drm_connector, - &sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA); + drm_connector_init_with_ddc(drm_dev, drm_connector, + &sti_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + hdmi->ddc_adapt); drm_connector_helper_add(drm_connector, &sti_hdmi_connector_helper_funcs); diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c index e1b3c8cb7287..aba79c172512 100644 --- a/drivers/gpu/drm/sti/sti_tvout.c +++ b/drivers/gpu/drm/sti/sti_tvout.c @@ -669,10 +669,9 @@ sti_tvout_create_dvo_encoder(struct drm_device *dev, encoder->tvout = tvout; - drm_encoder = (struct drm_encoder *)encoder; + drm_encoder = &encoder->encoder; drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; - drm_encoder->possible_clones = 1 << 0; drm_encoder_init(dev, drm_encoder, &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_LVDS, @@ -722,10 +721,9 @@ static struct drm_encoder *sti_tvout_create_hda_encoder(struct drm_device *dev, encoder->tvout = tvout; - drm_encoder = (struct drm_encoder *) encoder; + drm_encoder = &encoder->encoder; drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; - drm_encoder->possible_clones = 1 << 0; drm_encoder_init(dev, drm_encoder, &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_DAC, NULL); @@ -771,10 +769,9 @@ static struct drm_encoder *sti_tvout_create_hdmi_encoder(struct drm_device *dev, encoder->tvout = tvout; - drm_encoder = (struct drm_encoder *) encoder; + drm_encoder = &encoder->encoder; drm_encoder->possible_crtcs = ENCODER_CRTC_MASK; - drm_encoder->possible_clones = 1 << 1; drm_encoder_init(dev, drm_encoder, &sti_tvout_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL); @@ -790,6 +787,13 @@ static void sti_tvout_create_encoders(struct drm_device *dev, tvout->hdmi = sti_tvout_create_hdmi_encoder(dev, tvout); tvout->hda = sti_tvout_create_hda_encoder(dev, tvout); tvout->dvo = sti_tvout_create_dvo_encoder(dev, tvout); + + tvout->hdmi->possible_clones = drm_encoder_mask(tvout->hdmi) | + drm_encoder_mask(tvout->hda) | drm_encoder_mask(tvout->dvo); + tvout->hda->possible_clones = drm_encoder_mask(tvout->hdmi) | + drm_encoder_mask(tvout->hda) | drm_encoder_mask(tvout->dvo); + tvout->dvo->possible_clones = drm_encoder_mask(tvout->hdmi) | + drm_encoder_mask(tvout->hda) | drm_encoder_mask(tvout->dvo); } static void sti_tvout_destroy_encoders(struct sti_tvout *tvout) diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c index 9dee4e430de5..5a9f9aca8bc2 100644 --- a/drivers/gpu/drm/stm/drv.c +++ b/drivers/gpu/drm/stm/drv.c @@ -54,8 +54,7 @@ static int stm_gem_cma_dumb_create(struct drm_file *file, DEFINE_DRM_GEM_CMA_FOPS(drv_driver_fops); static struct drm_driver drv_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .name = "stm", .desc = "STMicroelectronics SoC DRM", .date = "20170330", @@ -68,8 +67,6 @@ static struct drm_driver drv_driver = { .prime_fd_to_handle = drm_gem_prime_fd_to_handle, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c index 0ab32fee6c1b..a03a642c147c 100644 --- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c +++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c @@ -8,13 +8,17 @@ #include <linux/clk.h> #include <linux/iopoll.h> +#include <linux/mod_devicetable.h> #include <linux/module.h> +#include <linux/platform_device.h> #include <linux/regulator/consumer.h> -#include <drm/drmP.h> -#include <drm/drm_mipi_dsi.h> -#include <drm/bridge/dw_mipi_dsi.h> + #include <video/mipi_display.h> +#include <drm/bridge/dw_mipi_dsi.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_print.h> + #define HWVER_130 0x31333000 /* IP version 1.30 */ #define HWVER_131 0x31333100 /* IP version 1.31 */ diff --git a/drivers/gpu/drm/stm/ltdc.c b/drivers/gpu/drm/stm/ltdc.c index 2fe6c4a8d915..3ab4fbf8eb0d 100644 --- a/drivers/gpu/drm/stm/ltdc.c +++ b/drivers/gpu/drm/stm/ltdc.c @@ -26,6 +26,7 @@ #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> @@ -922,6 +923,7 @@ static const struct drm_plane_funcs ltdc_plane_funcs = { }; static const struct drm_plane_helper_funcs ltdc_plane_helper_funcs = { + .prepare_fb = drm_gem_fb_prepare_fb, .atomic_check = ltdc_plane_atomic_check, .atomic_update = ltdc_plane_atomic_update, .atomic_disable = ltdc_plane_atomic_disable, diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c index 78d8c3afe825..4e29f4fe4a05 100644 --- a/drivers/gpu/drm/sun4i/sun4i_backend.c +++ b/drivers/gpu/drm/sun4i/sun4i_backend.c @@ -6,21 +6,23 @@ * Maxime Ripard <maxime.ripard@free-electrons.com> */ -#include <drm/drmP.h> +#include <linux/component.h> +#include <linux/list.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_graph.h> +#include <linux/platform_device.h> +#include <linux/reset.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <linux/component.h> -#include <linux/list.h> -#include <linux/of_device.h> -#include <linux/of_graph.h> -#include <linux/reset.h> - #include "sun4i_backend.h" #include "sun4i_drv.h" #include "sun4i_frontend.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_crtc.c b/drivers/gpu/drm/sun4i/sun4i_crtc.c index 9d8504f813a4..3a153648b369 100644 --- a/drivers/gpu/drm/sun4i/sun4i_crtc.c +++ b/drivers/gpu/drm/sun4i/sun4i_crtc.c @@ -6,12 +6,6 @@ * Maxime Ripard <maxime.ripard@free-electrons.com> */ -#include <drm/drmP.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_crtc.h> -#include <drm/drm_modes.h> -#include <drm/drm_probe_helper.h> - #include <linux/clk-provider.h> #include <linux/ioport.h> #include <linux/of_address.h> @@ -21,6 +15,13 @@ #include <video/videomode.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc.h> +#include <drm/drm_modes.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + #include "sun4i_backend.h" #include "sun4i_crtc.h" #include "sun4i_drv.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c index 1a1b52e6f73e..a5757b11b730 100644 --- a/drivers/gpu/drm/sun4i/sun4i_drv.c +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c @@ -8,16 +8,19 @@ #include <linux/component.h> #include <linux/kfifo.h> +#include <linux/module.h> #include <linux/of_graph.h> #include <linux/of_reserved_mem.h> +#include <linux/platform_device.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "sun4i_drv.h" #include "sun4i_frontend.h" @@ -38,7 +41,7 @@ static int drm_sun4i_gem_dumb_create(struct drm_file *file_priv, DEFINE_DRM_GEM_CMA_FOPS(sun4i_drv_fops); static struct drm_driver sun4i_drv_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, /* Generic Operations */ .fops = &sun4i_drv_fops, diff --git a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c index 35c040716680..1568f68f9a9e 100644 --- a/drivers/gpu/drm/sun4i/sun4i_framebuffer.c +++ b/drivers/gpu/drm/sun4i/sun4i_framebuffer.c @@ -9,7 +9,6 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drmP.h> #include "sun4i_drv.h" #include "sun4i_framebuffer.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c index 346c8071bd38..ec2a032e07b9 100644 --- a/drivers/gpu/drm/sun4i/sun4i_frontend.c +++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c @@ -3,9 +3,6 @@ * Copyright (C) 2017 Free Electrons * Maxime Ripard <maxime.ripard@free-electrons.com> */ -#include <drm/drmP.h> -#include <drm/drm_gem_cma_helper.h> -#include <drm/drm_fb_cma_helper.h> #include <linux/clk.h> #include <linux/component.h> @@ -16,6 +13,13 @@ #include <linux/regmap.h> #include <linux/reset.h> +#include <drm/drm_device.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_framebuffer.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_plane.h> + #include "sun4i_drv.h" #include "sun4i_frontend.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index 9c3f99339b82..eb8071a4d6d0 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -5,23 +5,24 @@ * Maxime Ripard <maxime.ripard@free-electrons.com> */ -#include <drm/drmP.h> -#include <drm/drm_atomic_helper.h> -#include <drm/drm_probe_helper.h> -#include <drm/drm_edid.h> -#include <drm/drm_encoder.h> -#include <drm/drm_of.h> -#include <drm/drm_panel.h> - #include <linux/clk.h> #include <linux/component.h> #include <linux/iopoll.h> +#include <linux/module.h> #include <linux/of_device.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/reset.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> +#include <drm/drm_encoder.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_print.h> +#include <drm/drm_probe_helper.h> + #include "sun4i_backend.h" #include "sun4i_crtc.h" #include "sun4i_drv.h" @@ -639,9 +640,10 @@ static int sun4i_hdmi_bind(struct device *dev, struct device *master, drm_connector_helper_add(&hdmi->connector, &sun4i_hdmi_connector_helper_funcs); - ret = drm_connector_init(drm, &hdmi->connector, - &sun4i_hdmi_connector_funcs, - DRM_MODE_CONNECTOR_HDMIA); + ret = drm_connector_init_with_ddc(drm, &hdmi->connector, + &sun4i_hdmi_connector_funcs, + DRM_MODE_CONNECTOR_HDMIA, + hdmi->ddc_i2c); if (ret) { dev_err(dev, "Couldn't initialise the HDMI connector\n"); diff --git a/drivers/gpu/drm/sun4i/sun4i_layer.c b/drivers/gpu/drm/sun4i/sun4i_layer.c index e72dd4de90ce..c04f4ba0d69d 100644 --- a/drivers/gpu/drm/sun4i/sun4i_layer.c +++ b/drivers/gpu/drm/sun4i/sun4i_layer.c @@ -7,9 +7,8 @@ */ #include <drm/drm_atomic_helper.h> -#include <drm/drm_plane_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drmP.h> +#include <drm/drm_plane_helper.h> #include "sun4i_backend.h" #include "sun4i_frontend.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_lvds.c b/drivers/gpu/drm/sun4i/sun4i_lvds.c index 3a3ba99fed22..7fbf425acb55 100644 --- a/drivers/gpu/drm/sun4i/sun4i_lvds.c +++ b/drivers/gpu/drm/sun4i/sun4i_lvds.c @@ -6,10 +6,10 @@ #include <linux/clk.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include "sun4i_crtc.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_rgb.c b/drivers/gpu/drm/sun4i/sun4i_rgb.c index a901ec689b62..aac56983f208 100644 --- a/drivers/gpu/drm/sun4i/sun4i_rgb.c +++ b/drivers/gpu/drm/sun4i/sun4i_rgb.c @@ -8,10 +8,10 @@ #include <linux/clk.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include "sun4i_crtc.h" diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 64c43ee6bd92..690aeb822704 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c @@ -6,7 +6,15 @@ * Maxime Ripard <maxime.ripard@free-electrons.com> */ -#include <drm/drmP.h> +#include <linux/component.h> +#include <linux/ioport.h> +#include <linux/module.h> +#include <linux/of_address.h> +#include <linux/of_device.h> +#include <linux/of_irq.h> +#include <linux/regmap.h> +#include <linux/reset.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_connector.h> #include <drm/drm_crtc.h> @@ -14,18 +22,12 @@ #include <drm/drm_modes.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include <uapi/drm/drm_mode.h> -#include <linux/component.h> -#include <linux/ioport.h> -#include <linux/of_address.h> -#include <linux/of_device.h> -#include <linux/of_irq.h> -#include <linux/regmap.h> -#include <linux/reset.h> - #include "sun4i_crtc.h" #include "sun4i_dotclock.h" #include "sun4i_drv.h" @@ -478,7 +480,7 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, const struct drm_display_mode *mode) { struct drm_connector *connector = sun4i_tcon_get_connector(encoder); - struct drm_display_info display_info = connector->display_info; + const struct drm_display_info *info = &connector->display_info; unsigned int bp, hsync, vsync; u8 clk_delay; u32 val = 0; @@ -539,7 +541,7 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, if (mode->flags & DRM_MODE_FLAG_PVSYNC) val |= SUN4I_TCON0_IO_POL_VSYNC_POSITIVE; - if (display_info.bus_flags & DRM_BUS_FLAG_DE_LOW) + if (info->bus_flags & DRM_BUS_FLAG_DE_LOW) val |= SUN4I_TCON0_IO_POL_DE_NEGATIVE; /* @@ -557,10 +559,10 @@ static void sun4i_tcon0_mode_set_rgb(struct sun4i_tcon *tcon, * Following code is a way to avoid quirks all around TCON * and DOTCLOCK drivers. */ - if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE) + if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE) clk_set_phase(tcon->dclk, 240); - if (display_info.bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) + if (info->bus_flags & DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE) clk_set_phase(tcon->dclk, 0); regmap_update_bits(tcon->regs, SUN4I_TCON0_IO_POL_REG, diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c index f998153c141f..39c15282e448 100644 --- a/drivers/gpu/drm/sun4i/sun4i_tv.c +++ b/drivers/gpu/drm/sun4i/sun4i_tv.c @@ -8,14 +8,16 @@ #include <linux/clk.h> #include <linux/component.h> +#include <linux/module.h> #include <linux/of_address.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <linux/reset.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_of.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include "sun4i_crtc.h" diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c index a1fc8b520985..472f73985deb 100644 --- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c +++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c @@ -9,19 +9,20 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/crc-ccitt.h> +#include <linux/module.h> #include <linux/of_address.h> +#include <linux/phy/phy-mipi-dphy.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/regmap.h> #include <linux/reset.h> #include <linux/slab.h> -#include <linux/phy/phy.h> -#include <linux/phy/phy-mipi-dphy.h> - -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_mipi_dsi.h> #include <drm/drm_panel.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> #include "sun4i_crtc.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.c b/drivers/gpu/drm/sun4i/sun8i_csc.c index b8c059f1a118..781955dd4995 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.c +++ b/drivers/gpu/drm/sun4i/sun8i_csc.c @@ -3,7 +3,7 @@ * Copyright (C) Jernej Skrabec <jernej.skrabec@siol.net> */ -#include <drm/drmP.h> +#include <drm/drm_print.h> #include "sun8i_csc.h" #include "sun8i_mixer.h" @@ -18,16 +18,59 @@ static const u32 ccsc_base[2][2] = { * First tree values in each line are multiplication factor and last * value is constant, which is added at the end. */ -static const u32 yuv2rgb[] = { - 0x000004A8, 0x00000000, 0x00000662, 0xFFFC845A, - 0x000004A8, 0xFFFFFE6F, 0xFFFFFCBF, 0x00021DF4, - 0x000004A8, 0x00000813, 0x00000000, 0xFFFBAC4A, + +static const u32 yuv2rgb[2][2][12] = { + [DRM_COLOR_YCBCR_LIMITED_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x000004A8, 0x00000000, 0x00000662, 0xFFFC8451, + 0x000004A8, 0xFFFFFE6F, 0xFFFFFCC0, 0x00021E4D, + 0x000004A8, 0x00000811, 0x00000000, 0xFFFBACA9, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x000004A8, 0x00000000, 0x0000072B, 0xFFFC1F99, + 0x000004A8, 0xFFFFFF26, 0xFFFFFDDF, 0x00013383, + 0x000004A8, 0x00000873, 0x00000000, 0xFFFB7BEF, + } + }, + [DRM_COLOR_YCBCR_FULL_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x00000400, 0x00000000, 0x0000059B, 0xFFFD322E, + 0x00000400, 0xFFFFFEA0, 0xFFFFFD25, 0x00021DD5, + 0x00000400, 0x00000716, 0x00000000, 0xFFFC74BD, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00000400, 0x00000000, 0x0000064C, 0xFFFCD9B4, + 0x00000400, 0xFFFFFF41, 0xFFFFFE21, 0x00014F96, + 0x00000400, 0x0000076C, 0x00000000, 0xFFFC49EF, + } + }, }; -static const u32 yvu2rgb[] = { - 0x000004A8, 0x00000662, 0x00000000, 0xFFFC845A, - 0x000004A8, 0xFFFFFCBF, 0xFFFFFE6F, 0x00021DF4, - 0x000004A8, 0x00000000, 0x00000813, 0xFFFBAC4A, +static const u32 yvu2rgb[2][2][12] = { + [DRM_COLOR_YCBCR_LIMITED_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x000004A8, 0x00000662, 0x00000000, 0xFFFC8451, + 0x000004A8, 0xFFFFFCC0, 0xFFFFFE6F, 0x00021E4D, + 0x000004A8, 0x00000000, 0x00000811, 0xFFFBACA9, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x000004A8, 0x0000072B, 0x00000000, 0xFFFC1F99, + 0x000004A8, 0xFFFFFDDF, 0xFFFFFF26, 0x00013383, + 0x000004A8, 0x00000000, 0x00000873, 0xFFFB7BEF, + } + }, + [DRM_COLOR_YCBCR_FULL_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x00000400, 0x0000059B, 0x00000000, 0xFFFD322E, + 0x00000400, 0xFFFFFD25, 0xFFFFFEA0, 0x00021DD5, + 0x00000400, 0x00000000, 0x00000716, 0xFFFC74BD, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00000400, 0x0000064C, 0x00000000, 0xFFFCD9B4, + 0x00000400, 0xFFFFFE21, 0xFFFFFF41, 0x00014F96, + 0x00000400, 0x00000000, 0x0000076C, 0xFFFC49EF, + } + }, }; /* @@ -53,57 +96,98 @@ static const u32 yvu2rgb[] = { * c20 c21 c22 [d2 const2] */ -static const u32 yuv2rgb_de3[] = { - 0x0002542a, 0x00000000, 0x0003312a, 0xffc00000, - 0x0002542a, 0xffff376b, 0xfffe5fc3, 0xfe000000, - 0x0002542a, 0x000408d3, 0x00000000, 0xfe000000, +static const u32 yuv2rgb_de3[2][2][12] = { + [DRM_COLOR_YCBCR_LIMITED_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x0002542A, 0x00000000, 0x0003312A, 0xFFC00000, + 0x0002542A, 0xFFFF376B, 0xFFFE5FC3, 0xFE000000, + 0x0002542A, 0x000408D2, 0x00000000, 0xFE000000, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x0002542A, 0x00000000, 0x000395E2, 0xFFC00000, + 0x0002542A, 0xFFFF92D2, 0xFFFEEF27, 0xFE000000, + 0x0002542A, 0x0004398C, 0x00000000, 0xFE000000, + } + }, + [DRM_COLOR_YCBCR_FULL_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x00020000, 0x00000000, 0x0002CDD2, 0x00000000, + 0x00020000, 0xFFFF4FCE, 0xFFFE925D, 0xFE000000, + 0x00020000, 0x00038B43, 0x00000000, 0xFE000000, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00020000, 0x00000000, 0x0003264C, 0x00000000, + 0x00020000, 0xFFFFA018, 0xFFFF1053, 0xFE000000, + 0x00020000, 0x0003B611, 0x00000000, 0xFE000000, + } + }, }; -static const u32 yvu2rgb_de3[] = { - 0x0002542a, 0x0003312a, 0x00000000, 0xffc00000, - 0x0002542a, 0xfffe5fc3, 0xffff376b, 0xfe000000, - 0x0002542a, 0x00000000, 0x000408d3, 0xfe000000, +static const u32 yvu2rgb_de3[2][2][12] = { + [DRM_COLOR_YCBCR_LIMITED_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x0002542A, 0x0003312A, 0x00000000, 0xFFC00000, + 0x0002542A, 0xFFFE5FC3, 0xFFFF376B, 0xFE000000, + 0x0002542A, 0x00000000, 0x000408D2, 0xFE000000, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x0002542A, 0x000395E2, 0x00000000, 0xFFC00000, + 0x0002542A, 0xFFFEEF27, 0xFFFF92D2, 0xFE000000, + 0x0002542A, 0x00000000, 0x0004398C, 0xFE000000, + } + }, + [DRM_COLOR_YCBCR_FULL_RANGE] = { + [DRM_COLOR_YCBCR_BT601] = { + 0x00020000, 0x0002CDD2, 0x00000000, 0x00000000, + 0x00020000, 0xFFFE925D, 0xFFFF4FCE, 0xFE000000, + 0x00020000, 0x00000000, 0x00038B43, 0xFE000000, + }, + [DRM_COLOR_YCBCR_BT709] = { + 0x00020000, 0x0003264C, 0x00000000, 0x00000000, + 0x00020000, 0xFFFF1053, 0xFFFFA018, 0xFE000000, + 0x00020000, 0x00000000, 0x0003B611, 0xFE000000, + } + }, }; static void sun8i_csc_set_coefficients(struct regmap *map, u32 base, - enum sun8i_csc_mode mode) + enum sun8i_csc_mode mode, + enum drm_color_encoding encoding, + enum drm_color_range range) { const u32 *table; - int i, data; + u32 base_reg; switch (mode) { case SUN8I_CSC_MODE_YUV2RGB: - table = yuv2rgb; + table = yuv2rgb[range][encoding]; break; case SUN8I_CSC_MODE_YVU2RGB: - table = yvu2rgb; + table = yvu2rgb[range][encoding]; break; default: DRM_WARN("Wrong CSC mode specified.\n"); return; } - for (i = 0; i < 12; i++) { - data = table[i]; - /* For some reason, 0x200 must be added to constant parts */ - if (((i + 1) & 3) == 0) - data += 0x200; - regmap_write(map, SUN8I_CSC_COEFF(base, i), data); - } + base_reg = SUN8I_CSC_COEFF(base, 0); + regmap_bulk_write(map, base_reg, table, 12); } static void sun8i_de3_ccsc_set_coefficients(struct regmap *map, int layer, - enum sun8i_csc_mode mode) + enum sun8i_csc_mode mode, + enum drm_color_encoding encoding, + enum drm_color_range range) { const u32 *table; u32 base_reg; switch (mode) { case SUN8I_CSC_MODE_YUV2RGB: - table = yuv2rgb_de3; + table = yuv2rgb_de3[range][encoding]; break; case SUN8I_CSC_MODE_YVU2RGB: - table = yvu2rgb_de3; + table = yvu2rgb_de3[range][encoding]; break; default: DRM_WARN("Wrong CSC mode specified.\n"); @@ -142,19 +226,22 @@ static void sun8i_de3_ccsc_enable(struct regmap *map, int layer, bool enable) } void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, - enum sun8i_csc_mode mode) + enum sun8i_csc_mode mode, + enum drm_color_encoding encoding, + enum drm_color_range range) { u32 base; if (mixer->cfg->is_de3) { - sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, - layer, mode); + sun8i_de3_ccsc_set_coefficients(mixer->engine.regs, layer, + mode, encoding, range); return; } base = ccsc_base[mixer->cfg->ccsc][layer]; - sun8i_csc_set_coefficients(mixer->engine.regs, base, mode); + sun8i_csc_set_coefficients(mixer->engine.regs, base, + mode, encoding, range); } void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable) diff --git a/drivers/gpu/drm/sun4i/sun8i_csc.h b/drivers/gpu/drm/sun4i/sun8i_csc.h index dce4c444bcd6..f42441b1b14d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_csc.h +++ b/drivers/gpu/drm/sun4i/sun8i_csc.h @@ -6,6 +6,8 @@ #ifndef _SUN8I_CSC_H_ #define _SUN8I_CSC_H_ +#include <drm/drm_color_mgmt.h> + struct sun8i_mixer; /* VI channel CSC units offsets */ @@ -26,7 +28,9 @@ enum sun8i_csc_mode { }; void sun8i_csc_set_ccsc_coefficients(struct sun8i_mixer *mixer, int layer, - enum sun8i_csc_mode mode); + enum sun8i_csc_mode mode, + enum drm_color_encoding encoding, + enum drm_color_range range); void sun8i_csc_enable_ccsc(struct sun8i_mixer *mixer, int layer, bool enable); #endif diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c index 39d8509d96a0..8ca5af0c912f 100644 --- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c +++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c @@ -8,9 +8,8 @@ #include <linux/of_device.h> #include <linux/platform_device.h> -#include <drm/drm_of.h> -#include <drm/drmP.h> #include <drm/drm_crtc_helper.h> +#include <drm/drm_of.h> #include "sun8i_dw_hdmi.h" #include "sun8i_tcon_top.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c index c2eedf58bf4b..8b803eb903b8 100644 --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c @@ -7,7 +7,13 @@ * Copyright (C) 2015 NextThing Co */ -#include <drm/drmP.h> +#include <linux/component.h> +#include <linux/dma-mapping.h> +#include <linux/module.h> +#include <linux/of_device.h> +#include <linux/of_graph.h> +#include <linux/reset.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> @@ -15,12 +21,6 @@ #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <linux/component.h> -#include <linux/dma-mapping.h> -#include <linux/of_device.h> -#include <linux/of_graph.h> -#include <linux/reset.h> - #include "sun4i_drv.h" #include "sun8i_mixer.h" #include "sun8i_ui_layer.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c index 3267d0f9b9b2..75d8e60c149d 100644 --- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c +++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c @@ -1,18 +1,18 @@ // SPDX-License-Identifier: GPL-2.0+ /* Copyright (c) 2018 Jernej Skrabec <jernej.skrabec@siol.net> */ -#include <drm/drmP.h> - -#include <dt-bindings/clock/sun8i-tcon-top.h> #include <linux/bitfield.h> #include <linux/component.h> #include <linux/device.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/of_device.h> #include <linux/of_graph.h> #include <linux/platform_device.h> +#include <dt-bindings/clock/sun8i-tcon-top.h> + #include "sun8i_tcon_top.h" struct sun8i_tcon_top_quirks { diff --git a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c index dd2a1c851939..c87fd842918e 100644 --- a/drivers/gpu/drm/sun4i/sun8i_ui_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_ui_layer.c @@ -13,11 +13,11 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> #include "sun8i_ui_layer.h" #include "sun8i_mixer.h" diff --git a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c index bd0e6a52d1d8..42d445d23773 100644 --- a/drivers/gpu/drm/sun4i/sun8i_vi_layer.c +++ b/drivers/gpu/drm/sun4i/sun8i_vi_layer.c @@ -11,7 +11,6 @@ #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> #include "sun8i_vi_layer.h" #include "sun8i_mixer.h" @@ -232,7 +231,9 @@ static int sun8i_vi_layer_update_formats(struct sun8i_mixer *mixer, int channel, SUN8I_MIXER_CHAN_VI_LAYER_ATTR_FBFMT_MASK, val); if (fmt_info->csc != SUN8I_CSC_MODE_OFF) { - sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_info->csc); + sun8i_csc_set_ccsc_coefficients(mixer, channel, fmt_info->csc, + state->color_encoding, + state->color_range); sun8i_csc_enable_ccsc(mixer, channel, true); } else { sun8i_csc_enable_ccsc(mixer, channel, false); @@ -441,6 +442,7 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, struct sun8i_mixer *mixer, int index) { + u32 supported_encodings, supported_ranges; struct sun8i_vi_layer *layer; unsigned int plane_cnt; int ret; @@ -469,6 +471,22 @@ struct sun8i_vi_layer *sun8i_vi_layer_init_one(struct drm_device *drm, return ERR_PTR(ret); } + supported_encodings = BIT(DRM_COLOR_YCBCR_BT601) | + BIT(DRM_COLOR_YCBCR_BT709); + + supported_ranges = BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | + BIT(DRM_COLOR_YCBCR_FULL_RANGE); + + ret = drm_plane_create_color_properties(&layer->plane, + supported_encodings, + supported_ranges, + DRM_COLOR_YCBCR_BT709, + DRM_COLOR_YCBCR_LIMITED_RANGE); + if (ret) { + dev_err(drm->dev, "Couldn't add encoding and range properties!\n"); + return ERR_PTR(ret); + } + drm_plane_helper_add(&layer->plane, &sun8i_vi_layer_helper_funcs); layer->mixer = mixer; layer->channel = index; diff --git a/drivers/gpu/drm/tdfx/tdfx_drv.c b/drivers/gpu/drm/tdfx/tdfx_drv.c index 3a1476818c65..c243af156ee7 100644 --- a/drivers/gpu/drm/tdfx/tdfx_drv.c +++ b/drivers/gpu/drm/tdfx/tdfx_drv.c @@ -32,11 +32,14 @@ #include <linux/module.h> -#include <drm/drmP.h> -#include "tdfx_drv.h" - -#include <drm/drm_pciids.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> #include <drm/drm_legacy.h> +#include <drm/drm_pci.h> +#include <drm/drm_pciids.h> + +#include "tdfx_drv.h" static struct pci_device_id pciidlist[] = { tdfx_PCI_IDS diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c index ddb802bce0a3..870904bfad78 100644 --- a/drivers/gpu/drm/tegra/drm.c +++ b/drivers/gpu/drm/tegra/drm.c @@ -888,33 +888,33 @@ static int tegra_gem_get_flags(struct drm_device *drm, void *data, static const struct drm_ioctl_desc tegra_drm_ioctls[] = { #ifdef CONFIG_DRM_TEGRA_STAGING DRM_IOCTL_DEF_DRV(TEGRA_GEM_CREATE, tegra_gem_create, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_GEM_MMAP, tegra_gem_mmap, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_READ, tegra_syncpt_read, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_INCR, tegra_syncpt_incr, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_SYNCPT_WAIT, tegra_syncpt_wait, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_OPEN_CHANNEL, tegra_open_channel, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_CLOSE_CHANNEL, tegra_close_channel, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT, tegra_get_syncpt, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_SUBMIT, tegra_submit, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_GET_SYNCPT_BASE, tegra_get_syncpt_base, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_TILING, tegra_gem_set_tiling, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_TILING, tegra_gem_get_tiling, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_GEM_SET_FLAGS, tegra_gem_set_flags, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(TEGRA_GEM_GET_FLAGS, tegra_gem_get_flags, - DRM_UNLOCKED | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), #endif }; @@ -1004,7 +1004,7 @@ static int tegra_debugfs_init(struct drm_minor *minor) #endif static struct drm_driver tegra_drm_driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC | DRIVER_RENDER, .load = tegra_drm_load, .unload = tegra_drm_unload, diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c index df53a46285a3..0a3d925d5284 100644 --- a/drivers/gpu/drm/tegra/gem.c +++ b/drivers/gpu/drm/tegra/gem.c @@ -626,20 +626,19 @@ static const struct dma_buf_ops tegra_gem_prime_dmabuf_ops = { .vunmap = tegra_gem_prime_vunmap, }; -struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, - struct drm_gem_object *gem, +struct dma_buf *tegra_gem_prime_export(struct drm_gem_object *gem, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); exp_info.exp_name = KBUILD_MODNAME; - exp_info.owner = drm->driver->fops->owner; + exp_info.owner = gem->dev->driver->fops->owner; exp_info.ops = &tegra_gem_prime_dmabuf_ops; exp_info.size = gem->size; exp_info.flags = flags; exp_info.priv = gem; - return drm_gem_dmabuf_export(drm, &exp_info); + return drm_gem_dmabuf_export(gem->dev, &exp_info); } struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, diff --git a/drivers/gpu/drm/tegra/gem.h b/drivers/gpu/drm/tegra/gem.h index 413eae83ad81..f1f758b25886 100644 --- a/drivers/gpu/drm/tegra/gem.h +++ b/drivers/gpu/drm/tegra/gem.h @@ -70,8 +70,7 @@ extern const struct vm_operations_struct tegra_bo_vm_ops; int __tegra_gem_mmap(struct drm_gem_object *gem, struct vm_area_struct *vma); int tegra_drm_mmap(struct file *file, struct vm_area_struct *vma); -struct dma_buf *tegra_gem_prime_export(struct drm_device *drm, - struct drm_gem_object *gem, +struct dma_buf *tegra_gem_prime_export(struct drm_gem_object *gem, int flags); struct drm_gem_object *tegra_gem_prime_import(struct drm_device *drm, struct dma_buf *buf); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index 650d162e374b..e9dd5e5cb4e7 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -4,16 +4,20 @@ * Author: Rob Clark <robdclark@gmail.com> */ +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/of_graph.h> +#include <linux/pm_runtime.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> -#include <drm/drm_flip_work.h> -#include <drm/drm_plane_helper.h> -#include <linux/workqueue.h> -#include <linux/completion.h> -#include <linux/dma-mapping.h> -#include <linux/of_graph.h> -#include <linux/math64.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_cma_helper.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_print.h> +#include <drm/drm_vblank.h> #include "tilcdc_drv.h" #include "tilcdc_regs.h" @@ -646,9 +650,6 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc, struct drm_crtc_state *state) { - struct drm_display_mode *mode = &state->mode; - int ret; - /* If we are not active we don't care */ if (!state->active) return 0; @@ -660,12 +661,6 @@ static int tilcdc_crtc_atomic_check(struct drm_crtc *crtc, return -EINVAL; } - ret = tilcdc_crtc_mode_valid(crtc, mode); - if (ret) { - dev_dbg(crtc->dev->dev, "Mode \"%s\" not valid", mode->name); - return -EINVAL; - } - return 0; } @@ -717,13 +712,6 @@ static const struct drm_crtc_funcs tilcdc_crtc_funcs = { .disable_vblank = tilcdc_crtc_disable_vblank, }; -static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { - .mode_fixup = tilcdc_crtc_mode_fixup, - .atomic_check = tilcdc_crtc_atomic_check, - .atomic_enable = tilcdc_crtc_atomic_enable, - .atomic_disable = tilcdc_crtc_atomic_disable, -}; - int tilcdc_crtc_max_width(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -738,7 +726,9 @@ int tilcdc_crtc_max_width(struct drm_crtc *crtc) return max_width; } -int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) +static enum drm_mode_status +tilcdc_crtc_mode_valid(struct drm_crtc *crtc, + const struct drm_display_mode *mode) { struct tilcdc_drm_private *priv = crtc->dev->dev_private; unsigned int bandwidth; @@ -826,6 +816,14 @@ int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode) return MODE_OK; } +static const struct drm_crtc_helper_funcs tilcdc_crtc_helper_funcs = { + .mode_valid = tilcdc_crtc_mode_valid, + .mode_fixup = tilcdc_crtc_mode_fixup, + .atomic_check = tilcdc_crtc_atomic_check, + .atomic_enable = tilcdc_crtc_atomic_enable, + .atomic_disable = tilcdc_crtc_atomic_disable, +}; + void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, const struct tilcdc_panel_info *info) { diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index 7339bab3a0a1..2a9e67597375 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -7,19 +7,30 @@ /* LCDC DRM driver, based on da8xx-fb */ #include <linux/component.h> +#include <linux/mod_devicetable.h> +#include <linux/module.h> #include <linux/pinctrl/consumer.h> -#include <linux/suspend.h> -#include <drm/drm_atomic.h> +#include <linux/platform_device.h> +#include <linux/pm_runtime.h> + #include <drm/drm_atomic_helper.h> +#include <drm/drm_debugfs.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_irq.h> +#include <drm/drm_mm.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + #include "tilcdc_drv.h" +#include "tilcdc_external.h" +#include "tilcdc_panel.h" #include "tilcdc_regs.h" #include "tilcdc_tfp410.h" -#include "tilcdc_panel.h" -#include "tilcdc_external.h" static LIST_HEAD(module_list); @@ -188,7 +199,6 @@ static void tilcdc_fini(struct drm_device *dev) drm_kms_helper_poll_fini(dev); drm_irq_uninstall(dev); drm_mode_config_cleanup(dev); - tilcdc_remove_external_device(dev); if (priv->clk) clk_put(priv->clk); @@ -501,8 +511,7 @@ static int tilcdc_debugfs_init(struct drm_minor *minor) DEFINE_DRM_GEM_CMA_FOPS(fops); static struct drm_driver tilcdc_driver = { - .driver_features = (DRIVER_GEM | DRIVER_MODESET | - DRIVER_PRIME | DRIVER_ATOMIC), + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .irq_handler = tilcdc_irq, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_print_info = drm_gem_cma_print_info, @@ -511,8 +520,6 @@ static struct drm_driver tilcdc_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index 99432296c0ff..18815e75ca4f 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -7,21 +7,24 @@ #ifndef __TILCDC_DRV_H__ #define __TILCDC_DRV_H__ -#include <linux/clk.h> #include <linux/cpufreq.h> -#include <linux/module.h> -#include <linux/platform_device.h> -#include <linux/pm.h> -#include <linux/pm_runtime.h> -#include <linux/slab.h> -#include <linux/of.h> -#include <linux/of_device.h> -#include <linux/list.h> - -#include <drm/drmP.h> -#include <drm/drm_bridge.h> -#include <drm/drm_fb_cma_helper.h> -#include <drm/drm_gem_cma_helper.h> +#include <linux/irqreturn.h> + +#include <drm/drm_print.h> + +struct clk; +struct workqueue_struct; + +struct drm_connector; +struct drm_connector_helper_funcs; +struct drm_crtc; +struct drm_device; +struct drm_display_mode; +struct drm_encoder; +struct drm_framebuffer; +struct drm_minor; +struct drm_pending_vblank_event; +struct drm_plane; /* Defaulting to pixel clock defined on AM335x */ #define TILCDC_DEFAULT_MAX_PIXELCLOCK 126000 @@ -74,7 +77,6 @@ struct tilcdc_drm_private { struct drm_encoder *external_encoder; struct drm_connector *external_connector; - const struct drm_connector_helper_funcs *connector_funcs; bool is_registered; bool is_componentized; @@ -156,7 +158,6 @@ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, const struct tilcdc_panel_info *info); void tilcdc_crtc_set_simulate_vesa_sync(struct drm_crtc *crtc, bool simulate_vesa_sync); -int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode); int tilcdc_crtc_max_width(struct drm_crtc *crtc); void tilcdc_crtc_shutdown(struct drm_crtc *crtc); int tilcdc_crtc_update_fb(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.c b/drivers/gpu/drm/tilcdc/tilcdc_external.c index 7050eb4cf152..43d756b7810e 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_external.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.c @@ -6,6 +6,7 @@ #include <linux/component.h> #include <linux/of_graph.h> + #include <drm/drm_atomic_helper.h> #include <drm/drm_of.h> @@ -37,64 +38,6 @@ static const struct tilcdc_panel_info panel_info_default = { .raster_order = 0, }; -static int tilcdc_external_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct tilcdc_drm_private *priv = connector->dev->dev_private; - int ret; - - ret = tilcdc_crtc_mode_valid(priv->crtc, mode); - if (ret != MODE_OK) - return ret; - - BUG_ON(priv->external_connector != connector); - BUG_ON(!priv->connector_funcs); - - /* If the connector has its own mode_valid call it. */ - if (!IS_ERR(priv->connector_funcs) && - priv->connector_funcs->mode_valid) - return priv->connector_funcs->mode_valid(connector, mode); - - return MODE_OK; -} - -static int tilcdc_add_external_connector(struct drm_device *dev, - struct drm_connector *connector) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - struct drm_connector_helper_funcs *connector_funcs; - - /* There should never be more than one connector */ - if (WARN_ON(priv->external_connector)) - return -EINVAL; - - priv->external_connector = connector; - connector_funcs = devm_kzalloc(dev->dev, sizeof(*connector_funcs), - GFP_KERNEL); - if (!connector_funcs) - return -ENOMEM; - - /* connector->helper_private contains always struct - * connector_helper_funcs pointer. For tilcdc crtc to have a - * say if a specific mode is Ok, we need to install our own - * helper functions. In our helper functions we copy - * everything else but use our own mode_valid() (above). - */ - if (connector->helper_private) { - priv->connector_funcs = connector->helper_private; - *connector_funcs = *priv->connector_funcs; - } else { - priv->connector_funcs = ERR_PTR(-ENOENT); - } - connector_funcs->mode_valid = tilcdc_external_mode_valid; - drm_connector_helper_add(connector, connector_funcs); - - dev_dbg(dev->dev, "External connector '%s' connected\n", - connector->name); - - return 0; -} - static struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev, struct drm_encoder *encoder) @@ -115,7 +58,6 @@ struct drm_connector *tilcdc_encoder_find_connector(struct drm_device *ddev, int tilcdc_add_component_encoder(struct drm_device *ddev) { struct tilcdc_drm_private *priv = ddev->dev_private; - struct drm_connector *connector; struct drm_encoder *encoder; list_for_each_entry(encoder, &ddev->mode_config.encoder_list, head) @@ -127,28 +69,17 @@ int tilcdc_add_component_encoder(struct drm_device *ddev) return -ENODEV; } - connector = tilcdc_encoder_find_connector(ddev, encoder); + priv->external_connector = + tilcdc_encoder_find_connector(ddev, encoder); - if (!connector) + if (!priv->external_connector) return -ENODEV; /* Only tda998x is supported at the moment. */ tilcdc_crtc_set_simulate_vesa_sync(priv->crtc, true); tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_tda998x); - return tilcdc_add_external_connector(ddev, connector); -} - -void tilcdc_remove_external_device(struct drm_device *dev) -{ - struct tilcdc_drm_private *priv = dev->dev_private; - - /* Restore the original helper functions, if any. */ - if (IS_ERR(priv->connector_funcs)) - drm_connector_helper_add(priv->external_connector, NULL); - else if (priv->connector_funcs) - drm_connector_helper_add(priv->external_connector, - priv->connector_funcs); + return 0; } static const struct drm_encoder_funcs tilcdc_external_encoder_funcs = { @@ -159,7 +90,6 @@ static int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge) { struct tilcdc_drm_private *priv = ddev->dev_private; - struct drm_connector *connector; int ret; priv->external_encoder->possible_crtcs = BIT(0); @@ -172,13 +102,12 @@ int tilcdc_attach_bridge(struct drm_device *ddev, struct drm_bridge *bridge) tilcdc_crtc_set_panel_info(priv->crtc, &panel_info_default); - connector = tilcdc_encoder_find_connector(ddev, priv->external_encoder); - if (!connector) + priv->external_connector = + tilcdc_encoder_find_connector(ddev, priv->external_encoder); + if (!priv->external_connector) return -ENODEV; - ret = tilcdc_add_external_connector(ddev, connector); - - return ret; + return 0; } int tilcdc_attach_external_device(struct drm_device *ddev) diff --git a/drivers/gpu/drm/tilcdc/tilcdc_external.h b/drivers/gpu/drm/tilcdc/tilcdc_external.h index 7024b4877fdf..fb4476694cd8 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_external.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_external.h @@ -8,7 +8,6 @@ #define __TILCDC_EXTERNAL_H__ int tilcdc_add_component_encoder(struct drm_device *dev); -void tilcdc_remove_external_device(struct drm_device *dev); int tilcdc_get_external_components(struct device *dev, struct component_match **match); int tilcdc_attach_external_device(struct drm_device *ddev); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 22b100d2e174..5584e656b857 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -4,14 +4,17 @@ * Author: Rob Clark <robdclark@gmail.com> */ -#include <linux/pinctrl/pinmux.h> -#include <linux/pinctrl/consumer.h> -#include <linux/backlight.h> #include <linux/gpio/consumer.h> +#include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> + #include <video/display_timing.h> #include <video/of_display_timing.h> #include <video/videomode.h> -#include <drm/drm_atomic_helper.h> + +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_connector.h> +#include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_probe_helper.h> #include "tilcdc_drv.h" @@ -160,14 +163,6 @@ static int panel_connector_get_modes(struct drm_connector *connector) return i; } -static int panel_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct tilcdc_drm_private *priv = connector->dev->dev_private; - /* our only constraints are what the crtc can generate: */ - return tilcdc_crtc_mode_valid(priv->crtc, mode); -} - static struct drm_encoder *panel_connector_best_encoder( struct drm_connector *connector) { @@ -185,7 +180,6 @@ static const struct drm_connector_funcs panel_connector_funcs = { static const struct drm_connector_helper_funcs panel_connector_helper_funcs = { .get_modes = panel_connector_get_modes, - .mode_valid = panel_connector_mode_valid, .best_encoder = panel_connector_best_encoder, }; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_plane.c b/drivers/gpu/drm/tilcdc/tilcdc_plane.c index 8c2776acdf99..3abb9641f212 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_plane.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_plane.c @@ -4,12 +4,10 @@ * Author: Jyri Sarha <jsarha@ti.com> */ -#include <drm/drmP.h> - #include <drm/drm_atomic.h> #include <drm/drm_plane_helper.h> #include <drm/drm_atomic_helper.h> -#include <uapi/drm/drm_fourcc.h> +#include <drm/drm_fourcc.h> #include "tilcdc_drv.h" diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index 62d014c20988..525dc1c0f1c1 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -4,12 +4,14 @@ * Author: Rob Clark <robdclark@gmail.com> */ -#include <linux/i2c.h> #include <linux/gpio.h> +#include <linux/mod_devicetable.h> #include <linux/of_gpio.h> -#include <linux/pinctrl/pinmux.h> -#include <linux/pinctrl/consumer.h> +#include <linux/platform_device.h> + #include <drm/drm_atomic_helper.h> +#include <drm/drm_encoder.h> +#include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_probe_helper.h> #include "tilcdc_drv.h" @@ -173,14 +175,6 @@ static int tfp410_connector_get_modes(struct drm_connector *connector) return ret; } -static int tfp410_connector_mode_valid(struct drm_connector *connector, - struct drm_display_mode *mode) -{ - struct tilcdc_drm_private *priv = connector->dev->dev_private; - /* our only constraints are what the crtc can generate: */ - return tilcdc_crtc_mode_valid(priv->crtc, mode); -} - static struct drm_encoder *tfp410_connector_best_encoder( struct drm_connector *connector) { @@ -199,7 +193,6 @@ static const struct drm_connector_funcs tfp410_connector_funcs = { static const struct drm_connector_helper_funcs tfp410_connector_helper_funcs = { .get_modes = tfp410_connector_get_modes, - .mode_valid = tfp410_connector_mode_valid, .best_encoder = tfp410_connector_best_encoder, }; diff --git a/drivers/gpu/drm/tinydrm/Kconfig b/drivers/gpu/drm/tiny/Kconfig index 87819c82bcce..504763423d46 100644 --- a/drivers/gpu/drm/tinydrm/Kconfig +++ b/drivers/gpu/drm/tiny/Kconfig @@ -1,21 +1,21 @@ # SPDX-License-Identifier: GPL-2.0-only -menuconfig DRM_TINYDRM - tristate "Support for simple displays" - depends on DRM + +config DRM_GM12U320 + tristate "GM12U320 driver for USB projectors" + depends on DRM && USB select DRM_KMS_HELPER - select DRM_KMS_CMA_HELPER + select DRM_GEM_SHMEM_HELPER help - Choose this option if you have a tinydrm supported display. - If M is selected the module will be called tinydrm. - -config TINYDRM_MIPI_DBI - tristate + This is a KMS driver for projectors which use the GM12U320 chipset + for video transfer over USB2/3, such as the Acer C120 mini projector. config TINYDRM_HX8357D tristate "DRM support for HX8357D display panels" - depends on DRM_TINYDRM && SPI - depends on BACKLIGHT_CLASS_DEVICE - select TINYDRM_MIPI_DBI + depends on DRM && SPI + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_MIPI_DBI + select BACKLIGHT_CLASS_DEVICE help DRM driver for the following HX8357D panels: * YX350HV15-T 3.5" 340x350 TFT (Adafruit 3.5") @@ -24,8 +24,10 @@ config TINYDRM_HX8357D config TINYDRM_ILI9225 tristate "DRM support for ILI9225 display panels" - depends on DRM_TINYDRM && SPI - select TINYDRM_MIPI_DBI + depends on DRM && SPI + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_MIPI_DBI help DRM driver for the following Ilitek ILI9225 panels: * No-name 2.2" color screen module @@ -34,9 +36,11 @@ config TINYDRM_ILI9225 config TINYDRM_ILI9341 tristate "DRM support for ILI9341 display panels" - depends on DRM_TINYDRM && SPI - depends on BACKLIGHT_CLASS_DEVICE - select TINYDRM_MIPI_DBI + depends on DRM && SPI + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_MIPI_DBI + select BACKLIGHT_CLASS_DEVICE help DRM driver for the following Ilitek ILI9341 panels: * YX240QV29-T 2.4" 240x320 TFT (Adafruit 2.4") @@ -45,16 +49,20 @@ config TINYDRM_ILI9341 config TINYDRM_MI0283QT tristate "DRM support for MI0283QT" - depends on DRM_TINYDRM && SPI - depends on BACKLIGHT_CLASS_DEVICE - select TINYDRM_MIPI_DBI + depends on DRM && SPI + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_MIPI_DBI + select BACKLIGHT_CLASS_DEVICE help DRM driver for the Multi-Inno MI0283QT display panel If M is selected the module will be called mi0283qt. config TINYDRM_REPAPER tristate "DRM support for Pervasive Displays RePaper panels (V231)" - depends on DRM_TINYDRM && SPI + depends on DRM && SPI + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER depends on THERMAL || !THERMAL help DRM driver for the following Pervasive Displays panels: @@ -67,8 +75,10 @@ config TINYDRM_REPAPER config TINYDRM_ST7586 tristate "DRM support for Sitronix ST7586 display panels" - depends on DRM_TINYDRM && SPI - select TINYDRM_MIPI_DBI + depends on DRM && SPI + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_MIPI_DBI help DRM driver for the following Sitronix ST7586 panels: * LEGO MINDSTORMS EV3 @@ -77,9 +87,11 @@ config TINYDRM_ST7586 config TINYDRM_ST7735R tristate "DRM support for Sitronix ST7735R display panels" - depends on DRM_TINYDRM && SPI - depends on BACKLIGHT_CLASS_DEVICE - select TINYDRM_MIPI_DBI + depends on DRM && SPI + select DRM_KMS_HELPER + select DRM_KMS_CMA_HELPER + select DRM_MIPI_DBI + select BACKLIGHT_CLASS_DEVICE help DRM driver Sitronix ST7735R with one of the following LCDs: * JD-T18003-T01 1.8" 128x160 TFT diff --git a/drivers/gpu/drm/tinydrm/Makefile b/drivers/gpu/drm/tiny/Makefile index 48ec8ed9dc16..896cf31132d3 100644 --- a/drivers/gpu/drm/tinydrm/Makefile +++ b/drivers/gpu/drm/tiny/Makefile @@ -1,10 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -obj-$(CONFIG_DRM_TINYDRM) += core/ -# Controllers -obj-$(CONFIG_TINYDRM_MIPI_DBI) += mipi-dbi.o - -# Displays +obj-$(CONFIG_DRM_GM12U320) += gm12u320.o obj-$(CONFIG_TINYDRM_HX8357D) += hx8357d.o obj-$(CONFIG_TINYDRM_ILI9225) += ili9225.o obj-$(CONFIG_TINYDRM_ILI9341) += ili9341.o diff --git a/drivers/gpu/drm/tiny/gm12u320.c b/drivers/gpu/drm/tiny/gm12u320.c new file mode 100644 index 000000000000..b6f47b8cf240 --- /dev/null +++ b/drivers/gpu/drm/tiny/gm12u320.c @@ -0,0 +1,814 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright 2019 Hans de Goede <hdegoede@redhat.com> + */ + +#include <linux/dma-buf.h> +#include <linux/module.h> +#include <linux/usb.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic_state_helper.h> +#include <drm/drm_connector.h> +#include <drm/drm_damage_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fb_helper.h> +#include <drm/drm_file.h> +#include <drm/drm_format_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_shmem_helper.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_simple_kms_helper.h> +#include <drm/drm_vblank.h> + +static bool eco_mode; +module_param(eco_mode, bool, 0644); +MODULE_PARM_DESC(eco_mode, "Turn on Eco mode (less bright, more silent)"); + +#define DRIVER_NAME "gm12u320" +#define DRIVER_DESC "Grain Media GM12U320 USB projector display" +#define DRIVER_DATE "2019" +#define DRIVER_MAJOR 1 +#define DRIVER_MINOR 0 +#define DRIVER_PATCHLEVEL 1 + +/* + * The DLP has an actual width of 854 pixels, but that is not a multiple + * of 8, breaking things left and right, so we export a width of 848. + */ +#define GM12U320_USER_WIDTH 848 +#define GM12U320_REAL_WIDTH 854 +#define GM12U320_HEIGHT 480 + +#define GM12U320_BLOCK_COUNT 20 + +#define MISC_RCV_EPT 1 +#define DATA_RCV_EPT 2 +#define DATA_SND_EPT 3 +#define MISC_SND_EPT 4 + +#define DATA_BLOCK_HEADER_SIZE 84 +#define DATA_BLOCK_CONTENT_SIZE 64512 +#define DATA_BLOCK_FOOTER_SIZE 20 +#define DATA_BLOCK_SIZE (DATA_BLOCK_HEADER_SIZE + \ + DATA_BLOCK_CONTENT_SIZE + \ + DATA_BLOCK_FOOTER_SIZE) +#define DATA_LAST_BLOCK_CONTENT_SIZE 4032 +#define DATA_LAST_BLOCK_SIZE (DATA_BLOCK_HEADER_SIZE + \ + DATA_LAST_BLOCK_CONTENT_SIZE + \ + DATA_BLOCK_FOOTER_SIZE) + +#define CMD_SIZE 31 +#define READ_STATUS_SIZE 13 +#define MISC_VALUE_SIZE 4 + +#define CMD_TIMEOUT msecs_to_jiffies(200) +#define DATA_TIMEOUT msecs_to_jiffies(1000) +#define IDLE_TIMEOUT msecs_to_jiffies(2000) +#define FIRST_FRAME_TIMEOUT msecs_to_jiffies(2000) + +#define MISC_REQ_GET_SET_ECO_A 0xff +#define MISC_REQ_GET_SET_ECO_B 0x35 +/* Windows driver does once every second, with arg d = 1, other args 0 */ +#define MISC_REQ_UNKNOWN1_A 0xff +#define MISC_REQ_UNKNOWN1_B 0x38 +/* Windows driver does this on init, with arg a, b = 0, c = 0xa0, d = 4 */ +#define MISC_REQ_UNKNOWN2_A 0xa5 +#define MISC_REQ_UNKNOWN2_B 0x00 + +struct gm12u320_device { + struct drm_device dev; + struct drm_simple_display_pipe pipe; + struct drm_connector conn; + struct usb_device *udev; + unsigned char *cmd_buf; + unsigned char *data_buf[GM12U320_BLOCK_COUNT]; + bool pipe_enabled; + struct { + bool run; + struct workqueue_struct *workq; + struct work_struct work; + wait_queue_head_t waitq; + struct mutex lock; + struct drm_framebuffer *fb; + struct drm_rect rect; + } fb_update; +}; + +static const char cmd_data[CMD_SIZE] = { + 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, + 0x68, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x10, 0xff, + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x80, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const char cmd_draw[CMD_SIZE] = { + 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0xfe, + 0x00, 0x00, 0x00, 0xc0, 0xd1, 0x05, 0x00, 0x40, + 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const char cmd_misc[CMD_SIZE] = { + 0x55, 0x53, 0x42, 0x43, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x80, 0x01, 0x10, 0xfd, + 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const char data_block_header[DATA_BLOCK_HEADER_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x04, 0x15, 0x00, 0x00, 0xfc, 0x00, 0x00, + 0x01, 0x00, 0x00, 0xdb +}; + +static const char data_last_block_header[DATA_BLOCK_HEADER_SIZE] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xfb, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x2a, 0x00, 0x20, 0x00, 0xc0, 0x0f, 0x00, 0x00, + 0x01, 0x00, 0x00, 0xd7 +}; + +static const char data_block_footer[DATA_BLOCK_FOOTER_SIZE] = { + 0xfb, 0x14, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x00, 0x00, 0x4f +}; + +static int gm12u320_usb_alloc(struct gm12u320_device *gm12u320) +{ + int i, block_size; + const char *hdr; + + gm12u320->cmd_buf = kmalloc(CMD_SIZE, GFP_KERNEL); + if (!gm12u320->cmd_buf) + return -ENOMEM; + + for (i = 0; i < GM12U320_BLOCK_COUNT; i++) { + if (i == GM12U320_BLOCK_COUNT - 1) { + block_size = DATA_LAST_BLOCK_SIZE; + hdr = data_last_block_header; + } else { + block_size = DATA_BLOCK_SIZE; + hdr = data_block_header; + } + + gm12u320->data_buf[i] = kzalloc(block_size, GFP_KERNEL); + if (!gm12u320->data_buf[i]) + return -ENOMEM; + + memcpy(gm12u320->data_buf[i], hdr, DATA_BLOCK_HEADER_SIZE); + memcpy(gm12u320->data_buf[i] + + (block_size - DATA_BLOCK_FOOTER_SIZE), + data_block_footer, DATA_BLOCK_FOOTER_SIZE); + } + + gm12u320->fb_update.workq = create_singlethread_workqueue(DRIVER_NAME); + if (!gm12u320->fb_update.workq) + return -ENOMEM; + + return 0; +} + +static void gm12u320_usb_free(struct gm12u320_device *gm12u320) +{ + int i; + + if (gm12u320->fb_update.workq) + destroy_workqueue(gm12u320->fb_update.workq); + + for (i = 0; i < GM12U320_BLOCK_COUNT; i++) + kfree(gm12u320->data_buf[i]); + + kfree(gm12u320->cmd_buf); +} + +static int gm12u320_misc_request(struct gm12u320_device *gm12u320, + u8 req_a, u8 req_b, + u8 arg_a, u8 arg_b, u8 arg_c, u8 arg_d) +{ + int ret, len; + + memcpy(gm12u320->cmd_buf, &cmd_misc, CMD_SIZE); + gm12u320->cmd_buf[20] = req_a; + gm12u320->cmd_buf[21] = req_b; + gm12u320->cmd_buf[22] = arg_a; + gm12u320->cmd_buf[23] = arg_b; + gm12u320->cmd_buf[24] = arg_c; + gm12u320->cmd_buf[25] = arg_d; + + /* Send request */ + ret = usb_bulk_msg(gm12u320->udev, + usb_sndbulkpipe(gm12u320->udev, MISC_SND_EPT), + gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT); + if (ret || len != CMD_SIZE) { + dev_err(&gm12u320->udev->dev, "Misc. req. error %d\n", ret); + return -EIO; + } + + /* Read value */ + ret = usb_bulk_msg(gm12u320->udev, + usb_rcvbulkpipe(gm12u320->udev, MISC_RCV_EPT), + gm12u320->cmd_buf, MISC_VALUE_SIZE, &len, + DATA_TIMEOUT); + if (ret || len != MISC_VALUE_SIZE) { + dev_err(&gm12u320->udev->dev, "Misc. value error %d\n", ret); + return -EIO; + } + /* cmd_buf[0] now contains the read value, which we don't use */ + + /* Read status */ + ret = usb_bulk_msg(gm12u320->udev, + usb_rcvbulkpipe(gm12u320->udev, MISC_RCV_EPT), + gm12u320->cmd_buf, READ_STATUS_SIZE, &len, + CMD_TIMEOUT); + if (ret || len != READ_STATUS_SIZE) { + dev_err(&gm12u320->udev->dev, "Misc. status error %d\n", ret); + return -EIO; + } + + return 0; +} + +static void gm12u320_32bpp_to_24bpp_packed(u8 *dst, u8 *src, int len) +{ + while (len--) { + *dst++ = *src++; + *dst++ = *src++; + *dst++ = *src++; + src++; + } +} + +static void gm12u320_copy_fb_to_blocks(struct gm12u320_device *gm12u320) +{ + int block, dst_offset, len, remain, ret, x1, x2, y1, y2; + struct drm_framebuffer *fb; + void *vaddr; + u8 *src; + + mutex_lock(&gm12u320->fb_update.lock); + + if (!gm12u320->fb_update.fb) + goto unlock; + + fb = gm12u320->fb_update.fb; + x1 = gm12u320->fb_update.rect.x1; + x2 = gm12u320->fb_update.rect.x2; + y1 = gm12u320->fb_update.rect.y1; + y2 = gm12u320->fb_update.rect.y2; + + vaddr = drm_gem_shmem_vmap(fb->obj[0]); + if (IS_ERR(vaddr)) { + DRM_ERROR("failed to vmap fb: %ld\n", PTR_ERR(vaddr)); + goto put_fb; + } + + if (fb->obj[0]->import_attach) { + ret = dma_buf_begin_cpu_access( + fb->obj[0]->import_attach->dmabuf, DMA_FROM_DEVICE); + if (ret) { + DRM_ERROR("dma_buf_begin_cpu_access err: %d\n", ret); + goto vunmap; + } + } + + src = vaddr + y1 * fb->pitches[0] + x1 * 4; + + x1 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2; + x2 += (GM12U320_REAL_WIDTH - GM12U320_USER_WIDTH) / 2; + + for (; y1 < y2; y1++) { + remain = 0; + len = (x2 - x1) * 3; + dst_offset = (y1 * GM12U320_REAL_WIDTH + x1) * 3; + block = dst_offset / DATA_BLOCK_CONTENT_SIZE; + dst_offset %= DATA_BLOCK_CONTENT_SIZE; + + if ((dst_offset + len) > DATA_BLOCK_CONTENT_SIZE) { + remain = dst_offset + len - DATA_BLOCK_CONTENT_SIZE; + len = DATA_BLOCK_CONTENT_SIZE - dst_offset; + } + + dst_offset += DATA_BLOCK_HEADER_SIZE; + len /= 3; + + gm12u320_32bpp_to_24bpp_packed( + gm12u320->data_buf[block] + dst_offset, + src, len); + + if (remain) { + block++; + dst_offset = DATA_BLOCK_HEADER_SIZE; + gm12u320_32bpp_to_24bpp_packed( + gm12u320->data_buf[block] + dst_offset, + src + len * 4, remain / 3); + } + src += fb->pitches[0]; + } + + if (fb->obj[0]->import_attach) { + ret = dma_buf_end_cpu_access(fb->obj[0]->import_attach->dmabuf, + DMA_FROM_DEVICE); + if (ret) + DRM_ERROR("dma_buf_end_cpu_access err: %d\n", ret); + } +vunmap: + drm_gem_shmem_vunmap(fb->obj[0], vaddr); +put_fb: + drm_framebuffer_put(fb); + gm12u320->fb_update.fb = NULL; +unlock: + mutex_unlock(&gm12u320->fb_update.lock); +} + +static int gm12u320_fb_update_ready(struct gm12u320_device *gm12u320) +{ + int ret; + + mutex_lock(&gm12u320->fb_update.lock); + ret = !gm12u320->fb_update.run || gm12u320->fb_update.fb != NULL; + mutex_unlock(&gm12u320->fb_update.lock); + + return ret; +} + +static void gm12u320_fb_update_work(struct work_struct *work) +{ + struct gm12u320_device *gm12u320 = + container_of(work, struct gm12u320_device, fb_update.work); + int draw_status_timeout = FIRST_FRAME_TIMEOUT; + int block, block_size, len; + int frame = 0; + int ret = 0; + + while (gm12u320->fb_update.run) { + gm12u320_copy_fb_to_blocks(gm12u320); + + for (block = 0; block < GM12U320_BLOCK_COUNT; block++) { + if (block == GM12U320_BLOCK_COUNT - 1) + block_size = DATA_LAST_BLOCK_SIZE; + else + block_size = DATA_BLOCK_SIZE; + + /* Send data command to device */ + memcpy(gm12u320->cmd_buf, cmd_data, CMD_SIZE); + gm12u320->cmd_buf[8] = block_size & 0xff; + gm12u320->cmd_buf[9] = block_size >> 8; + gm12u320->cmd_buf[20] = 0xfc - block * 4; + gm12u320->cmd_buf[21] = block | (frame << 7); + + ret = usb_bulk_msg(gm12u320->udev, + usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), + gm12u320->cmd_buf, CMD_SIZE, &len, + CMD_TIMEOUT); + if (ret || len != CMD_SIZE) + goto err; + + /* Send data block to device */ + ret = usb_bulk_msg(gm12u320->udev, + usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), + gm12u320->data_buf[block], block_size, + &len, DATA_TIMEOUT); + if (ret || len != block_size) + goto err; + + /* Read status */ + ret = usb_bulk_msg(gm12u320->udev, + usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT), + gm12u320->cmd_buf, READ_STATUS_SIZE, &len, + CMD_TIMEOUT); + if (ret || len != READ_STATUS_SIZE) + goto err; + } + + /* Send draw command to device */ + memcpy(gm12u320->cmd_buf, cmd_draw, CMD_SIZE); + ret = usb_bulk_msg(gm12u320->udev, + usb_sndbulkpipe(gm12u320->udev, DATA_SND_EPT), + gm12u320->cmd_buf, CMD_SIZE, &len, CMD_TIMEOUT); + if (ret || len != CMD_SIZE) + goto err; + + /* Read status */ + ret = usb_bulk_msg(gm12u320->udev, + usb_rcvbulkpipe(gm12u320->udev, DATA_RCV_EPT), + gm12u320->cmd_buf, READ_STATUS_SIZE, &len, + draw_status_timeout); + if (ret || len != READ_STATUS_SIZE) + goto err; + + draw_status_timeout = CMD_TIMEOUT; + frame = !frame; + + /* + * We must draw a frame every 2s otherwise the projector + * switches back to showing its logo. + */ + wait_event_timeout(gm12u320->fb_update.waitq, + gm12u320_fb_update_ready(gm12u320), + IDLE_TIMEOUT); + } + return; +err: + /* Do not log errors caused by module unload or device unplug */ + if (ret != -ECONNRESET && ret != -ESHUTDOWN) + dev_err(&gm12u320->udev->dev, "Frame update error: %d\n", ret); +} + +static void gm12u320_fb_mark_dirty(struct drm_framebuffer *fb, + struct drm_rect *dirty) +{ + struct gm12u320_device *gm12u320 = fb->dev->dev_private; + struct drm_framebuffer *old_fb = NULL; + bool wakeup = false; + + mutex_lock(&gm12u320->fb_update.lock); + + if (gm12u320->fb_update.fb != fb) { + old_fb = gm12u320->fb_update.fb; + drm_framebuffer_get(fb); + gm12u320->fb_update.fb = fb; + gm12u320->fb_update.rect = *dirty; + wakeup = true; + } else { + struct drm_rect *rect = &gm12u320->fb_update.rect; + + rect->x1 = min(rect->x1, dirty->x1); + rect->y1 = min(rect->y1, dirty->y1); + rect->x2 = max(rect->x2, dirty->x2); + rect->y2 = max(rect->y2, dirty->y2); + } + + mutex_unlock(&gm12u320->fb_update.lock); + + if (wakeup) + wake_up(&gm12u320->fb_update.waitq); + + if (old_fb) + drm_framebuffer_put(old_fb); +} + +static void gm12u320_start_fb_update(struct gm12u320_device *gm12u320) +{ + mutex_lock(&gm12u320->fb_update.lock); + gm12u320->fb_update.run = true; + mutex_unlock(&gm12u320->fb_update.lock); + + queue_work(gm12u320->fb_update.workq, &gm12u320->fb_update.work); +} + +static void gm12u320_stop_fb_update(struct gm12u320_device *gm12u320) +{ + mutex_lock(&gm12u320->fb_update.lock); + gm12u320->fb_update.run = false; + mutex_unlock(&gm12u320->fb_update.lock); + + wake_up(&gm12u320->fb_update.waitq); + cancel_work_sync(&gm12u320->fb_update.work); + + mutex_lock(&gm12u320->fb_update.lock); + if (gm12u320->fb_update.fb) { + drm_framebuffer_put(gm12u320->fb_update.fb); + gm12u320->fb_update.fb = NULL; + } + mutex_unlock(&gm12u320->fb_update.lock); +} + +static int gm12u320_set_ecomode(struct gm12u320_device *gm12u320) +{ + return gm12u320_misc_request(gm12u320, MISC_REQ_GET_SET_ECO_A, + MISC_REQ_GET_SET_ECO_B, 0x01 /* set */, + eco_mode ? 0x01 : 0x00, 0x00, 0x01); +} + +/* ------------------------------------------------------------------ */ +/* gm12u320 connector */ + +/* + * We use fake EDID info so that userspace know that it is dealing with + * an Acer projector, rather then listing this as an "unknown" monitor. + * Note this assumes this driver is only ever used with the Acer C120, if we + * add support for other devices the vendor and model should be parameterized. + */ +static struct edid gm12u320_edid = { + .header = { 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }, + .mfg_id = { 0x04, 0x72 }, /* "ACR" */ + .prod_code = { 0x20, 0xc1 }, /* C120h */ + .serial = 0xaa55aa55, + .mfg_week = 1, + .mfg_year = 16, + .version = 1, /* EDID 1.3 */ + .revision = 3, /* EDID 1.3 */ + .input = 0x08, /* Analog input */ + .features = 0x0a, /* Pref timing in DTD 1 */ + .standard_timings = { { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 }, + { 1, 1 }, { 1, 1 }, { 1, 1 }, { 1, 1 } }, + .detailed_timings = { { + .pixel_clock = 3383, + /* hactive = 848, hblank = 256 */ + .data.pixel_data.hactive_lo = 0x50, + .data.pixel_data.hblank_lo = 0x00, + .data.pixel_data.hactive_hblank_hi = 0x31, + /* vactive = 480, vblank = 28 */ + .data.pixel_data.vactive_lo = 0xe0, + .data.pixel_data.vblank_lo = 0x1c, + .data.pixel_data.vactive_vblank_hi = 0x10, + /* hsync offset 40 pw 128, vsync offset 1 pw 4 */ + .data.pixel_data.hsync_offset_lo = 0x28, + .data.pixel_data.hsync_pulse_width_lo = 0x80, + .data.pixel_data.vsync_offset_pulse_width_lo = 0x14, + .data.pixel_data.hsync_vsync_offset_pulse_width_hi = 0x00, + /* Digital separate syncs, hsync+, vsync+ */ + .data.pixel_data.misc = 0x1e, + }, { + .pixel_clock = 0, + .data.other_data.type = 0xfd, /* Monitor ranges */ + .data.other_data.data.range.min_vfreq = 59, + .data.other_data.data.range.max_vfreq = 61, + .data.other_data.data.range.min_hfreq_khz = 29, + .data.other_data.data.range.max_hfreq_khz = 32, + .data.other_data.data.range.pixel_clock_mhz = 4, /* 40 MHz */ + .data.other_data.data.range.flags = 0, + .data.other_data.data.range.formula.cvt = { + 0xa0, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }, + }, { + .pixel_clock = 0, + .data.other_data.type = 0xfc, /* Model string */ + .data.other_data.data.str.str = { + 'P', 'r', 'o', 'j', 'e', 'c', 't', 'o', 'r', '\n', + ' ', ' ', ' ' }, + }, { + .pixel_clock = 0, + .data.other_data.type = 0xfe, /* Unspecified text / padding */ + .data.other_data.data.str.str = { + '\n', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', + ' ', ' ', ' ' }, + } }, + .checksum = 0x13, +}; + +static int gm12u320_conn_get_modes(struct drm_connector *connector) +{ + drm_connector_update_edid_property(connector, &gm12u320_edid); + return drm_add_edid_modes(connector, &gm12u320_edid); +} + +static const struct drm_connector_helper_funcs gm12u320_conn_helper_funcs = { + .get_modes = gm12u320_conn_get_modes, +}; + +static const struct drm_connector_funcs gm12u320_conn_funcs = { + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .reset = drm_atomic_helper_connector_reset, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + +static int gm12u320_conn_init(struct gm12u320_device *gm12u320) +{ + drm_connector_helper_add(&gm12u320->conn, &gm12u320_conn_helper_funcs); + return drm_connector_init(&gm12u320->dev, &gm12u320->conn, + &gm12u320_conn_funcs, DRM_MODE_CONNECTOR_VGA); +} + +/* ------------------------------------------------------------------ */ +/* gm12u320 (simple) display pipe */ + +static void gm12u320_pipe_enable(struct drm_simple_display_pipe *pipe, + struct drm_crtc_state *crtc_state, + struct drm_plane_state *plane_state) +{ + struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private; + struct drm_rect rect = { 0, 0, GM12U320_USER_WIDTH, GM12U320_HEIGHT }; + + gm12u320_fb_mark_dirty(plane_state->fb, &rect); + gm12u320_start_fb_update(gm12u320); + gm12u320->pipe_enabled = true; +} + +static void gm12u320_pipe_disable(struct drm_simple_display_pipe *pipe) +{ + struct gm12u320_device *gm12u320 = pipe->crtc.dev->dev_private; + + gm12u320_stop_fb_update(gm12u320); + gm12u320->pipe_enabled = false; +} + +static void gm12u320_pipe_update(struct drm_simple_display_pipe *pipe, + struct drm_plane_state *old_state) +{ + struct drm_plane_state *state = pipe->plane.state; + struct drm_crtc *crtc = &pipe->crtc; + struct drm_rect rect; + + if (drm_atomic_helper_damage_merged(old_state, state, &rect)) + gm12u320_fb_mark_dirty(pipe->plane.state->fb, &rect); + + if (crtc->state->event) { + spin_lock_irq(&crtc->dev->event_lock); + drm_crtc_send_vblank_event(crtc, crtc->state->event); + crtc->state->event = NULL; + spin_unlock_irq(&crtc->dev->event_lock); + } +} + +static const struct drm_simple_display_pipe_funcs gm12u320_pipe_funcs = { + .enable = gm12u320_pipe_enable, + .disable = gm12u320_pipe_disable, + .update = gm12u320_pipe_update, +}; + +static const uint32_t gm12u320_pipe_formats[] = { + DRM_FORMAT_XRGB8888, +}; + +static const uint64_t gm12u320_pipe_modifiers[] = { + DRM_FORMAT_MOD_LINEAR, + DRM_FORMAT_MOD_INVALID +}; + +static void gm12u320_driver_release(struct drm_device *dev) +{ + struct gm12u320_device *gm12u320 = dev->dev_private; + + gm12u320_usb_free(gm12u320); + drm_mode_config_cleanup(dev); + drm_dev_fini(dev); + kfree(gm12u320); +} + +DEFINE_DRM_GEM_SHMEM_FOPS(gm12u320_fops); + +static struct drm_driver gm12u320_drm_driver = { + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, + + .name = DRIVER_NAME, + .desc = DRIVER_DESC, + .date = DRIVER_DATE, + .major = DRIVER_MAJOR, + .minor = DRIVER_MINOR, + + .release = gm12u320_driver_release, + .fops = &gm12u320_fops, + DRM_GEM_SHMEM_DRIVER_OPS, +}; + +static const struct drm_mode_config_funcs gm12u320_mode_config_funcs = { + .fb_create = drm_gem_fb_create_with_dirty, + .atomic_check = drm_atomic_helper_check, + .atomic_commit = drm_atomic_helper_commit, +}; + +static int gm12u320_usb_probe(struct usb_interface *interface, + const struct usb_device_id *id) +{ + struct gm12u320_device *gm12u320; + struct drm_device *dev; + int ret; + + /* + * The gm12u320 presents itself to the system as 2 usb mass-storage + * interfaces, we only care about / need the first one. + */ + if (interface->cur_altsetting->desc.bInterfaceNumber != 0) + return -ENODEV; + + gm12u320 = kzalloc(sizeof(*gm12u320), GFP_KERNEL); + if (gm12u320 == NULL) + return -ENOMEM; + + gm12u320->udev = interface_to_usbdev(interface); + INIT_WORK(&gm12u320->fb_update.work, gm12u320_fb_update_work); + mutex_init(&gm12u320->fb_update.lock); + init_waitqueue_head(&gm12u320->fb_update.waitq); + + dev = &gm12u320->dev; + ret = drm_dev_init(dev, &gm12u320_drm_driver, &interface->dev); + if (ret) { + kfree(gm12u320); + return ret; + } + dev->dev_private = gm12u320; + + drm_mode_config_init(dev); + dev->mode_config.min_width = GM12U320_USER_WIDTH; + dev->mode_config.max_width = GM12U320_USER_WIDTH; + dev->mode_config.min_height = GM12U320_HEIGHT; + dev->mode_config.max_height = GM12U320_HEIGHT; + dev->mode_config.funcs = &gm12u320_mode_config_funcs; + + ret = gm12u320_usb_alloc(gm12u320); + if (ret) + goto err_put; + + ret = gm12u320_set_ecomode(gm12u320); + if (ret) + goto err_put; + + ret = gm12u320_conn_init(gm12u320); + if (ret) + goto err_put; + + ret = drm_simple_display_pipe_init(&gm12u320->dev, + &gm12u320->pipe, + &gm12u320_pipe_funcs, + gm12u320_pipe_formats, + ARRAY_SIZE(gm12u320_pipe_formats), + gm12u320_pipe_modifiers, + &gm12u320->conn); + if (ret) + goto err_put; + + drm_mode_config_reset(dev); + + usb_set_intfdata(interface, dev); + ret = drm_dev_register(dev, 0); + if (ret) + goto err_put; + + drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth); + + return 0; + +err_put: + drm_dev_put(dev); + return ret; +} + +static void gm12u320_usb_disconnect(struct usb_interface *interface) +{ + struct drm_device *dev = usb_get_intfdata(interface); + struct gm12u320_device *gm12u320 = dev->dev_private; + + gm12u320_stop_fb_update(gm12u320); + drm_dev_unplug(dev); + drm_dev_put(dev); +} + +#ifdef CONFIG_PM +static int gm12u320_suspend(struct usb_interface *interface, + pm_message_t message) +{ + struct drm_device *dev = usb_get_intfdata(interface); + struct gm12u320_device *gm12u320 = dev->dev_private; + + if (gm12u320->pipe_enabled) + gm12u320_stop_fb_update(gm12u320); + + return 0; +} + +static int gm12u320_resume(struct usb_interface *interface) +{ + struct drm_device *dev = usb_get_intfdata(interface); + struct gm12u320_device *gm12u320 = dev->dev_private; + + gm12u320_set_ecomode(gm12u320); + if (gm12u320->pipe_enabled) + gm12u320_start_fb_update(gm12u320); + + return 0; +} +#endif + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x1de1, 0xc102) }, + {}, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver gm12u320_usb_driver = { + .name = "gm12u320", + .probe = gm12u320_usb_probe, + .disconnect = gm12u320_usb_disconnect, + .id_table = id_table, +#ifdef CONFIG_PM + .suspend = gm12u320_suspend, + .resume = gm12u320_resume, + .reset_resume = gm12u320_resume, +#endif +}; + +module_usb_driver(gm12u320_usb_driver); +MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>"); +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tinydrm/hx8357d.c b/drivers/gpu/drm/tiny/hx8357d.c index 5773d0fb6ca1..9af8ff84974f 100644 --- a/drivers/gpu/drm/tinydrm/hx8357d.c +++ b/drivers/gpu/drm/tiny/hx8357d.c @@ -21,9 +21,8 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> -#include <drm/tinydrm/mipi-dbi.h> -#include <drm/tinydrm/tinydrm-helpers.h> #include <video/mipi_display.h> #define HX8357D_SETOSC 0xb0 @@ -48,7 +47,8 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + struct mipi_dbi *dbi = &dbidev->dbi; u8 addr_mode; int ret, idx; @@ -57,29 +57,29 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, DRM_DEBUG_KMS("\n"); - ret = mipi_dbi_poweron_conditional_reset(mipi); + ret = mipi_dbi_poweron_conditional_reset(dbidev); if (ret < 0) goto out_exit; if (ret == 1) goto out_enable; /* setextc */ - mipi_dbi_command(mipi, HX8357D_SETEXTC, 0xFF, 0x83, 0x57); + mipi_dbi_command(dbi, HX8357D_SETEXTC, 0xFF, 0x83, 0x57); msleep(150); /* setRGB which also enables SDO */ - mipi_dbi_command(mipi, HX8357D_SETRGB, 0x00, 0x00, 0x06, 0x06); + mipi_dbi_command(dbi, HX8357D_SETRGB, 0x00, 0x00, 0x06, 0x06); /* -1.52V */ - mipi_dbi_command(mipi, HX8357D_SETCOM, 0x25); + mipi_dbi_command(dbi, HX8357D_SETCOM, 0x25); /* Normal mode 70Hz, Idle mode 55 Hz */ - mipi_dbi_command(mipi, HX8357D_SETOSC, 0x68); + mipi_dbi_command(dbi, HX8357D_SETOSC, 0x68); /* Set Panel - BGR, Gate direction swapped */ - mipi_dbi_command(mipi, HX8357D_SETPANEL, 0x05); + mipi_dbi_command(dbi, HX8357D_SETPANEL, 0x05); - mipi_dbi_command(mipi, HX8357D_SETPOWER, + mipi_dbi_command(dbi, HX8357D_SETPOWER, 0x00, /* Not deep standby */ 0x15, /* BT */ 0x1C, /* VSPR */ @@ -87,7 +87,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 0x83, /* AP */ 0xAA); /* FS */ - mipi_dbi_command(mipi, HX8357D_SETSTBA, + mipi_dbi_command(dbi, HX8357D_SETSTBA, 0x50, /* OPON normal */ 0x50, /* OPON idle */ 0x01, /* STBA */ @@ -95,7 +95,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 0x1E, /* STBA */ 0x08); /* GEN */ - mipi_dbi_command(mipi, HX8357D_SETCYC, + mipi_dbi_command(dbi, HX8357D_SETCYC, 0x02, /* NW 0x02 */ 0x40, /* RTN */ 0x00, /* DIV */ @@ -104,7 +104,7 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 0x0D, /* GDON */ 0x78); /* GDOFF */ - mipi_dbi_command(mipi, HX8357D_SETGAMMA, + mipi_dbi_command(dbi, HX8357D_SETGAMMA, 0x02, 0x0A, 0x11, @@ -141,25 +141,25 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, 0x01); /* 16 bit */ - mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, + mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); /* TE off */ - mipi_dbi_command(mipi, MIPI_DCS_SET_TEAR_ON, 0x00); + mipi_dbi_command(dbi, MIPI_DCS_SET_TEAR_ON, 0x00); /* tear line */ - mipi_dbi_command(mipi, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02); + mipi_dbi_command(dbi, MIPI_DCS_SET_TEAR_SCANLINE, 0x00, 0x02); /* Exit Sleep */ - mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); msleep(150); /* display on */ - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); usleep_range(5000, 7000); out_enable: - switch (mipi->rotation) { + switch (dbidev->rotation) { default: addr_mode = HX8357D_MADCTL_MX | HX8357D_MADCTL_MY; break; @@ -173,8 +173,8 @@ out_enable: addr_mode = HX8357D_MADCTL_MV | HX8357D_MADCTL_MX; break; } - mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); - mipi_dbi_enable_flush(mipi, crtc_state, plane_state); + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); out_exit: drm_dev_exit(idx); } @@ -193,7 +193,7 @@ static const struct drm_display_mode yx350hv15_mode = { DEFINE_DRM_GEM_CMA_FOPS(hx8357d_fops); static struct drm_driver hx8357d_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &hx8357d_fops, .release = mipi_dbi_release, DRM_GEM_CMA_VMAP_DRIVER_OPS, @@ -220,20 +220,20 @@ MODULE_DEVICE_TABLE(spi, hx8357d_id); static int hx8357d_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct mipi_dbi_dev *dbidev; struct drm_device *drm; - struct mipi_dbi *mipi; struct gpio_desc *dc; u32 rotation = 0; int ret; - mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); - if (!mipi) + dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); + if (!dbidev) return -ENOMEM; - drm = &mipi->drm; + drm = &dbidev->drm; ret = devm_drm_dev_init(dev, drm, &hx8357d_driver); if (ret) { - kfree(mipi); + kfree(dbidev); return ret; } @@ -245,17 +245,17 @@ static int hx8357d_probe(struct spi_device *spi) return PTR_ERR(dc); } - mipi->backlight = devm_of_find_backlight(dev); - if (IS_ERR(mipi->backlight)) - return PTR_ERR(mipi->backlight); + dbidev->backlight = devm_of_find_backlight(dev); + if (IS_ERR(dbidev->backlight)) + return PTR_ERR(dbidev->backlight); device_property_read_u32(dev, "rotation", &rotation); - ret = mipi_dbi_spi_init(spi, mipi, dc); + ret = mipi_dbi_spi_init(spi, &dbidev->dbi, dc); if (ret) return ret; - ret = mipi_dbi_init(mipi, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation); + ret = mipi_dbi_dev_init(dbidev, &hx8357d_pipe_funcs, &yx350hv15_mode, rotation); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/ili9225.c b/drivers/gpu/drm/tiny/ili9225.c index ea69019f2f33..c66acc566c2b 100644 --- a/drivers/gpu/drm/tinydrm/ili9225.c +++ b/drivers/gpu/drm/tiny/ili9225.c @@ -24,10 +24,9 @@ #include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_mipi_dbi.h> #include <drm/drm_rect.h> #include <drm/drm_vblank.h> -#include <drm/tinydrm/mipi-dbi.h> -#include <drm/tinydrm/tinydrm-helpers.h> #define ILI9225_DRIVER_READ_CODE 0x00 #define ILI9225_DRIVER_OUTPUT_CONTROL 0x01 @@ -69,27 +68,28 @@ #define ILI9225_GAMMA_CONTROL_9 0x58 #define ILI9225_GAMMA_CONTROL_10 0x59 -static inline int ili9225_command(struct mipi_dbi *mipi, u8 cmd, u16 data) +static inline int ili9225_command(struct mipi_dbi *dbi, u8 cmd, u16 data) { u8 par[2] = { data >> 8, data & 0xff }; - return mipi_dbi_command_buf(mipi, cmd, par, 2); + return mipi_dbi_command_buf(dbi, cmd, par, 2); } static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { struct drm_gem_cma_object *cma_obj = drm_fb_cma_get_gem_obj(fb, 0); - struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); unsigned int height = rect->y2 - rect->y1; unsigned int width = rect->x2 - rect->x1; - bool swap = mipi->swap_bytes; + struct mipi_dbi *dbi = &dbidev->dbi; + bool swap = dbi->swap_bytes; u16 x_start, y_start; u16 x1, x2, y1, y2; int idx, ret = 0; bool full; void *tr; - if (!mipi->enabled) + if (!dbidev->enabled) return; if (!drm_dev_enter(fb->dev, &idx)) @@ -99,17 +99,17 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); - if (!mipi->dc || !full || swap || + if (!dbi->dc || !full || swap || fb->format->format == DRM_FORMAT_XRGB8888) { - tr = mipi->tx_buf; - ret = mipi_dbi_buf_copy(mipi->tx_buf, fb, rect, swap); + tr = dbidev->tx_buf; + ret = mipi_dbi_buf_copy(dbidev->tx_buf, fb, rect, swap); if (ret) goto err_msg; } else { tr = cma_obj->vaddr; } - switch (mipi->rotation) { + switch (dbidev->rotation) { default: x1 = rect->x1; x2 = rect->x2 - 1; @@ -144,15 +144,15 @@ static void ili9225_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) break; } - ili9225_command(mipi, ILI9225_HORIZ_WINDOW_ADDR_1, x2); - ili9225_command(mipi, ILI9225_HORIZ_WINDOW_ADDR_2, x1); - ili9225_command(mipi, ILI9225_VERT_WINDOW_ADDR_1, y2); - ili9225_command(mipi, ILI9225_VERT_WINDOW_ADDR_2, y1); + ili9225_command(dbi, ILI9225_HORIZ_WINDOW_ADDR_1, x2); + ili9225_command(dbi, ILI9225_HORIZ_WINDOW_ADDR_2, x1); + ili9225_command(dbi, ILI9225_VERT_WINDOW_ADDR_1, y2); + ili9225_command(dbi, ILI9225_VERT_WINDOW_ADDR_2, y1); - ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_1, x_start); - ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, y_start); + ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_1, x_start); + ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_2, y_start); - ret = mipi_dbi_command_buf(mipi, ILI9225_WRITE_DATA_TO_GRAM, tr, + ret = mipi_dbi_command_buf(dbi, ILI9225_WRITE_DATA_TO_GRAM, tr, width * height * 2); err_msg: if (ret) @@ -183,9 +183,10 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); struct drm_framebuffer *fb = plane_state->fb; struct device *dev = pipe->crtc.dev->dev; + struct mipi_dbi *dbi = &dbidev->dbi; struct drm_rect rect = { .x1 = 0, .x2 = fb->width, @@ -200,7 +201,7 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, DRM_DEBUG_KMS("\n"); - mipi_dbi_hw_reset(mipi); + mipi_dbi_hw_reset(dbi); /* * There don't seem to be two example init sequences that match, so @@ -208,31 +209,31 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, * https://github.com/Nkawu/TFT_22_ILI9225/blob/master/src/TFT_22_ILI9225.cpp */ - ret = ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0000); + ret = ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0000); if (ret) { DRM_DEV_ERROR(dev, "Error sending command %d\n", ret); goto out_exit; } - ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0000); - ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x0000); - ili9225_command(mipi, ILI9225_POWER_CONTROL_4, 0x0000); - ili9225_command(mipi, ILI9225_POWER_CONTROL_5, 0x0000); + ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0000); + ili9225_command(dbi, ILI9225_POWER_CONTROL_3, 0x0000); + ili9225_command(dbi, ILI9225_POWER_CONTROL_4, 0x0000); + ili9225_command(dbi, ILI9225_POWER_CONTROL_5, 0x0000); msleep(40); - ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0018); - ili9225_command(mipi, ILI9225_POWER_CONTROL_3, 0x6121); - ili9225_command(mipi, ILI9225_POWER_CONTROL_4, 0x006f); - ili9225_command(mipi, ILI9225_POWER_CONTROL_5, 0x495f); - ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0800); + ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0018); + ili9225_command(dbi, ILI9225_POWER_CONTROL_3, 0x6121); + ili9225_command(dbi, ILI9225_POWER_CONTROL_4, 0x006f); + ili9225_command(dbi, ILI9225_POWER_CONTROL_5, 0x495f); + ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0800); msleep(10); - ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x103b); + ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x103b); msleep(50); - switch (mipi->rotation) { + switch (dbidev->rotation) { default: am_id = 0x30; break; @@ -246,43 +247,43 @@ static void ili9225_pipe_enable(struct drm_simple_display_pipe *pipe, am_id = 0x28; break; } - ili9225_command(mipi, ILI9225_DRIVER_OUTPUT_CONTROL, 0x011c); - ili9225_command(mipi, ILI9225_LCD_AC_DRIVING_CONTROL, 0x0100); - ili9225_command(mipi, ILI9225_ENTRY_MODE, 0x1000 | am_id); - ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0000); - ili9225_command(mipi, ILI9225_BLANK_PERIOD_CONTROL_1, 0x0808); - ili9225_command(mipi, ILI9225_FRAME_CYCLE_CONTROL, 0x1100); - ili9225_command(mipi, ILI9225_INTERFACE_CONTROL, 0x0000); - ili9225_command(mipi, ILI9225_OSCILLATION_CONTROL, 0x0d01); - ili9225_command(mipi, ILI9225_VCI_RECYCLING, 0x0020); - ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_1, 0x0000); - ili9225_command(mipi, ILI9225_RAM_ADDRESS_SET_2, 0x0000); - - ili9225_command(mipi, ILI9225_GATE_SCAN_CONTROL, 0x0000); - ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_1, 0x00db); - ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_2, 0x0000); - ili9225_command(mipi, ILI9225_VERTICAL_SCROLL_3, 0x0000); - ili9225_command(mipi, ILI9225_PARTIAL_DRIVING_POS_1, 0x00db); - ili9225_command(mipi, ILI9225_PARTIAL_DRIVING_POS_2, 0x0000); - - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_1, 0x0000); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_2, 0x0808); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_3, 0x080a); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_4, 0x000a); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_5, 0x0a08); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_6, 0x0808); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_7, 0x0000); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_8, 0x0a00); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_9, 0x0710); - ili9225_command(mipi, ILI9225_GAMMA_CONTROL_10, 0x0710); - - ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0012); + ili9225_command(dbi, ILI9225_DRIVER_OUTPUT_CONTROL, 0x011c); + ili9225_command(dbi, ILI9225_LCD_AC_DRIVING_CONTROL, 0x0100); + ili9225_command(dbi, ILI9225_ENTRY_MODE, 0x1000 | am_id); + ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0000); + ili9225_command(dbi, ILI9225_BLANK_PERIOD_CONTROL_1, 0x0808); + ili9225_command(dbi, ILI9225_FRAME_CYCLE_CONTROL, 0x1100); + ili9225_command(dbi, ILI9225_INTERFACE_CONTROL, 0x0000); + ili9225_command(dbi, ILI9225_OSCILLATION_CONTROL, 0x0d01); + ili9225_command(dbi, ILI9225_VCI_RECYCLING, 0x0020); + ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_1, 0x0000); + ili9225_command(dbi, ILI9225_RAM_ADDRESS_SET_2, 0x0000); + + ili9225_command(dbi, ILI9225_GATE_SCAN_CONTROL, 0x0000); + ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_1, 0x00db); + ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_2, 0x0000); + ili9225_command(dbi, ILI9225_VERTICAL_SCROLL_3, 0x0000); + ili9225_command(dbi, ILI9225_PARTIAL_DRIVING_POS_1, 0x00db); + ili9225_command(dbi, ILI9225_PARTIAL_DRIVING_POS_2, 0x0000); + + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_1, 0x0000); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_2, 0x0808); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_3, 0x080a); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_4, 0x000a); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_5, 0x0a08); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_6, 0x0808); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_7, 0x0000); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_8, 0x0a00); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_9, 0x0710); + ili9225_command(dbi, ILI9225_GAMMA_CONTROL_10, 0x0710); + + ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0012); msleep(50); - ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x1017); + ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x1017); - mipi->enabled = true; + dbidev->enabled = true; ili9225_fb_dirty(fb, &rect); out_exit: drm_dev_exit(idx); @@ -290,7 +291,8 @@ out_exit: static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + struct mipi_dbi *dbi = &dbidev->dbi; DRM_DEBUG_KMS("\n"); @@ -301,39 +303,39 @@ static void ili9225_pipe_disable(struct drm_simple_display_pipe *pipe) * unplug. */ - if (!mipi->enabled) + if (!dbidev->enabled) return; - ili9225_command(mipi, ILI9225_DISPLAY_CONTROL_1, 0x0000); + ili9225_command(dbi, ILI9225_DISPLAY_CONTROL_1, 0x0000); msleep(50); - ili9225_command(mipi, ILI9225_POWER_CONTROL_2, 0x0007); + ili9225_command(dbi, ILI9225_POWER_CONTROL_2, 0x0007); msleep(50); - ili9225_command(mipi, ILI9225_POWER_CONTROL_1, 0x0a02); + ili9225_command(dbi, ILI9225_POWER_CONTROL_1, 0x0a02); - mipi->enabled = false; + dbidev->enabled = false; } -static int ili9225_dbi_command(struct mipi_dbi *mipi, u8 *cmd, u8 *par, +static int ili9225_dbi_command(struct mipi_dbi *dbi, u8 *cmd, u8 *par, size_t num) { - struct spi_device *spi = mipi->spi; + struct spi_device *spi = dbi->spi; unsigned int bpw = 8; u32 speed_hz; int ret; - gpiod_set_value_cansleep(mipi->dc, 0); + gpiod_set_value_cansleep(dbi->dc, 0); speed_hz = mipi_dbi_spi_cmd_max_speed(spi, 1); - ret = tinydrm_spi_transfer(spi, speed_hz, NULL, 8, cmd, 1); + ret = mipi_dbi_spi_transfer(spi, speed_hz, 8, cmd, 1); if (ret || !num) return ret; - if (*cmd == ILI9225_WRITE_DATA_TO_GRAM && !mipi->swap_bytes) + if (*cmd == ILI9225_WRITE_DATA_TO_GRAM && !dbi->swap_bytes) bpw = 16; - gpiod_set_value_cansleep(mipi->dc, 1); + gpiod_set_value_cansleep(dbi->dc, 1); speed_hz = mipi_dbi_spi_cmd_max_speed(spi, num); - return tinydrm_spi_transfer(spi, speed_hz, NULL, bpw, par, num); + return mipi_dbi_spi_transfer(spi, speed_hz, bpw, par, num); } static const struct drm_simple_display_pipe_funcs ili9225_pipe_funcs = { @@ -350,8 +352,7 @@ static const struct drm_display_mode ili9225_mode = { DEFINE_DRM_GEM_CMA_FOPS(ili9225_fops); static struct drm_driver ili9225_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ili9225_fops, .release = mipi_dbi_release, DRM_GEM_CMA_VMAP_DRIVER_OPS, @@ -377,29 +378,31 @@ MODULE_DEVICE_TABLE(spi, ili9225_id); static int ili9225_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct mipi_dbi_dev *dbidev; struct drm_device *drm; - struct mipi_dbi *mipi; + struct mipi_dbi *dbi; struct gpio_desc *rs; u32 rotation = 0; int ret; - mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); - if (!mipi) + dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); + if (!dbidev) return -ENOMEM; - drm = &mipi->drm; + dbi = &dbidev->dbi; + drm = &dbidev->drm; ret = devm_drm_dev_init(dev, drm, &ili9225_driver); if (ret) { - kfree(mipi); + kfree(dbidev); return ret; } drm_mode_config_init(drm); - mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(mipi->reset)) { + dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(dbi->reset)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); - return PTR_ERR(mipi->reset); + return PTR_ERR(dbi->reset); } rs = devm_gpiod_get(dev, "rs", GPIOD_OUT_LOW); @@ -410,14 +413,14 @@ static int ili9225_probe(struct spi_device *spi) device_property_read_u32(dev, "rotation", &rotation); - ret = mipi_dbi_spi_init(spi, mipi, rs); + ret = mipi_dbi_spi_init(spi, dbi, rs); if (ret) return ret; /* override the command function set in mipi_dbi_spi_init() */ - mipi->command = ili9225_dbi_command; + dbi->command = ili9225_dbi_command; - ret = mipi_dbi_init(mipi, &ili9225_pipe_funcs, &ili9225_mode, rotation); + ret = mipi_dbi_dev_init(dbidev, &ili9225_pipe_funcs, &ili9225_mode, rotation); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/ili9341.c b/drivers/gpu/drm/tiny/ili9341.c index 4ade9e4b924f..33b51dc7faa8 100644 --- a/drivers/gpu/drm/tinydrm/ili9341.c +++ b/drivers/gpu/drm/tiny/ili9341.c @@ -20,9 +20,8 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> -#include <drm/tinydrm/mipi-dbi.h> -#include <drm/tinydrm/tinydrm-helpers.h> #include <video/mipi_display.h> #define ILI9341_FRMCTR1 0xb1 @@ -54,7 +53,8 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + struct mipi_dbi *dbi = &dbidev->dbi; u8 addr_mode; int ret, idx; @@ -63,57 +63,57 @@ static void yx240qv29_enable(struct drm_simple_display_pipe *pipe, DRM_DEBUG_KMS("\n"); - ret = mipi_dbi_poweron_conditional_reset(mipi); + ret = mipi_dbi_poweron_conditional_reset(dbidev); if (ret < 0) goto out_exit; if (ret == 1) goto out_enable; - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF); - mipi_dbi_command(mipi, ILI9341_PWCTRLB, 0x00, 0xc1, 0x30); - mipi_dbi_command(mipi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81); - mipi_dbi_command(mipi, ILI9341_DTCTRLA, 0x85, 0x00, 0x78); - mipi_dbi_command(mipi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02); - mipi_dbi_command(mipi, ILI9341_PUMPCTRL, 0x20); - mipi_dbi_command(mipi, ILI9341_DTCTRLB, 0x00, 0x00); + mipi_dbi_command(dbi, ILI9341_PWCTRLB, 0x00, 0xc1, 0x30); + mipi_dbi_command(dbi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81); + mipi_dbi_command(dbi, ILI9341_DTCTRLA, 0x85, 0x00, 0x78); + mipi_dbi_command(dbi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02); + mipi_dbi_command(dbi, ILI9341_PUMPCTRL, 0x20); + mipi_dbi_command(dbi, ILI9341_DTCTRLB, 0x00, 0x00); /* Power Control */ - mipi_dbi_command(mipi, ILI9341_PWCTRL1, 0x23); - mipi_dbi_command(mipi, ILI9341_PWCTRL2, 0x10); + mipi_dbi_command(dbi, ILI9341_PWCTRL1, 0x23); + mipi_dbi_command(dbi, ILI9341_PWCTRL2, 0x10); /* VCOM */ - mipi_dbi_command(mipi, ILI9341_VMCTRL1, 0x3e, 0x28); - mipi_dbi_command(mipi, ILI9341_VMCTRL2, 0x86); + mipi_dbi_command(dbi, ILI9341_VMCTRL1, 0x3e, 0x28); + mipi_dbi_command(dbi, ILI9341_VMCTRL2, 0x86); /* Memory Access Control */ - mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); + mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); /* Frame Rate */ - mipi_dbi_command(mipi, ILI9341_FRMCTR1, 0x00, 0x1b); + mipi_dbi_command(dbi, ILI9341_FRMCTR1, 0x00, 0x1b); /* Gamma */ - mipi_dbi_command(mipi, ILI9341_EN3GAM, 0x00); - mipi_dbi_command(mipi, MIPI_DCS_SET_GAMMA_CURVE, 0x01); - mipi_dbi_command(mipi, ILI9341_PGAMCTRL, + mipi_dbi_command(dbi, ILI9341_EN3GAM, 0x00); + mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, 0x01); + mipi_dbi_command(dbi, ILI9341_PGAMCTRL, 0x0f, 0x31, 0x2b, 0x0c, 0x0e, 0x08, 0x4e, 0xf1, 0x37, 0x07, 0x10, 0x03, 0x0e, 0x09, 0x00); - mipi_dbi_command(mipi, ILI9341_NGAMCTRL, + mipi_dbi_command(dbi, ILI9341_NGAMCTRL, 0x00, 0x0e, 0x14, 0x03, 0x11, 0x07, 0x31, 0xc1, 0x48, 0x08, 0x0f, 0x0c, 0x31, 0x36, 0x0f); /* DDRAM */ - mipi_dbi_command(mipi, ILI9341_ETMOD, 0x07); + mipi_dbi_command(dbi, ILI9341_ETMOD, 0x07); /* Display */ - mipi_dbi_command(mipi, ILI9341_DISCTRL, 0x08, 0x82, 0x27, 0x00); - mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dbi_command(dbi, ILI9341_DISCTRL, 0x08, 0x82, 0x27, 0x00); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); msleep(100); - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); msleep(100); out_enable: - switch (mipi->rotation) { + switch (dbidev->rotation) { default: addr_mode = ILI9341_MADCTL_MX; break; @@ -129,8 +129,8 @@ out_enable: break; } addr_mode |= ILI9341_MADCTL_BGR; - mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); - mipi_dbi_enable_flush(mipi, crtc_state, plane_state); + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); out_exit: drm_dev_exit(idx); } @@ -149,7 +149,7 @@ static const struct drm_display_mode yx240qv29_mode = { DEFINE_DRM_GEM_CMA_FOPS(ili9341_fops); static struct drm_driver ili9341_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &ili9341_fops, .release = mipi_dbi_release, DRM_GEM_CMA_VMAP_DRIVER_OPS, @@ -176,29 +176,31 @@ MODULE_DEVICE_TABLE(spi, ili9341_id); static int ili9341_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct mipi_dbi_dev *dbidev; struct drm_device *drm; - struct mipi_dbi *mipi; + struct mipi_dbi *dbi; struct gpio_desc *dc; u32 rotation = 0; int ret; - mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); - if (!mipi) + dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); + if (!dbidev) return -ENOMEM; - drm = &mipi->drm; + dbi = &dbidev->dbi; + drm = &dbidev->drm; ret = devm_drm_dev_init(dev, drm, &ili9341_driver); if (ret) { - kfree(mipi); + kfree(dbidev); return ret; } drm_mode_config_init(drm); - mipi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(mipi->reset)) { + dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(dbi->reset)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); - return PTR_ERR(mipi->reset); + return PTR_ERR(dbi->reset); } dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW); @@ -207,17 +209,17 @@ static int ili9341_probe(struct spi_device *spi) return PTR_ERR(dc); } - mipi->backlight = devm_of_find_backlight(dev); - if (IS_ERR(mipi->backlight)) - return PTR_ERR(mipi->backlight); + dbidev->backlight = devm_of_find_backlight(dev); + if (IS_ERR(dbidev->backlight)) + return PTR_ERR(dbidev->backlight); device_property_read_u32(dev, "rotation", &rotation); - ret = mipi_dbi_spi_init(spi, mipi, dc); + ret = mipi_dbi_spi_init(spi, dbi, dc); if (ret) return ret; - ret = mipi_dbi_init(mipi, &ili9341_pipe_funcs, &yx240qv29_mode, rotation); + ret = mipi_dbi_dev_init(dbidev, &ili9341_pipe_funcs, &yx240qv29_mode, rotation); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/mi0283qt.c b/drivers/gpu/drm/tiny/mi0283qt.c index fdefa53455d4..e2cfd9a17143 100644 --- a/drivers/gpu/drm/tinydrm/mi0283qt.c +++ b/drivers/gpu/drm/tiny/mi0283qt.c @@ -18,9 +18,8 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_mipi_dbi.h> #include <drm/drm_modeset_helper.h> -#include <drm/tinydrm/mipi-dbi.h> -#include <drm/tinydrm/tinydrm-helpers.h> #include <video/mipi_display.h> #define ILI9341_FRMCTR1 0xb1 @@ -52,7 +51,8 @@ static void mi0283qt_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + struct mipi_dbi *dbi = &dbidev->dbi; u8 addr_mode; int ret, idx; @@ -61,53 +61,53 @@ static void mi0283qt_enable(struct drm_simple_display_pipe *pipe, DRM_DEBUG_KMS("\n"); - ret = mipi_dbi_poweron_conditional_reset(mipi); + ret = mipi_dbi_poweron_conditional_reset(dbidev); if (ret < 0) goto out_exit; if (ret == 1) goto out_enable; - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF); - mipi_dbi_command(mipi, ILI9341_PWCTRLB, 0x00, 0x83, 0x30); - mipi_dbi_command(mipi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81); - mipi_dbi_command(mipi, ILI9341_DTCTRLA, 0x85, 0x01, 0x79); - mipi_dbi_command(mipi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02); - mipi_dbi_command(mipi, ILI9341_PUMPCTRL, 0x20); - mipi_dbi_command(mipi, ILI9341_DTCTRLB, 0x00, 0x00); + mipi_dbi_command(dbi, ILI9341_PWCTRLB, 0x00, 0x83, 0x30); + mipi_dbi_command(dbi, ILI9341_PWRSEQ, 0x64, 0x03, 0x12, 0x81); + mipi_dbi_command(dbi, ILI9341_DTCTRLA, 0x85, 0x01, 0x79); + mipi_dbi_command(dbi, ILI9341_PWCTRLA, 0x39, 0x2c, 0x00, 0x34, 0x02); + mipi_dbi_command(dbi, ILI9341_PUMPCTRL, 0x20); + mipi_dbi_command(dbi, ILI9341_DTCTRLB, 0x00, 0x00); /* Power Control */ - mipi_dbi_command(mipi, ILI9341_PWCTRL1, 0x26); - mipi_dbi_command(mipi, ILI9341_PWCTRL2, 0x11); + mipi_dbi_command(dbi, ILI9341_PWCTRL1, 0x26); + mipi_dbi_command(dbi, ILI9341_PWCTRL2, 0x11); /* VCOM */ - mipi_dbi_command(mipi, ILI9341_VMCTRL1, 0x35, 0x3e); - mipi_dbi_command(mipi, ILI9341_VMCTRL2, 0xbe); + mipi_dbi_command(dbi, ILI9341_VMCTRL1, 0x35, 0x3e); + mipi_dbi_command(dbi, ILI9341_VMCTRL2, 0xbe); /* Memory Access Control */ - mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); + mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); /* Frame Rate */ - mipi_dbi_command(mipi, ILI9341_FRMCTR1, 0x00, 0x1b); + mipi_dbi_command(dbi, ILI9341_FRMCTR1, 0x00, 0x1b); /* Gamma */ - mipi_dbi_command(mipi, ILI9341_EN3GAM, 0x08); - mipi_dbi_command(mipi, MIPI_DCS_SET_GAMMA_CURVE, 0x01); - mipi_dbi_command(mipi, ILI9341_PGAMCTRL, + mipi_dbi_command(dbi, ILI9341_EN3GAM, 0x08); + mipi_dbi_command(dbi, MIPI_DCS_SET_GAMMA_CURVE, 0x01); + mipi_dbi_command(dbi, ILI9341_PGAMCTRL, 0x1f, 0x1a, 0x18, 0x0a, 0x0f, 0x06, 0x45, 0x87, 0x32, 0x0a, 0x07, 0x02, 0x07, 0x05, 0x00); - mipi_dbi_command(mipi, ILI9341_NGAMCTRL, + mipi_dbi_command(dbi, ILI9341_NGAMCTRL, 0x00, 0x25, 0x27, 0x05, 0x10, 0x09, 0x3a, 0x78, 0x4d, 0x05, 0x18, 0x0d, 0x38, 0x3a, 0x1f); /* DDRAM */ - mipi_dbi_command(mipi, ILI9341_ETMOD, 0x07); + mipi_dbi_command(dbi, ILI9341_ETMOD, 0x07); /* Display */ - mipi_dbi_command(mipi, ILI9341_DISCTRL, 0x0a, 0x82, 0x27, 0x00); - mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dbi_command(dbi, ILI9341_DISCTRL, 0x0a, 0x82, 0x27, 0x00); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); msleep(100); - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); msleep(100); out_enable: @@ -117,7 +117,7 @@ out_enable: * As a result, we need to always apply the rotation value * regardless of the display "on/off" state. */ - switch (mipi->rotation) { + switch (dbidev->rotation) { default: addr_mode = ILI9341_MADCTL_MV | ILI9341_MADCTL_MY | ILI9341_MADCTL_MX; @@ -133,8 +133,8 @@ out_enable: break; } addr_mode |= ILI9341_MADCTL_BGR; - mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); - mipi_dbi_enable_flush(mipi, crtc_state, plane_state); + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); out_exit: drm_dev_exit(idx); } @@ -153,8 +153,7 @@ static const struct drm_display_mode mi0283qt_mode = { DEFINE_DRM_GEM_CMA_FOPS(mi0283qt_fops); static struct drm_driver mi0283qt_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &mi0283qt_fops, .release = mipi_dbi_release, DRM_GEM_CMA_VMAP_DRIVER_OPS, @@ -181,29 +180,31 @@ MODULE_DEVICE_TABLE(spi, mi0283qt_id); static int mi0283qt_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct mipi_dbi_dev *dbidev; struct drm_device *drm; - struct mipi_dbi *mipi; + struct mipi_dbi *dbi; struct gpio_desc *dc; u32 rotation = 0; int ret; - mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); - if (!mipi) + dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); + if (!dbidev) return -ENOMEM; - drm = &mipi->drm; + dbi = &dbidev->dbi; + drm = &dbidev->drm; ret = devm_drm_dev_init(dev, drm, &mi0283qt_driver); if (ret) { - kfree(mipi); + kfree(dbidev); return ret; } drm_mode_config_init(drm); - mipi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(mipi->reset)) { + dbi->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(dbi->reset)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); - return PTR_ERR(mipi->reset); + return PTR_ERR(dbi->reset); } dc = devm_gpiod_get_optional(dev, "dc", GPIOD_OUT_LOW); @@ -212,21 +213,21 @@ static int mi0283qt_probe(struct spi_device *spi) return PTR_ERR(dc); } - mipi->regulator = devm_regulator_get(dev, "power"); - if (IS_ERR(mipi->regulator)) - return PTR_ERR(mipi->regulator); + dbidev->regulator = devm_regulator_get(dev, "power"); + if (IS_ERR(dbidev->regulator)) + return PTR_ERR(dbidev->regulator); - mipi->backlight = devm_of_find_backlight(dev); - if (IS_ERR(mipi->backlight)) - return PTR_ERR(mipi->backlight); + dbidev->backlight = devm_of_find_backlight(dev); + if (IS_ERR(dbidev->backlight)) + return PTR_ERR(dbidev->backlight); device_property_read_u32(dev, "rotation", &rotation); - ret = mipi_dbi_spi_init(spi, mipi, dc); + ret = mipi_dbi_spi_init(spi, dbi, dc); if (ret) return ret; - ret = mipi_dbi_init(mipi, &mi0283qt_pipe_funcs, &mi0283qt_mode, rotation); + ret = mipi_dbi_dev_init(dbidev, &mi0283qt_pipe_funcs, &mi0283qt_mode, rotation); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/repaper.c b/drivers/gpu/drm/tiny/repaper.c index 97a874b40394..76d179200775 100644 --- a/drivers/gpu/drm/tinydrm/repaper.c +++ b/drivers/gpu/drm/tiny/repaper.c @@ -23,6 +23,7 @@ #include <linux/thermal.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_connector.h> #include <drm/drm_damage_helper.h> #include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> @@ -30,10 +31,11 @@ #include <drm/drm_format_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_modes.h> #include <drm/drm_rect.h> #include <drm/drm_vblank.h> +#include <drm/drm_probe_helper.h> #include <drm/drm_simple_kms_helper.h> -#include <drm/tinydrm/tinydrm-helpers.h> #define REPAPER_RID_G2_COG_ID 0x12 @@ -60,6 +62,8 @@ enum repaper_epd_border_byte { struct repaper_epd { struct drm_device drm; struct drm_simple_display_pipe pipe; + const struct drm_display_mode *mode; + struct drm_connector connector; struct spi_device *spi; struct gpio_desc *panel_on; @@ -873,6 +877,39 @@ static const struct drm_simple_display_pipe_funcs repaper_pipe_funcs = { .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; +static int repaper_connector_get_modes(struct drm_connector *connector) +{ + struct repaper_epd *epd = drm_to_epd(connector->dev); + struct drm_display_mode *mode; + + mode = drm_mode_duplicate(connector->dev, epd->mode); + if (!mode) { + DRM_ERROR("Failed to duplicate mode\n"); + return 0; + } + + drm_mode_set_name(mode); + mode->type |= DRM_MODE_TYPE_PREFERRED; + drm_mode_probed_add(connector, mode); + + connector->display_info.width_mm = mode->width_mm; + connector->display_info.height_mm = mode->height_mm; + + return 1; +} + +static const struct drm_connector_helper_funcs repaper_connector_hfuncs = { + .get_modes = repaper_connector_get_modes, +}; + +static const struct drm_connector_funcs repaper_connector_funcs = { + .reset = drm_atomic_helper_connector_reset, + .fill_modes = drm_helper_probe_single_connector_modes, + .destroy = drm_connector_cleanup, + .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, + .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, +}; + static const struct drm_mode_config_funcs repaper_mode_config_funcs = { .fb_create = drm_gem_fb_create_with_dirty, .atomic_check = drm_atomic_helper_check, @@ -925,8 +962,7 @@ static const u8 repaper_e2271cs021_cs[] = { 0x00, 0x00, 0x00, 0x7f, DEFINE_DRM_GEM_CMA_FOPS(repaper_fops); static struct drm_driver repaper_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &repaper_fops, .release = repaper_release, DRM_GEM_CMA_VMAP_DRIVER_OPS, @@ -1096,6 +1132,7 @@ static int repaper_probe(struct spi_device *spi) return -ENODEV; } + epd->mode = mode; epd->width = mode->hdisplay; epd->height = mode->vdisplay; epd->factored_stage_time = epd->stage_time; @@ -1110,10 +1147,20 @@ static int repaper_probe(struct spi_device *spi) if (!epd->current_frame) return -ENOMEM; - ret = tinydrm_display_pipe_init(drm, &epd->pipe, &repaper_pipe_funcs, - DRM_MODE_CONNECTOR_VIRTUAL, - repaper_formats, - ARRAY_SIZE(repaper_formats), mode, 0); + drm->mode_config.min_width = mode->hdisplay; + drm->mode_config.max_width = mode->hdisplay; + drm->mode_config.min_height = mode->vdisplay; + drm->mode_config.max_height = mode->vdisplay; + + drm_connector_helper_add(&epd->connector, &repaper_connector_hfuncs); + ret = drm_connector_init(drm, &epd->connector, &repaper_connector_funcs, + DRM_MODE_CONNECTOR_SPI); + if (ret) + return ret; + + ret = drm_simple_display_pipe_init(drm, &epd->pipe, &repaper_pipe_funcs, + repaper_formats, ARRAY_SIZE(repaper_formats), + NULL, &epd->connector); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/st7586.c b/drivers/gpu/drm/tiny/st7586.c index 9ac626265152..3cc21a1b30c8 100644 --- a/drivers/gpu/drm/tinydrm/st7586.c +++ b/drivers/gpu/drm/tiny/st7586.c @@ -21,10 +21,9 @@ #include <drm/drm_format_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_mipi_dbi.h> #include <drm/drm_rect.h> #include <drm/drm_vblank.h> -#include <drm/tinydrm/mipi-dbi.h> -#include <drm/tinydrm/tinydrm-helpers.h> /* controller-specific commands */ #define ST7586_DISP_MODE_GRAY 0x38 @@ -115,10 +114,11 @@ static int st7586_buf_copy(void *dst, struct drm_framebuffer *fb, static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(fb->dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(fb->dev); + struct mipi_dbi *dbi = &dbidev->dbi; int start, end, idx, ret = 0; - if (!mipi->enabled) + if (!dbidev->enabled) return; if (!drm_dev_enter(fb->dev, &idx)) @@ -130,7 +130,7 @@ static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) DRM_DEBUG_KMS("Flushing [FB:%d] " DRM_RECT_FMT "\n", fb->base.id, DRM_RECT_ARG(rect)); - ret = st7586_buf_copy(mipi->tx_buf, fb, rect); + ret = st7586_buf_copy(dbidev->tx_buf, fb, rect); if (ret) goto err_msg; @@ -138,15 +138,15 @@ static void st7586_fb_dirty(struct drm_framebuffer *fb, struct drm_rect *rect) start = rect->x1 / 3; end = rect->x2 / 3; - mipi_dbi_command(mipi, MIPI_DCS_SET_COLUMN_ADDRESS, + mipi_dbi_command(dbi, MIPI_DCS_SET_COLUMN_ADDRESS, (start >> 8) & 0xFF, start & 0xFF, (end >> 8) & 0xFF, (end - 1) & 0xFF); - mipi_dbi_command(mipi, MIPI_DCS_SET_PAGE_ADDRESS, + mipi_dbi_command(dbi, MIPI_DCS_SET_PAGE_ADDRESS, (rect->y1 >> 8) & 0xFF, rect->y1 & 0xFF, (rect->y2 >> 8) & 0xFF, (rect->y2 - 1) & 0xFF); - ret = mipi_dbi_command_buf(mipi, MIPI_DCS_WRITE_MEMORY_START, - (u8 *)mipi->tx_buf, + ret = mipi_dbi_command_buf(dbi, MIPI_DCS_WRITE_MEMORY_START, + (u8 *)dbidev->tx_buf, (end - start) * (rect->y2 - rect->y1)); err_msg: if (ret) @@ -177,8 +177,9 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); struct drm_framebuffer *fb = plane_state->fb; + struct mipi_dbi *dbi = &dbidev->dbi; struct drm_rect rect = { .x1 = 0, .x2 = fb->width, @@ -193,35 +194,35 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, DRM_DEBUG_KMS("\n"); - ret = mipi_dbi_poweron_reset(mipi); + ret = mipi_dbi_poweron_reset(dbidev); if (ret) goto out_exit; - mipi_dbi_command(mipi, ST7586_AUTO_READ_CTRL, 0x9f); - mipi_dbi_command(mipi, ST7586_OTP_RW_CTRL, 0x00); + mipi_dbi_command(dbi, ST7586_AUTO_READ_CTRL, 0x9f); + mipi_dbi_command(dbi, ST7586_OTP_RW_CTRL, 0x00); msleep(10); - mipi_dbi_command(mipi, ST7586_OTP_READ); + mipi_dbi_command(dbi, ST7586_OTP_READ); msleep(20); - mipi_dbi_command(mipi, ST7586_OTP_CTRL_OUT); - mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF); + mipi_dbi_command(dbi, ST7586_OTP_CTRL_OUT); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_OFF); msleep(50); - mipi_dbi_command(mipi, ST7586_SET_VOP_OFFSET, 0x00); - mipi_dbi_command(mipi, ST7586_SET_VOP, 0xe3, 0x00); - mipi_dbi_command(mipi, ST7586_SET_BIAS_SYSTEM, 0x02); - mipi_dbi_command(mipi, ST7586_SET_BOOST_LEVEL, 0x04); - mipi_dbi_command(mipi, ST7586_ENABLE_ANALOG, 0x1d); - mipi_dbi_command(mipi, ST7586_SET_NLINE_INV, 0x00); - mipi_dbi_command(mipi, ST7586_DISP_MODE_GRAY); - mipi_dbi_command(mipi, ST7586_ENABLE_DDRAM, 0x02); + mipi_dbi_command(dbi, ST7586_SET_VOP_OFFSET, 0x00); + mipi_dbi_command(dbi, ST7586_SET_VOP, 0xe3, 0x00); + mipi_dbi_command(dbi, ST7586_SET_BIAS_SYSTEM, 0x02); + mipi_dbi_command(dbi, ST7586_SET_BOOST_LEVEL, 0x04); + mipi_dbi_command(dbi, ST7586_ENABLE_ANALOG, 0x1d); + mipi_dbi_command(dbi, ST7586_SET_NLINE_INV, 0x00); + mipi_dbi_command(dbi, ST7586_DISP_MODE_GRAY); + mipi_dbi_command(dbi, ST7586_ENABLE_DDRAM, 0x02); - switch (mipi->rotation) { + switch (dbidev->rotation) { default: addr_mode = 0x00; break; @@ -235,26 +236,26 @@ static void st7586_pipe_enable(struct drm_simple_display_pipe *pipe, addr_mode = ST7586_DISP_CTRL_MX; break; } - mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); - mipi_dbi_command(mipi, ST7586_SET_DISP_DUTY, 0x7f); - mipi_dbi_command(mipi, ST7586_SET_PART_DISP, 0xa0); - mipi_dbi_command(mipi, MIPI_DCS_SET_PARTIAL_AREA, 0x00, 0x00, 0x00, 0x77); - mipi_dbi_command(mipi, MIPI_DCS_EXIT_INVERT_MODE); + mipi_dbi_command(dbi, ST7586_SET_DISP_DUTY, 0x7f); + mipi_dbi_command(dbi, ST7586_SET_PART_DISP, 0xa0); + mipi_dbi_command(dbi, MIPI_DCS_SET_PARTIAL_AREA, 0x00, 0x00, 0x00, 0x77); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_INVERT_MODE); msleep(100); - mipi->enabled = true; + dbidev->enabled = true; st7586_fb_dirty(fb, &rect); - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); out_exit: drm_dev_exit(idx); } static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); /* * This callback is not protected by drm_dev_enter/exit since we want to @@ -265,11 +266,11 @@ static void st7586_pipe_disable(struct drm_simple_display_pipe *pipe) DRM_DEBUG_KMS("\n"); - if (!mipi->enabled) + if (!dbidev->enabled) return; - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_OFF); - mipi->enabled = false; + mipi_dbi_command(&dbidev->dbi, MIPI_DCS_SET_DISPLAY_OFF); + dbidev->enabled = false; } static const u32 st7586_formats[] = { @@ -283,12 +284,6 @@ static const struct drm_simple_display_pipe_funcs st7586_pipe_funcs = { .prepare_fb = drm_gem_fb_simple_display_pipe_prepare_fb, }; -static const struct drm_mode_config_funcs st7586_mode_config_funcs = { - .fb_create = drm_gem_fb_create_with_dirty, - .atomic_check = drm_atomic_helper_check, - .atomic_commit = drm_atomic_helper_commit, -}; - static const struct drm_display_mode st7586_mode = { DRM_SIMPLE_MODE(178, 128, 37, 27), }; @@ -296,8 +291,7 @@ static const struct drm_display_mode st7586_mode = { DEFINE_DRM_GEM_CMA_FOPS(st7586_fops); static struct drm_driver st7586_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &st7586_fops, .release = mipi_dbi_release, DRM_GEM_CMA_VMAP_DRIVER_OPS, @@ -324,39 +318,34 @@ MODULE_DEVICE_TABLE(spi, st7586_id); static int st7586_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct mipi_dbi_dev *dbidev; struct drm_device *drm; - struct mipi_dbi *mipi; + struct mipi_dbi *dbi; struct gpio_desc *a0; u32 rotation = 0; size_t bufsize; int ret; - mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); - if (!mipi) + dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); + if (!dbidev) return -ENOMEM; - drm = &mipi->drm; + dbi = &dbidev->dbi; + drm = &dbidev->drm; ret = devm_drm_dev_init(dev, drm, &st7586_driver); if (ret) { - kfree(mipi); + kfree(dbidev); return ret; } drm_mode_config_init(drm); - drm->mode_config.preferred_depth = 32; - drm->mode_config.funcs = &st7586_mode_config_funcs; - - mutex_init(&mipi->cmdlock); bufsize = (st7586_mode.vdisplay + 2) / 3 * st7586_mode.hdisplay; - mipi->tx_buf = devm_kmalloc(dev, bufsize, GFP_KERNEL); - if (!mipi->tx_buf) - return -ENOMEM; - mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(mipi->reset)) { + dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(dbi->reset)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); - return PTR_ERR(mipi->reset); + return PTR_ERR(dbi->reset); } a0 = devm_gpiod_get(dev, "a0", GPIOD_OUT_LOW); @@ -366,14 +355,19 @@ static int st7586_probe(struct spi_device *spi) } device_property_read_u32(dev, "rotation", &rotation); - mipi->rotation = rotation; - ret = mipi_dbi_spi_init(spi, mipi, a0); + ret = mipi_dbi_spi_init(spi, dbi, a0); if (ret) return ret; /* Cannot read from this controller via SPI */ - mipi->read_commands = NULL; + dbi->read_commands = NULL; + + ret = mipi_dbi_dev_init_with_formats(dbidev, &st7586_pipe_funcs, + st7586_formats, ARRAY_SIZE(st7586_formats), + &st7586_mode, rotation, bufsize); + if (ret) + return ret; /* * we are using 8-bit data, so we are not actually swapping anything, @@ -382,16 +376,7 @@ static int st7586_probe(struct spi_device *spi) * bytes on little-endian systems and causes out of order data to be * sent to the display). */ - mipi->swap_bytes = true; - - ret = tinydrm_display_pipe_init(drm, &mipi->pipe, &st7586_pipe_funcs, - DRM_MODE_CONNECTOR_VIRTUAL, - st7586_formats, ARRAY_SIZE(st7586_formats), - &st7586_mode, rotation); - if (ret) - return ret; - - drm_plane_enable_fb_damage_clips(&mipi->pipe.plane); + dbi->swap_bytes = true; drm_mode_config_reset(drm); @@ -401,9 +386,6 @@ static int st7586_probe(struct spi_device *spi) spi_set_drvdata(spi, drm); - DRM_DEBUG_KMS("preferred_depth=%u, rotation = %u\n", - drm->mode_config.preferred_depth, rotation); - drm_fbdev_generic_setup(drm, 0); return 0; diff --git a/drivers/gpu/drm/tinydrm/st7735r.c b/drivers/gpu/drm/tiny/st7735r.c index ce9109e613e0..3f4487c71684 100644 --- a/drivers/gpu/drm/tinydrm/st7735r.c +++ b/drivers/gpu/drm/tiny/st7735r.c @@ -19,8 +19,7 @@ #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/tinydrm/mipi-dbi.h> -#include <drm/tinydrm/tinydrm-helpers.h> +#include <drm/drm_mipi_dbi.h> #define ST7735R_FRMCTR1 0xb1 #define ST7735R_FRMCTR2 0xb2 @@ -43,7 +42,8 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe, struct drm_crtc_state *crtc_state, struct drm_plane_state *plane_state) { - struct mipi_dbi *mipi = drm_to_mipi_dbi(pipe->crtc.dev); + struct mipi_dbi_dev *dbidev = drm_to_mipi_dbi_dev(pipe->crtc.dev); + struct mipi_dbi *dbi = &dbidev->dbi; int ret, idx; u8 addr_mode; @@ -52,28 +52,28 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe, DRM_DEBUG_KMS("\n"); - ret = mipi_dbi_poweron_reset(mipi); + ret = mipi_dbi_poweron_reset(dbidev); if (ret) goto out_exit; msleep(150); - mipi_dbi_command(mipi, MIPI_DCS_EXIT_SLEEP_MODE); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_SLEEP_MODE); msleep(500); - mipi_dbi_command(mipi, ST7735R_FRMCTR1, 0x01, 0x2c, 0x2d); - mipi_dbi_command(mipi, ST7735R_FRMCTR2, 0x01, 0x2c, 0x2d); - mipi_dbi_command(mipi, ST7735R_FRMCTR3, 0x01, 0x2c, 0x2d, 0x01, 0x2c, + mipi_dbi_command(dbi, ST7735R_FRMCTR1, 0x01, 0x2c, 0x2d); + mipi_dbi_command(dbi, ST7735R_FRMCTR2, 0x01, 0x2c, 0x2d); + mipi_dbi_command(dbi, ST7735R_FRMCTR3, 0x01, 0x2c, 0x2d, 0x01, 0x2c, 0x2d); - mipi_dbi_command(mipi, ST7735R_INVCTR, 0x07); - mipi_dbi_command(mipi, ST7735R_PWCTR1, 0xa2, 0x02, 0x84); - mipi_dbi_command(mipi, ST7735R_PWCTR2, 0xc5); - mipi_dbi_command(mipi, ST7735R_PWCTR3, 0x0a, 0x00); - mipi_dbi_command(mipi, ST7735R_PWCTR4, 0x8a, 0x2a); - mipi_dbi_command(mipi, ST7735R_PWCTR5, 0x8a, 0xee); - mipi_dbi_command(mipi, ST7735R_VMCTR1, 0x0e); - mipi_dbi_command(mipi, MIPI_DCS_EXIT_INVERT_MODE); - switch (mipi->rotation) { + mipi_dbi_command(dbi, ST7735R_INVCTR, 0x07); + mipi_dbi_command(dbi, ST7735R_PWCTR1, 0xa2, 0x02, 0x84); + mipi_dbi_command(dbi, ST7735R_PWCTR2, 0xc5); + mipi_dbi_command(dbi, ST7735R_PWCTR3, 0x0a, 0x00); + mipi_dbi_command(dbi, ST7735R_PWCTR4, 0x8a, 0x2a); + mipi_dbi_command(dbi, ST7735R_PWCTR5, 0x8a, 0xee); + mipi_dbi_command(dbi, ST7735R_VMCTR1, 0x0e); + mipi_dbi_command(dbi, MIPI_DCS_EXIT_INVERT_MODE); + switch (dbidev->rotation) { default: addr_mode = ST7735R_MX | ST7735R_MY; break; @@ -87,24 +87,24 @@ static void jd_t18003_t01_pipe_enable(struct drm_simple_display_pipe *pipe, addr_mode = ST7735R_MY | ST7735R_MV; break; } - mipi_dbi_command(mipi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); - mipi_dbi_command(mipi, MIPI_DCS_SET_PIXEL_FORMAT, + mipi_dbi_command(dbi, MIPI_DCS_SET_ADDRESS_MODE, addr_mode); + mipi_dbi_command(dbi, MIPI_DCS_SET_PIXEL_FORMAT, MIPI_DCS_PIXEL_FMT_16BIT); - mipi_dbi_command(mipi, ST7735R_GAMCTRP1, 0x02, 0x1c, 0x07, 0x12, 0x37, + mipi_dbi_command(dbi, ST7735R_GAMCTRP1, 0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10); - mipi_dbi_command(mipi, ST7735R_GAMCTRN1, 0x03, 0x1d, 0x07, 0x06, 0x2e, + mipi_dbi_command(dbi, ST7735R_GAMCTRN1, 0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e, 0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10); - mipi_dbi_command(mipi, MIPI_DCS_SET_DISPLAY_ON); + mipi_dbi_command(dbi, MIPI_DCS_SET_DISPLAY_ON); msleep(100); - mipi_dbi_command(mipi, MIPI_DCS_ENTER_NORMAL_MODE); + mipi_dbi_command(dbi, MIPI_DCS_ENTER_NORMAL_MODE); msleep(20); - mipi_dbi_enable_flush(mipi, crtc_state, plane_state); + mipi_dbi_enable_flush(dbidev, crtc_state, plane_state); out_exit: drm_dev_exit(idx); } @@ -123,8 +123,7 @@ static const struct drm_display_mode jd_t18003_t01_mode = { DEFINE_DRM_GEM_CMA_FOPS(st7735r_fops); static struct drm_driver st7735r_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .fops = &st7735r_fops, .release = mipi_dbi_release, DRM_GEM_CMA_VMAP_DRIVER_OPS, @@ -151,29 +150,31 @@ MODULE_DEVICE_TABLE(spi, st7735r_id); static int st7735r_probe(struct spi_device *spi) { struct device *dev = &spi->dev; + struct mipi_dbi_dev *dbidev; struct drm_device *drm; - struct mipi_dbi *mipi; + struct mipi_dbi *dbi; struct gpio_desc *dc; u32 rotation = 0; int ret; - mipi = kzalloc(sizeof(*mipi), GFP_KERNEL); - if (!mipi) + dbidev = kzalloc(sizeof(*dbidev), GFP_KERNEL); + if (!dbidev) return -ENOMEM; - drm = &mipi->drm; + dbi = &dbidev->dbi; + drm = &dbidev->drm; ret = devm_drm_dev_init(dev, drm, &st7735r_driver); if (ret) { - kfree(mipi); + kfree(dbidev); return ret; } drm_mode_config_init(drm); - mipi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); - if (IS_ERR(mipi->reset)) { + dbi->reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(dbi->reset)) { DRM_DEV_ERROR(dev, "Failed to get gpio 'reset'\n"); - return PTR_ERR(mipi->reset); + return PTR_ERR(dbi->reset); } dc = devm_gpiod_get(dev, "dc", GPIOD_OUT_LOW); @@ -182,20 +183,20 @@ static int st7735r_probe(struct spi_device *spi) return PTR_ERR(dc); } - mipi->backlight = devm_of_find_backlight(dev); - if (IS_ERR(mipi->backlight)) - return PTR_ERR(mipi->backlight); + dbidev->backlight = devm_of_find_backlight(dev); + if (IS_ERR(dbidev->backlight)) + return PTR_ERR(dbidev->backlight); device_property_read_u32(dev, "rotation", &rotation); - ret = mipi_dbi_spi_init(spi, mipi, dc); + ret = mipi_dbi_spi_init(spi, dbi, dc); if (ret) return ret; /* Cannot read from Adafruit 1.8" display via SPI */ - mipi->read_commands = NULL; + dbi->read_commands = NULL; - ret = mipi_dbi_init(mipi, &jd_t18003_t01_pipe_funcs, &jd_t18003_t01_mode, rotation); + ret = mipi_dbi_dev_init(dbidev, &jd_t18003_t01_pipe_funcs, &jd_t18003_t01_mode, rotation); if (ret) return ret; diff --git a/drivers/gpu/drm/tinydrm/core/Makefile b/drivers/gpu/drm/tinydrm/core/Makefile deleted file mode 100644 index 01065e920aea..000000000000 --- a/drivers/gpu/drm/tinydrm/core/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -# SPDX-License-Identifier: GPL-2.0-only -tinydrm-y := tinydrm-pipe.o tinydrm-helpers.o - -obj-$(CONFIG_DRM_TINYDRM) += tinydrm.o diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c b/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c deleted file mode 100644 index dfeafac4c656..000000000000 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-helpers.c +++ /dev/null @@ -1,207 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2016 Noralf Trønnes - */ - -#include <linux/backlight.h> -#include <linux/dma-buf.h> -#include <linux/module.h> -#include <linux/pm.h> -#include <linux/spi/spi.h> -#include <linux/swab.h> - -#include <drm/drm_device.h> -#include <drm/drm_drv.h> -#include <drm/drm_fourcc.h> -#include <drm/drm_framebuffer.h> -#include <drm/drm_print.h> -#include <drm/drm_rect.h> -#include <drm/tinydrm/tinydrm-helpers.h> - -static unsigned int spi_max; -module_param(spi_max, uint, 0400); -MODULE_PARM_DESC(spi_max, "Set a lower SPI max transfer size"); - -#if IS_ENABLED(CONFIG_SPI) - -/** - * tinydrm_spi_max_transfer_size - Determine max SPI transfer size - * @spi: SPI device - * @max_len: Maximum buffer size needed (optional) - * - * This function returns the maximum size to use for SPI transfers. It checks - * the SPI master, the optional @max_len and the module parameter spi_max and - * returns the smallest. - * - * Returns: - * Maximum size for SPI transfers - */ -size_t tinydrm_spi_max_transfer_size(struct spi_device *spi, size_t max_len) -{ - size_t ret; - - ret = min(spi_max_transfer_size(spi), spi->master->max_dma_len); - if (max_len) - ret = min(ret, max_len); - if (spi_max) - ret = min_t(size_t, ret, spi_max); - ret &= ~0x3; - if (ret < 4) - ret = 4; - - return ret; -} -EXPORT_SYMBOL(tinydrm_spi_max_transfer_size); - -/** - * tinydrm_spi_bpw_supported - Check if bits per word is supported - * @spi: SPI device - * @bpw: Bits per word - * - * This function checks to see if the SPI master driver supports @bpw. - * - * Returns: - * True if @bpw is supported, false otherwise. - */ -bool tinydrm_spi_bpw_supported(struct spi_device *spi, u8 bpw) -{ - u32 bpw_mask = spi->master->bits_per_word_mask; - - if (bpw == 8) - return true; - - if (!bpw_mask) { - dev_warn_once(&spi->dev, - "bits_per_word_mask not set, assume 8-bit only\n"); - return false; - } - - if (bpw_mask & SPI_BPW_MASK(bpw)) - return true; - - return false; -} -EXPORT_SYMBOL(tinydrm_spi_bpw_supported); - -static void -tinydrm_dbg_spi_print(struct spi_device *spi, struct spi_transfer *tr, - const void *buf, int idx, bool tx) -{ - u32 speed_hz = tr->speed_hz ? tr->speed_hz : spi->max_speed_hz; - char linebuf[3 * 32]; - - hex_dump_to_buffer(buf, tr->len, 16, - DIV_ROUND_UP(tr->bits_per_word, 8), - linebuf, sizeof(linebuf), false); - - printk(KERN_DEBUG - " tr(%i): speed=%u%s, bpw=%i, len=%u, %s_buf=[%s%s]\n", idx, - speed_hz > 1000000 ? speed_hz / 1000000 : speed_hz / 1000, - speed_hz > 1000000 ? "MHz" : "kHz", tr->bits_per_word, tr->len, - tx ? "tx" : "rx", linebuf, tr->len > 16 ? " ..." : ""); -} - -/* called through tinydrm_dbg_spi_message() */ -void _tinydrm_dbg_spi_message(struct spi_device *spi, struct spi_message *m) -{ - struct spi_transfer *tmp; - int i = 0; - - list_for_each_entry(tmp, &m->transfers, transfer_list) { - - if (tmp->tx_buf) - tinydrm_dbg_spi_print(spi, tmp, tmp->tx_buf, i, true); - if (tmp->rx_buf) - tinydrm_dbg_spi_print(spi, tmp, tmp->rx_buf, i, false); - i++; - } -} -EXPORT_SYMBOL(_tinydrm_dbg_spi_message); - -/** - * tinydrm_spi_transfer - SPI transfer helper - * @spi: SPI device - * @speed_hz: Override speed (optional) - * @header: Optional header transfer - * @bpw: Bits per word - * @buf: Buffer to transfer - * @len: Buffer length - * - * This SPI transfer helper breaks up the transfer of @buf into chunks which - * the SPI master driver can handle. If the machine is Little Endian and the - * SPI master driver doesn't support 16 bits per word, it swaps the bytes and - * does a 8-bit transfer. - * If @header is set, it is prepended to each SPI message. - * - * Returns: - * Zero on success, negative error code on failure. - */ -int tinydrm_spi_transfer(struct spi_device *spi, u32 speed_hz, - struct spi_transfer *header, u8 bpw, const void *buf, - size_t len) -{ - struct spi_transfer tr = { - .bits_per_word = bpw, - .speed_hz = speed_hz, - }; - struct spi_message m; - u16 *swap_buf = NULL; - size_t max_chunk; - size_t chunk; - int ret = 0; - - if (WARN_ON_ONCE(bpw != 8 && bpw != 16)) - return -EINVAL; - - max_chunk = tinydrm_spi_max_transfer_size(spi, 0); - - if (drm_debug & DRM_UT_DRIVER) - pr_debug("[drm:%s] bpw=%u, max_chunk=%zu, transfers:\n", - __func__, bpw, max_chunk); - - if (bpw == 16 && !tinydrm_spi_bpw_supported(spi, 16)) { - tr.bits_per_word = 8; - if (tinydrm_machine_little_endian()) { - swap_buf = kmalloc(min(len, max_chunk), GFP_KERNEL); - if (!swap_buf) - return -ENOMEM; - } - } - - spi_message_init(&m); - if (header) - spi_message_add_tail(header, &m); - spi_message_add_tail(&tr, &m); - - while (len) { - chunk = min(len, max_chunk); - - tr.tx_buf = buf; - tr.len = chunk; - - if (swap_buf) { - const u16 *buf16 = buf; - unsigned int i; - - for (i = 0; i < chunk / 2; i++) - swap_buf[i] = swab16(buf16[i]); - - tr.tx_buf = swap_buf; - } - - buf += chunk; - len -= chunk; - - tinydrm_dbg_spi_message(spi, &m); - ret = spi_sync(spi, &m); - if (ret) - return ret; - } - - return 0; -} -EXPORT_SYMBOL(tinydrm_spi_transfer); - -#endif /* CONFIG_SPI */ - -MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c b/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c deleted file mode 100644 index ed798fd95152..000000000000 --- a/drivers/gpu/drm/tinydrm/core/tinydrm-pipe.c +++ /dev/null @@ -1,179 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later -/* - * Copyright (C) 2016 Noralf Trønnes - */ - -#include <drm/drm_atomic_helper.h> -#include <drm/drm_drv.h> -#include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_modes.h> -#include <drm/drm_probe_helper.h> -#include <drm/drm_print.h> -#include <drm/drm_simple_kms_helper.h> - -struct tinydrm_connector { - struct drm_connector base; - struct drm_display_mode mode; -}; - -static inline struct tinydrm_connector * -to_tinydrm_connector(struct drm_connector *connector) -{ - return container_of(connector, struct tinydrm_connector, base); -} - -static int tinydrm_connector_get_modes(struct drm_connector *connector) -{ - struct tinydrm_connector *tconn = to_tinydrm_connector(connector); - struct drm_display_mode *mode; - - mode = drm_mode_duplicate(connector->dev, &tconn->mode); - if (!mode) { - DRM_ERROR("Failed to duplicate mode\n"); - return 0; - } - - if (mode->name[0] == '\0') - drm_mode_set_name(mode); - - mode->type |= DRM_MODE_TYPE_PREFERRED; - drm_mode_probed_add(connector, mode); - - if (mode->width_mm) { - connector->display_info.width_mm = mode->width_mm; - connector->display_info.height_mm = mode->height_mm; - } - - return 1; -} - -static const struct drm_connector_helper_funcs tinydrm_connector_hfuncs = { - .get_modes = tinydrm_connector_get_modes, -}; - -static enum drm_connector_status -tinydrm_connector_detect(struct drm_connector *connector, bool force) -{ - if (drm_dev_is_unplugged(connector->dev)) - return connector_status_disconnected; - - return connector->status; -} - -static void tinydrm_connector_destroy(struct drm_connector *connector) -{ - struct tinydrm_connector *tconn = to_tinydrm_connector(connector); - - drm_connector_cleanup(connector); - kfree(tconn); -} - -static const struct drm_connector_funcs tinydrm_connector_funcs = { - .reset = drm_atomic_helper_connector_reset, - .detect = tinydrm_connector_detect, - .fill_modes = drm_helper_probe_single_connector_modes, - .destroy = tinydrm_connector_destroy, - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, - .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, -}; - -struct drm_connector * -tinydrm_connector_create(struct drm_device *drm, - const struct drm_display_mode *mode, - int connector_type) -{ - struct tinydrm_connector *tconn; - struct drm_connector *connector; - int ret; - - tconn = kzalloc(sizeof(*tconn), GFP_KERNEL); - if (!tconn) - return ERR_PTR(-ENOMEM); - - drm_mode_copy(&tconn->mode, mode); - connector = &tconn->base; - - drm_connector_helper_add(connector, &tinydrm_connector_hfuncs); - ret = drm_connector_init(drm, connector, &tinydrm_connector_funcs, - connector_type); - if (ret) { - kfree(tconn); - return ERR_PTR(ret); - } - - connector->status = connector_status_connected; - - return connector; -} - -static int tinydrm_rotate_mode(struct drm_display_mode *mode, - unsigned int rotation) -{ - if (rotation == 0 || rotation == 180) { - return 0; - } else if (rotation == 90 || rotation == 270) { - swap(mode->hdisplay, mode->vdisplay); - swap(mode->hsync_start, mode->vsync_start); - swap(mode->hsync_end, mode->vsync_end); - swap(mode->htotal, mode->vtotal); - swap(mode->width_mm, mode->height_mm); - return 0; - } else { - return -EINVAL; - } -} - -/** - * tinydrm_display_pipe_init - Initialize display pipe - * @drm: DRM device - * @pipe: Display pipe - * @funcs: Display pipe functions - * @connector_type: Connector type - * @formats: Array of supported formats (DRM_FORMAT\_\*) - * @format_count: Number of elements in @formats - * @mode: Supported mode - * @rotation: Initial @mode rotation in degrees Counter Clock Wise - * - * This function sets up a &drm_simple_display_pipe with a &drm_connector that - * has one fixed &drm_display_mode which is rotated according to @rotation. - * - * Returns: - * Zero on success, negative error code on failure. - */ -int tinydrm_display_pipe_init(struct drm_device *drm, - struct drm_simple_display_pipe *pipe, - const struct drm_simple_display_pipe_funcs *funcs, - int connector_type, - const uint32_t *formats, - unsigned int format_count, - const struct drm_display_mode *mode, - unsigned int rotation) -{ - struct drm_display_mode mode_copy; - struct drm_connector *connector; - int ret; - static const uint64_t modifiers[] = { - DRM_FORMAT_MOD_LINEAR, - DRM_FORMAT_MOD_INVALID - }; - - drm_mode_copy(&mode_copy, mode); - ret = tinydrm_rotate_mode(&mode_copy, rotation); - if (ret) { - DRM_ERROR("Illegal rotation value %u\n", rotation); - return -EINVAL; - } - - drm->mode_config.min_width = mode_copy.hdisplay; - drm->mode_config.max_width = mode_copy.hdisplay; - drm->mode_config.min_height = mode_copy.vdisplay; - drm->mode_config.max_height = mode_copy.vdisplay; - - connector = tinydrm_connector_create(drm, &mode_copy, connector_type); - if (IS_ERR(connector)) - return PTR_ERR(connector); - - return drm_simple_display_pipe_init(drm, pipe, funcs, formats, - format_count, modifiers, connector); -} -EXPORT_SYMBOL(tinydrm_display_pipe_init); diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 58c403eda04e..10a861a1690c 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -160,7 +160,8 @@ static void ttm_bo_release_list(struct kref *list_kref) ttm_tt_destroy(bo->ttm); atomic_dec(&bo->bdev->glob->bo_count); dma_fence_put(bo->moving); - reservation_object_fini(&bo->ttm_resv); + if (!ttm_bo_uses_embedded_gem_object(bo)) + reservation_object_fini(&bo->base._resv); mutex_destroy(&bo->wu_mutex); bo->destroy(bo); ttm_mem_global_free(bdev->glob->mem_glob, acc_size); @@ -172,7 +173,7 @@ static void ttm_bo_add_mem_to_lru(struct ttm_buffer_object *bo, struct ttm_bo_device *bdev = bo->bdev; struct ttm_mem_type_manager *man; - reservation_object_assert_held(bo->resv); + reservation_object_assert_held(bo->base.resv); if (!list_empty(&bo->lru)) return; @@ -243,7 +244,7 @@ static void ttm_bo_bulk_move_set_pos(struct ttm_lru_bulk_move_pos *pos, void ttm_bo_move_to_lru_tail(struct ttm_buffer_object *bo, struct ttm_lru_bulk_move *bulk) { - reservation_object_assert_held(bo->resv); + reservation_object_assert_held(bo->base.resv); ttm_bo_del_from_lru(bo); ttm_bo_add_to_lru(bo); @@ -276,8 +277,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) if (!pos->first) continue; - reservation_object_assert_held(pos->first->resv); - reservation_object_assert_held(pos->last->resv); + reservation_object_assert_held(pos->first->base.resv); + reservation_object_assert_held(pos->last->base.resv); man = &pos->first->bdev->man[TTM_PL_TT]; list_bulk_move_tail(&man->lru[i], &pos->first->lru, @@ -291,8 +292,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) if (!pos->first) continue; - reservation_object_assert_held(pos->first->resv); - reservation_object_assert_held(pos->last->resv); + reservation_object_assert_held(pos->first->base.resv); + reservation_object_assert_held(pos->last->base.resv); man = &pos->first->bdev->man[TTM_PL_VRAM]; list_bulk_move_tail(&man->lru[i], &pos->first->lru, @@ -306,8 +307,8 @@ void ttm_bo_bulk_move_lru_tail(struct ttm_lru_bulk_move *bulk) if (!pos->first) continue; - reservation_object_assert_held(pos->first->resv); - reservation_object_assert_held(pos->last->resv); + reservation_object_assert_held(pos->first->base.resv); + reservation_object_assert_held(pos->last->base.resv); lru = &pos->first->bdev->glob->swap_lru[i]; list_bulk_move_tail(lru, &pos->first->swap, &pos->last->swap); @@ -438,14 +439,14 @@ static int ttm_bo_individualize_resv(struct ttm_buffer_object *bo) { int r; - if (bo->resv == &bo->ttm_resv) + if (bo->base.resv == &bo->base._resv) return 0; - BUG_ON(!reservation_object_trylock(&bo->ttm_resv)); + BUG_ON(!reservation_object_trylock(&bo->base._resv)); - r = reservation_object_copy_fences(&bo->ttm_resv, bo->resv); + r = reservation_object_copy_fences(&bo->base._resv, bo->base.resv); if (r) - reservation_object_unlock(&bo->ttm_resv); + reservation_object_unlock(&bo->base._resv); return r; } @@ -456,14 +457,14 @@ static void ttm_bo_flush_all_fences(struct ttm_buffer_object *bo) struct dma_fence *fence; int i; - fobj = reservation_object_get_list(&bo->ttm_resv); - fence = reservation_object_get_excl(&bo->ttm_resv); + fobj = reservation_object_get_list(&bo->base._resv); + fence = reservation_object_get_excl(&bo->base._resv); if (fence && !fence->ops->signaled) dma_fence_enable_sw_signaling(fence); for (i = 0; fobj && i < fobj->shared_count; ++i) { fence = rcu_dereference_protected(fobj->shared[i], - reservation_object_held(bo->resv)); + reservation_object_held(bo->base.resv)); if (!fence->ops->signaled) dma_fence_enable_sw_signaling(fence); @@ -481,23 +482,23 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) /* Last resort, if we fail to allocate memory for the * fences block for the BO to become idle */ - reservation_object_wait_timeout_rcu(bo->resv, true, false, + reservation_object_wait_timeout_rcu(bo->base.resv, true, false, 30 * HZ); spin_lock(&glob->lru_lock); goto error; } spin_lock(&glob->lru_lock); - ret = reservation_object_trylock(bo->resv) ? 0 : -EBUSY; + ret = reservation_object_trylock(bo->base.resv) ? 0 : -EBUSY; if (!ret) { - if (reservation_object_test_signaled_rcu(&bo->ttm_resv, true)) { + if (reservation_object_test_signaled_rcu(&bo->base._resv, true)) { ttm_bo_del_from_lru(bo); spin_unlock(&glob->lru_lock); - if (bo->resv != &bo->ttm_resv) - reservation_object_unlock(&bo->ttm_resv); + if (bo->base.resv != &bo->base._resv) + reservation_object_unlock(&bo->base._resv); ttm_bo_cleanup_memtype_use(bo); - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); return; } @@ -513,10 +514,10 @@ static void ttm_bo_cleanup_refs_or_queue(struct ttm_buffer_object *bo) ttm_bo_add_to_lru(bo); } - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); } - if (bo->resv != &bo->ttm_resv) - reservation_object_unlock(&bo->ttm_resv); + if (bo->base.resv != &bo->base._resv) + reservation_object_unlock(&bo->base._resv); error: kref_get(&bo->list_kref); @@ -549,9 +550,9 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, int ret; if (unlikely(list_empty(&bo->ddestroy))) - resv = bo->resv; + resv = bo->base.resv; else - resv = &bo->ttm_resv; + resv = &bo->base._resv; if (reservation_object_test_signaled_rcu(resv, true)) ret = 0; @@ -562,7 +563,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, long lret; if (unlock_resv) - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); spin_unlock(&glob->lru_lock); lret = reservation_object_wait_timeout_rcu(resv, true, @@ -575,7 +576,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, return -EBUSY; spin_lock(&glob->lru_lock); - if (unlock_resv && !reservation_object_trylock(bo->resv)) { + if (unlock_resv && !reservation_object_trylock(bo->base.resv)) { /* * We raced, and lost, someone else holds the reservation now, * and is probably busy in ttm_bo_cleanup_memtype_use. @@ -592,7 +593,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, if (ret || unlikely(list_empty(&bo->ddestroy))) { if (unlock_resv) - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); spin_unlock(&glob->lru_lock); return ret; } @@ -605,7 +606,7 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, ttm_bo_cleanup_memtype_use(bo); if (unlock_resv) - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); return 0; } @@ -631,14 +632,14 @@ static bool ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all) kref_get(&bo->list_kref); list_move_tail(&bo->ddestroy, &removed); - if (remove_all || bo->resv != &bo->ttm_resv) { + if (remove_all || bo->base.resv != &bo->base._resv) { spin_unlock(&glob->lru_lock); - reservation_object_lock(bo->resv, NULL); + reservation_object_lock(bo->base.resv, NULL); spin_lock(&glob->lru_lock); ttm_bo_cleanup_refs(bo, false, !remove_all, true); - } else if (reservation_object_trylock(bo->resv)) { + } else if (reservation_object_trylock(bo->base.resv)) { ttm_bo_cleanup_refs(bo, false, !remove_all, true); } else { spin_unlock(&glob->lru_lock); @@ -671,7 +672,7 @@ static void ttm_bo_release(struct kref *kref) struct ttm_bo_device *bdev = bo->bdev; struct ttm_mem_type_manager *man = &bdev->man[bo->mem.mem_type]; - drm_vma_offset_remove(&bdev->vma_manager, &bo->vma_node); + drm_vma_offset_remove(&bdev->vma_manager, &bo->base.vma_node); ttm_mem_io_lock(man, false); ttm_mem_io_free_vm(bo); ttm_mem_io_unlock(man); @@ -707,7 +708,7 @@ static int ttm_bo_evict(struct ttm_buffer_object *bo, struct ttm_placement placement; int ret = 0; - reservation_object_assert_held(bo->resv); + reservation_object_assert_held(bo->base.resv); placement.num_placement = 0; placement.num_busy_placement = 0; @@ -777,8 +778,8 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, { bool ret = false; - if (bo->resv == ctx->resv) { - reservation_object_assert_held(bo->resv); + if (bo->base.resv == ctx->resv) { + reservation_object_assert_held(bo->base.resv); if (ctx->flags & TTM_OPT_FLAG_ALLOW_RES_EVICT || !list_empty(&bo->ddestroy)) ret = true; @@ -786,7 +787,7 @@ static bool ttm_bo_evict_swapout_allowable(struct ttm_buffer_object *bo, if (busy) *busy = false; } else { - ret = reservation_object_trylock(bo->resv); + ret = reservation_object_trylock(bo->base.resv); *locked = ret; if (busy) *busy = !ret; @@ -814,10 +815,10 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, return -EBUSY; if (ctx->interruptible) - r = reservation_object_lock_interruptible(busy_bo->resv, + r = reservation_object_lock_interruptible(busy_bo->base.resv, ticket); else - r = reservation_object_lock(busy_bo->resv, ticket); + r = reservation_object_lock(busy_bo->base.resv, ticket); /* * TODO: It would be better to keep the BO locked until allocation is at @@ -825,7 +826,7 @@ static int ttm_mem_evict_wait_busy(struct ttm_buffer_object *busy_bo, * of TTM. */ if (!r) - reservation_object_unlock(busy_bo->resv); + reservation_object_unlock(busy_bo->base.resv); return r == -EDEADLK ? -EBUSY : r; } @@ -850,8 +851,8 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, if (!ttm_bo_evict_swapout_allowable(bo, ctx, &locked, &busy)) { - if (busy && !busy_bo && - bo->resv->lock.ctx != ticket) + if (busy && !busy_bo && ticket != + reservation_object_locking_ctx(bo->base.resv)) busy_bo = bo; continue; } @@ -859,7 +860,7 @@ static int ttm_mem_evict_first(struct ttm_bo_device *bdev, if (place && !bdev->driver->eviction_valuable(bo, place)) { if (locked) - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); continue; } break; @@ -931,9 +932,9 @@ static int ttm_bo_add_move_fence(struct ttm_buffer_object *bo, spin_unlock(&man->move_lock); if (fence) { - reservation_object_add_shared_fence(bo->resv, fence); + reservation_object_add_shared_fence(bo->base.resv, fence); - ret = reservation_object_reserve_shared(bo->resv, 1); + ret = reservation_object_reserve_shared(bo->base.resv, 1); if (unlikely(ret)) { dma_fence_put(fence); return ret; @@ -957,8 +958,10 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, { struct ttm_bo_device *bdev = bo->bdev; struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type]; + struct ww_acquire_ctx *ticket; int ret; + ticket = reservation_object_locking_ctx(bo->base.resv); do { ret = (*man->func->get_node)(man, bo, place, mem); if (unlikely(ret != 0)) @@ -966,7 +969,7 @@ static int ttm_bo_mem_force_space(struct ttm_buffer_object *bo, if (mem->mm_node) break; ret = ttm_mem_evict_first(bdev, mem->mem_type, place, ctx, - bo->resv->lock.ctx); + ticket); if (unlikely(ret != 0)) return ret; } while (1); @@ -1088,7 +1091,7 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, bool type_found = false; int i, ret; - ret = reservation_object_reserve_shared(bo->resv, 1); + ret = reservation_object_reserve_shared(bo->base.resv, 1); if (unlikely(ret)) return ret; @@ -1169,7 +1172,7 @@ static int ttm_bo_move_buffer(struct ttm_buffer_object *bo, int ret = 0; struct ttm_mem_reg mem; - reservation_object_assert_held(bo->resv); + reservation_object_assert_held(bo->base.resv); mem.num_pages = bo->num_pages; mem.size = mem.num_pages << PAGE_SHIFT; @@ -1239,7 +1242,7 @@ int ttm_bo_validate(struct ttm_buffer_object *bo, int ret; uint32_t new_flags; - reservation_object_assert_held(bo->resv); + reservation_object_assert_held(bo->base.resv); /* * Check whether we need to move buffer. */ @@ -1329,14 +1332,20 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, bo->acc_size = acc_size; bo->sg = sg; if (resv) { - bo->resv = resv; - reservation_object_assert_held(bo->resv); + bo->base.resv = resv; + reservation_object_assert_held(bo->base.resv); } else { - bo->resv = &bo->ttm_resv; + bo->base.resv = &bo->base._resv; + } + if (!ttm_bo_uses_embedded_gem_object(bo)) { + /* + * bo.gem is not initialized, so we have to setup the + * struct elements we want use regardless. + */ + reservation_object_init(&bo->base._resv); + drm_vma_node_reset(&bo->base.vma_node); } - reservation_object_init(&bo->ttm_resv); atomic_inc(&bo->bdev->glob->bo_count); - drm_vma_node_reset(&bo->vma_node); /* * For ttm_bo_type_device buffers, allocate @@ -1344,14 +1353,14 @@ int ttm_bo_init_reserved(struct ttm_bo_device *bdev, */ if (bo->type == ttm_bo_type_device || bo->type == ttm_bo_type_sg) - ret = drm_vma_offset_add(&bdev->vma_manager, &bo->vma_node, + ret = drm_vma_offset_add(&bdev->vma_manager, &bo->base.vma_node, bo->mem.num_pages); /* passed reservation objects should already be locked, * since otherwise lockdep will be angered in radeon. */ if (!resv) { - locked = reservation_object_trylock(bo->resv); + locked = reservation_object_trylock(bo->base.resv); WARN_ON(!locked); } @@ -1772,7 +1781,7 @@ void ttm_bo_unmap_virtual_locked(struct ttm_buffer_object *bo) { struct ttm_bo_device *bdev = bo->bdev; - drm_vma_node_unmap(&bo->vma_node, bdev->dev_mapping); + drm_vma_node_unmap(&bo->base.vma_node, bdev->dev_mapping); ttm_mem_io_free_vm(bo); } @@ -1795,13 +1804,13 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, long timeout = 15 * HZ; if (no_wait) { - if (reservation_object_test_signaled_rcu(bo->resv, true)) + if (reservation_object_test_signaled_rcu(bo->base.resv, true)) return 0; else return -EBUSY; } - timeout = reservation_object_wait_timeout_rcu(bo->resv, true, + timeout = reservation_object_wait_timeout_rcu(bo->base.resv, true, interruptible, timeout); if (timeout < 0) return timeout; @@ -1809,7 +1818,7 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, if (timeout == 0) return -EBUSY; - reservation_object_add_excl_fence(bo->resv, NULL); + reservation_object_add_excl_fence(bo->base.resv, NULL); return 0; } EXPORT_SYMBOL(ttm_bo_wait); @@ -1925,7 +1934,7 @@ out: * already swapped buffer. */ if (locked) - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); kref_put(&bo->list_kref, ttm_bo_release_list); return ret; } @@ -1963,14 +1972,14 @@ int ttm_bo_wait_unreserved(struct ttm_buffer_object *bo) ret = mutex_lock_interruptible(&bo->wu_mutex); if (unlikely(ret != 0)) return -ERESTARTSYS; - if (!ww_mutex_is_locked(&bo->resv->lock)) + if (!reservation_object_is_locked(bo->base.resv)) goto out_unlock; - ret = reservation_object_lock_interruptible(bo->resv, NULL); + ret = reservation_object_lock_interruptible(bo->base.resv, NULL); if (ret == -EINTR) ret = -ERESTARTSYS; if (unlikely(ret != 0)) goto out_unlock; - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); out_unlock: mutex_unlock(&bo->wu_mutex); diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index 9f918b992f7e..425a6d627b30 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c @@ -510,16 +510,16 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, INIT_LIST_HEAD(&fbo->base.io_reserve_lru); mutex_init(&fbo->base.wu_mutex); fbo->base.moving = NULL; - drm_vma_node_reset(&fbo->base.vma_node); + drm_vma_node_reset(&fbo->base.base.vma_node); atomic_set(&fbo->base.cpu_writers, 0); kref_init(&fbo->base.list_kref); kref_init(&fbo->base.kref); fbo->base.destroy = &ttm_transfered_destroy; fbo->base.acc_size = 0; - fbo->base.resv = &fbo->base.ttm_resv; - reservation_object_init(fbo->base.resv); - ret = reservation_object_trylock(fbo->base.resv); + fbo->base.base.resv = &fbo->base.base._resv; + reservation_object_init(fbo->base.base.resv); + ret = reservation_object_trylock(fbo->base.base.resv); WARN_ON(!ret); *new_obj = &fbo->base; @@ -689,7 +689,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, int ret; struct ttm_buffer_object *ghost_obj; - reservation_object_add_excl_fence(bo->resv, fence); + reservation_object_add_excl_fence(bo->base.resv, fence); if (evict) { ret = ttm_bo_wait(bo, false, false); if (ret) @@ -716,7 +716,7 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, if (ret) return ret; - reservation_object_add_excl_fence(ghost_obj->resv, fence); + reservation_object_add_excl_fence(ghost_obj->base.resv, fence); /** * If we're not moving to fixed memory, the TTM object @@ -752,7 +752,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, int ret; - reservation_object_add_excl_fence(bo->resv, fence); + reservation_object_add_excl_fence(bo->base.resv, fence); if (!evict) { struct ttm_buffer_object *ghost_obj; @@ -772,7 +772,7 @@ int ttm_bo_pipeline_move(struct ttm_buffer_object *bo, if (ret) return ret; - reservation_object_add_excl_fence(ghost_obj->resv, fence); + reservation_object_add_excl_fence(ghost_obj->base.resv, fence); /** * If we're not moving to fixed memory, the TTM object @@ -841,7 +841,7 @@ int ttm_bo_pipeline_gutting(struct ttm_buffer_object *bo) if (ret) return ret; - ret = reservation_object_copy_fences(ghost->resv, bo->resv); + ret = reservation_object_copy_fences(ghost->base.resv, bo->base.resv); /* Last resort, wait for the BO to be idle when we are OOM */ if (ret) ttm_bo_wait(bo, false, false); diff --git a/drivers/gpu/drm/ttm/ttm_bo_vm.c b/drivers/gpu/drm/ttm/ttm_bo_vm.c index 6dacff49c1cc..85f5bcbe0c76 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_vm.c +++ b/drivers/gpu/drm/ttm/ttm_bo_vm.c @@ -71,7 +71,7 @@ static vm_fault_t ttm_bo_vm_fault_idle(struct ttm_buffer_object *bo, ttm_bo_get(bo); up_read(&vmf->vma->vm_mm->mmap_sem); (void) dma_fence_wait(bo->moving, true); - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); ttm_bo_put(bo); goto out_unlock; } @@ -131,7 +131,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) * for reserve, and if it fails, retry the fault after waiting * for the buffer to become unreserved. */ - if (unlikely(!reservation_object_trylock(bo->resv))) { + if (unlikely(!reservation_object_trylock(bo->base.resv))) { if (vmf->flags & FAULT_FLAG_ALLOW_RETRY) { if (!(vmf->flags & FAULT_FLAG_RETRY_NOWAIT)) { ttm_bo_get(bo); @@ -211,9 +211,9 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) } page_offset = ((address - vma->vm_start) >> PAGE_SHIFT) + - vma->vm_pgoff - drm_vma_node_start(&bo->vma_node); + vma->vm_pgoff - drm_vma_node_start(&bo->base.vma_node); page_last = vma_pages(vma) + vma->vm_pgoff - - drm_vma_node_start(&bo->vma_node); + drm_vma_node_start(&bo->base.vma_node); if (unlikely(page_offset >= bo->num_pages)) { ret = VM_FAULT_SIGBUS; @@ -267,7 +267,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) } else if (unlikely(!page)) { break; } - page->index = drm_vma_node_start(&bo->vma_node) + + page->index = drm_vma_node_start(&bo->base.vma_node) + page_offset; pfn = page_to_pfn(page); } @@ -296,7 +296,7 @@ static vm_fault_t ttm_bo_vm_fault(struct vm_fault *vmf) out_io_unlock: ttm_mem_io_unlock(man); out_unlock: - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); return ret; } @@ -413,7 +413,8 @@ static struct ttm_buffer_object *ttm_bo_vm_lookup(struct ttm_bo_device *bdev, node = drm_vma_offset_lookup_locked(&bdev->vma_manager, offset, pages); if (likely(node)) { - bo = container_of(node, struct ttm_buffer_object, vma_node); + bo = container_of(node, struct ttm_buffer_object, + base.vma_node); bo = ttm_bo_get_unless_zero(bo); } diff --git a/drivers/gpu/drm/ttm/ttm_execbuf_util.c b/drivers/gpu/drm/ttm/ttm_execbuf_util.c index 957ec375a4ba..3aefe72fb5cb 100644 --- a/drivers/gpu/drm/ttm/ttm_execbuf_util.c +++ b/drivers/gpu/drm/ttm/ttm_execbuf_util.c @@ -39,7 +39,7 @@ static void ttm_eu_backoff_reservation_reverse(struct list_head *list, list_for_each_entry_continue_reverse(entry, list, head) { struct ttm_buffer_object *bo = entry->bo; - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); } } @@ -71,7 +71,7 @@ void ttm_eu_backoff_reservation(struct ww_acquire_ctx *ticket, if (list_empty(&bo->lru)) ttm_bo_add_to_lru(bo); - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); } spin_unlock(&glob->lru_lock); @@ -114,7 +114,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, ret = __ttm_bo_reserve(bo, intr, (ticket == NULL), ticket); if (!ret && unlikely(atomic_read(&bo->cpu_writers) > 0)) { - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); ret = -EBUSY; @@ -130,7 +130,7 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, if (!entry->num_shared) continue; - ret = reservation_object_reserve_shared(bo->resv, + ret = reservation_object_reserve_shared(bo->base.resv, entry->num_shared); if (!ret) continue; @@ -144,16 +144,16 @@ int ttm_eu_reserve_buffers(struct ww_acquire_ctx *ticket, if (ret == -EDEADLK) { if (intr) { - ret = ww_mutex_lock_slow_interruptible(&bo->resv->lock, - ticket); + ret = reservation_object_lock_slow_interruptible(bo->base.resv, + ticket); } else { - ww_mutex_lock_slow(&bo->resv->lock, ticket); + reservation_object_lock_slow(bo->base.resv, ticket); ret = 0; } } if (!ret && entry->num_shared) - ret = reservation_object_reserve_shared(bo->resv, + ret = reservation_object_reserve_shared(bo->base.resv, entry->num_shared); if (unlikely(ret != 0)) { @@ -201,14 +201,14 @@ void ttm_eu_fence_buffer_objects(struct ww_acquire_ctx *ticket, list_for_each_entry(entry, list, head) { bo = entry->bo; if (entry->num_shared) - reservation_object_add_shared_fence(bo->resv, fence); + reservation_object_add_shared_fence(bo->base.resv, fence); else - reservation_object_add_excl_fence(bo->resv, fence); + reservation_object_add_excl_fence(bo->base.resv, fence); if (list_empty(&bo->lru)) ttm_bo_add_to_lru(bo); else ttm_bo_move_to_lru_tail(bo, NULL); - reservation_object_unlock(bo->resv); + reservation_object_unlock(bo->base.resv); } spin_unlock(&glob->lru_lock); if (ticket) diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index e3a0691582ff..00b4a3337840 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -48,7 +48,7 @@ int ttm_tt_create(struct ttm_buffer_object *bo, bool zero_alloc) struct ttm_bo_device *bdev = bo->bdev; uint32_t page_flags = 0; - reservation_object_assert_held(bo->resv); + reservation_object_assert_held(bo->base.resv); if (bdev->need_dma32) page_flags |= TTM_PAGE_FLAG_DMA32; diff --git a/drivers/gpu/drm/tve200/tve200_display.c b/drivers/gpu/drm/tve200/tve200_display.c index 58fd31030834..d733bbc4ac0e 100644 --- a/drivers/gpu/drm/tve200/tve200_display.c +++ b/drivers/gpu/drm/tve200/tve200_display.c @@ -9,16 +9,18 @@ * Copyright (C) 2011 Texas Instruments * Copyright (C) 2017 Eric Anholt */ + #include <linux/clk.h> #include <linux/version.h> #include <linux/dma-buf.h> #include <linux/of_graph.h> -#include <drm/drmP.h> -#include <drm/drm_panel.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> -#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_panel.h> +#include <drm/drm_vblank.h> #include "tve200_drm.h" diff --git a/drivers/gpu/drm/tve200/tve200_drm.h b/drivers/gpu/drm/tve200/tve200_drm.h index 62061b518397..5420b52ea16b 100644 --- a/drivers/gpu/drm/tve200/tve200_drm.h +++ b/drivers/gpu/drm/tve200/tve200_drm.h @@ -13,6 +13,18 @@ #ifndef _TVE200_DRM_H_ #define _TVE200_DRM_H_ +#include <linux/irqreturn.h> + +#include <drm/drm_simple_kms_helper.h> + +struct clk; +struct drm_bridge; +struct drm_connector; +struct drm_device; +struct drm_file; +struct drm_mode_create_dumb; +struct drm_panel; + /* Bits 2-31 are valid physical base addresses */ #define TVE200_Y_FRAME_BASE_ADDR 0x00 #define TVE200_U_FRAME_BASE_ADDR 0x04 @@ -89,9 +101,6 @@ #define TVE200_CTRL_4 0x24 #define TVE200_CTRL_4_RESET BIT(0) /* triggers reset of TVE200 */ -#include <drm/drm_gem.h> -#include <drm/drm_simple_kms_helper.h> - struct tve200_drm_dev_private { struct drm_device *drm; diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c index 6e695fbeb6bc..416f24823c0a 100644 --- a/drivers/gpu/drm/tve200/tve200_drv.c +++ b/drivers/gpu/drm/tve200/tve200_drv.c @@ -37,9 +37,9 @@ #include <linux/slab.h> #include <linux/version.h> -#include <drm/drmP.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_bridge.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> @@ -47,6 +47,7 @@ #include <drm/drm_of.h> #include <drm/drm_panel.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "tve200_drm.h" @@ -137,8 +138,7 @@ finish: DEFINE_DRM_GEM_CMA_FOPS(drm_fops); static struct drm_driver tve200_drm_driver = { - .driver_features = - DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .ioctls = NULL, .fops = &drm_fops, .name = "tve200", @@ -153,8 +153,6 @@ static struct drm_driver tve200_drm_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 921561875d7f..ddb61a60c610 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c @@ -7,11 +7,9 @@ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> */ -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <drm/drm_edid.h> #include <drm/drm_crtc_helper.h> #include <drm/drm_probe_helper.h> + #include "udl_connector.h" #include "udl_drv.h" diff --git a/drivers/gpu/drm/udl/udl_connector.h b/drivers/gpu/drm/udl/udl_connector.h index 0fb0db5c4612..7f2d392df173 100644 --- a/drivers/gpu/drm/udl/udl_connector.h +++ b/drivers/gpu/drm/udl/udl_connector.h @@ -3,6 +3,8 @@ #include <drm/drm_crtc.h> +struct edid; + struct udl_drm_connector { struct drm_connector connector; /* last udl_detect edid */ diff --git a/drivers/gpu/drm/udl/udl_dmabuf.c b/drivers/gpu/drm/udl/udl_dmabuf.c index a28892146f7c..3108e9a9234b 100644 --- a/drivers/gpu/drm/udl/udl_dmabuf.c +++ b/drivers/gpu/drm/udl/udl_dmabuf.c @@ -5,11 +5,13 @@ * Copyright (c) 2014 The Chromium OS Authors */ -#include <drm/drmP.h> -#include "udl_drv.h" #include <linux/shmem_fs.h> #include <linux/dma-buf.h> +#include <drm/drm_prime.h> + +#include "udl_drv.h" + struct udl_drm_dmabuf_attachment { struct sg_table sgt; enum dma_data_direction dir; @@ -170,8 +172,7 @@ static const struct dma_buf_ops udl_dmabuf_ops = { .release = drm_gem_dmabuf_release, }; -struct dma_buf *udl_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, int flags) +struct dma_buf *udl_gem_prime_export(struct drm_gem_object *obj, int flags) { DEFINE_DMA_BUF_EXPORT_INFO(exp_info); @@ -180,7 +181,7 @@ struct dma_buf *udl_gem_prime_export(struct drm_device *dev, exp_info.flags = flags; exp_info.priv = obj; - return drm_gem_dmabuf_export(dev, &exp_info); + return drm_gem_dmabuf_export(obj->dev, &exp_info); } static int udl_prime_create(struct drm_device *dev, diff --git a/drivers/gpu/drm/udl/udl_drv.c b/drivers/gpu/drm/udl/udl_drv.c index 4a49facb608d..8426669433e4 100644 --- a/drivers/gpu/drm/udl/udl_drv.c +++ b/drivers/gpu/drm/udl/udl_drv.c @@ -4,9 +4,14 @@ */ #include <linux/module.h> -#include <drm/drmP.h> + #include <drm/drm_crtc_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_print.h> + #include "udl_drv.h" static int udl_usb_suspend(struct usb_interface *interface, @@ -54,7 +59,7 @@ static void udl_driver_release(struct drm_device *dev) } static struct drm_driver driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME, + .driver_features = DRIVER_MODESET | DRIVER_GEM, .release = udl_driver_release, /* gem hooks */ diff --git a/drivers/gpu/drm/udl/udl_drv.h b/drivers/gpu/drm/udl/udl_drv.h index a928801026c1..12a970fd9a87 100644 --- a/drivers/gpu/drm/udl/udl_drv.h +++ b/drivers/gpu/drm/udl/udl_drv.h @@ -11,9 +11,15 @@ #ifndef UDL_DRV_H #define UDL_DRV_H +#include <linux/mm_types.h> #include <linux/usb.h> + +#include <drm/drm_device.h> +#include <drm/drm_framebuffer.h> #include <drm/drm_gem.h> -#include <linux/mm_types.h> + +struct drm_encoder; +struct drm_mode_create_dumb; #define DRIVER_NAME "udl" #define DRIVER_DESC "DisplayLink" @@ -126,8 +132,7 @@ int udl_gem_mmap(struct drm_file *file_priv, struct drm_device *dev, void udl_gem_free_object(struct drm_gem_object *gem_obj); struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, size_t size); -struct dma_buf *udl_gem_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, int flags); +struct dma_buf *udl_gem_prime_export(struct drm_gem_object *obj, int flags); struct drm_gem_object *udl_gem_prime_import(struct drm_device *dev, struct dma_buf *dma_buf); diff --git a/drivers/gpu/drm/udl/udl_encoder.c b/drivers/gpu/drm/udl/udl_encoder.c index f87989e6ee51..203f041e737c 100644 --- a/drivers/gpu/drm/udl/udl_encoder.c +++ b/drivers/gpu/drm/udl/udl_encoder.c @@ -7,9 +7,9 @@ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> */ -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <drm/drm_crtc_helper.h> +#include <drm/drm_encoder.h> +#include <drm/drm_modeset_helper_vtables.h> + #include "udl_drv.h" /* dummy encoder */ diff --git a/drivers/gpu/drm/udl/udl_fb.c b/drivers/gpu/drm/udl/udl_fb.c index e1116bf7b9d7..ef3504d06343 100644 --- a/drivers/gpu/drm/udl/udl_fb.c +++ b/drivers/gpu/drm/udl/udl_fb.c @@ -7,18 +7,17 @@ * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> */ -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/fb.h> + +#include <linux/moduleparam.h> #include <linux/dma-buf.h> -#include <linux/mem_encrypt.h> -#include <drm/drmP.h> -#include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include "udl_drv.h" - +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_modeset_helper.h> + +#include "udl_drv.h" #define DL_DEFIO_WRITE_DELAY (HZ/20) /* fb_deferred_io.delay in jiffies */ diff --git a/drivers/gpu/drm/udl/udl_gem.c b/drivers/gpu/drm/udl/udl_gem.c index c6ca2c09bc97..b23a5c2fcd80 100644 --- a/drivers/gpu/drm/udl/udl_gem.c +++ b/drivers/gpu/drm/udl/udl_gem.c @@ -3,10 +3,13 @@ * Copyright (C) 2012 Red Hat */ -#include <drm/drmP.h> -#include "udl_drv.h" -#include <linux/shmem_fs.h> #include <linux/dma-buf.h> +#include <linux/vmalloc.h> + +#include <drm/drm_mode.h> +#include <drm/drm_prime.h> + +#include "udl_drv.h" struct udl_gem_object *udl_gem_alloc_object(struct drm_device *dev, size_t size) diff --git a/drivers/gpu/drm/udl/udl_main.c b/drivers/gpu/drm/udl/udl_main.c index 1a99c7647444..4e854e017390 100644 --- a/drivers/gpu/drm/udl/udl_main.c +++ b/drivers/gpu/drm/udl/udl_main.c @@ -7,9 +7,11 @@ * Copyright (C) 2009 Jaya Kumar <jayakumar.lkml@gmail.com> * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> */ -#include <drm/drmP.h> -#include <drm/drm_crtc_helper.h> + +#include <drm/drm.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> + #include "udl_drv.h" /* -BULK_SIZE as per usb-skeleton. Can we get full page and avoid overhead? */ diff --git a/drivers/gpu/drm/udl/udl_modeset.c b/drivers/gpu/drm/udl/udl_modeset.c index 793722d0c8cd..bc1ab6060dc6 100644 --- a/drivers/gpu/drm/udl/udl_modeset.c +++ b/drivers/gpu/drm/udl/udl_modeset.c @@ -9,10 +9,10 @@ */ -#include <drm/drmP.h> -#include <drm/drm_crtc.h> #include <drm/drm_crtc_helper.h> -#include <drm/drm_plane_helper.h> +#include <drm/drm_modeset_helper_vtables.h> +#include <drm/drm_vblank.h> + #include "udl_drv.h" /* diff --git a/drivers/gpu/drm/udl/udl_transfer.c b/drivers/gpu/drm/udl/udl_transfer.c index 6837f592f6ba..1973a4c1e358 100644 --- a/drivers/gpu/drm/udl/udl_transfer.c +++ b/drivers/gpu/drm/udl/udl_transfer.c @@ -7,12 +7,8 @@ * Copyright (C) 2009 Bernie Thompson <bernie@plugable.com> */ -#include <linux/module.h> -#include <linux/slab.h> -#include <linux/fb.h> #include <asm/unaligned.h> -#include <drm/drmP.h> #include "udl_drv.h" #define MAX_CMD_PIXELS 255 diff --git a/drivers/gpu/drm/v3d/v3d_debugfs.c b/drivers/gpu/drm/v3d/v3d_debugfs.c index 78a78938e81f..9e953ce64ef7 100644 --- a/drivers/gpu/drm/v3d/v3d_debugfs.c +++ b/drivers/gpu/drm/v3d/v3d_debugfs.c @@ -6,7 +6,8 @@ #include <linux/debugfs.h> #include <linux/pm_runtime.h> #include <linux/seq_file.h> -#include <drm/drmP.h> + +#include <drm/drm_debugfs.h> #include "v3d_drv.h" #include "v3d_regs.h" diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index fea597f4db8a..3506ae2723ae 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -14,16 +14,19 @@ #include <linux/clk.h> #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> + +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> +#include <uapi/drm/v3d_drm.h> -#include "uapi/drm/v3d_drm.h" #include "v3d_drv.h" #include "v3d_regs.h" @@ -188,7 +191,6 @@ static const struct drm_ioctl_desc v3d_drm_ioctls[] = { static struct drm_driver v3d_drm_driver = { .driver_features = (DRIVER_GEM | DRIVER_RENDER | - DRIVER_PRIME | DRIVER_SYNCOBJ), .open = v3d_open, diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 9aad9da1eb11..9a35c555ec52 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -1,14 +1,23 @@ // SPDX-License-Identifier: GPL-2.0+ /* Copyright (C) 2015-2018 Broadcom */ -#include <linux/mm_types.h> -#include <drm/drmP.h> +#include <linux/delay.h> +#include <linux/mutex.h> +#include <linux/spinlock_types.h> +#include <linux/workqueue.h> + #include <drm/drm_encoder.h> #include <drm/drm_gem.h> #include <drm/drm_gem_shmem_helper.h> #include <drm/gpu_scheduler.h> + #include "uapi/drm/v3d_drm.h" +struct clk; +struct device; +struct platform_device; +struct reset_control; + #define GMP_GRANULARITY (128 * 1024) /* Enum for each of the V3D queues. */ diff --git a/drivers/gpu/drm/v3d/v3d_gem.c b/drivers/gpu/drm/v3d/v3d_gem.c index 27e0f87075d9..79744137d89f 100644 --- a/drivers/gpu/drm/v3d/v3d_gem.c +++ b/drivers/gpu/drm/v3d/v3d_gem.c @@ -1,17 +1,19 @@ // SPDX-License-Identifier: GPL-2.0+ /* Copyright (C) 2014-2018 Broadcom */ -#include <drm/drmP.h> -#include <drm/drm_syncobj.h> +#include <linux/device.h> +#include <linux/dma-mapping.h> +#include <linux/io.h> #include <linux/module.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> #include <linux/reset.h> -#include <linux/device.h> -#include <linux/io.h> #include <linux/sched/signal.h> +#include <linux/uaccess.h> + +#include <drm/drm_syncobj.h> +#include <uapi/drm/v3d_drm.h> -#include "uapi/drm/v3d_drm.h" #include "v3d_drv.h" #include "v3d_regs.h" #include "v3d_trace.h" diff --git a/drivers/gpu/drm/v3d/v3d_irq.c b/drivers/gpu/drm/v3d/v3d_irq.c index 268d8a889ac5..662e67279a7b 100644 --- a/drivers/gpu/drm/v3d/v3d_irq.c +++ b/drivers/gpu/drm/v3d/v3d_irq.c @@ -13,6 +13,8 @@ * current job can make progress. */ +#include <linux/platform_device.h> + #include "v3d_drv.h" #include "v3d_regs.h" #include "v3d_trace.h" diff --git a/drivers/gpu/drm/vboxvideo/Makefile b/drivers/gpu/drm/vboxvideo/Makefile index 1224f313af0c..55d798c76b21 100644 --- a/drivers/gpu/drm/vboxvideo/Makefile +++ b/drivers/gpu/drm/vboxvideo/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 vboxvideo-y := hgsmi_base.o modesetting.o vbva_base.o \ vbox_drv.o vbox_fb.o vbox_hgsmi.o vbox_irq.o vbox_main.o \ - vbox_mode.o vbox_prime.o vbox_ttm.o + vbox_mode.o vbox_ttm.o obj-$(CONFIG_DRM_VBOXVIDEO) += vboxvideo.o diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.c b/drivers/gpu/drm/vboxvideo/vbox_drv.c index 02537ab9cc08..6189ea89bb71 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_drv.c +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.c @@ -196,7 +196,7 @@ static const struct file_operations vbox_fops = { static struct drm_driver driver = { .driver_features = - DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_ATOMIC, + DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC, .lastclose = drm_fb_helper_lastclose, @@ -210,17 +210,6 @@ static struct drm_driver driver = { .patchlevel = DRIVER_PATCHLEVEL, DRM_GEM_VRAM_DRIVER, - .prime_handle_to_fd = drm_gem_prime_handle_to_fd, - .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_pin = vbox_gem_prime_pin, - .gem_prime_unpin = vbox_gem_prime_unpin, - .gem_prime_get_sg_table = vbox_gem_prime_get_sg_table, - .gem_prime_import_sg_table = vbox_gem_prime_import_sg_table, - .gem_prime_vmap = vbox_gem_prime_vmap, - .gem_prime_vunmap = vbox_gem_prime_vunmap, - .gem_prime_mmap = vbox_gem_prime_mmap, }; static int __init vbox_init(void) diff --git a/drivers/gpu/drm/vboxvideo/vbox_drv.h b/drivers/gpu/drm/vboxvideo/vbox_drv.h index 9028f946bc06..e8cb9efc6088 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_drv.h +++ b/drivers/gpu/drm/vboxvideo/vbox_drv.h @@ -167,18 +167,6 @@ void vbox_mm_fini(struct vbox_private *vbox); int vbox_gem_create(struct vbox_private *vbox, u32 size, bool iskernel, struct drm_gem_object **obj); -/* vbox_prime.c */ -int vbox_gem_prime_pin(struct drm_gem_object *obj); -void vbox_gem_prime_unpin(struct drm_gem_object *obj); -struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj); -struct drm_gem_object *vbox_gem_prime_import_sg_table( - struct drm_device *dev, struct dma_buf_attachment *attach, - struct sg_table *table); -void *vbox_gem_prime_vmap(struct drm_gem_object *obj); -void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr); -int vbox_gem_prime_mmap(struct drm_gem_object *obj, - struct vm_area_struct *area); - /* vbox_irq.c */ int vbox_irq_init(struct vbox_private *vbox); void vbox_irq_fini(struct vbox_private *vbox); diff --git a/drivers/gpu/drm/vboxvideo/vbox_main.c b/drivers/gpu/drm/vboxvideo/vbox_main.c index 18693e2bf72a..02fa8277ff1e 100644 --- a/drivers/gpu/drm/vboxvideo/vbox_main.c +++ b/drivers/gpu/drm/vboxvideo/vbox_main.c @@ -292,7 +292,7 @@ int vbox_gem_create(struct vbox_private *vbox, return ret; } - *obj = &gbo->gem; + *obj = &gbo->bo.base; return 0; } diff --git a/drivers/gpu/drm/vboxvideo/vbox_prime.c b/drivers/gpu/drm/vboxvideo/vbox_prime.c deleted file mode 100644 index 702b1aa53494..000000000000 --- a/drivers/gpu/drm/vboxvideo/vbox_prime.c +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MIT -/* - * Copyright (C) 2017 Oracle Corporation - * Copyright 2017 Canonical - * Authors: Andreas Pokorny - */ - -#include "vbox_drv.h" - -/* - * Based on qxl_prime.c: - * Empty Implementations as there should not be any other driver for a virtual - * device that might share buffers with vboxvideo - */ - -int vbox_gem_prime_pin(struct drm_gem_object *obj) -{ - WARN_ONCE(1, "not implemented"); - return -ENODEV; -} - -void vbox_gem_prime_unpin(struct drm_gem_object *obj) -{ - WARN_ONCE(1, "not implemented"); -} - -struct sg_table *vbox_gem_prime_get_sg_table(struct drm_gem_object *obj) -{ - WARN_ONCE(1, "not implemented"); - return ERR_PTR(-ENODEV); -} - -struct drm_gem_object *vbox_gem_prime_import_sg_table( - struct drm_device *dev, struct dma_buf_attachment *attach, - struct sg_table *table) -{ - WARN_ONCE(1, "not implemented"); - return ERR_PTR(-ENODEV); -} - -void *vbox_gem_prime_vmap(struct drm_gem_object *obj) -{ - WARN_ONCE(1, "not implemented"); - return ERR_PTR(-ENODEV); -} - -void vbox_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) -{ - WARN_ONCE(1, "not implemented"); -} - -int vbox_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *area) -{ - WARN_ONCE(1, "not implemented"); - return -ENODEV; -} diff --git a/drivers/gpu/drm/vc4/vc4_bo.c b/drivers/gpu/drm/vc4/vc4_bo.c index a75a2f98b82f..72d30d90b856 100644 --- a/drivers/gpu/drm/vc4/vc4_bo.c +++ b/drivers/gpu/drm/vc4/vc4_bo.c @@ -655,8 +655,7 @@ static void vc4_bo_cache_time_timer(struct timer_list *t) schedule_work(&vc4->bo_cache.time_work); } -struct dma_buf * -vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) +struct dma_buf * vc4_prime_export(struct drm_gem_object *obj, int flags) { struct vc4_bo *bo = to_vc4_bo(obj); struct dma_buf *dmabuf; @@ -678,7 +677,7 @@ vc4_prime_export(struct drm_device *dev, struct drm_gem_object *obj, int flags) return ERR_PTR(ret); } - dmabuf = drm_gem_prime_export(dev, obj, flags); + dmabuf = drm_gem_prime_export(obj, flags); if (IS_ERR(dmabuf)) vc4_bo_dec_usecnt(bo); @@ -791,8 +790,6 @@ vc4_prime_import_sg_table(struct drm_device *dev, if (IS_ERR(obj)) return obj; - obj->resv = attach->dmabuf->resv; - return obj; } diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 5ea8db74418a..f1f0a7c87771 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -29,15 +29,18 @@ * ones that set the clock. */ +#include <linux/clk.h> +#include <linux/component.h> +#include <linux/of_device.h> + #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_atomic_uapi.h> +#include <drm/drm_fb_cma_helper.h> #include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <linux/clk.h> -#include <drm/drm_fb_cma_helper.h> -#include <linux/component.h> -#include <linux/of_device.h> +#include <drm/drm_vblank.h> + #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_debugfs.c b/drivers/gpu/drm/vc4/vc4_debugfs.c index 4829a00c16b0..b61b2d3407b5 100644 --- a/drivers/gpu/drm/vc4/vc4_debugfs.c +++ b/drivers/gpu/drm/vc4/vc4_debugfs.c @@ -7,7 +7,6 @@ #include <linux/circ_buf.h> #include <linux/ctype.h> #include <linux/debugfs.h> -#include <drm/drmP.h> #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c index bf11930e40e1..048c70a7b592 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.c +++ b/drivers/gpu/drm/vc4/vc4_drv.c @@ -23,16 +23,21 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/device.h> +#include <linux/dma-mapping.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of_platform.h> #include <linux/platform_device.h> #include <linux/pm_runtime.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> -#include <drm/drm_atomic_helper.h> +#include <drm/drm_vblank.h> #include "uapi/drm/vc4_drm.h" + #include "vc4_drv.h" #include "vc4_regs.h" @@ -177,7 +182,6 @@ static struct drm_driver vc4_drm_driver = { DRIVER_ATOMIC | DRIVER_GEM | DRIVER_RENDER | - DRIVER_PRIME | DRIVER_SYNCOBJ), .open = vc4_open, .postclose = vc4_close, @@ -199,7 +203,6 @@ static struct drm_driver vc4_drm_driver = { .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, .gem_prime_export = vc4_prime_export, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = vc4_prime_import_sg_table, diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h index 616c011bcb82..6627b20c99e9 100644 --- a/drivers/gpu/drm/vc4/vc4_drv.h +++ b/drivers/gpu/drm/vc4/vc4_drv.h @@ -3,16 +3,23 @@ * Copyright (C) 2015 Broadcom */ -#include <linux/mm_types.h> -#include <drm/drmP.h> -#include <drm/drm_util.h> +#include <linux/delay.h> +#include <linux/refcount.h> +#include <linux/uaccess.h> + +#include <drm/drm_atomic.h> +#include <drm/drm_debugfs.h> +#include <drm/drm_device.h> #include <drm/drm_encoder.h> #include <drm/drm_gem_cma_helper.h> -#include <drm/drm_atomic.h> -#include <drm/drm_syncobj.h> +#include <drm/drm_mm.h> +#include <drm/drm_modeset_lock.h> #include "uapi/drm/vc4_drm.h" +struct drm_device; +struct drm_gem_object; + /* Don't forget to update vc4_bo.c: bo_type_names[] when adding to * this. */ @@ -705,8 +712,7 @@ struct vc4_bo *vc4_bo_create(struct drm_device *dev, size_t size, int vc4_dumb_create(struct drm_file *file_priv, struct drm_device *dev, struct drm_mode_create_dumb *args); -struct dma_buf *vc4_prime_export(struct drm_device *dev, - struct drm_gem_object *obj, int flags); +struct dma_buf *vc4_prime_export(struct drm_gem_object *obj, int flags); int vc4_create_bo_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); int vc4_create_shader_bo_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c index 1db39b570cf4..c78fa8144776 100644 --- a/drivers/gpu/drm/vc4/vc4_dsi.c +++ b/drivers/gpu/drm/vc4/vc4_dsi.c @@ -18,22 +18,25 @@ * hopefully present. */ -#include <drm/drm_atomic_helper.h> -#include <drm/drm_edid.h> -#include <drm/drm_mipi_dsi.h> -#include <drm/drm_of.h> -#include <drm/drm_panel.h> -#include <drm/drm_probe_helper.h> -#include <linux/clk.h> #include <linux/clk-provider.h> +#include <linux/clk.h> #include <linux/completion.h> #include <linux/component.h> +#include <linux/dma-mapping.h> #include <linux/dmaengine.h> #include <linux/i2c.h> #include <linux/io.h> #include <linux/of_address.h> #include <linux/of_platform.h> #include <linux/pm_runtime.h> + +#include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> +#include <drm/drm_mipi_dsi.h> +#include <drm/drm_of.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> + #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_gem.c b/drivers/gpu/drm/vc4/vc4_gem.c index 84795d928f20..b72b760e3018 100644 --- a/drivers/gpu/drm/vc4/vc4_gem.c +++ b/drivers/gpu/drm/vc4/vc4_gem.c @@ -29,6 +29,8 @@ #include <linux/sched/signal.h> #include <linux/dma-fence-array.h> +#include <drm/drm_syncobj.h> + #include "uapi/drm/vc4_drm.h" #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c index 0f633bef6b9d..9936b15d0bf1 100644 --- a/drivers/gpu/drm/vc4/vc4_hvs.c +++ b/drivers/gpu/drm/vc4/vc4_hvs.c @@ -19,8 +19,11 @@ * each CRTC. */ -#include <drm/drm_atomic_helper.h> #include <linux/component.h> +#include <linux/platform_device.h> + +#include <drm/drm_atomic_helper.h> + #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_kms.c b/drivers/gpu/drm/vc4/vc4_kms.c index 70d079b7b39f..78d4fb0499e3 100644 --- a/drivers/gpu/drm/vc4/vc4_kms.c +++ b/drivers/gpu/drm/vc4/vc4_kms.c @@ -11,12 +11,14 @@ * crtc, HDMI encoder). */ -#include <drm/drm_crtc.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_crtc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 0a0207c350a5..5e5f90810aca 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -17,11 +17,14 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_atomic_uapi.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_plane_helper.h> -#include <drm/drm_atomic_uapi.h> #include "uapi/drm/vc4_drm.h" + #include "vc4_drv.h" #include "vc4_regs.h" @@ -1123,7 +1126,6 @@ static int vc4_prepare_fb(struct drm_plane *plane, struct drm_plane_state *state) { struct vc4_bo *bo; - struct dma_fence *fence; int ret; if (!state->fb) @@ -1131,8 +1133,7 @@ static int vc4_prepare_fb(struct drm_plane *plane, bo = to_vc4_bo(&drm_fb_cma_get_gem_obj(state->fb, 0)->base); - fence = reservation_object_get_excl_rcu(bo->base.base.resv); - drm_atomic_set_fence_for_plane(state, fence); + drm_gem_fb_prepare_fb(plane, state); if (plane->state->fb == state->fb) return 0; diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c index 96f91c1b4b6e..1ce4d7142b6e 100644 --- a/drivers/gpu/drm/vc4/vc4_txp.c +++ b/drivers/gpu/drm/vc4/vc4_txp.c @@ -7,18 +7,20 @@ * Boris Brezillon <boris.brezillon@bootlin.com> */ -#include <drm/drm_atomic_helper.h> -#include <drm/drm_fb_cma_helper.h> -#include <drm/drm_edid.h> -#include <drm/drm_panel.h> -#include <drm/drm_probe_helper.h> -#include <drm/drm_writeback.h> #include <linux/clk.h> #include <linux/component.h> #include <linux/of_graph.h> #include <linux/of_platform.h> #include <linux/pm_runtime.h> +#include <drm/drm_atomic_helper.h> +#include <drm/drm_edid.h> +#include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_panel.h> +#include <drm/drm_probe_helper.h> +#include <drm/drm_writeback.h> + #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c index fee4f90e71aa..cea77a21b205 100644 --- a/drivers/gpu/drm/vc4/vc4_v3d.c +++ b/drivers/gpu/drm/vc4/vc4_v3d.c @@ -7,7 +7,11 @@ #include <linux/clk.h> #include <linux/component.h> +#include <linux/platform_device.h> #include <linux/pm_runtime.h> + +#include <drm/drm_irq.h> + #include "vc4_drv.h" #include "vc4_regs.h" diff --git a/drivers/gpu/drm/vgem/vgem_drv.c b/drivers/gpu/drm/vgem/vgem_drv.c index 11a8f99ba18c..5bd60ded3d81 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.c +++ b/drivers/gpu/drm/vgem/vgem_drv.c @@ -30,10 +30,17 @@ * software renderer and the X server for efficient buffer sharing. */ +#include <linux/dma-buf.h> #include <linux/module.h> -#include <linux/ramfs.h> +#include <linux/platform_device.h> #include <linux/shmem_fs.h> -#include <linux/dma-buf.h> +#include <linux/vmalloc.h> + +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_ioctl.h> +#include <drm/drm_prime.h> + #include "vgem_drv.h" #define DRIVER_NAME "vgem" @@ -214,7 +221,7 @@ static int vgem_gem_dumb_create(struct drm_file *file, struct drm_device *dev, args->size = gem_object->size; args->pitch = pitch; - DRM_DEBUG_DRIVER("Created object of size %lld\n", size); + DRM_DEBUG("Created object of size %lld\n", size); return 0; } @@ -246,8 +253,8 @@ unref: } static struct drm_ioctl_desc vgem_ioctls[] = { - DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), - DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(VGEM_FENCE_ATTACH, vgem_fence_attach_ioctl, DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(VGEM_FENCE_SIGNAL, vgem_fence_signal_ioctl, DRM_RENDER_ALLOW), }; static int vgem_mmap(struct file *filp, struct vm_area_struct *vma) @@ -427,8 +434,7 @@ static void vgem_release(struct drm_device *dev) } static struct drm_driver vgem_driver = { - .driver_features = DRIVER_GEM | DRIVER_PRIME | - DRIVER_RENDER, + .driver_features = DRIVER_GEM | DRIVER_RENDER, .release = vgem_release, .open = vgem_open, .postclose = vgem_postclose, @@ -446,7 +452,6 @@ static struct drm_driver vgem_driver = { .gem_prime_pin = vgem_prime_pin, .gem_prime_unpin = vgem_prime_unpin, .gem_prime_import = vgem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_import_sg_table = vgem_prime_import_sg_table, .gem_prime_get_sg_table = vgem_prime_get_sg_table, .gem_prime_vmap = vgem_prime_vmap, diff --git a/drivers/gpu/drm/vgem/vgem_drv.h b/drivers/gpu/drm/vgem/vgem_drv.h index 5c8f6d619ff3..0ed300317f87 100644 --- a/drivers/gpu/drm/vgem/vgem_drv.h +++ b/drivers/gpu/drm/vgem/vgem_drv.h @@ -29,7 +29,6 @@ #ifndef _VGEM_DRV_H_ #define _VGEM_DRV_H_ -#include <drm/drmP.h> #include <drm/drm_gem.h> #include <drm/drm_cache.h> diff --git a/drivers/gpu/drm/vgem/vgem_fence.c b/drivers/gpu/drm/vgem/vgem_fence.c index eb17c0cd3727..d8630467549c 100644 --- a/drivers/gpu/drm/vgem/vgem_fence.c +++ b/drivers/gpu/drm/vgem/vgem_fence.c @@ -23,6 +23,8 @@ #include <linux/dma-buf.h> #include <linux/reservation.h> +#include <drm/drm_file.h> + #include "vgem_drv.h" #define VGEM_FENCE_TIMEOUT (10*HZ) @@ -100,22 +102,6 @@ static struct dma_fence *vgem_fence_create(struct vgem_file *vfile, return &fence->base; } -static int attach_dmabuf(struct drm_device *dev, - struct drm_gem_object *obj) -{ - struct dma_buf *dmabuf; - - if (obj->dma_buf) - return 0; - - dmabuf = dev->driver->gem_prime_export(dev, obj, 0); - if (IS_ERR(dmabuf)) - return PTR_ERR(dmabuf); - - obj->dma_buf = dmabuf; - return 0; -} - /* * vgem_fence_attach_ioctl (DRM_IOCTL_VGEM_FENCE_ATTACH): * @@ -157,10 +143,6 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, if (!obj) return -ENOENT; - ret = attach_dmabuf(dev, obj); - if (ret) - goto err; - fence = vgem_fence_create(vfile, arg->flags); if (!fence) { ret = -ENOMEM; @@ -168,7 +150,7 @@ int vgem_fence_attach_ioctl(struct drm_device *dev, } /* Check for a conflicting fence */ - resv = obj->dma_buf->resv; + resv = obj->resv; if (!reservation_object_test_signaled_rcu(resv, arg->flags & VGEM_FENCE_WRITE)) { ret = -EBUSY; diff --git a/drivers/gpu/drm/via/via_dma.c b/drivers/gpu/drm/via/via_dma.c index d17d8f245c1a..1208445e341d 100644 --- a/drivers/gpu/drm/via/via_dma.c +++ b/drivers/gpu/drm/via/via_dma.c @@ -34,8 +34,15 @@ * Thomas Hellstrom. */ -#include <drm/drmP.h> +#include <linux/delay.h> +#include <linux/uaccess.h> + +#include <drm/drm.h> +#include <drm/drm_agpsupport.h> +#include <drm/drm_device.h> +#include <drm/drm_file.h> #include <drm/via_drm.h> + #include "via_drv.h" #include "via_3d_reg.h" @@ -430,14 +437,14 @@ static int via_hook_segment(drm_via_private_t *dev_priv, diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; count = 10000000; while (diff == 0 && count--) { - paused = (VIA_READ(0x41c) & 0x80000000); + paused = (via_read(dev_priv, 0x41c) & 0x80000000); if (paused) break; reader = *(dev_priv->hw_addr_ptr); diff = (uint32_t) (ptr - reader) - dev_priv->dma_diff; } - paused = VIA_READ(0x41c) & 0x80000000; + paused = via_read(dev_priv, 0x41c) & 0x80000000; if (paused && !no_pci_fire) { reader = *(dev_priv->hw_addr_ptr); @@ -454,10 +461,10 @@ static int via_hook_segment(drm_via_private_t *dev_priv, * doesn't make a difference. */ - VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); - VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); - VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); - VIA_READ(VIA_REG_TRANSPACE); + via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); + via_read(dev_priv, VIA_REG_TRANSPACE); } } return paused; @@ -467,10 +474,10 @@ static int via_wait_idle(drm_via_private_t *dev_priv) { int count = 10000000; - while (!(VIA_READ(VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) + while (!(via_read(dev_priv, VIA_REG_STATUS) & VIA_VR_QUEUE_BUSY) && --count) ; - while (count && (VIA_READ(VIA_REG_STATUS) & + while (count && (via_read(dev_priv, VIA_REG_STATUS) & (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY | VIA_3D_ENG_BUSY))) --count; @@ -536,21 +543,21 @@ static void via_cmdbuf_start(drm_via_private_t *dev_priv) via_flush_write_combine(); (void) *(volatile uint32_t *)dev_priv->last_pause_ptr; - VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); - VIA_WRITE(VIA_REG_TRANSPACE, command); - VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo); - VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo); + via_write(dev_priv, VIA_REG_TRANSET, (HC_ParaType_PreCR << 16)); + via_write(dev_priv, VIA_REG_TRANSPACE, command); + via_write(dev_priv, VIA_REG_TRANSPACE, start_addr_lo); + via_write(dev_priv, VIA_REG_TRANSPACE, end_addr_lo); - VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi); - VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo); + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_hi); + via_write(dev_priv, VIA_REG_TRANSPACE, pause_addr_lo); wmb(); - VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); - VIA_READ(VIA_REG_TRANSPACE); + via_write(dev_priv, VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK); + via_read(dev_priv, VIA_REG_TRANSPACE); dev_priv->dma_diff = 0; count = 10000000; - while (!(VIA_READ(0x41c) & 0x80000000) && count--); + while (!(via_read(dev_priv, 0x41c) & 0x80000000) && count--); reader = *(dev_priv->hw_addr_ptr); ptr = ((volatile char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) + diff --git a/drivers/gpu/drm/via/via_dmablit.c b/drivers/gpu/drm/via/via_dmablit.c index 062067438f1d..feaa538026a0 100644 --- a/drivers/gpu/drm/via/via_dmablit.c +++ b/drivers/gpu/drm/via/via_dmablit.c @@ -34,13 +34,16 @@ * the same DMA mappings? */ -#include <drm/drmP.h> -#include <drm/via_drm.h> -#include "via_drv.h" -#include "via_dmablit.h" - #include <linux/pagemap.h> #include <linux/slab.h> +#include <linux/vmalloc.h> + +#include <drm/drm_device.h> +#include <drm/drm_pci.h> +#include <drm/via_drm.h> + +#include "via_dmablit.h" +#include "via_drv.h" #define VIA_PGDN(x) (((unsigned long)(x)) & PAGE_MASK) #define VIA_PGOFF(x) (((unsigned long)(x)) & ~PAGE_MASK) @@ -214,16 +217,16 @@ via_fire_dmablit(struct drm_device *dev, drm_via_sg_info_t *vsg, int engine) { drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - VIA_WRITE(VIA_PCI_DMA_MAR0 + engine*0x10, 0); - VIA_WRITE(VIA_PCI_DMA_DAR0 + engine*0x10, 0); - VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD | + via_write(dev_priv, VIA_PCI_DMA_MAR0 + engine*0x10, 0); + via_write(dev_priv, VIA_PCI_DMA_DAR0 + engine*0x10, 0); + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DD | VIA_DMA_CSR_TD | VIA_DMA_CSR_DE); - VIA_WRITE(VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); - VIA_WRITE(VIA_PCI_DMA_BCR0 + engine*0x10, 0); - VIA_WRITE(VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); + via_write(dev_priv, VIA_PCI_DMA_MR0 + engine*0x04, VIA_DMA_MR_CM | VIA_DMA_MR_TDIE); + via_write(dev_priv, VIA_PCI_DMA_BCR0 + engine*0x10, 0); + via_write(dev_priv, VIA_PCI_DMA_DPR0 + engine*0x10, vsg->chain_start); wmb(); - VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); - VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04); + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_DE | VIA_DMA_CSR_TS); + via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04); } /* @@ -291,7 +294,7 @@ via_abort_dmablit(struct drm_device *dev, int engine) { drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA); + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TA); } static void @@ -299,7 +302,7 @@ via_dmablit_engine_off(struct drm_device *dev, int engine) { drm_via_private_t *dev_priv = (drm_via_private_t *)dev->dev_private; - VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD); + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD | VIA_DMA_CSR_DD); } @@ -330,7 +333,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq) spin_lock_irqsave(&blitq->blit_lock, irqsave); done_transfer = blitq->is_active && - ((status = VIA_READ(VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD); + ((status = via_read(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04)) & VIA_DMA_CSR_TD); done_transfer = done_transfer || (blitq->aborting && !(status & VIA_DMA_CSR_DE)); cur = blitq->cur; @@ -349,7 +352,7 @@ via_dmablit_handler(struct drm_device *dev, int engine, int from_irq) * Clear transfer done flag. */ - VIA_WRITE(VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD); + via_write(dev_priv, VIA_PCI_DMA_CSR0 + engine*0x04, VIA_DMA_CSR_TD); blitq->is_active = 0; blitq->aborting = 0; @@ -436,7 +439,7 @@ via_dmablit_sync(struct drm_device *dev, uint32_t handle, int engine) int ret = 0; if (via_dmablit_active(blitq, engine, handle, &queue)) { - DRM_WAIT_ON(ret, *queue, 3 * HZ, + VIA_WAIT_ON(ret, *queue, 3 * HZ, !via_dmablit_active(blitq, engine, handle, NULL)); } DRM_DEBUG("DMA blit sync handle 0x%x engine %d returned %d\n", @@ -687,7 +690,7 @@ via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine) while (blitq->num_free == 0) { spin_unlock_irqrestore(&blitq->blit_lock, irqsave); - DRM_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0); + VIA_WAIT_ON(ret, blitq->busy_queue, HZ, blitq->num_free > 0); if (ret) return (-EINTR == ret) ? -EAGAIN : ret; diff --git a/drivers/gpu/drm/via/via_drv.c b/drivers/gpu/drm/via/via_drv.c index af6a12d3c058..666a16de84f9 100644 --- a/drivers/gpu/drm/via/via_drv.c +++ b/drivers/gpu/drm/via/via_drv.c @@ -24,11 +24,14 @@ #include <linux/module.h> -#include <drm/drmP.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> +#include <drm/drm_pci.h> +#include <drm/drm_pciids.h> #include <drm/via_drm.h> + #include "via_drv.h" -#include <drm/drm_pciids.h> static int via_driver_open(struct drm_device *dev, struct drm_file *file) { diff --git a/drivers/gpu/drm/via/via_drv.h b/drivers/gpu/drm/via/via_drv.h index 6d1ae834484c..d5ad1b05bf77 100644 --- a/drivers/gpu/drm/via/via_drv.h +++ b/drivers/gpu/drm/via/via_drv.h @@ -24,8 +24,16 @@ #ifndef _VIA_DRV_H_ #define _VIA_DRV_H_ -#include <drm/drm_mm.h> +#include <linux/irqreturn.h> +#include <linux/jiffies.h> +#include <linux/sched.h> +#include <linux/sched/signal.h> +#include <linux/wait.h> + +#include <drm/drm_ioctl.h> #include <drm/drm_legacy.h> +#include <drm/drm_mm.h> +#include <drm/via_drm.h> #define DRIVER_AUTHOR "Various" @@ -113,12 +121,67 @@ enum via_family { }; /* VIA MMIO register access */ -#define VIA_BASE ((dev_priv->mmio)) +static inline u32 via_read(struct drm_via_private *dev_priv, u32 reg) +{ + return readl((void __iomem *)(dev_priv->mmio->handle + reg)); +} + +static inline void via_write(struct drm_via_private *dev_priv, u32 reg, + u32 val) +{ + writel(val, (void __iomem *)(dev_priv->mmio->handle + reg)); +} + +static inline void via_write8(struct drm_via_private *dev_priv, u32 reg, + u32 val) +{ + writeb(val, (void __iomem *)(dev_priv->mmio->handle + reg)); +} + +static inline void via_write8_mask(struct drm_via_private *dev_priv, + u32 reg, u32 mask, u32 val) +{ + u32 tmp; + + tmp = readb((void __iomem *)(dev_priv->mmio->handle + reg)); + tmp = (tmp & ~mask) | (val & mask); + writeb(tmp, (void __iomem *)(dev_priv->mmio->handle + reg)); +} -#define VIA_READ(reg) DRM_READ32(VIA_BASE, reg) -#define VIA_WRITE(reg, val) DRM_WRITE32(VIA_BASE, reg, val) -#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg) -#define VIA_WRITE8(reg, val) DRM_WRITE8(VIA_BASE, reg, val) +/* + * Poll in a loop waiting for 'contidition' to be true. + * Note: A direct replacement with wait_event_interruptible_timeout() + * will not work unless driver is updated to emit wake_up() + * in relevant places that can impact the 'condition' + * + * Returns: + * ret keeps current value if 'condition' becomes true + * ret = -BUSY if timeout happens + * ret = -EINTR if a signal interrupted the waiting period + */ +#define VIA_WAIT_ON( ret, queue, timeout, condition ) \ +do { \ + DECLARE_WAITQUEUE(entry, current); \ + unsigned long end = jiffies + (timeout); \ + add_wait_queue(&(queue), &entry); \ + \ + for (;;) { \ + __set_current_state(TASK_INTERRUPTIBLE); \ + if (condition) \ + break; \ + if (time_after_eq(jiffies, end)) { \ + ret = -EBUSY; \ + break; \ + } \ + schedule_timeout((HZ/100 > 1) ? HZ/100 : 1); \ + if (signal_pending(current)) { \ + ret = -EINTR; \ + break; \ + } \ + } \ + __set_current_state(TASK_RUNNING); \ + remove_wait_queue(&(queue), &entry); \ +} while (0) extern const struct drm_ioctl_desc via_ioctls[]; extern int via_max_ioctl; diff --git a/drivers/gpu/drm/via/via_irq.c b/drivers/gpu/drm/via/via_irq.c index c96830ccc0ec..24cc445169e2 100644 --- a/drivers/gpu/drm/via/via_irq.c +++ b/drivers/gpu/drm/via/via_irq.c @@ -35,8 +35,10 @@ * The refresh rate is also calculated for video playback sync purposes. */ -#include <drm/drmP.h> +#include <drm/drm_device.h> +#include <drm/drm_vblank.h> #include <drm/via_drm.h> + #include "via_drv.h" #define VIA_REG_INTERRUPT 0x200 @@ -108,7 +110,7 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg) drm_via_irq_t *cur_irq = dev_priv->via_irqs; int i; - status = VIA_READ(VIA_REG_INTERRUPT); + status = via_read(dev_priv, VIA_REG_INTERRUPT); if (status & VIA_IRQ_VBLANK_PENDING) { atomic_inc(&dev_priv->vbl_received); if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) { @@ -143,7 +145,7 @@ irqreturn_t via_driver_irq_handler(int irq, void *arg) } /* Acknowledge interrupts */ - VIA_WRITE(VIA_REG_INTERRUPT, status); + via_write(dev_priv, VIA_REG_INTERRUPT, status); if (handled) @@ -158,8 +160,8 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t *dev_priv) if (dev_priv) { /* Acknowledge interrupts */ - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status | dev_priv->irq_pending_mask); } } @@ -174,11 +176,11 @@ int via_enable_vblank(struct drm_device *dev, unsigned int pipe) return -EINVAL; } - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE); + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_VBLANK_ENABLE); - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); return 0; } @@ -188,11 +190,11 @@ void via_disable_vblank(struct drm_device *dev, unsigned int pipe) drm_via_private_t *dev_priv = dev->dev_private; u32 status; - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE); + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status & ~VIA_IRQ_VBLANK_ENABLE); - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0); if (pipe != 0) DRM_ERROR("%s: bad crtc %u\n", __func__, pipe); @@ -233,12 +235,12 @@ via_driver_irq_wait(struct drm_device *dev, unsigned int irq, int force_sequence cur_irq = dev_priv->via_irqs + real_irq; if (masks[real_irq][2] && !force_sequence) { - DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, - ((VIA_READ(masks[irq][2]) & masks[irq][3]) == + VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, + ((via_read(dev_priv, masks[irq][2]) & masks[irq][3]) == masks[irq][4])); cur_irq_sequence = atomic_read(&cur_irq->irq_received); } else { - DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, + VIA_WAIT_ON(ret, cur_irq->irq_queue, 3 * HZ, (((cur_irq_sequence = atomic_read(&cur_irq->irq_received)) - *sequence) <= (1 << 23))); @@ -292,8 +294,8 @@ void via_driver_irq_preinstall(struct drm_device *dev) dev_priv->last_vblank_valid = 0; /* Clear VSync interrupt regs */ - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status & ~(dev_priv->irq_enable_mask)); /* Clear bits if they're already high */ @@ -310,13 +312,13 @@ int via_driver_irq_postinstall(struct drm_device *dev) if (!dev_priv) return -EINVAL; - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL | dev_priv->irq_enable_mask); /* Some magic, oh for some data sheets ! */ - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30); + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0x30); return 0; } @@ -331,11 +333,11 @@ void via_driver_irq_uninstall(struct drm_device *dev) /* Some more magic, oh for some data sheets ! */ - VIA_WRITE8(0x83d4, 0x11); - VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30); + via_write8(dev_priv, 0x83d4, 0x11); + via_write8_mask(dev_priv, 0x83d5, 0x30, 0); - status = VIA_READ(VIA_REG_INTERRUPT); - VIA_WRITE(VIA_REG_INTERRUPT, status & + status = via_read(dev_priv, VIA_REG_INTERRUPT); + via_write(dev_priv, VIA_REG_INTERRUPT, status & ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask)); } } diff --git a/drivers/gpu/drm/via/via_map.c b/drivers/gpu/drm/via/via_map.c index 2ad865870372..431c150df014 100644 --- a/drivers/gpu/drm/via/via_map.c +++ b/drivers/gpu/drm/via/via_map.c @@ -21,8 +21,12 @@ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ -#include <drm/drmP.h> + +#include <drm/drm_device.h> +#include <drm/drm_pci.h> +#include <drm/drm_vblank.h> #include <drm/via_drm.h> + #include "via_drv.h" static int via_do_init_map(struct drm_device *dev, drm_via_init_t *init) diff --git a/drivers/gpu/drm/via/via_mm.c b/drivers/gpu/drm/via/via_mm.c index 4217d66a5cc6..45cc9e900260 100644 --- a/drivers/gpu/drm/via/via_mm.c +++ b/drivers/gpu/drm/via/via_mm.c @@ -25,8 +25,13 @@ * Authors: Thomas Hellström <thomas-at-tungstengraphics-dot-com> */ -#include <drm/drmP.h> +#include <linux/slab.h> + +#include <drm/drm_device.h> +#include <drm/drm_file.h> +#include <drm/drm_irq.h> #include <drm/via_drm.h> + #include "via_drv.h" #define VIA_MM_ALIGN_SHIFT 4 diff --git a/drivers/gpu/drm/via/via_verifier.c b/drivers/gpu/drm/via/via_verifier.c index fb2609434df7..8d8135f424ef 100644 --- a/drivers/gpu/drm/via/via_verifier.c +++ b/drivers/gpu/drm/via/via_verifier.c @@ -28,13 +28,13 @@ * be very slow. */ -#include "via_3d_reg.h" -#include <drm/drmP.h> -#include <drm/via_drm.h> +#include <drm/drm_device.h> #include <drm/drm_legacy.h> -#include "via_verifier.h" +#include <drm/via_drm.h> + +#include "via_3d_reg.h" #include "via_drv.h" -#include <linux/kernel.h> +#include "via_verifier.h" typedef enum { state_command, @@ -725,14 +725,14 @@ via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer, next_fire = dev_priv->fire_offsets[*fire_count]; buf++; cmd = (*buf & 0xFFFF0000) >> 16; - VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++); + via_write(dev_priv, HC_REG_TRANS_SET + HC_REG_BASE, *buf++); switch (cmd) { case HC_ParaType_CmdVdata: while ((buf < buf_end) && (*fire_count < dev_priv->num_fire_offsets) && (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB) { while (buf <= next_fire) { - VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + + via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++); burst += 4; } @@ -753,7 +753,7 @@ via_parse_header2(drm_via_private_t *dev_priv, uint32_t const **buffer, (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6) break; - VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + + via_write(dev_priv, HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++); burst += 4; } @@ -843,7 +843,7 @@ via_parse_header1(drm_via_private_t *dev_priv, uint32_t const **buffer, cmd = *buf; if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) break; - VIA_WRITE((cmd & ~HALCYON_HEADER1MASK) << 2, *++buf); + via_write(dev_priv, (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf); buf++; } *buffer = buf; @@ -894,7 +894,7 @@ via_parse_vheader5(drm_via_private_t *dev_priv, uint32_t const **buffer, i = count = *buf; buf += 3; while (i--) - VIA_WRITE(addr, *buf++); + via_write(dev_priv, addr, *buf++); if (count & 3) buf += 4 - (count & 3); *buffer = buf; @@ -950,7 +950,7 @@ via_parse_vheader6(drm_via_private_t *dev_priv, uint32_t const **buffer, buf += 3; while (i--) { addr = *buf++; - VIA_WRITE(addr, *buf++); + via_write(dev_priv, addr, *buf++); } count <<= 1; if (count & 3) diff --git a/drivers/gpu/drm/via/via_video.c b/drivers/gpu/drm/via/via_video.c index a9ffbad1cfdd..53b1f58f99b4 100644 --- a/drivers/gpu/drm/via/via_video.c +++ b/drivers/gpu/drm/via/via_video.c @@ -25,8 +25,9 @@ * Video and XvMC related functions. */ -#include <drm/drmP.h> +#include <drm/drm_device.h> #include <drm/via_drm.h> + #include "via_drv.h" void via_init_futex(drm_via_private_t *dev_priv) @@ -82,7 +83,7 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_ switch (fx->func) { case VIA_FUTEX_WAIT: - DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock], + VIA_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock], (fx->ms / 10) * (HZ / 100), *lock != fx->val); return ret; case VIA_FUTEX_WAKE: diff --git a/drivers/gpu/drm/virtio/virtgpu_debugfs.c b/drivers/gpu/drm/virtio/virtgpu_debugfs.c index ed0fcda713c3..5156e6b279db 100644 --- a/drivers/gpu/drm/virtio/virtgpu_debugfs.c +++ b/drivers/gpu/drm/virtio/virtgpu_debugfs.c @@ -23,8 +23,8 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include <linux/debugfs.h> -#include <drm/drmP.h> +#include <drm/drm_debugfs.h> +#include <drm/drm_file.h> #include "virtgpu_drv.h" diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c index ba16e8cb7124..e622485ae826 100644 --- a/drivers/gpu/drm/virtio/virtgpu_display.c +++ b/drivers/gpu/drm/virtio/virtgpu_display.c @@ -25,11 +25,14 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include "virtgpu_drv.h" #include <drm/drm_atomic_helper.h> +#include <drm/drm_damage_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> -#include <drm/drm_damage_helper.h> +#include <drm/drm_vblank.h> + +#include "virtgpu_drv.h" #define XRES_MIN 32 #define YRES_MIN 32 diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c index c50868753132..0fc32fa0b3c0 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.c +++ b/drivers/gpu/drm/virtio/virtgpu_drv.c @@ -29,10 +29,13 @@ #include <linux/module.h> #include <linux/console.h> #include <linux/pci.h> -#include <drm/drmP.h> + #include <drm/drm.h> +#include <drm/drm_drv.h> +#include <drm/drm_file.h> #include "virtgpu_drv.h" + static struct drm_driver driver; static int virtio_gpu_modeset = -1; @@ -195,7 +198,7 @@ static const struct file_operations virtio_gpu_driver_fops = { }; static struct drm_driver driver = { - .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC, + .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_RENDER | DRIVER_ATOMIC, .open = virtio_gpu_driver_open, .postclose = virtio_gpu_driver_postclose, @@ -207,8 +210,6 @@ static struct drm_driver driver = { #endif .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table, .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table, .gem_prime_vmap = virtgpu_gem_prime_vmap, diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h index 9e2d3062b01d..e28829661724 100644 --- a/drivers/gpu/drm/virtio/virtgpu_drv.h +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h @@ -31,16 +31,16 @@ #include <linux/virtio_config.h> #include <linux/virtio_gpu.h> -#include <drm/drmP.h> -#include <drm/drm_gem.h> #include <drm/drm_atomic.h> #include <drm/drm_encoder.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_gem.h> +#include <drm/drm_ioctl.h> #include <drm/drm_probe_helper.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> #include <drm/ttm/ttm_module.h> +#include <drm/ttm/ttm_placement.h> #define DRIVER_NAME "virtio_gpu" #define DRIVER_DESC "virtio GPU" @@ -396,7 +396,7 @@ static inline void virtio_gpu_object_unref(struct virtio_gpu_object **bo) static inline u64 virtio_gpu_object_mmap_offset(struct virtio_gpu_object *bo) { - return drm_vma_node_offset_addr(&bo->tbo.vma_node); + return drm_vma_node_offset_addr(&bo->tbo.base.vma_node); } static inline int virtio_gpu_object_reserve(struct virtio_gpu_object *bo, diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c index 70d6c4329778..a0514f5bd006 100644 --- a/drivers/gpu/drm/virtio/virtgpu_fence.c +++ b/drivers/gpu/drm/virtio/virtgpu_fence.c @@ -23,8 +23,8 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include <drm/drmP.h> #include <trace/events/dma_fence.h> + #include "virtgpu_drv.h" static const char *virtio_get_driver_name(struct dma_fence *f) diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c index 1e49e08dd545..292566146814 100644 --- a/drivers/gpu/drm/virtio/virtgpu_gem.c +++ b/drivers/gpu/drm/virtio/virtgpu_gem.c @@ -23,7 +23,9 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include <drm/drmP.h> +#include <drm/drm_file.h> +#include <drm/drm_fourcc.h> + #include "virtgpu_drv.h" void virtio_gpu_gem_free_object(struct drm_gem_object *gem_obj) diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c index ac60be9b5c19..3c430dd65f67 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c @@ -25,11 +25,13 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <drm/drmP.h> -#include <drm/virtgpu_drm.h> -#include <drm/ttm/ttm_execbuf_util.h> +#include <linux/file.h> #include <linux/sync_file.h> +#include <drm/drm_file.h> +#include <drm/ttm/ttm_execbuf_util.h> +#include <drm/virtgpu_drm.h> + #include "virtgpu_drv.h" static void convert_to_hw_box(struct virtio_gpu_box *dst, @@ -394,7 +396,7 @@ static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, (vgdev, qobj->hw_res_handle, vfpriv->ctx_id, offset, args->level, &box, fence); - reservation_object_add_excl_fence(qobj->tbo.resv, + reservation_object_add_excl_fence(qobj->tbo.base.resv, &fence->f); dma_fence_put(&fence->f); @@ -448,7 +450,7 @@ static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, (vgdev, qobj, vfpriv ? vfpriv->ctx_id : 0, offset, args->level, &box, fence); - reservation_object_add_excl_fence(qobj->tbo.resv, + reservation_object_add_excl_fence(qobj->tbo.base.resv, &fence->f); dma_fence_put(&fence->f); } @@ -553,34 +555,34 @@ copy_exit: struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, virtio_gpu_resource_create_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), /* make transfer async to the main ring? - no sure, can we * thread these in the underlying GL */ DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, virtio_gpu_transfer_from_host_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, virtio_gpu_transfer_to_host_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, - DRM_AUTH | DRM_RENDER_ALLOW), + DRM_RENDER_ALLOW), }; diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c index 84b6a6bf00c6..c190702fab72 100644 --- a/drivers/gpu/drm/virtio/virtgpu_kms.c +++ b/drivers/gpu/drm/virtio/virtgpu_kms.c @@ -25,7 +25,9 @@ #include <linux/virtio.h> #include <linux/virtio_config.h> -#include <drm/drmP.h> + +#include <drm/drm_file.h> + #include "virtgpu_drv.h" static void virtio_gpu_config_changed_work_func(struct work_struct *work) diff --git a/drivers/gpu/drm/virtio/virtgpu_plane.c b/drivers/gpu/drm/virtio/virtgpu_plane.c index 024c2aa0c929..3dc08f991a8d 100644 --- a/drivers/gpu/drm/virtio/virtgpu_plane.c +++ b/drivers/gpu/drm/virtio/virtgpu_plane.c @@ -23,9 +23,11 @@ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -#include "virtgpu_drv.h" -#include <drm/drm_plane_helper.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> +#include <drm/drm_plane_helper.h> + +#include "virtgpu_drv.h" static const uint32_t virtio_gpu_formats[] = { DRM_FORMAT_HOST_XRGB8888, @@ -210,7 +212,7 @@ static void virtio_gpu_cursor_plane_update(struct drm_plane *plane, 0, 0, vgfb->fence); ret = virtio_gpu_object_reserve(bo, false); if (!ret) { - reservation_object_add_excl_fence(bo->tbo.resv, + reservation_object_add_excl_fence(bo->tbo.base.resv, &vgfb->fence->f); dma_fence_put(&vgfb->fence->f); vgfb->fence = NULL; diff --git a/drivers/gpu/drm/virtio/virtgpu_prime.c b/drivers/gpu/drm/virtio/virtgpu_prime.c index 8fbf71bd0c5e..dc642a884b88 100644 --- a/drivers/gpu/drm/virtio/virtgpu_prime.c +++ b/drivers/gpu/drm/virtio/virtgpu_prime.c @@ -22,6 +22,8 @@ * Authors: Andreas Pokorny */ +#include <drm/drm_prime.h> + #include "virtgpu_drv.h" /* Empty Implementations as there should not be any other driver for a virtual @@ -66,8 +68,5 @@ void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr) int virtgpu_gem_prime_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma) { - struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj); - - bo->gem_base.vma_node.vm_node.start = bo->tbo.vma_node.vm_node.start; return drm_gem_prime_mmap(obj, vma); } diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c index 300ef3a83538..f87903641847 100644 --- a/drivers/gpu/drm/virtio/virtgpu_ttm.c +++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c @@ -25,17 +25,18 @@ * OTHER DEALINGS IN THE SOFTWARE. */ +#include <linux/delay.h> + +#include <drm/drm.h> +#include <drm/drm_file.h> #include <drm/ttm/ttm_bo_api.h> #include <drm/ttm/ttm_bo_driver.h> -#include <drm/ttm/ttm_placement.h> -#include <drm/ttm/ttm_page_alloc.h> #include <drm/ttm/ttm_module.h> -#include <drm/drmP.h> -#include <drm/drm.h> +#include <drm/ttm/ttm_page_alloc.h> +#include <drm/ttm/ttm_placement.h> #include <drm/virtgpu_drm.h> -#include "virtgpu_drv.h" -#include <linux/delay.h> +#include "virtgpu_drv.h" static struct virtio_gpu_device *virtio_gpu_get_vgdev(struct ttm_bo_device *bdev) diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c index 981ee16e3ee9..7ac20490e1b4 100644 --- a/drivers/gpu/drm/virtio/virtgpu_vq.c +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c @@ -26,13 +26,14 @@ * OTHER DEALINGS IN THE SOFTWARE. */ -#include <drm/drmP.h> -#include "virtgpu_drv.h" -#include "virtgpu_trace.h" +#include <linux/dma-mapping.h> #include <linux/virtio.h> #include <linux/virtio_config.h> #include <linux/virtio_ring.h> +#include "virtgpu_drv.h" +#include "virtgpu_trace.h" + #define MAX_INLINE_CMD_SIZE 96 #define MAX_INLINE_RESP_SIZE 24 #define VBUFFER_SIZE (sizeof(struct virtio_gpu_vbuffer) \ diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 89f09bec7b23..0b767d7efa24 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -1,4 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only -vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o vkms_crc.o +vkms-y := vkms_drv.o vkms_plane.o vkms_output.o vkms_crtc.o vkms_gem.o vkms_composer.o obj-$(CONFIG_DRM_VKMS) += vkms.o diff --git a/drivers/gpu/drm/vkms/vkms_crc.c b/drivers/gpu/drm/vkms/vkms_composer.c index e66ff25c008e..d5585695c64d 100644 --- a/drivers/gpu/drm/vkms/vkms_crc.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -1,34 +1,37 @@ // 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> +#include <drm/drm_vblank.h> + +#include "vkms_drv.h" /** * compute_crc - Compute CRC value on output frame * * @vaddr_out: address to final framebuffer - * @crc_out: framebuffer's metadata + * @composer: 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) +static uint32_t compute_crc(void *vaddr_out, struct vkms_composer *composer) { 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; + int x_src = composer->src.x1 >> 16; + int y_src = composer->src.y1 >> 16; + int h_src = drm_rect_height(&composer->src) >> 16; + int w_src = drm_rect_width(&composer->src) >> 16; u32 crc = 0; 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); + src_offset = composer->offset + + (i * composer->pitch) + + (j * composer->cpp); /* XRGB format ignores Alpha channel */ memset(vaddr_out + src_offset + 24, 0, 8); crc = crc32_le(crc, vaddr_out + src_offset, @@ -43,8 +46,8 @@ static uint32_t compute_crc(void *vaddr_out, struct vkms_crc_data *crc_out) * 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 + * @dest_composer: destination framebuffer's metadata + * @src_composer: source framebuffer's metadata * * Blend value at vaddr_src with value at vaddr_dst. * Currently, this function write value at vaddr_src on value @@ -55,31 +58,31 @@ static uint32_t compute_crc(void *vaddr_out, struct vkms_crc_data *crc_out) * 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) + struct vkms_composer *dest_composer, + struct vkms_composer *src_composer) { 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_src = src_composer->src.x1 >> 16; + int y_src = src_composer->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 x_dst = src_composer->dst.x1; + int y_dst = src_composer->dst.y1; + int h_dst = drm_rect_height(&src_composer->dst); + int w_dst = drm_rect_width(&src_composer->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); + offset_dst = dest_composer->offset + + (i_dst * dest_composer->pitch) + + (j_dst++ * dest_composer->cpp); + offset_src = src_composer->offset + + (i * src_composer->pitch) + + (j * src_composer->cpp); memcpy(vaddr_dst + offset_dst, vaddr_src + offset_src, sizeof(u32)); @@ -88,31 +91,27 @@ static void blend(void *vaddr_dst, void *vaddr_src, } } -static void compose_cursor(struct vkms_crc_data *cursor_crc, - struct vkms_crc_data *primary_crc, void *vaddr_out) +static void compose_cursor(struct vkms_composer *cursor_composer, + struct vkms_composer *primary_composer, + 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_obj = drm_gem_fb_get_obj(&cursor_composer->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); + if (WARN_ON(!cursor_vkms_obj->vaddr)) + return; -out: - mutex_unlock(&cursor_vkms_obj->pages_lock); + blend(vaddr_out, cursor_vkms_obj->vaddr, + primary_composer, cursor_composer); } -static uint32_t _vkms_get_crc(struct vkms_crc_data *primary_crc, - struct vkms_crc_data *cursor_crc) +static uint32_t _vkms_get_crc(struct vkms_composer *primary_composer, + struct vkms_composer *cursor_composer) { - struct drm_framebuffer *fb = &primary_crc->fb; + struct drm_framebuffer *fb = &primary_composer->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); @@ -123,20 +122,17 @@ static uint32_t _vkms_get_crc(struct vkms_crc_data *primary_crc, return 0; } - mutex_lock(&vkms_obj->pages_lock); if (WARN_ON(!vkms_obj->vaddr)) { - mutex_unlock(&vkms_obj->pages_lock); kfree(vaddr_out); 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); + if (cursor_composer) + compose_cursor(cursor_composer, primary_composer, vaddr_out); - crc = compute_crc(vaddr_out, primary_crc); + crc = compute_crc(vaddr_out, primary_composer); kfree(vaddr_out); @@ -144,72 +140,57 @@ static uint32_t _vkms_get_crc(struct vkms_crc_data *primary_crc, } /** - * vkms_crc_work_handle - ordered work_struct to compute CRC + * vkms_composer_worker - ordered work_struct to compute CRC * * @work: work_struct * - * Work handler for computing CRCs. work_struct scheduled in + * Work handler for composing and computing CRCs. work_struct scheduled in * an ordered workqueue that's periodically scheduled to run by * _vblank_handle() and flushed at vkms_atomic_crtc_destroy_state(). */ -void vkms_crc_work_handle(struct work_struct *work) +void vkms_composer_worker(struct work_struct *work) { struct vkms_crtc_state *crtc_state = container_of(work, struct vkms_crtc_state, - crc_work); + composer_work); struct drm_crtc *crtc = crtc_state->base.crtc; struct vkms_output *out = drm_crtc_to_vkms_output(crtc); - 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; + struct vkms_composer *primary_composer = NULL; + struct vkms_composer *cursor_composer = NULL; u32 crc32 = 0; u64 frame_start, frame_end; - unsigned long flags; + bool crc_pending; - spin_lock_irqsave(&out->state_lock, flags); + spin_lock_irq(&out->composer_lock); frame_start = crtc_state->frame_start; frame_end = crtc_state->frame_end; - spin_unlock_irqrestore(&out->state_lock, flags); - - /* _vblank_handle() hasn't updated frame_start yet */ - if (!frame_start || frame_start == frame_end) - goto out; - - drm_for_each_plane(plane, &vdev->drm) { - struct vkms_plane_state *vplane_state; - struct vkms_crc_data *crc_data; - - vplane_state = to_vkms_plane_state(plane->state); - crc_data = vplane_state->crc_data; + crc_pending = crtc_state->crc_pending; + crtc_state->frame_start = 0; + crtc_state->frame_end = 0; + crtc_state->crc_pending = false; + spin_unlock_irq(&out->composer_lock); - if (drm_framebuffer_read_refcount(&crc_data->fb) == 0) - continue; + /* + * We raced with the vblank hrtimer and previous work already computed + * the crc, nothing to do. + */ + if (!crc_pending) + return; - if (plane->type == DRM_PLANE_TYPE_PRIMARY) - primary_crc = crc_data; - else - cursor_crc = crc_data; - } + if (crtc_state->num_active_planes >= 1) + primary_composer = crtc_state->active_planes[0]->composer; - if (primary_crc) - crc32 = _vkms_get_crc(primary_crc, cursor_crc); + if (crtc_state->num_active_planes == 2) + cursor_composer = crtc_state->active_planes[1]->composer; - frame_end = drm_crtc_accurate_vblank_count(crtc); + if (primary_composer) + crc32 = _vkms_get_crc(primary_composer, cursor_composer); - /* queue_work can fail to schedule crc_work; add crc for - * missing frames + /* + * The worker can fall behind the vblank hrtimer, make sure we catch up. */ while (frame_start <= frame_end) drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); - -out: - /* to avoid using the same value for frame number again */ - spin_lock_irqsave(&out->state_lock, flags); - crtc_state->frame_end = frame_end; - crtc_state->frame_start = 0; - spin_unlock_irqrestore(&out->state_lock, flags); } static const char * const pipe_crc_sources[] = {"auto"}; @@ -256,17 +237,13 @@ int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name) { struct vkms_output *out = drm_crtc_to_vkms_output(crtc); bool enabled = false; - unsigned long flags; int ret = 0; ret = vkms_crc_parse_source(src_name, &enabled); - /* make sure nothing is scheduled on crtc workq */ - flush_workqueue(out->crc_workq); - - spin_lock_irqsave(&out->lock, flags); - out->crc_enabled = enabled; - spin_unlock_irqrestore(&out->lock, flags); + spin_lock_irq(&out->lock); + out->composer_enabled = enabled; + spin_unlock_irq(&out->lock); return ret; } diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 4d11292bc6f3..927dafaebc76 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -1,15 +1,18 @@ // SPDX-License-Identifier: GPL-2.0+ -#include "vkms_drv.h" +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + +#include "vkms_drv.h" static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer) { struct vkms_output *output = container_of(timer, struct vkms_output, vblank_hrtimer); struct drm_crtc *crtc = &output->crtc; - struct vkms_crtc_state *state = to_vkms_crtc_state(crtc->state); + struct vkms_crtc_state *state; u64 ret_overrun; bool ret; @@ -23,20 +26,26 @@ static enum hrtimer_restart vkms_vblank_simulate(struct hrtimer *timer) if (!ret) DRM_ERROR("vkms failure on handling vblank"); - if (state && output->crc_enabled) { + state = output->composer_state; + if (state && output->composer_enabled) { u64 frame = drm_crtc_accurate_vblank_count(crtc); - /* update frame_start only if a queued vkms_crc_work_handle() + /* update frame_start only if a queued vkms_composer_worker() * has read the data */ - spin_lock(&output->state_lock); - if (!state->frame_start) + spin_lock(&output->composer_lock); + if (!state->crc_pending) state->frame_start = frame; - spin_unlock(&output->state_lock); + else + DRM_DEBUG_DRIVER("crc worker falling behind, frame_start: %llu, frame_end: %llu\n", + state->frame_start, frame); + state->frame_end = frame; + state->crc_pending = true; + spin_unlock(&output->composer_lock); - ret = queue_work(output->crc_workq, &state->crc_work); + ret = queue_work(output->composer_workq, &state->composer_work); if (!ret) - DRM_WARN("failed to queue vkms_crc_work_handle"); + DRM_DEBUG_DRIVER("Composer worker already queued\n"); } spin_unlock(&output->lock); @@ -107,7 +116,7 @@ vkms_atomic_crtc_duplicate_state(struct drm_crtc *crtc) __drm_atomic_helper_crtc_duplicate_state(crtc, &vkms_state->base); - INIT_WORK(&vkms_state->crc_work, vkms_crc_work_handle); + INIT_WORK(&vkms_state->composer_work, vkms_composer_worker); return &vkms_state->base; } @@ -119,10 +128,9 @@ static void vkms_atomic_crtc_destroy_state(struct drm_crtc *crtc, __drm_atomic_helper_crtc_destroy_state(state); - if (vkms_state) { - flush_work(&vkms_state->crc_work); - kfree(vkms_state); - } + WARN_ON(work_pending(&vkms_state->composer_work)); + kfree(vkms_state->active_planes); + kfree(vkms_state); } static void vkms_atomic_crtc_reset(struct drm_crtc *crtc) @@ -135,7 +143,7 @@ static void vkms_atomic_crtc_reset(struct drm_crtc *crtc) __drm_atomic_helper_crtc_reset(crtc, &vkms_state->base); if (vkms_state) - INIT_WORK(&vkms_state->crc_work, vkms_crc_work_handle); + INIT_WORK(&vkms_state->composer_work, vkms_composer_worker); } static const struct drm_crtc_funcs vkms_crtc_funcs = { @@ -152,6 +160,52 @@ static const struct drm_crtc_funcs vkms_crtc_funcs = { .verify_crc_source = vkms_verify_crc_source, }; +static int vkms_crtc_atomic_check(struct drm_crtc *crtc, + struct drm_crtc_state *state) +{ + struct vkms_crtc_state *vkms_state = to_vkms_crtc_state(state); + struct drm_plane *plane; + struct drm_plane_state *plane_state; + int i = 0, ret; + + if (vkms_state->active_planes) + return 0; + + ret = drm_atomic_add_affected_planes(state->state, crtc); + if (ret < 0) + return ret; + + drm_for_each_plane_mask(plane, crtc->dev, state->plane_mask) { + plane_state = drm_atomic_get_existing_plane_state(state->state, + plane); + WARN_ON(!plane_state); + + if (!plane_state->visible) + continue; + + i++; + } + + vkms_state->active_planes = kcalloc(i, sizeof(plane), GFP_KERNEL); + if (!vkms_state->active_planes) + return -ENOMEM; + vkms_state->num_active_planes = i; + + i = 0; + drm_for_each_plane_mask(plane, crtc->dev, state->plane_mask) { + plane_state = drm_atomic_get_existing_plane_state(state->state, + plane); + + if (!plane_state->visible) + continue; + + vkms_state->active_planes[i++] = + to_vkms_plane_state(plane_state); + } + + return 0; +} + static void vkms_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { @@ -170,7 +224,7 @@ static void vkms_crtc_atomic_begin(struct drm_crtc *crtc, struct vkms_output *vkms_output = drm_crtc_to_vkms_output(crtc); /* This lock is held across the atomic commit to block vblank timer - * from scheduling vkms_crc_work_handle until the crc_data is updated + * from scheduling vkms_composer_worker until the composer is updated */ spin_lock_irq(&vkms_output->lock); } @@ -179,25 +233,27 @@ static void vkms_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { struct vkms_output *vkms_output = drm_crtc_to_vkms_output(crtc); - unsigned long flags; if (crtc->state->event) { - spin_lock_irqsave(&crtc->dev->event_lock, flags); + spin_lock(&crtc->dev->event_lock); if (drm_crtc_vblank_get(crtc) != 0) drm_crtc_send_vblank_event(crtc, crtc->state->event); else drm_crtc_arm_vblank_event(crtc, crtc->state->event); - spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + spin_unlock(&crtc->dev->event_lock); crtc->state->event = NULL; } + vkms_output->composer_state = to_vkms_crtc_state(crtc->state); + spin_unlock_irq(&vkms_output->lock); } static const struct drm_crtc_helper_funcs vkms_crtc_helper_funcs = { + .atomic_check = vkms_crtc_atomic_check, .atomic_begin = vkms_crtc_atomic_begin, .atomic_flush = vkms_crtc_atomic_flush, .atomic_enable = vkms_crtc_atomic_enable, @@ -220,10 +276,10 @@ int vkms_crtc_init(struct drm_device *dev, struct drm_crtc *crtc, drm_crtc_helper_add(crtc, &vkms_crtc_helper_funcs); spin_lock_init(&vkms_out->lock); - spin_lock_init(&vkms_out->state_lock); + spin_lock_init(&vkms_out->composer_lock); - vkms_out->crc_workq = alloc_ordered_workqueue("vkms_crc_workq", 0); - if (!vkms_out->crc_workq) + vkms_out->composer_workq = alloc_ordered_workqueue("vkms_composer", 0); + if (!vkms_out->composer_workq) return -ENOMEM; return ret; diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index 738dd6206d85..44ab9f8ef8be 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -10,11 +10,19 @@ */ #include <linux/module.h> -#include <drm/drm_gem.h> +#include <linux/platform_device.h> + +#include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> -#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_helper.h> +#include <drm/drm_file.h> +#include <drm/drm_gem.h> +#include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_ioctl.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> + #include "vkms_drv.h" #define DRIVER_NAME "vkms" @@ -55,7 +63,36 @@ static void vkms_release(struct drm_device *dev) drm_atomic_helper_shutdown(&vkms->drm); drm_mode_config_cleanup(&vkms->drm); drm_dev_fini(&vkms->drm); - destroy_workqueue(vkms->output.crc_workq); + destroy_workqueue(vkms->output.composer_workq); +} + +static void vkms_atomic_commit_tail(struct drm_atomic_state *old_state) +{ + struct drm_device *dev = old_state->dev; + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + int i; + + drm_atomic_helper_commit_modeset_disables(dev, old_state); + + drm_atomic_helper_commit_planes(dev, old_state, 0); + + drm_atomic_helper_commit_modeset_enables(dev, old_state); + + drm_atomic_helper_fake_vblank(old_state); + + drm_atomic_helper_commit_hw_done(old_state); + + drm_atomic_helper_wait_for_vblanks(dev, old_state); + + for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { + struct vkms_crtc_state *vkms_state = + to_vkms_crtc_state(old_crtc_state); + + flush_work(&vkms_state->composer_work); + } + + drm_atomic_helper_cleanup_planes(dev, old_state); } static struct drm_driver vkms_driver = { @@ -80,6 +117,10 @@ static const struct drm_mode_config_funcs vkms_mode_funcs = { .atomic_commit = drm_atomic_helper_commit, }; +static const struct drm_mode_config_helper_funcs vkms_mode_config_helpers = { + .atomic_commit_tail = vkms_atomic_commit_tail, +}; + static int vkms_modeset_init(struct vkms_device *vkmsdev) { struct drm_device *dev = &vkmsdev->drm; @@ -91,8 +132,9 @@ static int vkms_modeset_init(struct vkms_device *vkmsdev) dev->mode_config.max_width = XRES_MAX; dev->mode_config.max_height = YRES_MAX; dev->mode_config.preferred_depth = 24; + dev->mode_config.helper_private = &vkms_mode_config_helpers; - return vkms_output_init(vkmsdev); + return vkms_output_init(vkmsdev, 0); } static int __init vkms_init(void) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index b92c30c66a6f..5a95100fa18b 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -3,11 +3,11 @@ #ifndef _VKMS_DRV_H_ #define _VKMS_DRV_H_ -#include <drm/drmP.h> +#include <linux/hrtimer.h> + #include <drm/drm.h> #include <drm/drm_gem.h> #include <drm/drm_encoder.h> -#include <linux/hrtimer.h> #define XRES_MIN 20 #define YRES_MIN 20 @@ -20,7 +20,7 @@ extern bool enable_cursor; -struct vkms_crc_data { +struct vkms_composer { struct drm_framebuffer fb; struct drm_rect src, dst; unsigned int offset; @@ -31,23 +31,30 @@ struct vkms_crc_data { /** * vkms_plane_state - Driver specific plane state * @base: base plane state - * @crc_data: data required for CRC computation + * @composer: data required for composing computation */ struct vkms_plane_state { struct drm_plane_state base; - struct vkms_crc_data *crc_data; + struct vkms_composer *composer; }; /** * vkms_crtc_state - Driver specific CRTC state * @base: base CRTC state - * @crc_work: work struct to compute and add CRC entries + * @composer_work: work struct to compose and add CRC entries * @n_frame_start: start frame number for computed CRC * @n_frame_end: end frame number for computed CRC */ struct vkms_crtc_state { struct drm_crtc_state base; - struct work_struct crc_work; + struct work_struct composer_work; + + int num_active_planes; + /* stack of active planes for crc computation, should be in z order */ + struct vkms_plane_state **active_planes; + + /* below three are protected by vkms_output.composer_lock */ + bool crc_pending; u64 frame_start; u64 frame_end; }; @@ -59,13 +66,16 @@ struct vkms_output { struct hrtimer vblank_hrtimer; ktime_t period_ns; struct drm_pending_vblank_event *event; - bool crc_enabled; - /* ordered wq for crc_work */ - struct workqueue_struct *crc_workq; - /* protects concurrent access to crc_data */ + /* ordered wq for composer_work */ + struct workqueue_struct *composer_workq; + /* protects concurrent access to composer */ spinlock_t lock; - /* protects concurrent access to crtc_state */ - spinlock_t state_lock; + + /* protected by @lock */ + bool composer_enabled; + struct vkms_crtc_state *composer_state; + + spinlock_t composer_lock; }; struct vkms_device { @@ -105,10 +115,10 @@ bool vkms_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, int *max_error, ktime_t *vblank_time, bool in_vblank_irq); -int vkms_output_init(struct vkms_device *vkmsdev); +int vkms_output_init(struct vkms_device *vkmsdev, int index); struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev, - enum drm_plane_type type); + enum drm_plane_type type, int index); /* Gem stuff */ struct drm_gem_object *vkms_gem_create(struct drm_device *dev, @@ -133,6 +143,8 @@ const char *const *vkms_get_crc_sources(struct drm_crtc *crtc, int vkms_set_crc_source(struct drm_crtc *crtc, const char *src_name); int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, size_t *values_cnt); -void vkms_crc_work_handle(struct work_struct *work); + +/* Composer Support */ +void vkms_composer_worker(struct work_struct *work); #endif /* _VKMS_DRV_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_gem.c b/drivers/gpu/drm/vkms/vkms_gem.c index 69048e73377d..6489bfe0a149 100644 --- a/drivers/gpu/drm/vkms/vkms_gem.c +++ b/drivers/gpu/drm/vkms/vkms_gem.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0+ #include <linux/shmem_fs.h> +#include <linux/vmalloc.h> #include "vkms_drv.h" diff --git a/drivers/gpu/drm/vkms/vkms_output.c b/drivers/gpu/drm/vkms/vkms_output.c index 56fb5c2a2315..fb1941a6522c 100644 --- a/drivers/gpu/drm/vkms/vkms_output.c +++ b/drivers/gpu/drm/vkms/vkms_output.c @@ -35,7 +35,7 @@ static const struct drm_connector_helper_funcs vkms_conn_helper_funcs = { .get_modes = vkms_conn_get_modes, }; -int vkms_output_init(struct vkms_device *vkmsdev) +int vkms_output_init(struct vkms_device *vkmsdev, int index) { struct vkms_output *output = &vkmsdev->output; struct drm_device *dev = &vkmsdev->drm; @@ -45,12 +45,12 @@ int vkms_output_init(struct vkms_device *vkmsdev) struct drm_plane *primary, *cursor = NULL; int ret; - primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY); + primary = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_PRIMARY, index); if (IS_ERR(primary)) return PTR_ERR(primary); if (enable_cursor) { - cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR); + cursor = vkms_plane_init(vkmsdev, DRM_PLANE_TYPE_CURSOR, index); if (IS_ERR(cursor)) { ret = PTR_ERR(cursor); goto err_cursor; diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 0fceb6258422..5fc8f85aaf3d 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -1,10 +1,12 @@ // SPDX-License-Identifier: GPL-2.0+ -#include "vkms_drv.h" -#include <drm/drm_plane_helper.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_framebuffer_helper.h> +#include <drm/drm_plane_helper.h> + +#include "vkms_drv.h" static const u32 vkms_formats[] = { DRM_FORMAT_XRGB8888, @@ -18,20 +20,20 @@ static struct drm_plane_state * vkms_plane_duplicate_state(struct drm_plane *plane) { struct vkms_plane_state *vkms_state; - struct vkms_crc_data *crc_data; + struct vkms_composer *composer; vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL); if (!vkms_state) return NULL; - crc_data = kzalloc(sizeof(*crc_data), GFP_KERNEL); - if (!crc_data) { - DRM_DEBUG_KMS("Couldn't allocate crc_data\n"); + composer = kzalloc(sizeof(*composer), GFP_KERNEL); + if (!composer) { + DRM_DEBUG_KMS("Couldn't allocate composer\n"); kfree(vkms_state); return NULL; } - vkms_state->crc_data = crc_data; + vkms_state->composer = composer; __drm_atomic_helper_plane_duplicate_state(plane, &vkms_state->base); @@ -49,12 +51,12 @@ static void vkms_plane_destroy_state(struct drm_plane *plane, /* dropping the reference we acquired in * vkms_primary_plane_update() */ - if (drm_framebuffer_read_refcount(&vkms_state->crc_data->fb)) - drm_framebuffer_put(&vkms_state->crc_data->fb); + if (drm_framebuffer_read_refcount(&vkms_state->composer->fb)) + drm_framebuffer_put(&vkms_state->composer->fb); } - kfree(vkms_state->crc_data); - vkms_state->crc_data = NULL; + kfree(vkms_state->composer); + vkms_state->composer = NULL; __drm_atomic_helper_plane_destroy_state(old_state); kfree(vkms_state); @@ -91,21 +93,21 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, { struct vkms_plane_state *vkms_plane_state; struct drm_framebuffer *fb = plane->state->fb; - struct vkms_crc_data *crc_data; + struct vkms_composer *composer; 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->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]; + composer = vkms_plane_state->composer; + memcpy(&composer->src, &plane->state->src, sizeof(struct drm_rect)); + memcpy(&composer->dst, &plane->state->dst, sizeof(struct drm_rect)); + memcpy(&composer->fb, fb, sizeof(struct drm_framebuffer)); + drm_framebuffer_get(&composer->fb); + composer->offset = fb->offsets[0]; + composer->pitch = fb->pitches[0]; + composer->cpp = fb->format->cpp[0]; } static int vkms_plane_atomic_check(struct drm_plane *plane, @@ -176,7 +178,7 @@ static const struct drm_plane_helper_funcs vkms_primary_helper_funcs = { }; struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev, - enum drm_plane_type type) + enum drm_plane_type type, int index) { struct drm_device *dev = &vkmsdev->drm; const struct drm_plane_helper_funcs *funcs; @@ -198,7 +200,7 @@ struct drm_plane *vkms_plane_init(struct vkms_device *vkmsdev, funcs = &vkms_primary_helper_funcs; } - ret = drm_universal_plane_init(dev, plane, 0, + ret = drm_universal_plane_init(dev, plane, 1 << index, &vkms_plane_funcs, formats, nformats, NULL, type, NULL); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c index fc6673cde289..6c01ad2785dd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c @@ -459,9 +459,9 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, /* Buffer objects need to be either pinned or reserved: */ if (!(dst->mem.placement & TTM_PL_FLAG_NO_EVICT)) - lockdep_assert_held(&dst->resv->lock.base); + reservation_object_assert_held(dst->base.resv); if (!(src->mem.placement & TTM_PL_FLAG_NO_EVICT)) - lockdep_assert_held(&src->resv->lock.base); + reservation_object_assert_held(src->base.resv); if (dst->ttm->state == tt_unpopulated) { ret = dst->ttm->bdev->driver->ttm_tt_populate(dst->ttm, &ctx); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index 5d5c2bce01f3..369034c0de31 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -342,7 +342,7 @@ void vmw_bo_pin_reserved(struct vmw_buffer_object *vbo, bool pin) uint32_t old_mem_type = bo->mem.mem_type; int ret; - lockdep_assert_held(&bo->resv->lock.base); + reservation_object_assert_held(bo->base.resv); if (pin) { if (vbo->pin_count++ > 0) @@ -690,7 +690,7 @@ static int vmw_user_bo_synccpu_grab(struct vmw_user_buffer_object *user_bo, long lret; lret = reservation_object_wait_timeout_rcu - (bo->resv, true, true, + (bo->base.resv, true, true, nonblock ? 0 : MAX_SCHEDULE_TIMEOUT); if (!lret) return -EBUSY; @@ -835,7 +835,7 @@ int vmw_bo_alloc_ioctl(struct drm_device *dev, void *data, goto out_no_bo; rep->handle = handle; - rep->map_handle = drm_vma_node_offset_addr(&vbo->base.vma_node); + rep->map_handle = drm_vma_node_offset_addr(&vbo->base.base.vma_node); rep->cur_gmr_id = handle; rep->cur_gmr_offset = 0; @@ -1007,10 +1007,10 @@ void vmw_bo_fence_single(struct ttm_buffer_object *bo, if (fence == NULL) { vmw_execbuf_fence_commands(NULL, dev_priv, &fence, NULL); - reservation_object_add_excl_fence(bo->resv, &fence->base); + reservation_object_add_excl_fence(bo->base.resv, &fence->base); dma_fence_put(&fence->base); } else - reservation_object_add_excl_fence(bo->resv, &fence->base); + reservation_object_add_excl_fence(bo->base.resv, &fence->base); } @@ -1077,7 +1077,7 @@ int vmw_dumb_map_offset(struct drm_file *file_priv, if (ret != 0) return -EINVAL; - *offset = drm_vma_node_offset_addr(&out_buf->base.vma_node); + *offset = drm_vma_node_offset_addr(&out_buf->base.base.vma_node); vmw_bo_unreference(&out_buf); return 0; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c index b4f6e1217c9d..7984f172ec4a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c @@ -169,7 +169,7 @@ static int vmw_cotable_unscrub(struct vmw_resource *res) } *cmd; WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB); - lockdep_assert_held(&bo->resv->lock.base); + reservation_object_assert_held(bo->base.resv); cmd = VMW_FIFO_RESERVE(dev_priv, sizeof(*cmd)); if (!cmd) @@ -311,7 +311,7 @@ static int vmw_cotable_unbind(struct vmw_resource *res, return 0; WARN_ON_ONCE(bo->mem.mem_type != VMW_PL_MOB); - lockdep_assert_held(&bo->resv->lock.base); + reservation_object_assert_held(bo->base.resv); mutex_lock(&dev_priv->binding_mutex); if (!vcotbl->scrubbed) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 9506190a0300..cd0d49d8a8da 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -186,7 +186,7 @@ static const struct drm_ioctl_desc vmw_ioctls[] = { DRM_RENDER_ALLOW), VMW_IOCTL_DEF(VMW_REF_SURFACE, vmw_surface_reference_ioctl, DRM_AUTH | DRM_RENDER_ALLOW), - VMW_IOCTL_DEF(VMW_EXECBUF, NULL, DRM_AUTH | + VMW_IOCTL_DEF(VMW_EXECBUF, vmw_execbuf_ioctl, DRM_AUTH | DRM_RENDER_ALLOW), VMW_IOCTL_DEF(VMW_FENCE_WAIT, vmw_fence_obj_wait_ioctl, DRM_RENDER_ALLOW), @@ -641,7 +641,6 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) INIT_LIST_HEAD(&dev_priv->res_lru[i]); } - mutex_init(&dev_priv->init_mutex); init_waitqueue_head(&dev_priv->fence_queue); init_waitqueue_head(&dev_priv->fifo_queue); dev_priv->fence_queue_waiters = 0; @@ -1121,15 +1120,7 @@ static long vmw_generic_ioctl(struct file *filp, unsigned int cmd, &vmw_ioctls[nr - DRM_COMMAND_BASE]; if (nr == DRM_COMMAND_BASE + DRM_VMW_EXECBUF) { - ret = (long) drm_ioctl_permit(ioctl->flags, file_priv); - if (unlikely(ret != 0)) - return ret; - - if (unlikely((cmd & (IOC_IN | IOC_OUT)) != IOC_IN)) - goto out_io_encoding; - - return (long) vmw_execbuf_ioctl(dev, arg, file_priv, - _IOC_SIZE(cmd)); + return ioctl_func(filp, cmd, arg); } else if (nr == DRM_COMMAND_BASE + DRM_VMW_UPDATE_LAYOUT) { if (!drm_is_current_master(file_priv) && !capable(CAP_SYS_ADMIN)) @@ -1180,10 +1171,6 @@ static long vmw_compat_ioctl(struct file *filp, unsigned int cmd, } #endif -static void vmw_lastclose(struct drm_device *dev) -{ -} - static void vmw_master_init(struct vmw_master *vmaster) { ttm_lock_init(&vmaster->lock); @@ -1551,10 +1538,9 @@ static const struct file_operations vmwgfx_driver_fops = { static struct drm_driver driver = { .driver_features = - DRIVER_MODESET | DRIVER_PRIME | DRIVER_RENDER | DRIVER_ATOMIC, + DRIVER_MODESET | DRIVER_RENDER | DRIVER_ATOMIC, .load = vmw_driver_load, .unload = vmw_driver_unload, - .lastclose = vmw_lastclose, .get_vblank_counter = vmw_get_vblank_counter, .enable_vblank = vmw_enable_vblank, .disable_vblank = vmw_disable_vblank, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 366dcfc1f9bb..dbb04dbcf478 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -484,11 +484,6 @@ struct vmw_private { spinlock_t resource_lock; struct idr res_idr[vmw_res_max]; - /* - * Block lastclose from racing with firstopen. - */ - - struct mutex init_mutex; /* * A resource manager for kernel-only surfaces and @@ -915,8 +910,8 @@ static inline struct page *vmw_piter_page(struct vmw_piter *viter) * Command submission - vmwgfx_execbuf.c */ -extern int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data, - struct drm_file *file_priv, size_t size); +extern int vmw_execbuf_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int vmw_execbuf_process(struct drm_file *file_priv, struct vmw_private *dev_priv, void __user *user_commands, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 33533d126277..ff86d49dc5e8 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -3995,54 +3995,40 @@ void vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv) mutex_unlock(&dev_priv->cmdbuf_mutex); } -int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data, - struct drm_file *file_priv, size_t size) +int vmw_execbuf_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { struct vmw_private *dev_priv = vmw_priv(dev); - struct drm_vmw_execbuf_arg arg; + struct drm_vmw_execbuf_arg *arg = data; int ret; - static const size_t copy_offset[] = { - offsetof(struct drm_vmw_execbuf_arg, context_handle), - sizeof(struct drm_vmw_execbuf_arg)}; struct dma_fence *in_fence = NULL; - if (unlikely(size < copy_offset[0])) { - VMW_DEBUG_USER("Invalid command size, ioctl %d\n", - DRM_VMW_EXECBUF); - return -EINVAL; - } - - if (copy_from_user(&arg, (void __user *) data, copy_offset[0]) != 0) - return -EFAULT; - /* * Extend the ioctl argument while maintaining backwards compatibility: - * We take different code paths depending on the value of arg.version. + * We take different code paths depending on the value of arg->version. + * + * Note: The ioctl argument is extended and zeropadded by core DRM. */ - if (unlikely(arg.version > DRM_VMW_EXECBUF_VERSION || - arg.version == 0)) { + if (unlikely(arg->version > DRM_VMW_EXECBUF_VERSION || + arg->version == 0)) { VMW_DEBUG_USER("Incorrect execbuf version.\n"); return -EINVAL; } - if (arg.version > 1 && - copy_from_user(&arg.context_handle, - (void __user *) (data + copy_offset[0]), - copy_offset[arg.version - 1] - copy_offset[0]) != 0) - return -EFAULT; - - switch (arg.version) { + switch (arg->version) { case 1: - arg.context_handle = (uint32_t) -1; + /* For v1 core DRM have extended + zeropadded the data */ + arg->context_handle = (uint32_t) -1; break; case 2: default: + /* For v2 and later core DRM would have correctly copied it */ break; } /* If imported a fence FD from elsewhere, then wait on it */ - if (arg.flags & DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD) { - in_fence = sync_file_get_fence(arg.imported_fence_fd); + if (arg->flags & DRM_VMW_EXECBUF_FLAG_IMPORT_FENCE_FD) { + in_fence = sync_file_get_fence(arg->imported_fence_fd); if (!in_fence) { VMW_DEBUG_USER("Cannot get imported fence\n"); @@ -4059,11 +4045,11 @@ int vmw_execbuf_ioctl(struct drm_device *dev, unsigned long data, return ret; ret = vmw_execbuf_process(file_priv, dev_priv, - (void __user *)(unsigned long)arg.commands, - NULL, arg.command_size, arg.throttle_us, - arg.context_handle, - (void __user *)(unsigned long)arg.fence_rep, - NULL, arg.flags); + (void __user *)(unsigned long)arg->commands, + NULL, arg->command_size, arg->throttle_us, + arg->context_handle, + (void __user *)(unsigned long)arg->fence_rep, + NULL, arg->flags); ttm_read_unlock(&dev_priv->reservation_sem); if (unlikely(ret != 0)) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b97bc8e5944b..34284f0f5084 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -1704,14 +1704,6 @@ vmw_kms_atomic_check_modeset(struct drm_device *dev, if (ret) return ret; - if (!state->allow_modeset) - return ret; - - /* - * Legacy path do not set allow_modeset properly like - * @drm_atomic_helper_update_plane, This will result in unnecessary call - * to vmw_kms_check_topology. So extra set of check. - */ for_each_new_crtc_in_state(state, crtc, crtc_state, i) { if (drm_atomic_crtc_needs_modeset(crtc_state)) need_modeset = true; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 1d38a8b2f2ec..701643b7b0c4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -402,14 +402,14 @@ void vmw_resource_unreserve(struct vmw_resource *res, if (switch_backup && new_backup != res->backup) { if (res->backup) { - lockdep_assert_held(&res->backup->base.resv->lock.base); + reservation_object_assert_held(res->backup->base.base.resv); list_del_init(&res->mob_head); vmw_bo_unreference(&res->backup); } if (new_backup) { res->backup = vmw_bo_reference(new_backup); - lockdep_assert_held(&new_backup->base.resv->lock.base); + reservation_object_assert_held(new_backup->base.base.resv); list_add_tail(&res->mob_head, &new_backup->res_list); } else { res->backup = NULL; @@ -691,7 +691,7 @@ void vmw_resource_unbind_list(struct vmw_buffer_object *vbo) .num_shared = 0 }; - lockdep_assert_held(&vbo->base.resv->lock.base); + reservation_object_assert_held(vbo->base.base.resv); list_for_each_entry_safe(res, next, &vbo->res_list, mob_head) { if (!res->func->unbind) continue; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index 219471903bc1..3a6da3b66484 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c @@ -1669,7 +1669,7 @@ vmw_gb_surface_define_internal(struct drm_device *dev, rep->backup_size = res->backup_size; if (res->backup) { rep->buffer_map_handle = - drm_vma_node_offset_addr(&res->backup->base.vma_node); + drm_vma_node_offset_addr(&res->backup->base.base.vma_node); rep->buffer_size = res->backup->base.num_pages * PAGE_SIZE; rep->buffer_handle = backup_handle; } else { @@ -1745,7 +1745,7 @@ vmw_gb_surface_reference_internal(struct drm_device *dev, rep->crep.backup_size = srf->res.backup_size; rep->crep.buffer_handle = backup_handle; rep->crep.buffer_map_handle = - drm_vma_node_offset_addr(&srf->res.backup->base.vma_node); + drm_vma_node_offset_addr(&srf->res.backup->base.base.vma_node); rep->crep.buffer_size = srf->res.backup->base.num_pages * PAGE_SIZE; rep->creq.version = drm_vmw_gb_surface_v1; diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 84aa4d61dc42..ba1828acd8c9 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -8,13 +8,18 @@ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> */ -#include <drm/drmP.h> +#include <linux/delay.h> +#include <linux/dma-mapping.h> +#include <linux/module.h> +#include <linux/of_device.h> + #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_ioctl.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_file.h> #include <drm/drm_gem.h> -#include <linux/of_device.h> - #include <xen/platform_pci.h> #include <xen/xen.h> #include <xen/xenbus.h> @@ -485,15 +490,12 @@ static const struct vm_operations_struct xen_drm_drv_vm_ops = { }; static struct drm_driver xen_drm_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | - DRIVER_PRIME | DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .release = xen_drm_drv_release, .gem_vm_ops = &xen_drm_drv_vm_ops, .gem_free_object_unlocked = xen_drm_drv_free_object_unlocked, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_import = drm_gem_prime_import, - .gem_prime_export = drm_gem_prime_export, .gem_prime_import_sg_table = xen_drm_front_gem_import_sg_table, .gem_prime_get_sg_table = xen_drm_front_gem_get_sg_table, .gem_prime_vmap = xen_drm_front_gem_prime_vmap, diff --git a/drivers/gpu/drm/xen/xen_drm_front.h b/drivers/gpu/drm/xen/xen_drm_front.h index 5693b4a4b02b..f92c258350ca 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.h +++ b/drivers/gpu/drm/xen/xen_drm_front.h @@ -11,13 +11,18 @@ #ifndef __XEN_DRM_FRONT_H_ #define __XEN_DRM_FRONT_H_ -#include <drm/drmP.h> -#include <drm/drm_simple_kms_helper.h> - #include <linux/scatterlist.h> +#include <drm/drm_connector.h> +#include <drm/drm_simple_kms_helper.h> + #include "xen_drm_front_cfg.h" +struct drm_device; +struct drm_framebuffer; +struct drm_gem_object; +struct drm_pending_vblank_event; + /** * DOC: Driver modes of operation in terms of display buffers used * diff --git a/drivers/gpu/drm/xen/xen_drm_front_cfg.c b/drivers/gpu/drm/xen/xen_drm_front_cfg.c index 5baf2b9de93c..ec53b9cc9e0e 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_cfg.c +++ b/drivers/gpu/drm/xen/xen_drm_front_cfg.c @@ -8,10 +8,10 @@ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> */ -#include <drm/drmP.h> - #include <linux/device.h> +#include <drm/drm_print.h> + #include <xen/interface/io/displif.h> #include <xen/xenbus.h> diff --git a/drivers/gpu/drm/xen/xen_drm_front_conn.c b/drivers/gpu/drm/xen/xen_drm_front_conn.c index 9f5f31f77f1e..459702fa990e 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_conn.c +++ b/drivers/gpu/drm/xen/xen_drm_front_conn.c @@ -9,6 +9,7 @@ */ #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> #include <drm/drm_probe_helper.h> #include <video/videomode.h> diff --git a/drivers/gpu/drm/xen/xen_drm_front_conn.h b/drivers/gpu/drm/xen/xen_drm_front_conn.h index 39de7cf5adbe..3adacba9a23b 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_conn.h +++ b/drivers/gpu/drm/xen/xen_drm_front_conn.h @@ -11,11 +11,10 @@ #ifndef __XEN_DRM_FRONT_CONN_H_ #define __XEN_DRM_FRONT_CONN_H_ -#include <drm/drmP.h> -#include <drm/drm_crtc.h> -#include <drm/drm_encoder.h> +#include <linux/types.h> -#include <linux/wait.h> +struct drm_connector; +struct xen_drm_front_drm_info; struct xen_drm_front_drm_info; diff --git a/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c b/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c index 945226a95e9b..e10d95dddb99 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c +++ b/drivers/gpu/drm/xen/xen_drm_front_evtchnl.c @@ -8,11 +8,11 @@ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> */ -#include <drm/drmP.h> - #include <linux/errno.h> #include <linux/irq.h> +#include <drm/drm_print.h> + #include <xen/xenbus.h> #include <xen/events.h> #include <xen/grant_table.h> diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.c b/drivers/gpu/drm/xen/xen_drm_front_gem.c index a24548489dde..f0b85e094111 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.c +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.c @@ -8,20 +8,19 @@ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> */ -#include "xen_drm_front_gem.h" +#include <linux/dma-buf.h> +#include <linux/scatterlist.h> +#include <linux/shmem_fs.h> -#include <drm/drmP.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem.h> +#include <drm/drm_prime.h> #include <drm/drm_probe_helper.h> -#include <linux/dma-buf.h> -#include <linux/scatterlist.h> -#include <linux/shmem_fs.h> - #include <xen/balloon.h> #include "xen_drm_front.h" +#include "xen_drm_front_gem.h" struct xen_gem_object { struct drm_gem_object base; diff --git a/drivers/gpu/drm/xen/xen_drm_front_gem.h b/drivers/gpu/drm/xen/xen_drm_front_gem.h index d5ab734fdafe..a39675fa31b2 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_gem.h +++ b/drivers/gpu/drm/xen/xen_drm_front_gem.h @@ -11,7 +11,12 @@ #ifndef __XEN_DRM_FRONT_GEM_H #define __XEN_DRM_FRONT_GEM_H -#include <drm/drmP.h> +struct dma_buf_attachment; +struct drm_device; +struct drm_gem_object; +struct file; +struct sg_table; +struct vm_area_struct; struct drm_gem_object *xen_drm_front_gem_create(struct drm_device *dev, size_t size); diff --git a/drivers/gpu/drm/xen/xen_drm_front_kms.c b/drivers/gpu/drm/xen/xen_drm_front_kms.c index c2955d375394..de990036199d 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_kms.c +++ b/drivers/gpu/drm/xen/xen_drm_front_kms.c @@ -8,17 +8,18 @@ * Author: Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com> */ -#include "xen_drm_front_kms.h" - -#include <drm/drmP.h> #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_drv.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_probe_helper.h> +#include <drm/drm_vblank.h> #include "xen_drm_front.h" #include "xen_drm_front_conn.h" +#include "xen_drm_front_kms.h" /* * Timeout in ms to wait for frame done event from the backend: diff --git a/drivers/gpu/drm/zte/zx_drm_drv.c b/drivers/gpu/drm/zte/zx_drm_drv.c index 520d7369f85a..1141c1ed1ed0 100644 --- a/drivers/gpu/drm/zte/zx_drm_drv.c +++ b/drivers/gpu/drm/zte/zx_drm_drv.c @@ -14,13 +14,14 @@ #include <drm/drm_atomic_helper.h> #include <drm/drm_crtc.h> +#include <drm/drm_drv.h> #include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_helper.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_framebuffer_helper.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> +#include <drm/drm_vblank.h> #include "zx_drm_drv.h" #include "zx_vou.h" @@ -34,15 +35,12 @@ static const struct drm_mode_config_funcs zx_drm_mode_config_funcs = { DEFINE_DRM_GEM_CMA_FOPS(zx_drm_fops); static struct drm_driver zx_drm_driver = { - .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME | - DRIVER_ATOMIC, + .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC, .gem_free_object_unlocked = drm_gem_cma_free_object, .gem_vm_ops = &drm_gem_cma_vm_ops, .dumb_create = drm_gem_cma_dumb_create, .prime_handle_to_fd = drm_gem_prime_handle_to_fd, .prime_fd_to_handle = drm_gem_prime_fd_to_handle, - .gem_prime_export = drm_gem_prime_export, - .gem_prime_import = drm_gem_prime_import, .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table, .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table, .gem_prime_vmap = drm_gem_cma_prime_vmap, diff --git a/drivers/gpu/drm/zte/zx_hdmi.c b/drivers/gpu/drm/zte/zx_hdmi.c index bfe918b27c5c..a50f5a1f09b8 100644 --- a/drivers/gpu/drm/zte/zx_hdmi.c +++ b/drivers/gpu/drm/zte/zx_hdmi.c @@ -19,7 +19,7 @@ #include <drm/drm_edid.h> #include <drm/drm_of.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> +#include <drm/drm_print.h> #include <sound/hdmi-codec.h> diff --git a/drivers/gpu/drm/zte/zx_plane.c b/drivers/gpu/drm/zte/zx_plane.c index 6b812aad411b..086c50fac689 100644 --- a/drivers/gpu/drm/zte/zx_plane.c +++ b/drivers/gpu/drm/zte/zx_plane.c @@ -7,10 +7,10 @@ #include <drm/drm_atomic.h> #include <drm/drm_atomic_helper.h> #include <drm/drm_fb_cma_helper.h> +#include <drm/drm_fourcc.h> #include <drm/drm_gem_cma_helper.h> #include <drm/drm_modeset_helper_vtables.h> #include <drm/drm_plane_helper.h> -#include <drm/drmP.h> #include "zx_common_regs.h" #include "zx_drm_drv.h" diff --git a/drivers/gpu/drm/zte/zx_tvenc.c b/drivers/gpu/drm/zte/zx_tvenc.c index a768c567b557..c598b7daf1f1 100644 --- a/drivers/gpu/drm/zte/zx_tvenc.c +++ b/drivers/gpu/drm/zte/zx_tvenc.c @@ -7,11 +7,13 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> #include "zx_drm_drv.h" #include "zx_tvenc_regs.h" diff --git a/drivers/gpu/drm/zte/zx_vga.c b/drivers/gpu/drm/zte/zx_vga.c index 1634a08707fb..9b67e419280c 100644 --- a/drivers/gpu/drm/zte/zx_vga.c +++ b/drivers/gpu/drm/zte/zx_vga.c @@ -7,11 +7,13 @@ #include <linux/clk.h> #include <linux/component.h> #include <linux/mfd/syscon.h> +#include <linux/module.h> +#include <linux/platform_device.h> #include <linux/regmap.h> #include <drm/drm_atomic_helper.h> +#include <drm/drm_print.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> #include "zx_drm_drv.h" #include "zx_vga_regs.h" diff --git a/drivers/gpu/drm/zte/zx_vou.c b/drivers/gpu/drm/zte/zx_vou.c index 81b4cf107b75..5259ff2825f9 100644 --- a/drivers/gpu/drm/zte/zx_vou.c +++ b/drivers/gpu/drm/zte/zx_vou.c @@ -6,7 +6,10 @@ #include <linux/clk.h> #include <linux/component.h> +#include <linux/module.h> #include <linux/of_address.h> +#include <linux/platform_device.h> + #include <video/videomode.h> #include <drm/drm_atomic_helper.h> @@ -17,7 +20,7 @@ #include <drm/drm_of.h> #include <drm/drm_plane_helper.h> #include <drm/drm_probe_helper.h> -#include <drm/drmP.h> +#include <drm/drm_vblank.h> #include "zx_common_regs.h" #include "zx_drm_drv.h" |