mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-21 13:24:15 +08:00
drm-misc-next for v6.1:
UAPI Changes: Cross-subsystem Changes: - DMA-buf: documentation updates. - Assorted small fixes to vga16fb - Fix fbdev drivers to use the aperture helpers. - Make removal of conflicting drivers work correctly without fbdev enabled. Core Changes: - bridge, scheduler, dp-mst: Assorted small fixes. - Add more format helpers to fourcc, and use it to replace the cpp usage. - Add DRM_FORMAT_Cxx, DRM_FORMAT_Rxx (single channel), and DRM_FORMAT_Dxx ("darkness", inverted single channel) - Add packed AYUV8888 and XYUV8888 formats. - Assorted documentation updates. - Rename ttm_bo_init to ttm_bo_init_validate. - Allow TTM bo's to exist without backing store. - Convert drm selftests to kunit. - Add managed init functions for (panel) bridge, crtc, encoder and connector. - Fix endianness handling in various format conversion helpers. - Make tests pass on big-endian platforms, and add test for rgb888 -> rgb565 - Move DRM_PLANE_HELPER_NO_SCALING to atomic helpers and rename, so drm_plane_helper is no longer needed in most drivers. - Use idr_init_base instead of idr_init. - Rename FB and GEM CMA helpers to DMA helpers. - Rework XRGB8888 related conversion helpers, and add drm_fb_blit() that takes a iosys_map. Make drm_fb_memcpy take an iosys_map too. - Move edid luminance calculation to core, and use it in i915. Driver Changes: - bridge/{adv7511,ti-sn65dsi86,parade-ps8640}, panel/{simple,nt35510,tc358767}, nouveau, sun4i, mipi-dsi, mgag200, bochs, arm, komeda, vmwgfx, pl111: Assorted small fixes and doc updates. - vc4: Rework hdmi power up, and depend on PM. - panel/simple: Add Samsung LTL101AL01. - ingenic: Add JZ4760(B) support, avoid a modeset when sharpness property is unchanged, and use the new PM ops. - Revert some amdgpu commits that cause garbaged graphics when starting X, and reapply them with the real problem fixed. - Completely rework vc4 init to use managed helpers. - Rename via_drv to via_dri1, and move all stuff there only used by the dri1 implementation in preperation for atomic modeset. - Use regmap bulk write in ssd130x. - Power sequence and clock updates to it6505. - Split panel-sitrox-st7701 init sequence and rework mode programming code. - virtio: Improve error and edge conditions handling, and convert to use managed helpers. - Add Samsung LTL101AL01, B120XAN01.0, R140NWF5 RH, DMT028VGHMCMI-1A T, panels. - Add generic fbdev support to komeda. - Split mgag200 modeset handling to make it more model-specific. - Convert simpledrm to use atomic helpers. - Improve udl suspend/disconnect handling. -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEuXvWqAysSYEJGuVH/lWMcqZwE8MFAmMA59MACgkQ/lWMcqZw E8MBihAAtttSIF8fvRIgnoFeswteB5HlXtrSOVRns+0h7mNzcmUL3yp/jV9betND NEfBCERRIRk5vqkzm2o9P/rTG+KMYCyyCNdcvvh+rVn+HU2V9MwtJdowZqLu7Rxi Qn59SaL6fMQanJwF8yHcii1ikqelU8TfsMXcFXt2d/yjn5D/h80tNOULEB74zIDH Vey/xTawcqEz3Qbj2mL4VihEnzU1cziGTpZvAWU2GTdWLxxN88uA4RD2JDyvGaXG oO6oilYT9TW+2C+0jfMUysu7RcNYuo4KD8dSVLvec+UKDKdO1pSqn40vgTZp0MBw V0VGg/Lqg6+u33UQkxeRpdzTboD4cMjoeP0/IJdHQVMYYH449tXDgZEjXqVHdz2c Ea8JIm36CHjqA0Ua3DT8y1qRtdrjuATJauoB6MXW8RpguqMzVuI4e9Dio77WRNYe Lg/V5AlQEKcwxeqe6v+8K7aB4lvHZ9g0WSMFHoxYz28d2cFWDVeKgK/GCW3WWMKo AQigRS84z3QBqK+IeTjbfZREoRFtx7NzQpzU9jQdL06XGWExhGOs8yU2OCoDNN8+ iFMBStEPHLPg27HrLV5JYeMRUBPJMnwQhAEnrSv9KqIfPD3/g2jonoGm3J57p+OI Ag7pwg88spzP1DC7M6+UvzUnH76Dhf4hdnfQjz10c6BfS1ODPbA= =kU/l -----END PGP SIGNATURE----- Merge tag 'drm-misc-next-2022-08-20-1' of git://anongit.freedesktop.org/drm/drm-misc into drm-next drm-misc-next for v6.1: UAPI Changes: Cross-subsystem Changes: - DMA-buf: documentation updates. - Assorted small fixes to vga16fb - Fix fbdev drivers to use the aperture helpers. - Make removal of conflicting drivers work correctly without fbdev enabled. Core Changes: - bridge, scheduler, dp-mst: Assorted small fixes. - Add more format helpers to fourcc, and use it to replace the cpp usage. - Add DRM_FORMAT_Cxx, DRM_FORMAT_Rxx (single channel), and DRM_FORMAT_Dxx ("darkness", inverted single channel) - Add packed AYUV8888 and XYUV8888 formats. - Assorted documentation updates. - Rename ttm_bo_init to ttm_bo_init_validate. - Allow TTM bo's to exist without backing store. - Convert drm selftests to kunit. - Add managed init functions for (panel) bridge, crtc, encoder and connector. - Fix endianness handling in various format conversion helpers. - Make tests pass on big-endian platforms, and add test for rgb888 -> rgb565 - Move DRM_PLANE_HELPER_NO_SCALING to atomic helpers and rename, so drm_plane_helper is no longer needed in most drivers. - Use idr_init_base instead of idr_init. - Rename FB and GEM CMA helpers to DMA helpers. - Rework XRGB8888 related conversion helpers, and add drm_fb_blit() that takes a iosys_map. Make drm_fb_memcpy take an iosys_map too. - Move edid luminance calculation to core, and use it in i915. Driver Changes: - bridge/{adv7511,ti-sn65dsi86,parade-ps8640}, panel/{simple,nt35510,tc358767}, nouveau, sun4i, mipi-dsi, mgag200, bochs, arm, komeda, vmwgfx, pl111: Assorted small fixes and doc updates. - vc4: Rework hdmi power up, and depend on PM. - panel/simple: Add Samsung LTL101AL01. - ingenic: Add JZ4760(B) support, avoid a modeset when sharpness property is unchanged, and use the new PM ops. - Revert some amdgpu commits that cause garbaged graphics when starting X, and reapply them with the real problem fixed. - Completely rework vc4 init to use managed helpers. - Rename via_drv to via_dri1, and move all stuff there only used by the dri1 implementation in preperation for atomic modeset. - Use regmap bulk write in ssd130x. - Power sequence and clock updates to it6505. - Split panel-sitrox-st7701 init sequence and rework mode programming code. - virtio: Improve error and edge conditions handling, and convert to use managed helpers. - Add Samsung LTL101AL01, B120XAN01.0, R140NWF5 RH, DMT028VGHMCMI-1A T, panels. - Add generic fbdev support to komeda. - Split mgag200 modeset handling to make it more model-specific. - Convert simpledrm to use atomic helpers. - Improve udl suspend/disconnect handling. Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch> From: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/f0c71766-61e8-19b7-763a-5fbcdefc633d@linux.intel.com
This commit is contained in:
commit
8284bae723
@ -17,6 +17,8 @@ properties:
|
||||
enum:
|
||||
- ingenic,jz4740-lcd
|
||||
- ingenic,jz4725b-lcd
|
||||
- ingenic,jz4760-lcd
|
||||
- ingenic,jz4760b-lcd
|
||||
- ingenic,jz4770-lcd
|
||||
- ingenic,jz4780-lcd
|
||||
|
||||
|
@ -280,6 +280,8 @@ properties:
|
||||
- samsung,atna33xc20
|
||||
# Samsung 12.2" (2560x1600 pixels) TFT LCD panel
|
||||
- samsung,lsn122dl01-c01
|
||||
# Samsung Electronics 10.1" WXGA (1280x800) TFT LCD panel
|
||||
- samsung,ltl101al01
|
||||
# Samsung Electronics 10.1" WSVGA TFT LCD panel
|
||||
- samsung,ltn101nt05
|
||||
# Samsung Electronics 14" WXGA (1366x768) TFT LCD panel
|
||||
|
@ -17,6 +17,9 @@ description: |
|
||||
Techstar TS8550B is 480x854, 2-lane MIPI DSI LCD panel which has
|
||||
inbuilt ST7701 chip.
|
||||
|
||||
Densitron DMT028VGHMCMI-1A is 480x640, 2-lane MIPI DSI LCD panel
|
||||
which has built-in ST7701 chip.
|
||||
|
||||
allOf:
|
||||
- $ref: panel-common.yaml#
|
||||
|
||||
@ -24,6 +27,7 @@ properties:
|
||||
compatible:
|
||||
items:
|
||||
- enum:
|
||||
- densitron,dmt028vghmcmi-1a
|
||||
- techstar,ts8550b
|
||||
- const: sitronix,st7701
|
||||
|
||||
|
@ -122,13 +122,13 @@ format Helper Functions Reference
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_format_helper.c
|
||||
:export:
|
||||
|
||||
Framebuffer CMA Helper Functions Reference
|
||||
Framebuffer DMA Helper Functions Reference
|
||||
==========================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
|
||||
:doc: framebuffer cma helper functions
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c
|
||||
:doc: framebuffer dma helper functions
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_cma_helper.c
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_fb_dma_helper.c
|
||||
:export:
|
||||
|
||||
Framebuffer GEM Helper Reference
|
||||
|
@ -300,12 +300,12 @@ Drivers that want to map the GEM object upfront instead of handling page
|
||||
faults can implement their own mmap file operation handler.
|
||||
|
||||
For platforms without MMU the GEM core provides a helper method
|
||||
drm_gem_cma_get_unmapped_area(). The mmap() routines will call this to get a
|
||||
drm_gem_dma_get_unmapped_area(). The mmap() routines will call this to get a
|
||||
proposed address for the mapping.
|
||||
|
||||
To use drm_gem_cma_get_unmapped_area(), drivers must fill the struct
|
||||
To use drm_gem_dma_get_unmapped_area(), drivers must fill the struct
|
||||
:c:type:`struct file_operations <file_operations>` get_unmapped_area field with
|
||||
a pointer on drm_gem_cma_get_unmapped_area().
|
||||
a pointer on drm_gem_dma_get_unmapped_area().
|
||||
|
||||
More detailed information about get_unmapped_area can be found in
|
||||
Documentation/admin-guide/mm/nommu-mmap.rst
|
||||
@ -355,16 +355,16 @@ GEM Function Reference
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem.c
|
||||
:export:
|
||||
|
||||
GEM CMA Helper Functions Reference
|
||||
GEM DMA Helper Functions Reference
|
||||
----------------------------------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
:doc: cma helpers
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c
|
||||
:doc: dma helpers
|
||||
|
||||
.. kernel-doc:: include/drm/drm_gem_cma_helper.h
|
||||
.. kernel-doc:: include/drm/drm_gem_dma_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_cma_helper.c
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_gem_dma_helper.c
|
||||
:export:
|
||||
|
||||
GEM SHMEM Helper Function Reference
|
||||
|
@ -322,18 +322,6 @@ Contact: Daniel Vetter, Noralf Tronnes
|
||||
|
||||
Level: Advanced
|
||||
|
||||
idr_init_base()
|
||||
---------------
|
||||
|
||||
DRM core&drivers uses a lot of idr (integer lookup directories) for mapping
|
||||
userspace IDs to internal objects, and in most places ID=0 means NULL and hence
|
||||
is never used. Switching to idr_init_base() for these would make the idr more
|
||||
efficient.
|
||||
|
||||
Contact: Daniel Vetter
|
||||
|
||||
Level: Starter
|
||||
|
||||
struct drm_gem_object_funcs
|
||||
---------------------------
|
||||
|
||||
@ -343,19 +331,6 @@ converted, except for struct drm_driver.gem_prime_mmap.
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Rename CMA helpers to DMA helpers
|
||||
---------------------------------
|
||||
|
||||
CMA (standing for contiguous memory allocator) is really a bit an accident of
|
||||
what these were used for first, a much better name would be DMA helpers. In the
|
||||
text these should even be called coherent DMA memory helpers (so maybe CDM, but
|
||||
no one knows what that means) since underneath they just use dma_alloc_coherent.
|
||||
|
||||
Contact: Laurent Pinchart, Daniel Vetter
|
||||
|
||||
Level: Intermediate (mostly because it is a huge tasks without good partial
|
||||
milestones, not technically itself that challenging)
|
||||
|
||||
connector register/unregister fixes
|
||||
-----------------------------------
|
||||
|
||||
@ -617,17 +592,6 @@ Contact: Javier Martinez Canillas <javierm@redhat.com>
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Convert Kernel Selftests (kselftest) to KUnit tests when appropriate
|
||||
--------------------------------------------------------------------
|
||||
|
||||
Many of the `Kselftest <https://www.kernel.org/doc/html/latest/dev-tools/kselftest.html>`_
|
||||
tests in DRM could be converted to Kunit tests instead, since that framework
|
||||
is more suitable for unit testing.
|
||||
|
||||
Contact: Javier Martinez Canillas <javierm@redhat.com>
|
||||
|
||||
Level: Starter
|
||||
|
||||
Enable trinity for DRM
|
||||
----------------------
|
||||
|
||||
|
@ -132,7 +132,7 @@ EXPORT_SYMBOL(sync_file_get_fence);
|
||||
char *sync_file_get_name(struct sync_file *sync_file, char *buf, int len)
|
||||
{
|
||||
if (sync_file->user_name[0]) {
|
||||
strlcpy(buf, sync_file->user_name, len);
|
||||
strscpy(buf, sync_file->user_name, len);
|
||||
} else {
|
||||
struct dma_fence *fence = sync_file->fence;
|
||||
|
||||
@ -172,7 +172,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
|
||||
return NULL;
|
||||
}
|
||||
sync_file->fence = fence;
|
||||
strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
|
||||
strscpy(sync_file->user_name, name, sizeof(sync_file->user_name));
|
||||
return sync_file;
|
||||
}
|
||||
|
||||
@ -262,9 +262,9 @@ err_put_fd:
|
||||
static int sync_fill_fence_info(struct dma_fence *fence,
|
||||
struct sync_fence_info *info)
|
||||
{
|
||||
strlcpy(info->obj_name, fence->ops->get_timeline_name(fence),
|
||||
strscpy(info->obj_name, fence->ops->get_timeline_name(fence),
|
||||
sizeof(info->obj_name));
|
||||
strlcpy(info->driver_name, fence->ops->get_driver_name(fence),
|
||||
strscpy(info->driver_name, fence->ops->get_driver_name(fence),
|
||||
sizeof(info->driver_name));
|
||||
|
||||
info->status = dma_fence_get_status(fence);
|
||||
|
@ -94,6 +94,10 @@ static __init int sysfb_init(void)
|
||||
name = "efi-framebuffer";
|
||||
else if (si->orig_video_isVGA == VIDEO_TYPE_VLFB)
|
||||
name = "vesa-framebuffer";
|
||||
else if (si->orig_video_isVGA == VIDEO_TYPE_VGAC)
|
||||
name = "vga-framebuffer";
|
||||
else if (si->orig_video_isVGA == VIDEO_TYPE_EGAC)
|
||||
name = "ega-framebuffer";
|
||||
else
|
||||
name = "platform-framebuffer";
|
||||
|
||||
|
@ -50,10 +50,9 @@ config DRM_DEBUG_MM
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_DEBUG_SELFTEST
|
||||
tristate "kselftests for DRM"
|
||||
depends on DRM
|
||||
depends on DEBUG_KERNEL
|
||||
config DRM_KUNIT_TEST
|
||||
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
|
||||
depends on DRM && KUNIT
|
||||
select PRIME_NUMBERS
|
||||
select DRM_DISPLAY_DP_HELPER
|
||||
select DRM_DISPLAY_HELPER
|
||||
@ -61,19 +60,6 @@ config DRM_DEBUG_SELFTEST
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_BUDDY
|
||||
select DRM_EXPORT_FOR_TESTS if m
|
||||
default n
|
||||
help
|
||||
This option provides kernel modules that can be used to run
|
||||
various selftests on parts of the DRM api. This option is not
|
||||
useful for distributions or general kernels, but only for kernel
|
||||
developers working on DRM and associated drivers.
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_KUNIT_TEST
|
||||
tristate "KUnit tests for DRM" if !KUNIT_ALL_TESTS
|
||||
depends on DRM && KUNIT=y
|
||||
select DRM_KMS_HELPER
|
||||
default KUNIT_ALL_TESTS
|
||||
help
|
||||
This builds unit tests for DRM. This option is not useful for
|
||||
@ -214,11 +200,11 @@ config DRM_TTM_HELPER
|
||||
help
|
||||
Helpers for ttm-based gem objects
|
||||
|
||||
config DRM_GEM_CMA_HELPER
|
||||
config DRM_GEM_DMA_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
help
|
||||
Choose this if you need the GEM CMA helper functions
|
||||
Choose this if you need the GEM DMA helper functions
|
||||
|
||||
config DRM_GEM_SHMEM_HELPER
|
||||
tristate
|
||||
|
@ -40,9 +40,9 @@ obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
|
||||
|
||||
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
|
||||
|
||||
drm_cma_helper-y := drm_gem_cma_helper.o
|
||||
drm_cma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_cma_helper.o
|
||||
obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o
|
||||
drm_dma_helper-y := drm_gem_dma_helper.o
|
||||
drm_dma_helper-$(CONFIG_DRM_KMS_HELPER) += drm_fb_dma_helper.o
|
||||
obj-$(CONFIG_DRM_GEM_DMA_HELPER) += drm_dma_helper.o
|
||||
|
||||
drm_shmem_helper-y := drm_gem_shmem_helper.o
|
||||
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
|
||||
@ -75,7 +75,6 @@ obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
|
||||
# Drivers and the rest
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
|
||||
obj-$(CONFIG_DRM_KUNIT_TEST) += tests/
|
||||
|
||||
obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
|
||||
|
@ -848,7 +848,7 @@ void amdgpu_ctx_mgr_init(struct amdgpu_ctx_mgr *mgr,
|
||||
|
||||
mgr->adev = adev;
|
||||
mutex_init(&mgr->lock);
|
||||
idr_init(&mgr->ctx_handles);
|
||||
idr_init_base(&mgr->ctx_handles, 1);
|
||||
|
||||
for (i = 0; i < AMDGPU_HW_IP_NUM; ++i)
|
||||
atomic64_set(&mgr->time_spend[i], 0);
|
||||
|
@ -1160,7 +1160,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, struct drm_file *file_priv)
|
||||
}
|
||||
|
||||
mutex_init(&fpriv->bo_list_lock);
|
||||
idr_init(&fpriv->bo_list_handles);
|
||||
idr_init_base(&fpriv->bo_list_handles, 1);
|
||||
|
||||
amdgpu_ctx_mgr_init(&fpriv->ctx_mgr, adev);
|
||||
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
|
@ -591,7 +591,7 @@ int amdgpu_bo_create(struct amdgpu_device *adev,
|
||||
if (!bp->destroy)
|
||||
bp->destroy = &amdgpu_bo_destroy;
|
||||
|
||||
r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, size, bp->type,
|
||||
r = ttm_bo_init_reserved(&adev->mman.bdev, &bo->tbo, bp->type,
|
||||
&bo->placement, page_align, &ctx, NULL,
|
||||
bp->resv, bp->destroy);
|
||||
if (unlikely(r != 0))
|
||||
@ -1309,7 +1309,7 @@ void amdgpu_bo_release_notify(struct ttm_buffer_object *bo)
|
||||
if (bo->base.resv == &bo->base._resv)
|
||||
amdgpu_amdkfd_remove_fence_on_pt_pd_bos(abo);
|
||||
|
||||
if (bo->resource->mem_type != TTM_PL_VRAM ||
|
||||
if (!bo->resource || bo->resource->mem_type != TTM_PL_VRAM ||
|
||||
!(abo->flags & AMDGPU_GEM_CREATE_VRAM_WIPE_ON_RELEASE) ||
|
||||
adev->in_suspend || adev->shutdown)
|
||||
return;
|
||||
|
@ -471,7 +471,8 @@ static int amdgpu_bo_move(struct ttm_buffer_object *bo, bool evict,
|
||||
|
||||
adev = amdgpu_ttm_adev(bo->bdev);
|
||||
|
||||
if (old_mem->mem_type == TTM_PL_SYSTEM && bo->ttm == NULL) {
|
||||
if (!old_mem || (old_mem->mem_type == TTM_PL_SYSTEM &&
|
||||
bo->ttm == NULL)) {
|
||||
ttm_bo_move_null(bo, new_mem);
|
||||
goto out;
|
||||
}
|
||||
|
@ -282,8 +282,8 @@ static int amdgpu_vkms_plane_atomic_check(struct drm_plane *plane,
|
||||
return PTR_ERR(crtc_state);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, true);
|
||||
if (ret != 0)
|
||||
return ret;
|
||||
|
@ -88,6 +88,7 @@
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/drm_audio_component.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "ivsrcid/dcn/irqsrcs_dcn_1_0.h"
|
||||
|
||||
@ -2812,15 +2813,12 @@ static struct drm_mode_config_helper_funcs amdgpu_dm_mode_config_helperfuncs = {
|
||||
|
||||
static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
||||
{
|
||||
u32 max_avg, min_cll, max, min, q, r;
|
||||
struct amdgpu_dm_backlight_caps *caps;
|
||||
struct amdgpu_display_manager *dm;
|
||||
struct drm_connector *conn_base;
|
||||
struct amdgpu_device *adev;
|
||||
struct dc_link *link = NULL;
|
||||
static const u8 pre_computed_values[] = {
|
||||
50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
|
||||
71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98};
|
||||
struct drm_luminance_range_info *luminance_range;
|
||||
int i;
|
||||
|
||||
if (!aconnector || !aconnector->dc_link)
|
||||
@ -2842,8 +2840,6 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
||||
caps = &dm->backlight_caps[i];
|
||||
caps->ext_caps = &aconnector->dc_link->dpcd_sink_ext_caps;
|
||||
caps->aux_support = false;
|
||||
max_avg = conn_base->hdr_sink_metadata.hdmi_type1.max_fall;
|
||||
min_cll = conn_base->hdr_sink_metadata.hdmi_type1.min_cll;
|
||||
|
||||
if (caps->ext_caps->bits.oled == 1 /*||
|
||||
caps->ext_caps->bits.sdr_aux_backlight_control == 1 ||
|
||||
@ -2855,31 +2851,9 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
|
||||
else if (amdgpu_backlight == 1)
|
||||
caps->aux_support = true;
|
||||
|
||||
/* From the specification (CTA-861-G), for calculating the maximum
|
||||
* luminance we need to use:
|
||||
* Luminance = 50*2**(CV/32)
|
||||
* Where CV is a one-byte value.
|
||||
* For calculating this expression we may need float point precision;
|
||||
* to avoid this complexity level, we take advantage that CV is divided
|
||||
* by a constant. From the Euclids division algorithm, we know that CV
|
||||
* can be written as: CV = 32*q + r. Next, we replace CV in the
|
||||
* Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just
|
||||
* need to pre-compute the value of r/32. For pre-computing the values
|
||||
* We just used the following Ruby line:
|
||||
* (0...32).each {|cv| puts (50*2**(cv/32.0)).round}
|
||||
* The results of the above expressions can be verified at
|
||||
* pre_computed_values.
|
||||
*/
|
||||
q = max_avg >> 5;
|
||||
r = max_avg % 32;
|
||||
max = (1 << q) * pre_computed_values[r];
|
||||
|
||||
// min luminance: maxLum * (CV/255)^2 / 100
|
||||
q = DIV_ROUND_CLOSEST(min_cll, 255);
|
||||
min = max * DIV_ROUND_CLOSEST((q * q), 100);
|
||||
|
||||
caps->aux_max_input_signal = max;
|
||||
caps->aux_min_input_signal = min;
|
||||
luminance_range = &conn_base->display_info.luminance_range;
|
||||
caps->aux_min_input_signal = luminance_range->min_luminance;
|
||||
caps->aux_max_input_signal = luminance_range->max_luminance;
|
||||
}
|
||||
|
||||
void amdgpu_dm_update_connector_after_detect(
|
||||
|
@ -1562,7 +1562,7 @@ int dm_drm_plane_get_property(struct drm_plane *plane,
|
||||
static const struct drm_plane_funcs dm_plane_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = drm_primary_helper_destroy,
|
||||
.destroy = drm_plane_helper_destroy,
|
||||
.reset = dm_drm_plane_reset,
|
||||
.atomic_duplicate_state = dm_drm_plane_duplicate_state,
|
||||
.atomic_destroy_state = dm_drm_plane_destroy_state,
|
||||
|
@ -6,7 +6,7 @@ config DRM_HDLCD
|
||||
depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
|
||||
depends on COMMON_CLK
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
help
|
||||
Choose this option if you have an ARM High Definition Colour LCD
|
||||
controller.
|
||||
@ -27,7 +27,7 @@ config DRM_MALI_DISPLAY
|
||||
depends on DRM && OF && (ARM || ARM64 || COMPILE_TEST)
|
||||
depends on COMMON_CLK
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Choose this option if you want to compile the ARM Mali Display
|
||||
|
@ -4,7 +4,7 @@ config DRM_KOMEDA
|
||||
depends on DRM && OF
|
||||
depends on COMMON_CLK
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select VIDEOMODE_HELPERS
|
||||
help
|
||||
Choose this option if you want to compile the ARM Komeda display
|
||||
|
@ -310,8 +310,7 @@ static int d71_reset(struct d71_dev *d71)
|
||||
u32 __iomem *gcu = d71->gcu_addr;
|
||||
int ret;
|
||||
|
||||
malidp_write32_mask(gcu, BLK_CONTROL,
|
||||
GCU_CONTROL_SRST, GCU_CONTROL_SRST);
|
||||
malidp_write32(gcu, BLK_CONTROL, GCU_CONTROL_SRST);
|
||||
|
||||
ret = dp_wait_cond(!(malidp_read32(gcu, BLK_CONTROL) & GCU_CONTROL_SRST),
|
||||
100, 1000, 10000);
|
||||
|
@ -11,7 +11,6 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
@ -235,7 +234,7 @@ void komeda_crtc_handle_event(struct komeda_crtc *kcrtc,
|
||||
crtc->state->event = NULL;
|
||||
drm_crtc_send_vblank_event(crtc, event);
|
||||
} else {
|
||||
DRM_WARN("CRTC[%d]: FLIP happen but no pending commit.\n",
|
||||
DRM_WARN("CRTC[%d]: FLIP happened but no pending commit.\n",
|
||||
drm_crtc_index(&kcrtc->base));
|
||||
}
|
||||
spin_unlock_irqrestore(&crtc->dev->event_lock, flags);
|
||||
@ -286,7 +285,7 @@ komeda_crtc_atomic_enable(struct drm_crtc *crtc,
|
||||
komeda_crtc_do_flush(crtc, old);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
|
||||
struct completion *input_flip_done)
|
||||
{
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include "komeda_dev.h"
|
||||
@ -72,6 +73,7 @@ static int komeda_bind(struct device *dev)
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, mdrv);
|
||||
drm_fbdev_generic_setup(&mdrv->kms->base, 32);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
*
|
||||
*/
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fb_dma_helper.h>
|
||||
#include <drm/drm_gem.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
|
||||
#include "komeda_framebuffer.h"
|
||||
@ -137,7 +137,7 @@ komeda_fb_none_afbc_size_check(struct komeda_dev *mdev, struct komeda_fb *kfb,
|
||||
}
|
||||
|
||||
min_size = komeda_fb_get_pixel_addr(kfb, 0, fb->height, i)
|
||||
- to_drm_gem_cma_obj(obj)->paddr;
|
||||
- to_drm_gem_dma_obj(obj)->dma_addr;
|
||||
if (obj->size < min_size) {
|
||||
DRM_DEBUG_KMS("The fb->obj[%d] size: 0x%zx lower than the minimum requirement: 0x%llx.\n",
|
||||
i, obj->size, min_size);
|
||||
@ -239,7 +239,7 @@ dma_addr_t
|
||||
komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
|
||||
{
|
||||
struct drm_framebuffer *fb = &kfb->base;
|
||||
const struct drm_gem_cma_object *obj;
|
||||
const struct drm_gem_dma_object *obj;
|
||||
u32 offset, plane_x, plane_y, block_w, block_sz;
|
||||
|
||||
if (plane >= fb->format->num_planes) {
|
||||
@ -247,7 +247,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
obj = drm_fb_cma_get_gem_obj(fb, plane);
|
||||
obj = drm_fb_dma_get_gem_obj(fb, plane);
|
||||
|
||||
offset = fb->offsets[plane];
|
||||
if (!fb->modifier) {
|
||||
@ -260,7 +260,7 @@ komeda_fb_get_pixel_addr(struct komeda_fb *kfb, int x, int y, int plane)
|
||||
+ plane_y * fb->pitches[plane];
|
||||
}
|
||||
|
||||
return obj->paddr + offset;
|
||||
return obj->dma_addr + offset;
|
||||
}
|
||||
|
||||
/* if the fb can be supported by a specific layer */
|
||||
|
@ -11,7 +11,7 @@
|
||||
#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_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@ -21,9 +21,9 @@
|
||||
#include "komeda_framebuffer.h"
|
||||
#include "komeda_kms.h"
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(komeda_cma_fops);
|
||||
DEFINE_DRM_GEM_DMA_FOPS(komeda_cma_fops);
|
||||
|
||||
static int komeda_gem_cma_dumb_create(struct drm_file *file,
|
||||
static int komeda_gem_dma_dumb_create(struct drm_file *file,
|
||||
struct drm_device *dev,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
@ -32,7 +32,7 @@ static int komeda_gem_cma_dumb_create(struct drm_file *file,
|
||||
|
||||
args->pitch = ALIGN(pitch, mdev->chip.bus_width);
|
||||
|
||||
return drm_gem_cma_dumb_create_internal(file, dev, args);
|
||||
return drm_gem_dma_dumb_create_internal(file, dev, args);
|
||||
}
|
||||
|
||||
static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
|
||||
@ -60,7 +60,7 @@ static irqreturn_t komeda_kms_irq_handler(int irq, void *data)
|
||||
static const struct drm_driver komeda_kms_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.lastclose = drm_fb_helper_lastclose,
|
||||
DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_cma_dumb_create),
|
||||
DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(komeda_gem_dma_dumb_create),
|
||||
.fops = &komeda_cma_fops,
|
||||
.name = "komeda",
|
||||
.desc = "Arm Komeda Display Processor driver",
|
||||
@ -69,6 +69,25 @@ static const struct drm_driver komeda_kms_driver = {
|
||||
.minor = 1,
|
||||
};
|
||||
|
||||
static void komeda_kms_atomic_commit_hw_done(struct drm_atomic_state *state)
|
||||
{
|
||||
struct drm_device *dev = state->dev;
|
||||
struct komeda_kms_dev *kms = to_kdev(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < kms->n_crtcs; i++) {
|
||||
struct komeda_crtc *kcrtc = &kms->crtcs[i];
|
||||
|
||||
if (kcrtc->base.state->active) {
|
||||
struct completion *flip_done = NULL;
|
||||
if (kcrtc->base.state->event)
|
||||
flip_done = kcrtc->base.state->event->base.completion;
|
||||
komeda_crtc_flush_and_wait_for_flip_done(kcrtc, flip_done);
|
||||
}
|
||||
}
|
||||
drm_atomic_helper_commit_hw_done(state);
|
||||
}
|
||||
|
||||
static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
|
||||
{
|
||||
struct drm_device *dev = old_state->dev;
|
||||
@ -81,7 +100,7 @@ static void komeda_kms_commit_tail(struct drm_atomic_state *old_state)
|
||||
|
||||
drm_atomic_helper_commit_modeset_enables(dev, old_state);
|
||||
|
||||
drm_atomic_helper_commit_hw_done(old_state);
|
||||
komeda_kms_atomic_commit_hw_done(old_state);
|
||||
|
||||
drm_atomic_helper_wait_for_flip_done(dev, old_state);
|
||||
|
||||
|
@ -183,6 +183,8 @@ void komeda_kms_cleanup_private_objs(struct komeda_kms_dev *kms);
|
||||
|
||||
void komeda_crtc_handle_event(struct komeda_crtc *kcrtc,
|
||||
struct komeda_events *evts);
|
||||
void komeda_crtc_flush_and_wait_for_flip_done(struct komeda_crtc *kcrtc,
|
||||
struct completion *input_flip_done);
|
||||
|
||||
struct komeda_kms_dev *komeda_kms_attach(struct komeda_dev *mdev);
|
||||
void komeda_kms_detach(struct komeda_kms_dev *kms);
|
||||
|
@ -1271,7 +1271,7 @@ int komeda_release_unclaimed_resources(struct komeda_pipeline *pipe,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Since standalong disabled components must be disabled separately and in the
|
||||
/* Since standalone disabled components must be disabled separately and in the
|
||||
* last, So a complete disable operation may needs to call pipeline_disable
|
||||
* twice (two phase disabling).
|
||||
* Phase 1: disable the common components, flush it.
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include "komeda_dev.h"
|
||||
#include "komeda_kms.h"
|
||||
|
@ -18,12 +18,11 @@
|
||||
#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_fb_dma_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
@ -252,8 +251,8 @@ static int hdlcd_plane_atomic_check(struct drm_plane *plane,
|
||||
return -EINVAL;
|
||||
return drm_atomic_helper_check_plane_state(new_plane_state,
|
||||
crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, true);
|
||||
}
|
||||
|
||||
@ -274,7 +273,7 @@ static void hdlcd_plane_atomic_update(struct drm_plane *plane,
|
||||
return;
|
||||
|
||||
dest_h = drm_rect_height(&new_plane_state->dst);
|
||||
scanout_start = drm_fb_cma_get_gem_addr(fb, new_plane_state, 0);
|
||||
scanout_start = drm_fb_dma_get_gem_addr(fb, new_plane_state, 0);
|
||||
|
||||
hdlcd = plane->dev->dev_private;
|
||||
hdlcd_write(hdlcd, HDLCD_REG_FB_LINE_LENGTH, fb->pitches[0]);
|
||||
|
@ -21,13 +21,13 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drm_aperture.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_debugfs.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_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
@ -40,8 +40,7 @@
|
||||
|
||||
static irqreturn_t hdlcd_irq(int irq, void *arg)
|
||||
{
|
||||
struct drm_device *drm = arg;
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
struct hdlcd_drm_private *hdlcd = arg;
|
||||
unsigned long irq_status;
|
||||
|
||||
irq_status = hdlcd_read(hdlcd, HDLCD_REG_INT_STATUS);
|
||||
@ -69,61 +68,32 @@ static irqreturn_t hdlcd_irq(int irq, void *arg)
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void hdlcd_irq_preinstall(struct drm_device *drm)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
/* Ensure interrupts are disabled */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
|
||||
}
|
||||
|
||||
static void hdlcd_irq_postinstall(struct drm_device *drm)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
|
||||
|
||||
/* enable debug interrupts */
|
||||
irq_mask |= HDLCD_DEBUG_INT_MASK;
|
||||
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int hdlcd_irq_install(struct drm_device *drm, int irq)
|
||||
static int hdlcd_irq_install(struct hdlcd_drm_private *hdlcd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (irq == IRQ_NOTCONNECTED)
|
||||
return -ENOTCONN;
|
||||
/* Ensure interrupts are disabled */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_CLEAR, ~0);
|
||||
|
||||
hdlcd_irq_preinstall(drm);
|
||||
|
||||
ret = request_irq(irq, hdlcd_irq, 0, drm->driver->name, drm);
|
||||
ret = request_irq(hdlcd->irq, hdlcd_irq, 0, "hdlcd", hdlcd);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hdlcd_irq_postinstall(drm);
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* enable debug interrupts */
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, HDLCD_DEBUG_INT_MASK);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hdlcd_irq_uninstall(struct drm_device *drm)
|
||||
static void hdlcd_irq_uninstall(struct hdlcd_drm_private *hdlcd)
|
||||
{
|
||||
struct hdlcd_drm_private *hdlcd = drm->dev_private;
|
||||
/* disable all the interrupts that we might have enabled */
|
||||
unsigned long irq_mask = hdlcd_read(hdlcd, HDLCD_REG_INT_MASK);
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, 0);
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
/* disable debug interrupts */
|
||||
irq_mask &= ~HDLCD_DEBUG_INT_MASK;
|
||||
#endif
|
||||
|
||||
/* disable vsync interrupts */
|
||||
irq_mask &= ~HDLCD_INTERRUPT_VSYNC;
|
||||
hdlcd_write(hdlcd, HDLCD_REG_INT_MASK, irq_mask);
|
||||
|
||||
free_irq(hdlcd->irq, drm);
|
||||
free_irq(hdlcd->irq, hdlcd);
|
||||
}
|
||||
|
||||
static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
||||
@ -183,7 +153,7 @@ static int hdlcd_load(struct drm_device *drm, unsigned long flags)
|
||||
goto irq_fail;
|
||||
hdlcd->irq = ret;
|
||||
|
||||
ret = hdlcd_irq_install(drm, hdlcd->irq);
|
||||
ret = hdlcd_irq_install(hdlcd);
|
||||
if (ret < 0) {
|
||||
DRM_ERROR("failed to install IRQ handler\n");
|
||||
goto irq_fail;
|
||||
@ -255,11 +225,11 @@ static void hdlcd_debugfs_init(struct drm_minor *minor)
|
||||
}
|
||||
#endif
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
DEFINE_DRM_GEM_DMA_FOPS(fops);
|
||||
|
||||
static const struct drm_driver hdlcd_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
DRM_GEM_DMA_DRIVER_OPS,
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = hdlcd_debugfs_init,
|
||||
#endif
|
||||
@ -314,6 +284,15 @@ static int hdlcd_drm_bind(struct device *dev)
|
||||
goto err_vblank;
|
||||
}
|
||||
|
||||
/*
|
||||
* If EFI left us running, take over from simple framebuffer
|
||||
* drivers. Read HDLCD_REG_COMMAND to see if we are enabled.
|
||||
*/
|
||||
if (hdlcd_read(hdlcd, HDLCD_REG_COMMAND)) {
|
||||
hdlcd_write(hdlcd, HDLCD_REG_COMMAND, 0);
|
||||
drm_aperture_remove_framebuffers(false, &hdlcd_driver);
|
||||
}
|
||||
|
||||
drm_mode_config_reset(drm);
|
||||
drm_kms_helper_poll_init(drm);
|
||||
|
||||
@ -335,7 +314,7 @@ err_pm_active:
|
||||
err_unload:
|
||||
of_node_put(hdlcd->crtc.port);
|
||||
hdlcd->crtc.port = NULL;
|
||||
hdlcd_irq_uninstall(drm);
|
||||
hdlcd_irq_uninstall(hdlcd);
|
||||
of_reserved_mem_device_release(drm->dev);
|
||||
err_free:
|
||||
drm_mode_config_cleanup(drm);
|
||||
@ -357,7 +336,7 @@ static void hdlcd_drm_unbind(struct device *dev)
|
||||
hdlcd->crtc.port = NULL;
|
||||
pm_runtime_get_sync(dev);
|
||||
drm_atomic_helper_shutdown(drm);
|
||||
hdlcd_irq_uninstall(drm);
|
||||
hdlcd_irq_uninstall(hdlcd);
|
||||
pm_runtime_put(dev);
|
||||
if (pm_runtime_enabled(dev))
|
||||
pm_runtime_disable(dev);
|
||||
|
@ -19,10 +19,9 @@
|
||||
#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_fourcc.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
@ -457,7 +456,7 @@ static int malidp_irq_init(struct platform_device *pdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
DEFINE_DRM_GEM_DMA_FOPS(fops);
|
||||
|
||||
static int malidp_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *drm,
|
||||
@ -469,7 +468,7 @@ static int malidp_dumb_create(struct drm_file *file_priv,
|
||||
|
||||
args->pitch = ALIGN(DIV_ROUND_UP(args->width * args->bpp, 8), alignment);
|
||||
|
||||
return drm_gem_cma_dumb_create_internal(file_priv, drm, args);
|
||||
return drm_gem_dma_dumb_create_internal(file_priv, drm, args);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
@ -566,7 +565,7 @@ static void malidp_debugfs_init(struct drm_minor *minor)
|
||||
|
||||
static const struct drm_driver malidp_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create),
|
||||
DRM_GEM_DMA_DRIVER_OPS_WITH_DUMB_CREATE(malidp_dumb_create),
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
.debugfs_init = malidp_debugfs_init,
|
||||
#endif
|
||||
|
@ -10,10 +10,10 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fb_dma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_writeback.h>
|
||||
|
||||
@ -160,7 +160,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
|
||||
n_planes = fb->format->num_planes;
|
||||
for (i = 0; i < n_planes; i++) {
|
||||
struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, i);
|
||||
struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, i);
|
||||
/* memory write buffers are never rotated */
|
||||
u8 alignment = malidp_hw_get_pitch_align(malidp->dev, 0);
|
||||
|
||||
@ -170,7 +170,7 @@ malidp_mw_encoder_atomic_check(struct drm_encoder *encoder,
|
||||
return -EINVAL;
|
||||
}
|
||||
mw_state->pitches[i] = fb->pitches[i];
|
||||
mw_state->addrs[i] = obj->paddr + fb->offsets[i];
|
||||
mw_state->addrs[i] = obj->dma_addr + fb->offsets[i];
|
||||
}
|
||||
mw_state->n_planes = n_planes;
|
||||
|
||||
|
@ -13,12 +13,11 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fb_dma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "malidp_hw.h"
|
||||
@ -334,15 +333,15 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
|
||||
|
||||
for (i = 0; i < ms->n_planes; i++) {
|
||||
struct drm_gem_object *obj;
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
struct sg_table *sgt;
|
||||
struct scatterlist *sgl;
|
||||
|
||||
obj = drm_gem_fb_get_obj(ms->base.fb, i);
|
||||
cma_obj = to_drm_gem_cma_obj(obj);
|
||||
dma_obj = to_drm_gem_dma_obj(obj);
|
||||
|
||||
if (cma_obj->sgt)
|
||||
sgt = cma_obj->sgt;
|
||||
if (dma_obj->sgt)
|
||||
sgt = dma_obj->sgt;
|
||||
else
|
||||
sgt = obj->funcs->get_sg_table(obj);
|
||||
|
||||
@ -353,14 +352,14 @@ static bool malidp_check_pages_threshold(struct malidp_plane_state *ms,
|
||||
|
||||
while (sgl) {
|
||||
if (sgl->length < pgsize) {
|
||||
if (!cma_obj->sgt)
|
||||
if (!dma_obj->sgt)
|
||||
kfree(sgt);
|
||||
return false;
|
||||
}
|
||||
|
||||
sgl = sg_next(sgl);
|
||||
}
|
||||
if (!cma_obj->sgt)
|
||||
if (!dma_obj->sgt)
|
||||
kfree(sgt);
|
||||
}
|
||||
|
||||
@ -715,7 +714,7 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
|
||||
struct malidp_plane *mp,
|
||||
int plane_index)
|
||||
{
|
||||
dma_addr_t paddr;
|
||||
dma_addr_t dma_addr;
|
||||
u16 ptr;
|
||||
struct drm_plane *plane = &mp->base;
|
||||
bool afbc = fb->modifier ? true : false;
|
||||
@ -723,27 +722,27 @@ static void malidp_set_plane_base_addr(struct drm_framebuffer *fb,
|
||||
ptr = mp->layer->ptr + (plane_index << 4);
|
||||
|
||||
/*
|
||||
* drm_fb_cma_get_gem_addr() alters the physical base address of the
|
||||
* drm_fb_dma_get_gem_addr() alters the physical base address of the
|
||||
* framebuffer as per the plane's src_x, src_y co-ordinates (ie to
|
||||
* take care of source cropping).
|
||||
* For AFBC, this is not needed as the cropping is handled by _AD_CROP_H
|
||||
* and _AD_CROP_V registers.
|
||||
*/
|
||||
if (!afbc) {
|
||||
paddr = drm_fb_cma_get_gem_addr(fb, plane->state,
|
||||
plane_index);
|
||||
dma_addr = drm_fb_dma_get_gem_addr(fb, plane->state,
|
||||
plane_index);
|
||||
} else {
|
||||
struct drm_gem_cma_object *obj;
|
||||
struct drm_gem_dma_object *obj;
|
||||
|
||||
obj = drm_fb_cma_get_gem_obj(fb, plane_index);
|
||||
obj = drm_fb_dma_get_gem_obj(fb, plane_index);
|
||||
|
||||
if (WARN_ON(!obj))
|
||||
return;
|
||||
paddr = obj->paddr;
|
||||
dma_addr = obj->dma_addr;
|
||||
}
|
||||
|
||||
malidp_hw_write(mp->hwdev, lower_32_bits(paddr), ptr);
|
||||
malidp_hw_write(mp->hwdev, upper_32_bits(paddr), ptr + 4);
|
||||
malidp_hw_write(mp->hwdev, lower_32_bits(dma_addr), ptr);
|
||||
malidp_hw_write(mp->hwdev, upper_32_bits(dma_addr), ptr + 4);
|
||||
}
|
||||
|
||||
static void malidp_de_set_plane_afbc(struct drm_plane *plane)
|
||||
|
@ -145,7 +145,7 @@
|
||||
#define MALIDP_SE_COEFFTAB_DATA_MASK 0x3fff
|
||||
#define MALIDP_SE_SET_COEFFTAB_DATA(x) \
|
||||
((x) & MALIDP_SE_COEFFTAB_DATA_MASK)
|
||||
/* Enhance coeffents reigster offset */
|
||||
/* Enhance coefficients register offset */
|
||||
#define MALIDP_SE_IMAGE_ENH 0x3C
|
||||
/* ENH_LIMITS offset 0x0 */
|
||||
#define MALIDP_SE_ENH_LOW_LEVEL 24
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
|
@ -107,11 +107,11 @@ armada_gem_linear_back(struct drm_device *dev, struct armada_gem_object *obj)
|
||||
}
|
||||
|
||||
/*
|
||||
* We could grab something from CMA if it's enabled, but that
|
||||
* We could grab something from DMA if it's enabled, but that
|
||||
* involves building in a problem:
|
||||
*
|
||||
* CMA's interface uses dma_alloc_coherent(), which provides us
|
||||
* with an CPU virtual address and a device address.
|
||||
* GEM DMA helper interface uses dma_alloc_coherent(), which provides
|
||||
* us with an CPU virtual address and a device address.
|
||||
*
|
||||
* The CPU virtual address may be either an address in the kernel
|
||||
* direct mapped region (for example, as it would be on x86) or
|
||||
|
@ -298,12 +298,6 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void armada_ovl_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
drm_plane_cleanup(plane);
|
||||
kfree(plane);
|
||||
}
|
||||
|
||||
static void armada_overlay_reset(struct drm_plane *plane)
|
||||
{
|
||||
struct armada_overlay_state *state;
|
||||
@ -468,7 +462,7 @@ static int armada_overlay_get_property(struct drm_plane *plane,
|
||||
static const struct drm_plane_funcs armada_ovl_plane_funcs = {
|
||||
.update_plane = armada_overlay_plane_update,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = armada_ovl_plane_destroy,
|
||||
.destroy = drm_plane_helper_destroy,
|
||||
.reset = armada_overlay_reset,
|
||||
.atomic_duplicate_state = armada_overlay_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
||||
|
@ -288,7 +288,7 @@ struct drm_plane_state *armada_plane_duplicate_state(struct drm_plane *plane)
|
||||
static const struct drm_plane_funcs armada_primary_plane_funcs = {
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.destroy = drm_primary_helper_destroy,
|
||||
.destroy = drm_plane_helper_destroy,
|
||||
.reset = armada_plane_reset,
|
||||
.atomic_duplicate_state = armada_plane_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
||||
|
@ -5,7 +5,7 @@ config DRM_ASPEED_GFX
|
||||
depends on (COMPILE_TEST || ARCH_ASPEED)
|
||||
depends on MMU
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select DMA_CMA if HAVE_DMA_CONTIGUOUS
|
||||
select CMA if HAVE_DMA_CONTIGUOUS
|
||||
select MFD_SYSCON
|
||||
|
@ -7,11 +7,11 @@
|
||||
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fb_dma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
@ -168,7 +168,7 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe,
|
||||
struct drm_crtc *crtc = &pipe->crtc;
|
||||
struct drm_framebuffer *fb = pipe->plane.state->fb;
|
||||
struct drm_pending_vblank_event *event;
|
||||
struct drm_gem_cma_object *gem;
|
||||
struct drm_gem_dma_object *gem;
|
||||
|
||||
spin_lock_irq(&crtc->dev->event_lock);
|
||||
event = crtc->state->event;
|
||||
@ -185,10 +185,10 @@ static void aspeed_gfx_pipe_update(struct drm_simple_display_pipe *pipe,
|
||||
if (!fb)
|
||||
return;
|
||||
|
||||
gem = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
gem = drm_fb_dma_get_gem_obj(fb, 0);
|
||||
if (!gem)
|
||||
return;
|
||||
writel(gem->paddr, priv->base + CRT_ADDR);
|
||||
writel(gem->dma_addr, priv->base + CRT_ADDR);
|
||||
}
|
||||
|
||||
static int aspeed_gfx_enable_vblank(struct drm_simple_display_pipe *pipe)
|
||||
|
@ -16,9 +16,8 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_device.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_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@ -246,11 +245,11 @@ static void aspeed_gfx_unload(struct drm_device *drm)
|
||||
drm_kms_helper_poll_fini(drm);
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
DEFINE_DRM_GEM_DMA_FOPS(fops);
|
||||
|
||||
static const struct drm_driver aspeed_gfx_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
DRM_GEM_DMA_DRIVER_OPS,
|
||||
.fops = &fops,
|
||||
.name = "aspeed-gfx-drm",
|
||||
.desc = "ASPEED GFX DRM",
|
||||
|
@ -42,7 +42,6 @@
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
@ -555,8 +554,8 @@ static int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
new_plane_state->crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -779,8 +778,8 @@ static int ast_cursor_plane_helper_atomic_check(struct drm_plane *plane,
|
||||
new_plane_state->crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
true, true);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -2,7 +2,7 @@
|
||||
config DRM_ATMEL_HLCDC
|
||||
tristate "DRM Support for ATMEL HLCDC Display Controller"
|
||||
depends on DRM && OF && COMMON_CLK && MFD_ATMEL_HLCDC && ARM
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_PANEL
|
||||
help
|
||||
|
@ -20,7 +20,7 @@
|
||||
#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_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@ -730,11 +730,11 @@ static void atmel_hlcdc_dc_unload(struct drm_device *dev)
|
||||
clk_disable_unprepare(dc->hlcdc->periph_clk);
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fops);
|
||||
DEFINE_DRM_GEM_DMA_FOPS(fops);
|
||||
|
||||
static const struct drm_driver atmel_hlcdc_dc_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
DRM_GEM_DMA_DRIVER_OPS,
|
||||
.fops = &fops,
|
||||
.name = "atmel-hlcdc",
|
||||
.desc = "Atmel HLCD Controller DRM",
|
||||
|
@ -12,11 +12,10 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fb_dma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
|
||||
#include "atmel_hlcdc_dc.h"
|
||||
|
||||
@ -449,9 +448,9 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane,
|
||||
sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR);
|
||||
|
||||
for (i = 0; i < state->nplanes; i++) {
|
||||
struct drm_gem_cma_object *gem = drm_fb_cma_get_gem_obj(fb, i);
|
||||
struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i);
|
||||
|
||||
state->dscrs[i]->addr = gem->paddr + state->offsets[i];
|
||||
state->dscrs[i]->addr = gem->dma_addr + state->offsets[i];
|
||||
|
||||
atmel_hlcdc_layer_write_reg(&plane->layer,
|
||||
ATMEL_HLCDC_LAYER_PLANE_HEAD(i),
|
||||
|
@ -394,10 +394,7 @@ void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
|
||||
#else
|
||||
static inline int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
|
||||
{
|
||||
unsigned int offset = adv7511->type == ADV7533 ?
|
||||
ADV7533_REG_CEC_OFFSET : 0;
|
||||
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
|
||||
ADV7511_CEC_CTRL_POWER_DOWN);
|
||||
return 0;
|
||||
}
|
||||
|
@ -359,7 +359,7 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
|
||||
goto err_cec_alloc;
|
||||
}
|
||||
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL, 0);
|
||||
/* cec soft reset */
|
||||
regmap_write(adv7511->regmap_cec,
|
||||
ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
|
||||
@ -386,7 +386,7 @@ err_cec_alloc:
|
||||
dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
|
||||
ret);
|
||||
err_cec_parse_dt:
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
|
||||
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL,
|
||||
ADV7511_CEC_CTRL_POWER_DOWN);
|
||||
return ret == -EPROBE_DEFER ? ret : 0;
|
||||
}
|
||||
|
@ -1340,9 +1340,6 @@ static int adv7511_remove(struct i2c_client *i2c)
|
||||
{
|
||||
struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
|
||||
|
||||
i2c_unregister_device(adv7511->i2c_cec);
|
||||
clk_disable_unprepare(adv7511->cec_clk);
|
||||
|
||||
adv7511_uninit_regulators(adv7511);
|
||||
|
||||
drm_bridge_remove(&adv7511->bridge);
|
||||
@ -1350,6 +1347,8 @@ static int adv7511_remove(struct i2c_client *i2c)
|
||||
adv7511_audio_exit(adv7511);
|
||||
|
||||
cec_unregister_adapter(adv7511->cec_adap);
|
||||
i2c_unregister_device(adv7511->i2c_cec);
|
||||
clk_disable_unprepare(adv7511->cec_clk);
|
||||
|
||||
i2c_unregister_device(adv7511->i2c_packet);
|
||||
i2c_unregister_device(adv7511->i2c_edid);
|
||||
|
@ -1642,6 +1642,7 @@ static int anx7625_parse_dt(struct device *dev,
|
||||
anx7625_get_swing_setting(dev, pdata);
|
||||
|
||||
pdata->is_dpi = 0; /* default dsi mode */
|
||||
of_node_put(pdata->mipi_host_node);
|
||||
pdata->mipi_host_node = of_graph_get_remote_node(np, 0, 0);
|
||||
if (!pdata->mipi_host_node) {
|
||||
DRM_DEV_ERROR(dev, "fail to get internal panel.\n");
|
||||
|
@ -735,14 +735,12 @@ static int chipone_i2c_probe(struct i2c_client *client,
|
||||
return chipone_dsi_host_attach(icn);
|
||||
}
|
||||
|
||||
static int chipone_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
static void chipone_dsi_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct chipone *icn = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_bridge_remove(&icn->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id chipone_of_match[] = {
|
||||
|
@ -506,6 +506,9 @@ static int it6505_read(struct it6505 *it6505, unsigned int reg_addr)
|
||||
int err;
|
||||
struct device *dev = &it6505->client->dev;
|
||||
|
||||
if (!it6505->powered)
|
||||
return -ENODEV;
|
||||
|
||||
err = regmap_read(it6505->regmap, reg_addr, &value);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "read failed reg[0x%x] err: %d", reg_addr, err);
|
||||
@ -521,6 +524,9 @@ static int it6505_write(struct it6505 *it6505, unsigned int reg_addr,
|
||||
int err;
|
||||
struct device *dev = &it6505->client->dev;
|
||||
|
||||
if (!it6505->powered)
|
||||
return -ENODEV;
|
||||
|
||||
err = regmap_write(it6505->regmap, reg_addr, reg_val);
|
||||
|
||||
if (err < 0) {
|
||||
@ -538,6 +544,9 @@ static int it6505_set_bits(struct it6505 *it6505, unsigned int reg,
|
||||
int err;
|
||||
struct device *dev = &it6505->client->dev;
|
||||
|
||||
if (!it6505->powered)
|
||||
return -ENODEV;
|
||||
|
||||
err = regmap_update_bits(it6505->regmap, reg, mask, value);
|
||||
if (err < 0) {
|
||||
dev_err(dev, "write reg[0x%x] = 0x%x mask = 0x%x failed err %d",
|
||||
@ -682,7 +691,7 @@ static void it6505_calc_video_info(struct it6505 *it6505)
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "hactive_start:%d, vactive_start:%d",
|
||||
hdes, vdes);
|
||||
|
||||
for (i = 0; i < 10; i++) {
|
||||
for (i = 0; i < 3; i++) {
|
||||
it6505_set_bits(it6505, REG_DATA_CTRL0, ENABLE_PCLK_COUNTER,
|
||||
ENABLE_PCLK_COUNTER);
|
||||
usleep_range(10000, 15000);
|
||||
@ -699,7 +708,7 @@ static void it6505_calc_video_info(struct it6505 *it6505)
|
||||
return;
|
||||
}
|
||||
|
||||
sum /= 10;
|
||||
sum /= 3;
|
||||
pclk = 13500 * 2048 / sum;
|
||||
it6505->video_info.clock = pclk;
|
||||
it6505->video_info.hdisplay = hdew;
|
||||
@ -2341,8 +2350,6 @@ static void it6505_irq_hpd(struct it6505 *it6505)
|
||||
|
||||
if (!it6505_get_video_status(it6505))
|
||||
it6505_video_reset(it6505);
|
||||
|
||||
it6505_calc_video_info(it6505);
|
||||
} else {
|
||||
memset(it6505->dpcd, 0, sizeof(it6505->dpcd));
|
||||
|
||||
@ -2559,13 +2566,12 @@ static int it6505_poweron(struct it6505 *it6505)
|
||||
usleep_range(10000, 20000);
|
||||
}
|
||||
|
||||
it6505->powered = true;
|
||||
it6505_reset_logic(it6505);
|
||||
it6505_int_mask_enable(it6505);
|
||||
it6505_init(it6505);
|
||||
it6505_lane_off(it6505);
|
||||
|
||||
it6505->powered = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2945,6 +2951,9 @@ static void it6505_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
if (ret)
|
||||
dev_err(dev, "Failed to setup AVI infoframe: %d", ret);
|
||||
|
||||
it6505_drm_dp_link_set_power(&it6505->aux, &it6505->link,
|
||||
DP_SET_POWER_D0);
|
||||
|
||||
it6505_update_video_parameter(it6505, mode);
|
||||
|
||||
ret = it6505_send_video_infoframe(it6505, &frame);
|
||||
@ -3044,7 +3053,7 @@ static int it6505_init_pdata(struct it6505 *it6505)
|
||||
return PTR_ERR(pdata->ovdd);
|
||||
}
|
||||
|
||||
pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
|
||||
pdata->gpiod_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR(pdata->gpiod_reset)) {
|
||||
dev_err(dev, "gpiod_reset gpio not found");
|
||||
return PTR_ERR(pdata->gpiod_reset);
|
||||
|
@ -813,13 +813,14 @@ static int lt9611_connector_init(struct drm_bridge *bridge, struct lt9611 *lt961
|
||||
|
||||
drm_connector_helper_add(<9611->connector,
|
||||
<9611_bridge_connector_helper_funcs);
|
||||
drm_connector_attach_encoder(<9611->connector, bridge->encoder);
|
||||
|
||||
if (!bridge->encoder) {
|
||||
DRM_ERROR("Parent encoder object not found");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
drm_connector_attach_encoder(<9611->connector, bridge->encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
@ -367,6 +368,44 @@ struct drm_bridge *devm_drm_panel_bridge_add_typed(struct device *dev,
|
||||
}
|
||||
EXPORT_SYMBOL(devm_drm_panel_bridge_add_typed);
|
||||
|
||||
static void drmm_drm_panel_bridge_release(struct drm_device *drm, void *ptr)
|
||||
{
|
||||
struct drm_bridge *bridge = ptr;
|
||||
|
||||
drm_panel_bridge_remove(bridge);
|
||||
}
|
||||
|
||||
/**
|
||||
* drmm_panel_bridge_add - Creates a DRM-managed &drm_bridge and
|
||||
* &drm_connector that just calls the
|
||||
* appropriate functions from &drm_panel.
|
||||
*
|
||||
* @drm: DRM device to tie the bridge lifetime to
|
||||
* @panel: The drm_panel being wrapped. Must be non-NULL.
|
||||
*
|
||||
* This is the DRM-managed version of drm_panel_bridge_add() which
|
||||
* automatically calls drm_panel_bridge_remove() when @dev is cleaned
|
||||
* up.
|
||||
*/
|
||||
struct drm_bridge *drmm_panel_bridge_add(struct drm_device *drm,
|
||||
struct drm_panel *panel)
|
||||
{
|
||||
struct drm_bridge *bridge;
|
||||
int ret;
|
||||
|
||||
bridge = drm_panel_bridge_add_typed(panel, panel->connector_type);
|
||||
if (IS_ERR(bridge))
|
||||
return bridge;
|
||||
|
||||
ret = drmm_add_action_or_reset(drm, drmm_drm_panel_bridge_release,
|
||||
bridge);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return bridge;
|
||||
}
|
||||
EXPORT_SYMBOL(drmm_panel_bridge_add);
|
||||
|
||||
/**
|
||||
* drm_panel_bridge_connector - return the connector for the panel bridge
|
||||
* @bridge: The drm_bridge.
|
||||
@ -420,4 +459,39 @@ struct drm_bridge *devm_drm_of_get_bridge(struct device *dev,
|
||||
return bridge;
|
||||
}
|
||||
EXPORT_SYMBOL(devm_drm_of_get_bridge);
|
||||
|
||||
/**
|
||||
* drmm_of_get_bridge - Return next bridge in the chain
|
||||
* @drm: device to tie the bridge lifetime to
|
||||
* @np: device tree node containing encoder output ports
|
||||
* @port: port in the device tree node
|
||||
* @endpoint: endpoint in the device tree node
|
||||
*
|
||||
* Given a DT node's port and endpoint number, finds the connected node
|
||||
* and returns the associated bridge if any, or creates and returns a
|
||||
* drm panel bridge instance if a panel is connected.
|
||||
*
|
||||
* Returns a drmm managed pointer to the bridge if successful, or an error
|
||||
* pointer otherwise.
|
||||
*/
|
||||
struct drm_bridge *drmm_of_get_bridge(struct drm_device *drm,
|
||||
struct device_node *np,
|
||||
u32 port, u32 endpoint)
|
||||
{
|
||||
struct drm_bridge *bridge;
|
||||
struct drm_panel *panel;
|
||||
int ret;
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(np, port, endpoint,
|
||||
&panel, &bridge);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
if (panel)
|
||||
bridge = drmm_panel_bridge_add(drm, panel);
|
||||
|
||||
return bridge;
|
||||
}
|
||||
EXPORT_SYMBOL(drmm_of_get_bridge);
|
||||
|
||||
#endif
|
||||
|
@ -631,8 +631,8 @@ static int ps8640_probe(struct i2c_client *client)
|
||||
if (!ps_bridge)
|
||||
return -ENOMEM;
|
||||
|
||||
ps_bridge->supplies[0].supply = "vdd33";
|
||||
ps_bridge->supplies[1].supply = "vdd12";
|
||||
ps_bridge->supplies[0].supply = "vdd12";
|
||||
ps_bridge->supplies[1].supply = "vdd33";
|
||||
ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(ps_bridge->supplies),
|
||||
ps_bridge->supplies);
|
||||
if (ret)
|
||||
|
@ -241,14 +241,12 @@ static int tc358762_probe(struct mipi_dsi_device *dsi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc358762_remove(struct mipi_dsi_device *dsi)
|
||||
static void tc358762_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct tc358762 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_bridge_remove(&ctx->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tc358762_of_match[] = {
|
||||
|
@ -381,14 +381,12 @@ static int tc358764_probe(struct mipi_dsi_device *dsi)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tc358764_remove(struct mipi_dsi_device *dsi)
|
||||
static void tc358764_remove(struct mipi_dsi_device *dsi)
|
||||
{
|
||||
struct tc358764 *ctx = mipi_dsi_get_drvdata(dsi);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
drm_bridge_remove(&ctx->bridge);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id tc358764_of_match[] = {
|
||||
|
@ -889,6 +889,7 @@ static int tc_set_edp_video_mode(struct tc_data *tc,
|
||||
u32 dp0_syncval;
|
||||
u32 bits_per_pixel = 24;
|
||||
u32 in_bw, out_bw;
|
||||
u32 dpipxlfmt;
|
||||
|
||||
/*
|
||||
* Recommended maximum number of symbols transferred in a transfer unit:
|
||||
@ -938,10 +939,15 @@ static int tc_set_edp_video_mode(struct tc_data *tc,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
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);
|
||||
dpipxlfmt = DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NVSYNC)
|
||||
dpipxlfmt |= VS_POL_ACTIVE_LOW;
|
||||
|
||||
if (mode->flags & DRM_MODE_FLAG_NHSYNC)
|
||||
dpipxlfmt |= HS_POL_ACTIVE_LOW;
|
||||
|
||||
ret = regmap_write(tc->regmap, DPIPXLFMT, dpipxlfmt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@ -1244,7 +1250,13 @@ static int tc_main_link_disable(struct tc_data *tc)
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_write(tc->regmap, DP0CTL, 0);
|
||||
ret = regmap_write(tc->regmap, DP0CTL, 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return regmap_update_bits(tc->regmap, DP_PHY_CTRL,
|
||||
PHY_M0_RST | PHY_M1_RST | PHY_M0_EN,
|
||||
PHY_M0_RST | PHY_M1_RST);
|
||||
}
|
||||
|
||||
static int tc_dsi_rx_enable(struct tc_data *tc)
|
||||
@ -1252,10 +1264,10 @@ static int tc_dsi_rx_enable(struct tc_data *tc)
|
||||
u32 value;
|
||||
int ret;
|
||||
|
||||
regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 3);
|
||||
regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 3);
|
||||
regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 3);
|
||||
regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 3);
|
||||
regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 5);
|
||||
regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 5);
|
||||
regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 5);
|
||||
regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 5);
|
||||
regmap_write(tc->regmap, PPI_D0S_ATMR, 0);
|
||||
regmap_write(tc->regmap, PPI_D1S_ATMR, 0);
|
||||
regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
|
||||
@ -1496,41 +1508,16 @@ tc_edp_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
dev_err(tc->dev, "main link disable error: %d\n", ret);
|
||||
}
|
||||
|
||||
static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adj)
|
||||
{
|
||||
/* Fixup sync polarities, both hsync and vsync are active low */
|
||||
adj->flags = mode->flags;
|
||||
adj->flags |= (DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC);
|
||||
adj->flags &= ~(DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int tc_common_atomic_check(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state,
|
||||
const unsigned int max_khz)
|
||||
{
|
||||
tc_bridge_mode_fixup(bridge, &crtc_state->mode,
|
||||
&crtc_state->adjusted_mode);
|
||||
|
||||
if (crtc_state->adjusted_mode.clock > max_khz)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc_dpi_atomic_check(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
/* DSI->DPI interface clock limitation: upto 100 MHz */
|
||||
return tc_common_atomic_check(bridge, bridge_state, crtc_state,
|
||||
conn_state, 100000);
|
||||
if (crtc_state->adjusted_mode.clock > 100000)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tc_edp_atomic_check(struct drm_bridge *bridge,
|
||||
@ -1539,8 +1526,10 @@ static int tc_edp_atomic_check(struct drm_bridge *bridge,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
/* DPI->(e)DP interface clock limitation: upto 154 MHz */
|
||||
return tc_common_atomic_check(bridge, bridge_state, crtc_state,
|
||||
conn_state, 154000);
|
||||
if (crtc_state->adjusted_mode.clock > 154000)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum drm_mode_status
|
||||
@ -1783,7 +1772,6 @@ static const struct drm_bridge_funcs tc_edp_bridge_funcs = {
|
||||
.atomic_check = tc_edp_atomic_check,
|
||||
.atomic_enable = tc_edp_bridge_atomic_enable,
|
||||
.atomic_disable = tc_edp_bridge_atomic_disable,
|
||||
.mode_fixup = tc_bridge_mode_fixup,
|
||||
.detect = tc_bridge_detect,
|
||||
.get_edid = tc_get_edid,
|
||||
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||
@ -2010,9 +1998,10 @@ static int tc_probe_bridge_endpoint(struct tc_data *tc)
|
||||
|
||||
for_each_endpoint_of_node(dev->of_node, node) {
|
||||
of_graph_parse_endpoint(node, &endpoint);
|
||||
if (endpoint.port > 2)
|
||||
if (endpoint.port > 2) {
|
||||
of_node_put(node);
|
||||
return -EINVAL;
|
||||
|
||||
}
|
||||
mode |= BIT(endpoint.port);
|
||||
}
|
||||
|
||||
|
@ -698,11 +698,6 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
|
||||
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
|
||||
int ret;
|
||||
|
||||
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
|
||||
DRM_ERROR("Fix bridge driver to make connector optional!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pdata->aux.drm_dev = bridge->dev;
|
||||
ret = drm_dp_aux_register(&pdata->aux);
|
||||
if (ret < 0) {
|
||||
@ -710,15 +705,18 @@ static int ti_sn_bridge_attach(struct drm_bridge *bridge,
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We never want the next bridge to *also* create a connector: */
|
||||
flags |= DRM_BRIDGE_ATTACH_NO_CONNECTOR;
|
||||
|
||||
/* Attach the next bridge */
|
||||
/*
|
||||
* Attach the next bridge.
|
||||
* We never want the next bridge to *also* create a connector.
|
||||
*/
|
||||
ret = drm_bridge_attach(bridge->encoder, pdata->next_bridge,
|
||||
&pdata->bridge, flags);
|
||||
&pdata->bridge, flags | DRM_BRIDGE_ATTACH_NO_CONNECTOR);
|
||||
if (ret < 0)
|
||||
goto err_initted_aux;
|
||||
|
||||
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
|
||||
return 0;
|
||||
|
||||
pdata->connector = drm_bridge_connector_init(pdata->bridge.dev,
|
||||
pdata->bridge.encoder);
|
||||
if (IS_ERR(pdata->connector)) {
|
||||
@ -779,9 +777,9 @@ static void ti_sn_bridge_set_dsi_rate(struct ti_sn65dsi86 *pdata)
|
||||
regmap_write(pdata->regmap, SN_DSIA_CLK_FREQ_REG, val);
|
||||
}
|
||||
|
||||
static unsigned int ti_sn_bridge_get_bpp(struct ti_sn65dsi86 *pdata)
|
||||
static unsigned int ti_sn_bridge_get_bpp(struct drm_connector *connector)
|
||||
{
|
||||
if (pdata->connector->display_info.bpc <= 6)
|
||||
if (connector->display_info.bpc <= 6)
|
||||
return 18;
|
||||
else
|
||||
return 24;
|
||||
@ -796,7 +794,7 @@ static const unsigned int ti_sn_bridge_dp_rate_lut[] = {
|
||||
0, 1620, 2160, 2430, 2700, 3240, 4320, 5400
|
||||
};
|
||||
|
||||
static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata)
|
||||
static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata, unsigned int bpp)
|
||||
{
|
||||
unsigned int bit_rate_khz, dp_rate_mhz;
|
||||
unsigned int i;
|
||||
@ -804,7 +802,7 @@ static int ti_sn_bridge_calc_min_dp_rate_idx(struct ti_sn65dsi86 *pdata)
|
||||
&pdata->bridge.encoder->crtc->state->adjusted_mode;
|
||||
|
||||
/* Calculate minimum bit rate based on our pixel clock. */
|
||||
bit_rate_khz = mode->clock * ti_sn_bridge_get_bpp(pdata);
|
||||
bit_rate_khz = mode->clock * bpp;
|
||||
|
||||
/* Calculate minimum DP data rate, taking 80% as per DP spec */
|
||||
dp_rate_mhz = DIV_ROUND_UP(bit_rate_khz * DP_CLK_FUDGE_NUM,
|
||||
@ -1016,12 +1014,21 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct ti_sn65dsi86 *pdata = bridge_to_ti_sn65dsi86(bridge);
|
||||
struct drm_connector *connector;
|
||||
const char *last_err_str = "No supported DP rate";
|
||||
unsigned int valid_rates;
|
||||
int dp_rate_idx;
|
||||
unsigned int val;
|
||||
int ret = -EINVAL;
|
||||
int max_dp_lanes;
|
||||
unsigned int bpp;
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(old_bridge_state->base.state,
|
||||
bridge->encoder);
|
||||
if (!connector) {
|
||||
dev_err_ratelimited(pdata->dev, "Could not get the connector\n");
|
||||
return;
|
||||
}
|
||||
|
||||
max_dp_lanes = ti_sn_get_max_lanes(pdata);
|
||||
pdata->dp_lanes = min(pdata->dp_lanes, max_dp_lanes);
|
||||
@ -1047,8 +1054,9 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
drm_dp_dpcd_writeb(&pdata->aux, DP_EDP_CONFIGURATION_SET,
|
||||
DP_ALTERNATE_SCRAMBLER_RESET_ENABLE);
|
||||
|
||||
bpp = ti_sn_bridge_get_bpp(connector);
|
||||
/* Set the DP output format (18 bpp or 24 bpp) */
|
||||
val = (ti_sn_bridge_get_bpp(pdata) == 18) ? BPP_18_RGB : 0;
|
||||
val = bpp == 18 ? BPP_18_RGB : 0;
|
||||
regmap_update_bits(pdata->regmap, SN_DATA_FORMAT_REG, BPP_18_RGB, val);
|
||||
|
||||
/* DP lane config */
|
||||
@ -1059,7 +1067,7 @@ static void ti_sn_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
valid_rates = ti_sn_bridge_read_valid_rates(pdata);
|
||||
|
||||
/* Train until we run out of rates */
|
||||
for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata);
|
||||
for (dp_rate_idx = ti_sn_bridge_calc_min_dp_rate_idx(pdata, bpp);
|
||||
dp_rate_idx < ARRAY_SIZE(ti_sn_bridge_dp_rate_lut);
|
||||
dp_rate_idx++) {
|
||||
if (!(valid_rates & BIT(dp_rate_idx)))
|
||||
@ -1198,10 +1206,9 @@ static int ti_sn_bridge_probe(struct auxiliary_device *adev,
|
||||
int ret;
|
||||
|
||||
pdata->next_bridge = devm_drm_of_get_bridge(pdata->dev, np, 1, 0);
|
||||
if (IS_ERR(pdata->next_bridge)) {
|
||||
DRM_ERROR("failed to create panel bridge\n");
|
||||
return PTR_ERR(pdata->next_bridge);
|
||||
}
|
||||
if (IS_ERR(pdata->next_bridge))
|
||||
return dev_err_probe(pdata->dev, PTR_ERR(pdata->next_bridge),
|
||||
"failed to create panel bridge\n");
|
||||
|
||||
ti_sn_bridge_parse_lanes(pdata, np);
|
||||
|
||||
|
@ -1597,7 +1597,7 @@ static int drm_dp_aux_reply_duration(const struct drm_dp_aux_msg *msg)
|
||||
|
||||
/*
|
||||
* Calculate the length of the i2c transfer in usec, assuming
|
||||
* the i2c bus speed is as specified. Gives the the "worst"
|
||||
* the i2c bus speed is as specified. Gives the "worst"
|
||||
* case estimate, ie. successful while as long as possible.
|
||||
* Doesn't account the "MOT" bit, and instead assumes each
|
||||
* message includes a START, ADDRESS and STOP. Neither does it
|
||||
|
@ -4907,14 +4907,14 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
|
||||
seq_printf(m, "dpcd: %*ph\n", DP_RECEIVER_CAP_SIZE, buf);
|
||||
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_FAUX_CAP, buf, 2);
|
||||
if (ret) {
|
||||
if (ret != 2) {
|
||||
seq_printf(m, "faux/mst read failed\n");
|
||||
goto out;
|
||||
}
|
||||
seq_printf(m, "faux/mst: %*ph\n", 2, buf);
|
||||
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_MSTM_CTRL, buf, 1);
|
||||
if (ret) {
|
||||
if (ret != 1) {
|
||||
seq_printf(m, "mst ctrl read failed\n");
|
||||
goto out;
|
||||
}
|
||||
@ -4922,7 +4922,7 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
|
||||
|
||||
/* dump the standard OUI branch header */
|
||||
ret = drm_dp_dpcd_read(mgr->aux, DP_BRANCH_OUI, buf, DP_BRANCH_OUI_HEADER_SIZE);
|
||||
if (ret) {
|
||||
if (ret != DP_BRANCH_OUI_HEADER_SIZE) {
|
||||
seq_printf(m, "branch oui read failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
@ -38,7 +38,6 @@
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_self_refresh_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
@ -140,14 +140,14 @@ struct drm_master *drm_master_create(struct drm_device *dev)
|
||||
|
||||
kref_init(&master->refcount);
|
||||
drm_master_legacy_init(master);
|
||||
idr_init(&master->magic_map);
|
||||
idr_init_base(&master->magic_map, 1);
|
||||
master->dev = dev;
|
||||
|
||||
/* initialize the tree of output resource lessees */
|
||||
INIT_LIST_HEAD(&master->lessees);
|
||||
INIT_LIST_HEAD(&master->lessee_list);
|
||||
idr_init(&master->leases);
|
||||
idr_init(&master->lessee_idr);
|
||||
idr_init_base(&master->lessee_idr, 1);
|
||||
|
||||
return master;
|
||||
}
|
||||
|
@ -847,8 +847,8 @@ static int select_bus_fmt_recursive(struct drm_bridge *first_bridge,
|
||||
struct drm_connector_state *conn_state,
|
||||
u32 out_bus_fmt)
|
||||
{
|
||||
unsigned int i, num_in_bus_fmts = 0;
|
||||
struct drm_bridge_state *cur_state;
|
||||
unsigned int num_in_bus_fmts, i;
|
||||
struct drm_bridge *prev_bridge;
|
||||
u32 *in_bus_fmts;
|
||||
int ret;
|
||||
@ -969,7 +969,7 @@ drm_atomic_bridge_chain_select_bus_fmts(struct drm_bridge *bridge,
|
||||
struct drm_connector *conn = conn_state->connector;
|
||||
struct drm_encoder *encoder = bridge->encoder;
|
||||
struct drm_bridge_state *last_bridge_state;
|
||||
unsigned int i, num_out_bus_fmts;
|
||||
unsigned int i, num_out_bus_fmts = 0;
|
||||
struct drm_bridge *last_bridge;
|
||||
u32 *out_bus_fmts;
|
||||
int ret = 0;
|
||||
|
@ -264,7 +264,7 @@ drm_client_buffer_create(struct drm_client_dev *client, u32 width, u32 height, u
|
||||
|
||||
dumb_args.width = width;
|
||||
dumb_args.height = height;
|
||||
dumb_args.bpp = info->cpp[0] * 8;
|
||||
dumb_args.bpp = drm_format_info_bpp(info, 0);
|
||||
ret = drm_mode_create_dumb(dev, &dumb_args, client->file);
|
||||
if (ret)
|
||||
goto err_delete;
|
||||
@ -373,7 +373,7 @@ static int drm_client_buffer_addfb(struct drm_client_buffer *buffer,
|
||||
int ret;
|
||||
|
||||
info = drm_format_info(format);
|
||||
fb_req.bpp = info->cpp[0] * 8;
|
||||
fb_req.bpp = drm_format_info_bpp(info, 0);
|
||||
fb_req.depth = info->depth;
|
||||
fb_req.width = width;
|
||||
fb_req.height = height;
|
||||
|
@ -575,7 +575,7 @@ int drm_plane_create_color_properties(struct drm_plane *plane,
|
||||
len++;
|
||||
}
|
||||
|
||||
prop = drm_property_create_enum(dev, 0, "COLOR_RANGE",
|
||||
prop = drm_property_create_enum(dev, 0, "COLOR_RANGE",
|
||||
enum_list, len);
|
||||
if (!prop)
|
||||
return -ENOMEM;
|
||||
|
@ -22,15 +22,16 @@
|
||||
|
||||
#include <drm/drm_auth.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_utils.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_file.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_panel.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_privacy_screen_consumer.h>
|
||||
#include <drm/drm_sysfs.h>
|
||||
#include <drm/drm_utils.h>
|
||||
|
||||
#include <linux/fb.h>
|
||||
#include <linux/uaccess.h>
|
||||
@ -214,23 +215,11 @@ void drm_connector_free_work_fn(struct work_struct *work)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_init - 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
|
||||
*
|
||||
* Initialises a preallocated connector. Connectors should be
|
||||
* subclassed as part of driver connector objects.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_connector_init(struct drm_device *dev,
|
||||
struct drm_connector *connector,
|
||||
const struct drm_connector_funcs *funcs,
|
||||
int connector_type)
|
||||
static int __drm_connector_init(struct drm_device *dev,
|
||||
struct drm_connector *connector,
|
||||
const struct drm_connector_funcs *funcs,
|
||||
int connector_type,
|
||||
struct i2c_adapter *ddc)
|
||||
{
|
||||
struct drm_mode_config *config = &dev->mode_config;
|
||||
int ret;
|
||||
@ -278,6 +267,9 @@ int drm_connector_init(struct drm_device *dev,
|
||||
goto out_put_type_id;
|
||||
}
|
||||
|
||||
/* provide ddc symlink in sysfs */
|
||||
connector->ddc = ddc;
|
||||
|
||||
INIT_LIST_HEAD(&connector->global_connector_list_entry);
|
||||
INIT_LIST_HEAD(&connector->probed_modes);
|
||||
INIT_LIST_HEAD(&connector->modes);
|
||||
@ -334,6 +326,38 @@ out_put:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_connector_init - 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
|
||||
*
|
||||
* Initialises a preallocated connector. Connectors should be
|
||||
* subclassed as part of driver connector objects.
|
||||
*
|
||||
* At driver unload time the driver's &drm_connector_funcs.destroy hook
|
||||
* should call drm_connector_cleanup() and free the connector structure.
|
||||
* The connector structure should not be allocated with devm_kzalloc().
|
||||
*
|
||||
* Note: consider using drmm_connector_init() instead of
|
||||
* drm_connector_init() to let the DRM managed resource infrastructure
|
||||
* take care of cleanup and deallocation.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drm_connector_init(struct drm_device *dev,
|
||||
struct drm_connector *connector,
|
||||
const struct drm_connector_funcs *funcs,
|
||||
int connector_type)
|
||||
{
|
||||
if (drm_WARN_ON(dev, !(funcs && funcs->destroy)))
|
||||
return -EINVAL;
|
||||
|
||||
return __drm_connector_init(dev, connector, funcs, connector_type, NULL);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_init);
|
||||
|
||||
/**
|
||||
@ -347,8 +371,16 @@ EXPORT_SYMBOL(drm_connector_init);
|
||||
* Initialises a preallocated connector. Connectors should be
|
||||
* subclassed as part of driver connector objects.
|
||||
*
|
||||
* At driver unload time the driver's &drm_connector_funcs.destroy hook
|
||||
* should call drm_connector_cleanup() and free the connector structure.
|
||||
* The connector structure should not be allocated with devm_kzalloc().
|
||||
*
|
||||
* Ensures that the ddc field of the connector is correctly set.
|
||||
*
|
||||
* Note: consider using drmm_connector_init() instead of
|
||||
* drm_connector_init_with_ddc() to let the DRM managed resource
|
||||
* infrastructure take care of cleanup and deallocation.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
@ -357,19 +389,64 @@ int drm_connector_init_with_ddc(struct drm_device *dev,
|
||||
const struct drm_connector_funcs *funcs,
|
||||
int connector_type,
|
||||
struct i2c_adapter *ddc)
|
||||
{
|
||||
if (drm_WARN_ON(dev, !(funcs && funcs->destroy)))
|
||||
return -EINVAL;
|
||||
|
||||
return __drm_connector_init(dev, connector, funcs, connector_type, ddc);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_init_with_ddc);
|
||||
|
||||
static void drm_connector_cleanup_action(struct drm_device *dev,
|
||||
void *ptr)
|
||||
{
|
||||
struct drm_connector *connector = ptr;
|
||||
|
||||
drm_connector_cleanup(connector);
|
||||
}
|
||||
|
||||
/**
|
||||
* drmm_connector_init - 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: optional pointer to the associated ddc adapter
|
||||
*
|
||||
* Initialises a preallocated connector. Connectors should be
|
||||
* subclassed as part of driver connector objects.
|
||||
*
|
||||
* Cleanup is automatically handled with a call to
|
||||
* drm_connector_cleanup() in a DRM-managed action.
|
||||
*
|
||||
* The connector structure should be allocated with drmm_kzalloc().
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drmm_connector_init(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 (drm_WARN_ON(dev, funcs && funcs->destroy))
|
||||
return -EINVAL;
|
||||
|
||||
ret = __drm_connector_init(dev, connector, funcs, connector_type, NULL);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* provide ddc symlink in sysfs */
|
||||
connector->ddc = ddc;
|
||||
ret = drmm_add_action_or_reset(dev, drm_connector_cleanup_action,
|
||||
connector);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_connector_init_with_ddc);
|
||||
EXPORT_SYMBOL(drmm_connector_init);
|
||||
|
||||
/**
|
||||
* drm_connector_attach_edid_property - attach edid property.
|
||||
@ -517,6 +594,9 @@ EXPORT_SYMBOL(drm_connector_cleanup);
|
||||
* e.g. DP MST connectors. All other connectors will be registered automatically
|
||||
* when calling drm_dev_register().
|
||||
*
|
||||
* When the connector is no longer available, callers must call
|
||||
* drm_connector_unregister().
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
@ -573,9 +653,8 @@ EXPORT_SYMBOL(drm_connector_register);
|
||||
* @connector: the connector to unregister
|
||||
*
|
||||
* Unregister userspace interfaces for a connector. Only call this for
|
||||
* connectors which have registered explicitly by calling drm_dev_register(),
|
||||
* since connectors are unregistered automatically when drm_dev_unregister() is
|
||||
* called.
|
||||
* connectors which have been registered explicitly by calling
|
||||
* drm_connector_register().
|
||||
*/
|
||||
void drm_connector_unregister(struct drm_connector *connector)
|
||||
{
|
||||
|
@ -343,9 +343,10 @@ static int __drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *
|
||||
* The @primary and @cursor planes are only relevant for legacy uAPI, see
|
||||
* &drm_crtc.primary and &drm_crtc.cursor.
|
||||
*
|
||||
* Note: consider using drmm_crtc_alloc_with_planes() instead of
|
||||
* drm_crtc_init_with_planes() to let the DRM managed resource infrastructure
|
||||
* take care of cleanup and deallocation.
|
||||
* Note: consider using drmm_crtc_alloc_with_planes() or
|
||||
* drmm_crtc_init_with_planes() instead of drm_crtc_init_with_planes()
|
||||
* to let the DRM managed resource infrastructure take care of cleanup
|
||||
* and deallocation.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
@ -370,14 +371,88 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_crtc_init_with_planes);
|
||||
|
||||
static void drmm_crtc_alloc_with_planes_cleanup(struct drm_device *dev,
|
||||
void *ptr)
|
||||
static void drmm_crtc_init_with_planes_cleanup(struct drm_device *dev,
|
||||
void *ptr)
|
||||
{
|
||||
struct drm_crtc *crtc = ptr;
|
||||
|
||||
drm_crtc_cleanup(crtc);
|
||||
}
|
||||
|
||||
__printf(6, 0)
|
||||
static int __drmm_crtc_init_with_planes(struct drm_device *dev,
|
||||
struct drm_crtc *crtc,
|
||||
struct drm_plane *primary,
|
||||
struct drm_plane *cursor,
|
||||
const struct drm_crtc_funcs *funcs,
|
||||
const char *name,
|
||||
va_list args)
|
||||
{
|
||||
int ret;
|
||||
|
||||
drm_WARN_ON(dev, funcs && funcs->destroy);
|
||||
|
||||
ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
|
||||
name, args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drmm_add_action_or_reset(dev, drmm_crtc_init_with_planes_cleanup,
|
||||
crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drmm_crtc_init_with_planes - Initialise a new CRTC object with
|
||||
* specified primary and cursor planes.
|
||||
* @dev: DRM device
|
||||
* @crtc: CRTC object to init
|
||||
* @primary: Primary plane for CRTC
|
||||
* @cursor: Cursor plane for CRTC
|
||||
* @funcs: callbacks for the new CRTC
|
||||
* @name: printf style format string for the CRTC name, or NULL for default name
|
||||
*
|
||||
* Inits a new object created as base part of a driver crtc object. Drivers
|
||||
* should use this function instead of drm_crtc_init(), which is only provided
|
||||
* for backwards compatibility with drivers which do not yet support universal
|
||||
* planes). For really simple hardware which has only 1 plane look at
|
||||
* drm_simple_display_pipe_init() instead.
|
||||
*
|
||||
* Cleanup is automatically handled through registering
|
||||
* drmm_crtc_cleanup() with drmm_add_action(). The crtc structure should
|
||||
* be allocated with drmm_kzalloc().
|
||||
*
|
||||
* The @drm_crtc_funcs.destroy hook must be NULL.
|
||||
*
|
||||
* The @primary and @cursor planes are only relevant for legacy uAPI, see
|
||||
* &drm_crtc.primary and &drm_crtc.cursor.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drmm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
|
||||
struct drm_plane *primary,
|
||||
struct drm_plane *cursor,
|
||||
const struct drm_crtc_funcs *funcs,
|
||||
const char *name, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, name);
|
||||
ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
|
||||
name, ap);
|
||||
va_end(ap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drmm_crtc_init_with_planes);
|
||||
|
||||
void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
|
||||
size_t size, size_t offset,
|
||||
struct drm_plane *primary,
|
||||
@ -400,17 +475,12 @@ void *__drmm_crtc_alloc_with_planes(struct drm_device *dev,
|
||||
crtc = container + offset;
|
||||
|
||||
va_start(ap, name);
|
||||
ret = __drm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
|
||||
name, ap);
|
||||
ret = __drmm_crtc_init_with_planes(dev, crtc, primary, cursor, funcs,
|
||||
name, ap);
|
||||
va_end(ap);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ret = drmm_add_action_or_reset(dev, drmm_crtc_alloc_with_planes_cleanup,
|
||||
crtc);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return container;
|
||||
}
|
||||
EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
|
||||
|
@ -45,7 +45,6 @@
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
|
||||
|
@ -5165,6 +5165,51 @@ static void fixup_detailed_cea_mode_clock(struct drm_display_mode *mode)
|
||||
mode->clock = clock;
|
||||
}
|
||||
|
||||
static void drm_calculate_luminance_range(struct drm_connector *connector)
|
||||
{
|
||||
struct hdr_static_metadata *hdr_metadata = &connector->hdr_sink_metadata.hdmi_type1;
|
||||
struct drm_luminance_range_info *luminance_range =
|
||||
&connector->display_info.luminance_range;
|
||||
static const u8 pre_computed_values[] = {
|
||||
50, 51, 52, 53, 55, 56, 57, 58, 59, 61, 62, 63, 65, 66, 68, 69,
|
||||
71, 72, 74, 75, 77, 79, 81, 82, 84, 86, 88, 90, 92, 94, 96, 98
|
||||
};
|
||||
u32 max_avg, min_cll, max, min, q, r;
|
||||
|
||||
if (!(hdr_metadata->metadata_type & BIT(HDMI_STATIC_METADATA_TYPE1)))
|
||||
return;
|
||||
|
||||
max_avg = hdr_metadata->max_fall;
|
||||
min_cll = hdr_metadata->min_cll;
|
||||
|
||||
/*
|
||||
* From the specification (CTA-861-G), for calculating the maximum
|
||||
* luminance we need to use:
|
||||
* Luminance = 50*2**(CV/32)
|
||||
* Where CV is a one-byte value.
|
||||
* For calculating this expression we may need float point precision;
|
||||
* to avoid this complexity level, we take advantage that CV is divided
|
||||
* by a constant. From the Euclids division algorithm, we know that CV
|
||||
* can be written as: CV = 32*q + r. Next, we replace CV in the
|
||||
* Luminance expression and get 50*(2**q)*(2**(r/32)), hence we just
|
||||
* need to pre-compute the value of r/32. For pre-computing the values
|
||||
* We just used the following Ruby line:
|
||||
* (0...32).each {|cv| puts (50*2**(cv/32.0)).round}
|
||||
* The results of the above expressions can be verified at
|
||||
* pre_computed_values.
|
||||
*/
|
||||
q = max_avg >> 5;
|
||||
r = max_avg % 32;
|
||||
max = (1 << q) * pre_computed_values[r];
|
||||
|
||||
/* min luminance: maxLum * (CV/255)^2 / 100 */
|
||||
q = DIV_ROUND_CLOSEST(min_cll, 255);
|
||||
min = max * DIV_ROUND_CLOSEST((q * q), 100);
|
||||
|
||||
luminance_range->min_luminance = min;
|
||||
luminance_range->max_luminance = max;
|
||||
}
|
||||
|
||||
static uint8_t eotf_supported(const u8 *edid_ext)
|
||||
{
|
||||
return edid_ext[2] &
|
||||
@ -5196,8 +5241,12 @@ drm_parse_hdr_metadata_block(struct drm_connector *connector, const u8 *db)
|
||||
connector->hdr_sink_metadata.hdmi_type1.max_cll = db[4];
|
||||
if (len >= 5)
|
||||
connector->hdr_sink_metadata.hdmi_type1.max_fall = db[5];
|
||||
if (len >= 6)
|
||||
if (len >= 6) {
|
||||
connector->hdr_sink_metadata.hdmi_type1.min_cll = db[6];
|
||||
|
||||
/* Calculate only when all values are available */
|
||||
drm_calculate_luminance_range(connector);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -6101,6 +6150,7 @@ static void drm_reset_display_info(struct drm_connector *connector)
|
||||
|
||||
info->non_desktop = 0;
|
||||
memset(&info->monitor_range, 0, sizeof(info->monitor_range));
|
||||
memset(&info->luminance_range, 0, sizeof(info->luminance_range));
|
||||
|
||||
info->mso_stream_count = 0;
|
||||
info->mso_pixel_overlap = 0;
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_internal.h"
|
||||
|
||||
@ -148,9 +149,9 @@ out_put:
|
||||
* the encoder structure. The encoder structure should not be allocated with
|
||||
* devm_kzalloc().
|
||||
*
|
||||
* Note: consider using drmm_encoder_alloc() instead of drm_encoder_init() to
|
||||
* let the DRM managed resource infrastructure take care of cleanup and
|
||||
* deallocation.
|
||||
* Note: consider using drmm_encoder_alloc() or drmm_encoder_init()
|
||||
* instead of drm_encoder_init() to let the DRM managed resource
|
||||
* infrastructure take care of cleanup and deallocation.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
@ -212,6 +213,30 @@ static void drmm_encoder_alloc_release(struct drm_device *dev, void *ptr)
|
||||
drm_encoder_cleanup(encoder);
|
||||
}
|
||||
|
||||
__printf(5, 0)
|
||||
static int __drmm_encoder_init(struct drm_device *dev,
|
||||
struct drm_encoder *encoder,
|
||||
const struct drm_encoder_funcs *funcs,
|
||||
int encoder_type,
|
||||
const char *name,
|
||||
va_list args)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (drm_WARN_ON(dev, funcs && funcs->destroy))
|
||||
return -EINVAL;
|
||||
|
||||
ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
|
||||
const struct drm_encoder_funcs *funcs,
|
||||
int encoder_type, const char *name, ...)
|
||||
@ -221,9 +246,6 @@ void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
if (WARN_ON(funcs && funcs->destroy))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
container = drmm_kzalloc(dev, size, GFP_KERNEL);
|
||||
if (!container)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
@ -231,19 +253,50 @@ void *__drmm_encoder_alloc(struct drm_device *dev, size_t size, size_t offset,
|
||||
encoder = container + offset;
|
||||
|
||||
va_start(ap, name);
|
||||
ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
|
||||
ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
|
||||
va_end(ap);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
ret = drmm_add_action_or_reset(dev, drmm_encoder_alloc_release, encoder);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return container;
|
||||
}
|
||||
EXPORT_SYMBOL(__drmm_encoder_alloc);
|
||||
|
||||
/**
|
||||
* drmm_encoder_init - Initialize a preallocated encoder
|
||||
* @dev: drm device
|
||||
* @encoder: the encoder to init
|
||||
* @funcs: callbacks for this encoder (optional)
|
||||
* @encoder_type: user visible type of the encoder
|
||||
* @name: printf style format string for the encoder name, or NULL for default name
|
||||
*
|
||||
* Initializes a preallocated encoder. Encoder should be subclassed as
|
||||
* part of driver encoder objects. Cleanup is automatically handled
|
||||
* through registering drm_encoder_cleanup() with drmm_add_action(). The
|
||||
* encoder structure should be allocated with drmm_kzalloc().
|
||||
*
|
||||
* The @drm_encoder_funcs.destroy hook must be NULL.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, error code on failure.
|
||||
*/
|
||||
int drmm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder,
|
||||
const struct drm_encoder_funcs *funcs,
|
||||
int encoder_type, const char *name, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int ret;
|
||||
|
||||
va_start(ap, name);
|
||||
ret = __drmm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
|
||||
va_end(ap);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(drmm_encoder_init);
|
||||
|
||||
static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* drm kms/fb cma (contiguous memory allocator) helper functions
|
||||
* drm kms/fb dma helper functions
|
||||
*
|
||||
* Copyright (C) 2012 Analog Devices Inc.
|
||||
* Author: Lars-Peter Clausen <lars@metafoo.de>
|
||||
@ -10,35 +10,40 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_damage_helper.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_fb_dma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_plane.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/module.h>
|
||||
|
||||
/**
|
||||
* DOC: framebuffer cma helper functions
|
||||
* DOC: framebuffer dma helper functions
|
||||
*
|
||||
* Provides helper functions for creating a cma (contiguous memory allocator)
|
||||
* backed framebuffer.
|
||||
* Provides helper functions for creating a DMA-contiguous framebuffer.
|
||||
*
|
||||
* Depending on the platform, the buffers may be physically non-contiguous and
|
||||
* mapped through an IOMMU or a similar mechanism, or allocated from
|
||||
* physically-contiguous memory (using, for instance, CMA or a pool of memory
|
||||
* reserved at early boot). This is handled behind the scenes by the DMA mapping
|
||||
* API.
|
||||
*
|
||||
* drm_gem_fb_create() is used in the &drm_mode_config_funcs.fb_create
|
||||
* callback function to create a cma backed framebuffer.
|
||||
* callback function to create a DMA-contiguous framebuffer.
|
||||
*/
|
||||
|
||||
/**
|
||||
* drm_fb_cma_get_gem_obj() - Get CMA GEM object for framebuffer
|
||||
* drm_fb_dma_get_gem_obj() - Get DMA GEM object for framebuffer
|
||||
* @fb: The framebuffer
|
||||
* @plane: Which plane
|
||||
*
|
||||
* Return the CMA GEM object for given framebuffer.
|
||||
* Return the DMA GEM object for given framebuffer.
|
||||
*
|
||||
* This function will usually be called from the CRTC callback functions.
|
||||
*/
|
||||
struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
|
||||
struct drm_gem_dma_object *drm_fb_dma_get_gem_obj(struct drm_framebuffer *fb,
|
||||
unsigned int plane)
|
||||
{
|
||||
struct drm_gem_object *gem;
|
||||
@ -47,27 +52,27 @@ struct drm_gem_cma_object *drm_fb_cma_get_gem_obj(struct drm_framebuffer *fb,
|
||||
if (!gem)
|
||||
return NULL;
|
||||
|
||||
return to_drm_gem_cma_obj(gem);
|
||||
return to_drm_gem_dma_obj(gem);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_obj);
|
||||
EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_obj);
|
||||
|
||||
/**
|
||||
* drm_fb_cma_get_gem_addr() - Get physical address for framebuffer, for pixel
|
||||
* drm_fb_dma_get_gem_addr() - Get DMA (bus) address for framebuffer, for pixel
|
||||
* formats where values are grouped in blocks this will get you the beginning of
|
||||
* the block
|
||||
* @fb: The framebuffer
|
||||
* @state: Which state of drm plane
|
||||
* @plane: Which plane
|
||||
* Return the CMA GEM address for given framebuffer.
|
||||
* Return the DMA GEM address for given framebuffer.
|
||||
*
|
||||
* This function will usually be called from the PLANE callback functions.
|
||||
*/
|
||||
dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
|
||||
dma_addr_t drm_fb_dma_get_gem_addr(struct drm_framebuffer *fb,
|
||||
struct drm_plane_state *state,
|
||||
unsigned int plane)
|
||||
{
|
||||
struct drm_gem_cma_object *obj;
|
||||
dma_addr_t paddr;
|
||||
struct drm_gem_dma_object *obj;
|
||||
dma_addr_t dma_addr;
|
||||
u8 h_div = 1, v_div = 1;
|
||||
u32 block_w = drm_format_info_block_width(fb->format, plane);
|
||||
u32 block_h = drm_format_info_block_height(fb->format, plane);
|
||||
@ -77,11 +82,11 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
|
||||
u32 block_start_y;
|
||||
u32 num_hblocks;
|
||||
|
||||
obj = drm_fb_cma_get_gem_obj(fb, plane);
|
||||
obj = drm_fb_dma_get_gem_obj(fb, plane);
|
||||
if (!obj)
|
||||
return 0;
|
||||
|
||||
paddr = obj->paddr + fb->offsets[plane];
|
||||
dma_addr = obj->dma_addr + fb->offsets[plane];
|
||||
|
||||
if (plane > 0) {
|
||||
h_div = fb->format->hsub;
|
||||
@ -93,43 +98,43 @@ dma_addr_t drm_fb_cma_get_gem_addr(struct drm_framebuffer *fb,
|
||||
block_start_y = (sample_y / block_h) * block_h;
|
||||
num_hblocks = sample_x / block_w;
|
||||
|
||||
paddr += fb->pitches[plane] * block_start_y;
|
||||
paddr += block_size * num_hblocks;
|
||||
dma_addr += fb->pitches[plane] * block_start_y;
|
||||
dma_addr += block_size * num_hblocks;
|
||||
|
||||
return paddr;
|
||||
return dma_addr;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_fb_cma_get_gem_addr);
|
||||
EXPORT_SYMBOL_GPL(drm_fb_dma_get_gem_addr);
|
||||
|
||||
/**
|
||||
* drm_fb_cma_sync_non_coherent - Sync GEM object to non-coherent backing
|
||||
* drm_fb_dma_sync_non_coherent - Sync GEM object to non-coherent backing
|
||||
* memory
|
||||
* @drm: DRM device
|
||||
* @old_state: Old plane state
|
||||
* @state: New plane state
|
||||
*
|
||||
* This function can be used by drivers that use damage clips and have
|
||||
* CMA GEM objects backed by non-coherent memory. Calling this function
|
||||
* DMA GEM objects backed by non-coherent memory. Calling this function
|
||||
* in a plane's .atomic_update ensures that all the data in the backing
|
||||
* memory have been written to RAM.
|
||||
*/
|
||||
void drm_fb_cma_sync_non_coherent(struct drm_device *drm,
|
||||
void drm_fb_dma_sync_non_coherent(struct drm_device *drm,
|
||||
struct drm_plane_state *old_state,
|
||||
struct drm_plane_state *state)
|
||||
{
|
||||
const struct drm_format_info *finfo = state->fb->format;
|
||||
struct drm_atomic_helper_damage_iter iter;
|
||||
const struct drm_gem_cma_object *cma_obj;
|
||||
const struct drm_gem_dma_object *dma_obj;
|
||||
unsigned int offset, i;
|
||||
struct drm_rect clip;
|
||||
dma_addr_t daddr;
|
||||
size_t nb_bytes;
|
||||
|
||||
for (i = 0; i < finfo->num_planes; i++) {
|
||||
cma_obj = drm_fb_cma_get_gem_obj(state->fb, i);
|
||||
if (!cma_obj->map_noncoherent)
|
||||
dma_obj = drm_fb_dma_get_gem_obj(state->fb, i);
|
||||
if (!dma_obj->map_noncoherent)
|
||||
continue;
|
||||
|
||||
daddr = drm_fb_cma_get_gem_addr(state->fb, state, i);
|
||||
daddr = drm_fb_dma_get_gem_addr(state->fb, state, i);
|
||||
drm_atomic_helper_damage_iter_init(&iter, old_state, state);
|
||||
|
||||
drm_atomic_for_each_plane_damage(&iter, &clip) {
|
||||
@ -142,4 +147,4 @@ void drm_fb_cma_sync_non_coherent(struct drm_device *drm,
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_fb_cma_sync_non_coherent);
|
||||
EXPORT_SYMBOL_GPL(drm_fb_dma_sync_non_coherent);
|
@ -377,12 +377,31 @@ static void drm_fb_helper_damage_blit_real(struct drm_fb_helper *fb_helper,
|
||||
struct iosys_map *dst)
|
||||
{
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
unsigned int cpp = fb->format->cpp[0];
|
||||
size_t offset = clip->y1 * fb->pitches[0] + clip->x1 * cpp;
|
||||
void *src = fb_helper->fbdev->screen_buffer + offset;
|
||||
size_t len = (clip->x2 - clip->x1) * cpp;
|
||||
size_t offset = clip->y1 * fb->pitches[0];
|
||||
size_t len = clip->x2 - clip->x1;
|
||||
unsigned int y;
|
||||
void *src;
|
||||
|
||||
switch (drm_format_info_bpp(fb->format, 0)) {
|
||||
case 1:
|
||||
offset += clip->x1 / 8;
|
||||
len = DIV_ROUND_UP(len + clip->x1 % 8, 8);
|
||||
break;
|
||||
case 2:
|
||||
offset += clip->x1 / 4;
|
||||
len = DIV_ROUND_UP(len + clip->x1 % 4, 4);
|
||||
break;
|
||||
case 4:
|
||||
offset += clip->x1 / 2;
|
||||
len = DIV_ROUND_UP(len + clip->x1 % 2, 2);
|
||||
break;
|
||||
default:
|
||||
offset += clip->x1 * fb->format->cpp[0];
|
||||
len *= fb->format->cpp[0];
|
||||
break;
|
||||
}
|
||||
|
||||
src = fb_helper->fbdev->screen_buffer + offset;
|
||||
iosys_map_incr(dst, offset); /* go to first pixel within clip rect */
|
||||
|
||||
for (y = clip->y1; y < clip->y2; y++) {
|
||||
@ -1274,19 +1293,23 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,
|
||||
}
|
||||
|
||||
static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
|
||||
u8 depth)
|
||||
const struct drm_format_info *format)
|
||||
{
|
||||
switch (depth) {
|
||||
case 8:
|
||||
u8 depth = format->depth;
|
||||
|
||||
if (format->is_color_indexed) {
|
||||
var->red.offset = 0;
|
||||
var->green.offset = 0;
|
||||
var->blue.offset = 0;
|
||||
var->red.length = 8; /* 8bit DAC */
|
||||
var->green.length = 8;
|
||||
var->blue.length = 8;
|
||||
var->red.length = depth;
|
||||
var->green.length = depth;
|
||||
var->blue.length = depth;
|
||||
var->transp.offset = 0;
|
||||
var->transp.length = 0;
|
||||
break;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (depth) {
|
||||
case 15:
|
||||
var->red.offset = 10;
|
||||
var->green.offset = 5;
|
||||
@ -1341,7 +1364,9 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
{
|
||||
struct drm_fb_helper *fb_helper = info->par;
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
const struct drm_format_info *format = fb->format;
|
||||
struct drm_device *dev = fb_helper->dev;
|
||||
unsigned int bpp;
|
||||
|
||||
if (in_dbg_master())
|
||||
return -EINVAL;
|
||||
@ -1351,22 +1376,33 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
var->pixclock = 0;
|
||||
}
|
||||
|
||||
if ((drm_format_info_block_width(fb->format, 0) > 1) ||
|
||||
(drm_format_info_block_height(fb->format, 0) > 1))
|
||||
return -EINVAL;
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_C1:
|
||||
case DRM_FORMAT_C2:
|
||||
case DRM_FORMAT_C4:
|
||||
/* supported format with sub-byte pixels */
|
||||
break;
|
||||
|
||||
default:
|
||||
if ((drm_format_info_block_width(format, 0) > 1) ||
|
||||
(drm_format_info_block_height(format, 0) > 1))
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Changes struct fb_var_screeninfo are currently not pushed back
|
||||
* to KMS, hence fail if different settings are requested.
|
||||
*/
|
||||
if (var->bits_per_pixel > fb->format->cpp[0] * 8 ||
|
||||
bpp = drm_format_info_bpp(format, 0);
|
||||
if (var->bits_per_pixel > bpp ||
|
||||
var->xres > fb->width || var->yres > fb->height ||
|
||||
var->xres_virtual > fb->width || var->yres_virtual > fb->height) {
|
||||
drm_dbg_kms(dev, "fb requested width/height/bpp can't fit in current fb "
|
||||
"request %dx%d-%d (virtual %dx%d) > %dx%d-%d\n",
|
||||
var->xres, var->yres, var->bits_per_pixel,
|
||||
var->xres_virtual, var->yres_virtual,
|
||||
fb->width, fb->height, fb->format->cpp[0] * 8);
|
||||
fb->width, fb->height, bpp);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@ -1381,13 +1417,13 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
|
||||
!var->blue.length && !var->transp.length &&
|
||||
!var->red.msb_right && !var->green.msb_right &&
|
||||
!var->blue.msb_right && !var->transp.msb_right) {
|
||||
drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
|
||||
drm_fb_helper_fill_pixel_fmt(var, format);
|
||||
}
|
||||
|
||||
/*
|
||||
* Likewise, bits_per_pixel should be rounded up to a supported value.
|
||||
*/
|
||||
var->bits_per_pixel = fb->format->cpp[0] * 8;
|
||||
var->bits_per_pixel = bpp;
|
||||
|
||||
/*
|
||||
* drm fbdev emulation doesn't support changing the pixel format at all,
|
||||
@ -1723,11 +1759,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper,
|
||||
}
|
||||
|
||||
static void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
|
||||
uint32_t depth)
|
||||
bool is_color_indexed)
|
||||
{
|
||||
info->fix.type = FB_TYPE_PACKED_PIXELS;
|
||||
info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
|
||||
FB_VISUAL_TRUECOLOR;
|
||||
info->fix.visual = is_color_indexed ? FB_VISUAL_PSEUDOCOLOR
|
||||
: FB_VISUAL_TRUECOLOR;
|
||||
info->fix.mmio_start = 0;
|
||||
info->fix.mmio_len = 0;
|
||||
info->fix.type_aux = 0;
|
||||
@ -1744,19 +1780,31 @@ static void drm_fb_helper_fill_var(struct fb_info *info,
|
||||
uint32_t fb_width, uint32_t fb_height)
|
||||
{
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
const struct drm_format_info *format = fb->format;
|
||||
|
||||
switch (format->format) {
|
||||
case DRM_FORMAT_C1:
|
||||
case DRM_FORMAT_C2:
|
||||
case DRM_FORMAT_C4:
|
||||
/* supported format with sub-byte pixels */
|
||||
break;
|
||||
|
||||
default:
|
||||
WARN_ON((drm_format_info_block_width(format, 0) > 1) ||
|
||||
(drm_format_info_block_height(format, 0) > 1));
|
||||
break;
|
||||
}
|
||||
|
||||
WARN_ON((drm_format_info_block_width(fb->format, 0) > 1) ||
|
||||
(drm_format_info_block_height(fb->format, 0) > 1));
|
||||
info->pseudo_palette = fb_helper->pseudo_palette;
|
||||
info->var.xres_virtual = fb->width;
|
||||
info->var.yres_virtual = fb->height;
|
||||
info->var.bits_per_pixel = fb->format->cpp[0] * 8;
|
||||
info->var.bits_per_pixel = drm_format_info_bpp(format, 0);
|
||||
info->var.accel_flags = FB_ACCELF_TEXT;
|
||||
info->var.xoffset = 0;
|
||||
info->var.yoffset = 0;
|
||||
info->var.activate = FB_ACTIVATE_NOW;
|
||||
|
||||
drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);
|
||||
drm_fb_helper_fill_pixel_fmt(&info->var, format);
|
||||
|
||||
info->var.xres = fb_width;
|
||||
info->var.yres = fb_height;
|
||||
@ -1781,7 +1829,8 @@ void drm_fb_helper_fill_info(struct fb_info *info,
|
||||
{
|
||||
struct drm_framebuffer *fb = fb_helper->fb;
|
||||
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
|
||||
drm_fb_helper_fill_fix(info, fb->pitches[0],
|
||||
fb->format->is_color_indexed);
|
||||
drm_fb_helper_fill_var(info, fb_helper,
|
||||
sizes->fb_width, sizes->fb_height);
|
||||
|
||||
|
@ -48,11 +48,6 @@
|
||||
#include "drm_internal.h"
|
||||
#include "drm_legacy.h"
|
||||
|
||||
#if defined(CONFIG_MMU) && defined(CONFIG_TRANSPARENT_HUGEPAGE)
|
||||
#include <uapi/asm/mman.h>
|
||||
#include <drm/drm_vma_manager.h>
|
||||
#endif
|
||||
|
||||
/* from BKL pushdown */
|
||||
DEFINE_MUTEX(drm_global_mutex);
|
||||
|
||||
@ -131,7 +126,7 @@ bool drm_dev_needs_global_mutex(struct drm_device *dev)
|
||||
* };
|
||||
*
|
||||
* For plain GEM based drivers there is the DEFINE_DRM_GEM_FOPS() macro, and for
|
||||
* CMA based drivers there is the DEFINE_DRM_GEM_CMA_FOPS() macro to make this
|
||||
* DMA based drivers there is the DEFINE_DRM_GEM_DMA_FOPS() macro to make this
|
||||
* simpler.
|
||||
*
|
||||
* The driver's &file_operations must be stored in &drm_driver.fops.
|
||||
@ -912,139 +907,3 @@ struct file *mock_drm_getfile(struct drm_minor *minor, unsigned int flags)
|
||||
return file;
|
||||
}
|
||||
EXPORT_SYMBOL_FOR_TESTS_ONLY(mock_drm_getfile);
|
||||
|
||||
#ifdef CONFIG_MMU
|
||||
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
||||
/*
|
||||
* drm_addr_inflate() attempts to construct an aligned area by inflating
|
||||
* the area size and skipping the unaligned start of the area.
|
||||
* adapted from shmem_get_unmapped_area()
|
||||
*/
|
||||
static unsigned long drm_addr_inflate(unsigned long addr,
|
||||
unsigned long len,
|
||||
unsigned long pgoff,
|
||||
unsigned long flags,
|
||||
unsigned long huge_size)
|
||||
{
|
||||
unsigned long offset, inflated_len;
|
||||
unsigned long inflated_addr;
|
||||
unsigned long inflated_offset;
|
||||
|
||||
offset = (pgoff << PAGE_SHIFT) & (huge_size - 1);
|
||||
if (offset && offset + len < 2 * huge_size)
|
||||
return addr;
|
||||
if ((addr & (huge_size - 1)) == offset)
|
||||
return addr;
|
||||
|
||||
inflated_len = len + huge_size - PAGE_SIZE;
|
||||
if (inflated_len > TASK_SIZE)
|
||||
return addr;
|
||||
if (inflated_len < len)
|
||||
return addr;
|
||||
|
||||
inflated_addr = current->mm->get_unmapped_area(NULL, 0, inflated_len,
|
||||
0, flags);
|
||||
if (IS_ERR_VALUE(inflated_addr))
|
||||
return addr;
|
||||
if (inflated_addr & ~PAGE_MASK)
|
||||
return addr;
|
||||
|
||||
inflated_offset = inflated_addr & (huge_size - 1);
|
||||
inflated_addr += offset - inflated_offset;
|
||||
if (inflated_offset > offset)
|
||||
inflated_addr += huge_size;
|
||||
|
||||
if (inflated_addr > TASK_SIZE - len)
|
||||
return addr;
|
||||
|
||||
return inflated_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_get_unmapped_area() - Get an unused user-space virtual memory area
|
||||
* suitable for huge page table entries.
|
||||
* @file: The struct file representing the address space being mmap()'d.
|
||||
* @uaddr: Start address suggested by user-space.
|
||||
* @len: Length of the area.
|
||||
* @pgoff: The page offset into the address space.
|
||||
* @flags: mmap flags
|
||||
* @mgr: The address space manager used by the drm driver. This argument can
|
||||
* probably be removed at some point when all drivers use the same
|
||||
* address space manager.
|
||||
*
|
||||
* This function attempts to find an unused user-space virtual memory area
|
||||
* that can accommodate the size we want to map, and that is properly
|
||||
* aligned to facilitate huge page table entries matching actual
|
||||
* huge pages or huge page aligned memory in buffer objects. Buffer objects
|
||||
* are assumed to start at huge page boundary pfns (io memory) or be
|
||||
* populated by huge pages aligned to the start of the buffer object
|
||||
* (system- or coherent memory). Adapted from shmem_get_unmapped_area.
|
||||
*
|
||||
* Return: aligned user-space address.
|
||||
*/
|
||||
unsigned long drm_get_unmapped_area(struct file *file,
|
||||
unsigned long uaddr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags,
|
||||
struct drm_vma_offset_manager *mgr)
|
||||
{
|
||||
unsigned long addr;
|
||||
unsigned long inflated_addr;
|
||||
struct drm_vma_offset_node *node;
|
||||
|
||||
if (len > TASK_SIZE)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* @pgoff is the file page-offset the huge page boundaries of
|
||||
* which typically aligns to physical address huge page boundaries.
|
||||
* That's not true for DRM, however, where physical address huge
|
||||
* page boundaries instead are aligned with the offset from
|
||||
* buffer object start. So adjust @pgoff to be the offset from
|
||||
* buffer object start.
|
||||
*/
|
||||
drm_vma_offset_lock_lookup(mgr);
|
||||
node = drm_vma_offset_lookup_locked(mgr, pgoff, 1);
|
||||
if (node)
|
||||
pgoff -= node->vm_node.start;
|
||||
drm_vma_offset_unlock_lookup(mgr);
|
||||
|
||||
addr = current->mm->get_unmapped_area(file, uaddr, len, pgoff, flags);
|
||||
if (IS_ERR_VALUE(addr))
|
||||
return addr;
|
||||
if (addr & ~PAGE_MASK)
|
||||
return addr;
|
||||
if (addr > TASK_SIZE - len)
|
||||
return addr;
|
||||
|
||||
if (len < HPAGE_PMD_SIZE)
|
||||
return addr;
|
||||
if (flags & MAP_FIXED)
|
||||
return addr;
|
||||
/*
|
||||
* Our priority is to support MAP_SHARED mapped hugely;
|
||||
* and support MAP_PRIVATE mapped hugely too, until it is COWed.
|
||||
* But if caller specified an address hint, respect that as before.
|
||||
*/
|
||||
if (uaddr)
|
||||
return addr;
|
||||
|
||||
inflated_addr = drm_addr_inflate(addr, len, pgoff, flags,
|
||||
HPAGE_PMD_SIZE);
|
||||
|
||||
if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) &&
|
||||
len >= HPAGE_PUD_SIZE)
|
||||
inflated_addr = drm_addr_inflate(inflated_addr, len, pgoff,
|
||||
flags, HPAGE_PUD_SIZE);
|
||||
return inflated_addr;
|
||||
}
|
||||
#else /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
unsigned long drm_get_unmapped_area(struct file *file,
|
||||
unsigned long uaddr, unsigned long len,
|
||||
unsigned long pgoff, unsigned long flags,
|
||||
struct drm_vma_offset_manager *mgr)
|
||||
{
|
||||
return current->mm->get_unmapped_area(file, uaddr, len, pgoff, flags);
|
||||
}
|
||||
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
||||
EXPORT_SYMBOL_GPL(drm_get_unmapped_area);
|
||||
#endif /* CONFIG_MMU */
|
||||
|
@ -8,9 +8,10 @@
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/io.h>
|
||||
#include <linux/iosys-map.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_format_helper.h>
|
||||
@ -40,11 +41,11 @@ unsigned int drm_fb_clip_offset(unsigned int pitch, const struct drm_format_info
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_clip_offset);
|
||||
|
||||
/* TODO: Make this functon work with multi-plane formats. */
|
||||
static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool vaddr_cached_hint,
|
||||
void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
|
||||
/* TODO: Make this function work with multi-plane formats. */
|
||||
static int __drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool vaddr_cached_hint,
|
||||
void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
|
||||
{
|
||||
unsigned long linepixels = drm_rect_width(clip);
|
||||
unsigned long lines = drm_rect_height(clip);
|
||||
@ -54,7 +55,7 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix
|
||||
const void *sbuf;
|
||||
|
||||
/*
|
||||
* Some source buffers, such as CMA memory, use write-combine
|
||||
* Some source buffers, such as DMA memory, use write-combine
|
||||
* caching, so reads are uncached. Speed up access by fetching
|
||||
* one line at a time.
|
||||
*/
|
||||
@ -83,11 +84,11 @@ static int drm_fb_xfrm(void *dst, unsigned long dst_pitch, unsigned long dst_pix
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Make this functon work with multi-plane formats. */
|
||||
static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool vaddr_cached_hint,
|
||||
void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
|
||||
/* TODO: Make this function work with multi-plane formats. */
|
||||
static int __drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned long dst_pixsize,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool vaddr_cached_hint,
|
||||
void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
|
||||
{
|
||||
unsigned long linepixels = drm_rect_width(clip);
|
||||
unsigned long lines = drm_rect_height(clip);
|
||||
@ -128,66 +129,83 @@ static int drm_fb_xfrm_toio(void __iomem *dst, unsigned long dst_pitch, unsigned
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Make this function work with multi-plane formats. */
|
||||
static int drm_fb_xfrm(struct iosys_map *dst,
|
||||
const unsigned int *dst_pitch, const u8 *dst_pixsize,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool vaddr_cached_hint,
|
||||
void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels))
|
||||
{
|
||||
static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
if (!dst_pitch)
|
||||
dst_pitch = default_dst_pitch;
|
||||
|
||||
/* TODO: handle src in I/O memory here */
|
||||
if (dst[0].is_iomem)
|
||||
return __drm_fb_xfrm_toio(dst[0].vaddr_iomem, dst_pitch[0], dst_pixsize[0],
|
||||
src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line);
|
||||
else
|
||||
return __drm_fb_xfrm(dst[0].vaddr, dst_pitch[0], dst_pixsize[0],
|
||||
src[0].vaddr, fb, clip, vaddr_cached_hint, xfrm_line);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_memcpy - Copy clip buffer
|
||||
* @dst: Destination buffer
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: Source buffer
|
||||
* @dst: Array of destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function does not apply clipping on dst, i.e. the destination
|
||||
* is at the top-left corner.
|
||||
* This function copies parts of a framebuffer to display memory. Destination and
|
||||
* framebuffer formats must match. No conversion takes place. The parameters @dst,
|
||||
* @dst_pitch and @src refer to arrays. Each array must have at least as many entries
|
||||
* as there are planes in @fb's format. Each entry stores the value for the format's
|
||||
* respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*/
|
||||
void drm_fb_memcpy(void *dst, unsigned int dst_pitch, const void *vaddr,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip)
|
||||
void drm_fb_memcpy(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
unsigned int cpp = fb->format->cpp[0];
|
||||
size_t len = (clip->x2 - clip->x1) * cpp;
|
||||
unsigned int y, lines = clip->y2 - clip->y1;
|
||||
static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
|
||||
0, 0, 0, 0
|
||||
};
|
||||
|
||||
const struct drm_format_info *format = fb->format;
|
||||
unsigned int i, y, lines = drm_rect_height(clip);
|
||||
|
||||
if (!dst_pitch)
|
||||
dst_pitch = len;
|
||||
dst_pitch = default_dst_pitch;
|
||||
|
||||
vaddr += clip_offset(clip, fb->pitches[0], cpp);
|
||||
for (y = 0; y < lines; y++) {
|
||||
memcpy(dst, vaddr, len);
|
||||
vaddr += fb->pitches[0];
|
||||
dst += dst_pitch;
|
||||
for (i = 0; i < format->num_planes; ++i) {
|
||||
unsigned int bpp_i = drm_format_info_bpp(format, i);
|
||||
unsigned int cpp_i = DIV_ROUND_UP(bpp_i, 8);
|
||||
size_t len_i = DIV_ROUND_UP(drm_rect_width(clip) * bpp_i, 8);
|
||||
unsigned int dst_pitch_i = dst_pitch[i];
|
||||
struct iosys_map dst_i = dst[i];
|
||||
struct iosys_map src_i = src[i];
|
||||
|
||||
if (!dst_pitch_i)
|
||||
dst_pitch_i = len_i;
|
||||
|
||||
iosys_map_incr(&src_i, clip_offset(clip, fb->pitches[i], cpp_i));
|
||||
for (y = 0; y < lines; y++) {
|
||||
/* TODO: handle src_i in I/O memory here */
|
||||
iosys_map_memcpy_to(&dst_i, 0, src_i.vaddr, len_i);
|
||||
iosys_map_incr(&src_i, fb->pitches[i]);
|
||||
iosys_map_incr(&dst_i, dst_pitch_i);
|
||||
}
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_memcpy);
|
||||
|
||||
/**
|
||||
* drm_fb_memcpy_toio - Copy clip buffer
|
||||
* @dst: Destination buffer (iomem)
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: Source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function does not apply clipping on dst, i.e. the destination
|
||||
* is at the top-left corner.
|
||||
*/
|
||||
void drm_fb_memcpy_toio(void __iomem *dst, unsigned int dst_pitch, const void *vaddr,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip)
|
||||
{
|
||||
unsigned int cpp = fb->format->cpp[0];
|
||||
size_t len = (clip->x2 - clip->x1) * cpp;
|
||||
unsigned int y, lines = clip->y2 - clip->y1;
|
||||
|
||||
if (!dst_pitch)
|
||||
dst_pitch = len;
|
||||
|
||||
vaddr += clip_offset(clip, fb->pitches[0], cpp);
|
||||
for (y = 0; y < lines; y++) {
|
||||
memcpy_toio(dst, vaddr, len);
|
||||
vaddr += fb->pitches[0];
|
||||
dst += dst_pitch;
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_memcpy_toio);
|
||||
|
||||
static void drm_fb_swab16_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u16 *dbuf16 = dbuf;
|
||||
@ -210,37 +228,47 @@ static void drm_fb_swab32_line(void *dbuf, const void *sbuf, unsigned int pixels
|
||||
|
||||
/**
|
||||
* drm_fb_swab - Swap bytes into clip buffer
|
||||
* @dst: Destination buffer
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @src: Source buffer
|
||||
* @dst: Array of destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
* @cached: Source buffer is mapped cached (eg. not write-combined)
|
||||
*
|
||||
* If @cached is false a temporary buffer is used to cache one pixel line at a
|
||||
* time to speed up slow uncached reads.
|
||||
* This function copies parts of a framebuffer to display memory and swaps per-pixel
|
||||
* bytes during the process. Destination and framebuffer formats must match. The
|
||||
* parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||
* least as many entries as there are planes in @fb's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index. If @cached is
|
||||
* false a temporary buffer is used to cache one pixel line at a time to speed up
|
||||
* slow uncached reads.
|
||||
*
|
||||
* This function does not apply clipping on dst, i.e. the destination
|
||||
* is at the top-left corner.
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*/
|
||||
void drm_fb_swab(void *dst, unsigned int dst_pitch, const void *src,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip,
|
||||
bool cached)
|
||||
void drm_fb_swab(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool cached)
|
||||
{
|
||||
u8 cpp = fb->format->cpp[0];
|
||||
const struct drm_format_info *format = fb->format;
|
||||
u8 cpp = DIV_ROUND_UP(drm_format_info_bpp(format, 0), 8);
|
||||
void (*swab_line)(void *dbuf, const void *sbuf, unsigned int npixels);
|
||||
|
||||
switch (cpp) {
|
||||
case 4:
|
||||
drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab32_line);
|
||||
swab_line = drm_fb_swab32_line;
|
||||
break;
|
||||
case 2:
|
||||
drm_fb_xfrm(dst, dst_pitch, cpp, src, fb, clip, cached, drm_fb_swab16_line);
|
||||
swab_line = drm_fb_swab16_line;
|
||||
break;
|
||||
default:
|
||||
drm_warn_once(fb->dev, "Format %p4cc has unsupported pixel size.\n",
|
||||
&fb->format->format);
|
||||
break;
|
||||
&format->format);
|
||||
return;
|
||||
}
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, &cpp, src, fb, clip, cached, swab_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_swab);
|
||||
|
||||
@ -261,32 +289,50 @@ static void drm_fb_xrgb8888_to_rgb332_line(void *dbuf, const void *sbuf, unsigne
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_rgb332 - Convert XRGB8888 to RGB332 clip buffer
|
||||
* @dst: RGB332 destination buffer
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @src: XRGB8888 source buffer
|
||||
* @dst: Array of RGB332 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* Drivers can use this function for RGB332 devices that don't natively support XRGB8888.
|
||||
* This function copies parts of a framebuffer to display memory and converts the
|
||||
* color format during the process. Destination and framebuffer formats must match. The
|
||||
* parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||
* least as many entries as there are planes in @fb's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for RGB332 devices that don't support XRGB8888 natively.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_rgb332(void *dst, unsigned int dst_pitch, const void *src,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip)
|
||||
void drm_fb_xrgb8888_to_rgb332(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
drm_fb_xfrm(dst, dst_pitch, 1, src, fb, clip, false, drm_fb_xrgb8888_to_rgb332_line);
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
1,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgb332_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb332);
|
||||
|
||||
static void drm_fb_xrgb8888_to_rgb565_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u16 *dbuf16 = dbuf;
|
||||
const u32 *sbuf32 = sbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u16 val16;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
val16 = ((sbuf32[x] & 0x00F80000) >> 8) |
|
||||
((sbuf32[x] & 0x0000FC00) >> 5) |
|
||||
((sbuf32[x] & 0x000000F8) >> 3);
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
val16 = ((pix & 0x00F80000) >> 8) |
|
||||
((pix & 0x0000FC00) >> 5) |
|
||||
((pix & 0x000000F8) >> 3);
|
||||
dbuf16[x] = val16;
|
||||
}
|
||||
}
|
||||
@ -295,146 +341,143 @@ static void drm_fb_xrgb8888_to_rgb565_swab_line(void *dbuf, const void *sbuf,
|
||||
unsigned int pixels)
|
||||
{
|
||||
u16 *dbuf16 = dbuf;
|
||||
const u32 *sbuf32 = sbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u16 val16;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
val16 = ((sbuf32[x] & 0x00F80000) >> 8) |
|
||||
((sbuf32[x] & 0x0000FC00) >> 5) |
|
||||
((sbuf32[x] & 0x000000F8) >> 3);
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
val16 = ((pix & 0x00F80000) >> 8) |
|
||||
((pix & 0x0000FC00) >> 5) |
|
||||
((pix & 0x000000F8) >> 3);
|
||||
dbuf16[x] = swab16(val16);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_rgb565 - Convert XRGB8888 to RGB565 clip buffer
|
||||
* @dst: RGB565 destination buffer
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: XRGB8888 source buffer
|
||||
* @dst: Array of RGB565 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
* @swab: Swap bytes
|
||||
*
|
||||
* Drivers can use this function for RGB565 devices that don't natively
|
||||
* support XRGB8888.
|
||||
* This function copies parts of a framebuffer to display memory and converts the
|
||||
* color format during the process. Destination and framebuffer formats must match. The
|
||||
* parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||
* least as many entries as there are planes in @fb's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for RGB565 devices that don't support XRGB8888 natively.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_rgb565(void *dst, unsigned int dst_pitch, const void *vaddr,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip,
|
||||
bool swab)
|
||||
void drm_fb_xrgb8888_to_rgb565(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool swab)
|
||||
{
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
2,
|
||||
};
|
||||
|
||||
void (*xfrm_line)(void *dbuf, const void *sbuf, unsigned int npixels);
|
||||
|
||||
if (swab)
|
||||
drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgb565_swab_line);
|
||||
xfrm_line = drm_fb_xrgb8888_to_rgb565_swab_line;
|
||||
else
|
||||
drm_fb_xfrm(dst, dst_pitch, 2, vaddr, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgb565_line);
|
||||
xfrm_line = drm_fb_xrgb8888_to_rgb565_line;
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false, xfrm_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565);
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_rgb565_toio - Convert XRGB8888 to RGB565 clip buffer
|
||||
* @dst: RGB565 destination buffer (iomem)
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: XRGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
* @swab: Swap bytes
|
||||
*
|
||||
* Drivers can use this function for RGB565 devices that don't natively
|
||||
* support XRGB8888.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_rgb565_toio(void __iomem *dst, unsigned int dst_pitch,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip, bool swab)
|
||||
{
|
||||
if (swab)
|
||||
drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgb565_swab_line);
|
||||
else
|
||||
drm_fb_xfrm_toio(dst, dst_pitch, 2, vaddr, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgb565_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb565_toio);
|
||||
|
||||
static void drm_fb_xrgb8888_to_rgb888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u8 *dbuf8 = dbuf;
|
||||
const u32 *sbuf32 = sbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
*dbuf8++ = (sbuf32[x] & 0x000000FF) >> 0;
|
||||
*dbuf8++ = (sbuf32[x] & 0x0000FF00) >> 8;
|
||||
*dbuf8++ = (sbuf32[x] & 0x00FF0000) >> 16;
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
*dbuf8++ = (pix & 0x000000FF) >> 0;
|
||||
*dbuf8++ = (pix & 0x0000FF00) >> 8;
|
||||
*dbuf8++ = (pix & 0x00FF0000) >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_rgb888 - Convert XRGB8888 to RGB888 clip buffer
|
||||
* @dst: RGB888 destination buffer
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @src: XRGB8888 source buffer
|
||||
* @dst: Array of RGB888 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory and converts the
|
||||
* color format during the process. Destination and framebuffer formats must match. The
|
||||
* parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||
* least as many entries as there are planes in @fb's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for RGB888 devices that don't natively
|
||||
* support XRGB8888.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_rgb888(void *dst, unsigned int dst_pitch, const void *src,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip)
|
||||
void drm_fb_xrgb8888_to_rgb888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
drm_fb_xfrm(dst, dst_pitch, 3, src, fb, clip, false, drm_fb_xrgb8888_to_rgb888_line);
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
3,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgb888_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888);
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_rgb888_toio - Convert XRGB8888 to RGB888 clip buffer
|
||||
* @dst: RGB565 destination buffer (iomem)
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: XRGB8888 source buffer
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* Drivers can use this function for RGB888 devices that don't natively
|
||||
* support XRGB8888.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_rgb888_toio(void __iomem *dst, unsigned int dst_pitch,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
drm_fb_xfrm_toio(dst, dst_pitch, 3, vaddr, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_rgb888_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_rgb888_toio);
|
||||
|
||||
static void drm_fb_rgb565_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u32 *dbuf32 = dbuf;
|
||||
const u16 *sbuf16 = sbuf;
|
||||
__le32 *dbuf32 = dbuf;
|
||||
const __le16 *sbuf16 = sbuf;
|
||||
unsigned int x;
|
||||
|
||||
for (x = 0; x < pixels; x++, ++sbuf16, ++dbuf32) {
|
||||
u32 val32 = ((*sbuf16 & 0xf800) << 8) |
|
||||
((*sbuf16 & 0x07e0) << 5) |
|
||||
((*sbuf16 & 0x001f) << 3);
|
||||
*dbuf32 = 0xff000000 | val32 |
|
||||
((val32 >> 3) & 0x00070007) |
|
||||
((val32 >> 2) & 0x00000300);
|
||||
for (x = 0; x < pixels; x++) {
|
||||
u16 val16 = le16_to_cpu(sbuf16[x]);
|
||||
u32 val32 = ((val16 & 0xf800) << 8) |
|
||||
((val16 & 0x07e0) << 5) |
|
||||
((val16 & 0x001f) << 3);
|
||||
val32 = 0xff000000 | val32 |
|
||||
((val32 >> 3) & 0x00070007) |
|
||||
((val32 >> 2) & 0x00000300);
|
||||
dbuf32[x] = cpu_to_le32(val32);
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_fb_rgb565_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
static void drm_fb_rgb565_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src,
|
||||
const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
|
||||
drm_fb_rgb565_to_xrgb8888_line);
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
4,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_rgb565_to_xrgb8888_line);
|
||||
}
|
||||
|
||||
static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u32 *dbuf32 = dbuf;
|
||||
__le32 *dbuf32 = dbuf;
|
||||
const u8 *sbuf8 = sbuf;
|
||||
unsigned int x;
|
||||
|
||||
@ -442,117 +485,158 @@ static void drm_fb_rgb888_to_xrgb8888_line(void *dbuf, const void *sbuf, unsigne
|
||||
u8 r = *sbuf8++;
|
||||
u8 g = *sbuf8++;
|
||||
u8 b = *sbuf8++;
|
||||
*dbuf32++ = 0xff000000 | (r << 16) | (g << 8) | b;
|
||||
u32 pix = 0xff000000 | (r << 16) | (g << 8) | b;
|
||||
dbuf32[x] = cpu_to_le32(pix);
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_fb_rgb888_to_xrgb8888_toio(void __iomem *dst, unsigned int dst_pitch,
|
||||
const void *vaddr, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
static void drm_fb_rgb888_to_xrgb8888(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src,
|
||||
const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
|
||||
drm_fb_rgb888_to_xrgb8888_line);
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
4,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_rgb888_to_xrgb8888_line);
|
||||
}
|
||||
|
||||
static void drm_fb_xrgb8888_to_xrgb2101010_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u32 *dbuf32 = dbuf;
|
||||
const u32 *sbuf32 = sbuf;
|
||||
__le32 *dbuf32 = dbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
u32 val32;
|
||||
u32 pix;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
val32 = ((sbuf32[x] & 0x000000FF) << 2) |
|
||||
((sbuf32[x] & 0x0000FF00) << 4) |
|
||||
((sbuf32[x] & 0x00FF0000) << 6);
|
||||
*dbuf32++ = val32 | ((val32 >> 8) & 0x00300C03);
|
||||
pix = le32_to_cpu(sbuf32[x]);
|
||||
val32 = ((pix & 0x000000FF) << 2) |
|
||||
((pix & 0x0000FF00) << 4) |
|
||||
((pix & 0x00FF0000) << 6);
|
||||
pix = val32 | ((val32 >> 8) & 0x00300C03);
|
||||
*dbuf32++ = cpu_to_le32(pix);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_xrgb2101010_toio - Convert XRGB8888 to XRGB2101010 clip
|
||||
* buffer
|
||||
* @dst: XRGB2101010 destination buffer (iomem)
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: XRGB8888 source buffer
|
||||
* drm_fb_xrgb8888_to_xrgb2101010 - Convert XRGB8888 to XRGB2101010 clip buffer
|
||||
* @dst: Array of XRGB2101010 destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* Drivers can use this function for XRGB2101010 devices that don't natively
|
||||
* support XRGB8888.
|
||||
* This function copies parts of a framebuffer to display memory and converts the
|
||||
* color format during the process. Destination and framebuffer formats must match. The
|
||||
* parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||
* least as many entries as there are planes in @fb's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Drivers can use this function for XRGB2101010 devices that don't support XRGB8888
|
||||
* natively.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_xrgb2101010_toio(void __iomem *dst,
|
||||
unsigned int dst_pitch, const void *vaddr,
|
||||
const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
void drm_fb_xrgb8888_to_xrgb2101010(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
drm_fb_xfrm_toio(dst, dst_pitch, 4, vaddr, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_xrgb2101010_line);
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
4,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_xrgb2101010_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_xrgb2101010_toio);
|
||||
|
||||
static void drm_fb_xrgb8888_to_gray8_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
u8 *dbuf8 = dbuf;
|
||||
const u32 *sbuf32 = sbuf;
|
||||
const __le32 *sbuf32 = sbuf;
|
||||
unsigned int x;
|
||||
|
||||
for (x = 0; x < pixels; x++) {
|
||||
u8 r = (*sbuf32 & 0x00ff0000) >> 16;
|
||||
u8 g = (*sbuf32 & 0x0000ff00) >> 8;
|
||||
u8 b = *sbuf32 & 0x000000ff;
|
||||
u32 pix = le32_to_cpu(sbuf32[x]);
|
||||
u8 r = (pix & 0x00ff0000) >> 16;
|
||||
u8 g = (pix & 0x0000ff00) >> 8;
|
||||
u8 b = pix & 0x000000ff;
|
||||
|
||||
/* ITU BT.601: Y = 0.299 R + 0.587 G + 0.114 B */
|
||||
*dbuf8++ = (3 * r + 6 * g + b) / 10;
|
||||
sbuf32++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_gray8 - Convert XRGB8888 to grayscale
|
||||
* @dst: 8-bit grayscale destination buffer
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: XRGB8888 source buffer
|
||||
* @dst: Array of 8-bit grayscale destination buffers
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* Drm doesn't have native monochrome or grayscale support.
|
||||
* Such drivers can announce the commonly supported XR24 format to userspace
|
||||
* and use this function to convert to the native format.
|
||||
* This function copies parts of a framebuffer to display memory and converts the
|
||||
* color format during the process. Destination and framebuffer formats must match. The
|
||||
* parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||
* least as many entries as there are planes in @fb's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index.
|
||||
*
|
||||
* Monochrome drivers will use the most significant bit,
|
||||
* where 1 means foreground color and 0 background color.
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* ITU BT.601 is used for the RGB -> luma (brightness) conversion.
|
||||
* DRM doesn't have native monochrome or grayscale support. Drivers can use this
|
||||
* function for grayscale devices that don't support XRGB8888 natively.Such
|
||||
* drivers can announce the commonly supported XR24 format to userspace and use
|
||||
* this function to convert to the native format. Monochrome drivers will use the
|
||||
* most significant bit, where 1 means foreground color and 0 background color.
|
||||
* ITU BT.601 is being used for the RGB -> luma (brightness) conversion.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_gray8(void *dst, unsigned int dst_pitch, const void *vaddr,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip)
|
||||
void drm_fb_xrgb8888_to_gray8(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
drm_fb_xfrm(dst, dst_pitch, 1, vaddr, fb, clip, false, drm_fb_xrgb8888_to_gray8_line);
|
||||
static const u8 dst_pixsize[DRM_FORMAT_MAX_PLANES] = {
|
||||
1,
|
||||
};
|
||||
|
||||
drm_fb_xfrm(dst, dst_pitch, dst_pixsize, src, fb, clip, false,
|
||||
drm_fb_xrgb8888_to_gray8_line);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_xrgb8888_to_gray8);
|
||||
|
||||
/**
|
||||
* drm_fb_blit_toio - Copy parts of a framebuffer to display memory
|
||||
* @dst: The display memory to copy to
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* drm_fb_blit - Copy parts of a framebuffer to display memory
|
||||
* @dst: Array of display-memory addresses to copy to
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @dst_format: FOURCC code of the display's color format
|
||||
* @vmap: The framebuffer memory to copy from
|
||||
* @src: The framebuffer memory to copy from
|
||||
* @fb: The framebuffer to copy from
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* This function copies parts of a framebuffer to display memory. If the
|
||||
* formats of the display and the framebuffer mismatch, the blit function
|
||||
* will attempt to convert between them.
|
||||
* will attempt to convert between them during the process. The parameters @dst,
|
||||
* @dst_pitch and @src refer to arrays. Each array must have at least as many
|
||||
* entries as there are planes in @dst_format's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner).
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, or
|
||||
* -EINVAL if the color-format conversion failed, or
|
||||
* a negative error code otherwise.
|
||||
*/
|
||||
int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_format,
|
||||
const void *vmap, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
int drm_fb_blit(struct iosys_map *dst, const unsigned int *dst_pitch, uint32_t dst_format,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
uint32_t fb_format = fb->format->format;
|
||||
|
||||
@ -567,30 +651,30 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
|
||||
dst_format = DRM_FORMAT_XRGB2101010;
|
||||
|
||||
if (dst_format == fb_format) {
|
||||
drm_fb_memcpy_toio(dst, dst_pitch, vmap, fb, clip);
|
||||
drm_fb_memcpy(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
|
||||
} else if (dst_format == DRM_FORMAT_RGB565) {
|
||||
if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
drm_fb_xrgb8888_to_rgb565_toio(dst, dst_pitch, vmap, fb, clip, false);
|
||||
drm_fb_xrgb8888_to_rgb565(dst, dst_pitch, src, fb, clip, false);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == DRM_FORMAT_RGB888) {
|
||||
if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
drm_fb_xrgb8888_to_rgb888_toio(dst, dst_pitch, vmap, fb, clip);
|
||||
drm_fb_xrgb8888_to_rgb888(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == DRM_FORMAT_XRGB8888) {
|
||||
if (fb_format == DRM_FORMAT_RGB888) {
|
||||
drm_fb_rgb888_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip);
|
||||
drm_fb_rgb888_to_xrgb8888(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
} else if (fb_format == DRM_FORMAT_RGB565) {
|
||||
drm_fb_rgb565_to_xrgb8888_toio(dst, dst_pitch, vmap, fb, clip);
|
||||
drm_fb_rgb565_to_xrgb8888(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
}
|
||||
} else if (dst_format == DRM_FORMAT_XRGB2101010) {
|
||||
if (fb_format == DRM_FORMAT_XRGB8888) {
|
||||
drm_fb_xrgb8888_to_xrgb2101010_toio(dst, dst_pitch, vmap, fb, clip);
|
||||
drm_fb_xrgb8888_to_xrgb2101010(dst, dst_pitch, src, fb, clip);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -600,8 +684,7 @@ int drm_fb_blit_toio(void __iomem *dst, unsigned int dst_pitch, uint32_t dst_for
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_fb_blit_toio);
|
||||
|
||||
EXPORT_SYMBOL(drm_fb_blit);
|
||||
|
||||
static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int pixels)
|
||||
{
|
||||
@ -622,49 +705,67 @@ static void drm_fb_gray8_to_mono_line(void *dbuf, const void *sbuf, unsigned int
|
||||
|
||||
/**
|
||||
* drm_fb_xrgb8888_to_mono - Convert XRGB8888 to monochrome
|
||||
* @dst: monochrome destination buffer (0=black, 1=white)
|
||||
* @dst_pitch: Number of bytes between two consecutive scanlines within dst
|
||||
* @vaddr: XRGB8888 source buffer
|
||||
* @dst: Array of monochrome destination buffers (0=black, 1=white)
|
||||
* @dst_pitch: Array of numbers of bytes between the start of two consecutive scanlines
|
||||
* within @dst; can be NULL if scanlines are stored next to each other.
|
||||
* @src: Array of XRGB8888 source buffers
|
||||
* @fb: DRM framebuffer
|
||||
* @clip: Clip rectangle area to copy
|
||||
*
|
||||
* DRM doesn't have native monochrome support.
|
||||
* Such drivers can announce the commonly supported XR24 format to userspace
|
||||
* and use this function to convert to the native format.
|
||||
* This function copies parts of a framebuffer to display memory and converts the
|
||||
* color format during the process. Destination and framebuffer formats must match. The
|
||||
* parameters @dst, @dst_pitch and @src refer to arrays. Each array must have at
|
||||
* least as many entries as there are planes in @fb's format. Each entry stores the
|
||||
* value for the format's respective color plane at the same index.
|
||||
*
|
||||
* This function does not apply clipping on @dst (i.e. the destination is at the
|
||||
* top-left corner). The first pixel (upper left corner of the clip rectangle) will
|
||||
* be converted and copied to the first bit (LSB) in the first byte of the monochrome
|
||||
* destination buffer. If the caller requires that the first pixel in a byte must
|
||||
* be located at an x-coordinate that is a multiple of 8, then the caller must take
|
||||
* care itself of supplying a suitable clip rectangle.
|
||||
*
|
||||
* DRM doesn't have native monochrome support. Drivers can use this function for
|
||||
* monochrome devices that don't support XRGB8888 natively. Such drivers can
|
||||
* announce the commonly supported XR24 format to userspace and use this function
|
||||
* to convert to the native format.
|
||||
*
|
||||
* This function uses drm_fb_xrgb8888_to_gray8() to convert to grayscale and
|
||||
* then the result is converted from grayscale to monochrome.
|
||||
*
|
||||
* The first pixel (upper left corner of the clip rectangle) will be converted
|
||||
* and copied to the first bit (LSB) in the first byte of the monochrome
|
||||
* destination buffer.
|
||||
* If the caller requires that the first pixel in a byte must be located at an
|
||||
* x-coordinate that is a multiple of 8, then the caller must take care itself
|
||||
* of supplying a suitable clip rectangle.
|
||||
*/
|
||||
void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vaddr,
|
||||
const struct drm_framebuffer *fb, const struct drm_rect *clip)
|
||||
void drm_fb_xrgb8888_to_mono(struct iosys_map *dst, const unsigned int *dst_pitch,
|
||||
const struct iosys_map *src, const struct drm_framebuffer *fb,
|
||||
const struct drm_rect *clip)
|
||||
{
|
||||
static const unsigned int default_dst_pitch[DRM_FORMAT_MAX_PLANES] = {
|
||||
0, 0, 0, 0
|
||||
};
|
||||
unsigned int linepixels = drm_rect_width(clip);
|
||||
unsigned int lines = drm_rect_height(clip);
|
||||
unsigned int cpp = fb->format->cpp[0];
|
||||
unsigned int len_src32 = linepixels * cpp;
|
||||
struct drm_device *dev = fb->dev;
|
||||
void *vaddr = src[0].vaddr;
|
||||
unsigned int dst_pitch_0;
|
||||
unsigned int y;
|
||||
u8 *mono = dst, *gray8;
|
||||
u8 *mono = dst[0].vaddr, *gray8;
|
||||
u32 *src32;
|
||||
|
||||
if (drm_WARN_ON(dev, fb->format->format != DRM_FORMAT_XRGB8888))
|
||||
return;
|
||||
|
||||
if (!dst_pitch)
|
||||
dst_pitch = default_dst_pitch;
|
||||
dst_pitch_0 = dst_pitch[0];
|
||||
|
||||
/*
|
||||
* The mono destination buffer contains 1 bit per pixel
|
||||
*/
|
||||
if (!dst_pitch)
|
||||
dst_pitch = DIV_ROUND_UP(linepixels, 8);
|
||||
if (!dst_pitch_0)
|
||||
dst_pitch_0 = DIV_ROUND_UP(linepixels, 8);
|
||||
|
||||
/*
|
||||
* The cma memory is write-combined so reads are uncached.
|
||||
* The dma memory is write-combined so reads are uncached.
|
||||
* Speed up by fetching one line at a time.
|
||||
*
|
||||
* Also, format conversion from XR24 to monochrome are done
|
||||
@ -686,7 +787,7 @@ void drm_fb_xrgb8888_to_mono(void *dst, unsigned int dst_pitch, const void *vadd
|
||||
drm_fb_xrgb8888_to_gray8_line(gray8, src32, linepixels);
|
||||
drm_fb_gray8_to_mono_line(mono, gray8, linepixels);
|
||||
vaddr += fb->pitches[0];
|
||||
mono += dst_pitch;
|
||||
mono += dst_pitch_0;
|
||||
}
|
||||
|
||||
kfree(src32);
|
||||
|
@ -43,6 +43,21 @@ uint32_t drm_mode_legacy_fb_format(uint32_t bpp, uint32_t depth)
|
||||
uint32_t fmt = DRM_FORMAT_INVALID;
|
||||
|
||||
switch (bpp) {
|
||||
case 1:
|
||||
if (depth == 1)
|
||||
fmt = DRM_FORMAT_C1;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (depth == 2)
|
||||
fmt = DRM_FORMAT_C2;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (depth == 4)
|
||||
fmt = DRM_FORMAT_C4;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
if (depth == 8)
|
||||
fmt = DRM_FORMAT_C8;
|
||||
@ -132,7 +147,26 @@ EXPORT_SYMBOL(drm_driver_legacy_fb_format);
|
||||
const struct drm_format_info *__drm_format_info(u32 format)
|
||||
{
|
||||
static const struct drm_format_info formats[] = {
|
||||
{ .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_C1, .depth = 1, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
|
||||
{ .format = DRM_FORMAT_C2, .depth = 2, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
|
||||
{ .format = DRM_FORMAT_C4, .depth = 4, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
|
||||
{ .format = DRM_FORMAT_C8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1, .is_color_indexed = true },
|
||||
{ .format = DRM_FORMAT_D1, .depth = 1, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_D2, .depth = 2, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_D4, .depth = 4, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_D8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_R1, .depth = 1, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 8, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_R2, .depth = 2, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 4, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_R4, .depth = 4, .num_planes = 1,
|
||||
.char_per_block = { 1, }, .block_w = { 2, }, .block_h = { 1, }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_R8, .depth = 8, .num_planes = 1, .cpp = { 1, 0, 0 }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_R10, .depth = 10, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
|
||||
{ .format = DRM_FORMAT_R12, .depth = 12, .num_planes = 1, .cpp = { 2, 0, 0 }, .hsub = 1, .vsub = 1 },
|
||||
@ -370,6 +404,25 @@ unsigned int drm_format_info_block_height(const struct drm_format_info *info,
|
||||
}
|
||||
EXPORT_SYMBOL(drm_format_info_block_height);
|
||||
|
||||
/**
|
||||
* drm_format_info_bpp - number of bits per pixel
|
||||
* @info: pixel format info
|
||||
* @plane: plane index
|
||||
*
|
||||
* Returns:
|
||||
* The actual number of bits per pixel, depending on the plane index.
|
||||
*/
|
||||
unsigned int drm_format_info_bpp(const struct drm_format_info *info, int plane)
|
||||
{
|
||||
if (!info || plane < 0 || plane >= info->num_planes)
|
||||
return 0;
|
||||
|
||||
return info->char_per_block[plane] * 8 /
|
||||
(drm_format_info_block_width(info, plane) *
|
||||
drm_format_info_block_height(info, plane));
|
||||
}
|
||||
EXPORT_SYMBOL(drm_format_info_bpp);
|
||||
|
||||
/**
|
||||
* drm_format_info_min_pitch - computes the minimum required pitch in bytes
|
||||
* @info: pixel format info
|
||||
|
@ -530,7 +530,7 @@ int drm_mode_getfb(struct drm_device *dev,
|
||||
r->height = fb->height;
|
||||
r->width = fb->width;
|
||||
r->depth = fb->format->depth;
|
||||
r->bpp = fb->format->cpp[0] * 8;
|
||||
r->bpp = drm_format_info_bpp(fb->format, 0);
|
||||
r->pitch = fb->pitches[0];
|
||||
|
||||
/* GET_FB() is an unprivileged ioctl so we must not return a
|
||||
@ -935,7 +935,7 @@ EXPORT_SYMBOL(drm_framebuffer_unregister_private);
|
||||
* the id and get back -EINVAL. Obviously no concern at driver unload time.
|
||||
*
|
||||
* Also, the framebuffer will not be removed from the lookup idr - for
|
||||
* user-created framebuffers this will happen in in the rmfb ioctl. For
|
||||
* user-created framebuffers this will happen in the rmfb ioctl. For
|
||||
* driver-private objects (e.g. for fbdev) drivers need to explicitly call
|
||||
* drm_framebuffer_unregister_private.
|
||||
*/
|
||||
|
@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
/*
|
||||
* drm gem CMA (contiguous memory allocator) helper functions
|
||||
* drm gem DMA helper functions
|
||||
*
|
||||
* Copyright (C) 2012 Sascha Hauer, Pengutronix
|
||||
*
|
||||
@ -20,20 +20,17 @@
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_vma_manager.h>
|
||||
|
||||
/**
|
||||
* DOC: cma helpers
|
||||
* DOC: dma helpers
|
||||
*
|
||||
* The DRM GEM/CMA helpers are a means to provide buffer objects that are
|
||||
* The DRM GEM/DMA helpers are a means to provide buffer objects that are
|
||||
* presented to the device as a contiguous chunk of memory. This is useful
|
||||
* for devices that do not support scatter-gather DMA (either directly or
|
||||
* by using an intimately attached IOMMU).
|
||||
*
|
||||
* Despite the name, the DRM GEM/CMA helpers are not hardwired to use the
|
||||
* Contiguous Memory Allocator (CMA).
|
||||
*
|
||||
* For devices that access the memory bus through an (external) IOMMU then
|
||||
* the buffer objects are allocated using a traditional page-based
|
||||
* allocator and may be scattered through physical memory. However they
|
||||
@ -44,36 +41,36 @@
|
||||
* objects that are physically contiguous in memory.
|
||||
*
|
||||
* For GEM callback helpers in struct &drm_gem_object functions, see likewise
|
||||
* named functions with an _object_ infix (e.g., drm_gem_cma_object_vmap() wraps
|
||||
* drm_gem_cma_vmap()). These helpers perform the necessary type conversion.
|
||||
* named functions with an _object_ infix (e.g., drm_gem_dma_object_vmap() wraps
|
||||
* drm_gem_dma_vmap()). These helpers perform the necessary type conversion.
|
||||
*/
|
||||
|
||||
static const struct drm_gem_object_funcs drm_gem_cma_default_funcs = {
|
||||
.free = drm_gem_cma_object_free,
|
||||
.print_info = drm_gem_cma_object_print_info,
|
||||
.get_sg_table = drm_gem_cma_object_get_sg_table,
|
||||
.vmap = drm_gem_cma_object_vmap,
|
||||
.mmap = drm_gem_cma_object_mmap,
|
||||
.vm_ops = &drm_gem_cma_vm_ops,
|
||||
static const struct drm_gem_object_funcs drm_gem_dma_default_funcs = {
|
||||
.free = drm_gem_dma_object_free,
|
||||
.print_info = drm_gem_dma_object_print_info,
|
||||
.get_sg_table = drm_gem_dma_object_get_sg_table,
|
||||
.vmap = drm_gem_dma_object_vmap,
|
||||
.mmap = drm_gem_dma_object_mmap,
|
||||
.vm_ops = &drm_gem_dma_vm_ops,
|
||||
};
|
||||
|
||||
/**
|
||||
* __drm_gem_cma_create - Create a GEM CMA object without allocating memory
|
||||
* __drm_gem_dma_create - Create a GEM DMA object without allocating memory
|
||||
* @drm: DRM device
|
||||
* @size: size of the object to allocate
|
||||
* @private: true if used for internal purposes
|
||||
*
|
||||
* This function creates and initializes a GEM CMA object of the given size,
|
||||
* This function creates and initializes a GEM DMA object of the given size,
|
||||
* but doesn't allocate any memory to back the object.
|
||||
*
|
||||
* Returns:
|
||||
* A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
|
||||
* A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
|
||||
* error code on failure.
|
||||
*/
|
||||
static struct drm_gem_cma_object *
|
||||
__drm_gem_cma_create(struct drm_device *drm, size_t size, bool private)
|
||||
static struct drm_gem_dma_object *
|
||||
__drm_gem_dma_create(struct drm_device *drm, size_t size, bool private)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
struct drm_gem_object *gem_obj;
|
||||
int ret = 0;
|
||||
|
||||
@ -81,22 +78,22 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size, bool private)
|
||||
gem_obj = drm->driver->gem_create_object(drm, size);
|
||||
if (IS_ERR(gem_obj))
|
||||
return ERR_CAST(gem_obj);
|
||||
cma_obj = to_drm_gem_cma_obj(gem_obj);
|
||||
dma_obj = to_drm_gem_dma_obj(gem_obj);
|
||||
} else {
|
||||
cma_obj = kzalloc(sizeof(*cma_obj), GFP_KERNEL);
|
||||
if (!cma_obj)
|
||||
dma_obj = kzalloc(sizeof(*dma_obj), GFP_KERNEL);
|
||||
if (!dma_obj)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
gem_obj = &cma_obj->base;
|
||||
gem_obj = &dma_obj->base;
|
||||
}
|
||||
|
||||
if (!gem_obj->funcs)
|
||||
gem_obj->funcs = &drm_gem_cma_default_funcs;
|
||||
gem_obj->funcs = &drm_gem_dma_default_funcs;
|
||||
|
||||
if (private) {
|
||||
drm_gem_private_object_init(drm, gem_obj, size);
|
||||
|
||||
/* Always use writecombine for dma-buf mappings */
|
||||
cma_obj->map_noncoherent = false;
|
||||
dma_obj->map_noncoherent = false;
|
||||
} else {
|
||||
ret = drm_gem_object_init(drm, gem_obj, size);
|
||||
}
|
||||
@ -109,19 +106,19 @@ __drm_gem_cma_create(struct drm_device *drm, size_t size, bool private)
|
||||
goto error;
|
||||
}
|
||||
|
||||
return cma_obj;
|
||||
return dma_obj;
|
||||
|
||||
error:
|
||||
kfree(cma_obj);
|
||||
kfree(dma_obj);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_gem_cma_create - allocate an object with the given size
|
||||
* drm_gem_dma_create - allocate an object with the given size
|
||||
* @drm: DRM device
|
||||
* @size: size of the object to allocate
|
||||
*
|
||||
* This function creates a CMA GEM object and allocates memory as backing store.
|
||||
* This function creates a DMA GEM object and allocates memory as backing store.
|
||||
* The allocated memory will occupy a contiguous chunk of bus address space.
|
||||
*
|
||||
* For devices that are directly connected to the memory bus then the allocated
|
||||
@ -131,78 +128,79 @@ error:
|
||||
* requirements.
|
||||
*
|
||||
* Returns:
|
||||
* A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
|
||||
* A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
|
||||
* error code on failure.
|
||||
*/
|
||||
struct drm_gem_cma_object *drm_gem_cma_create(struct drm_device *drm,
|
||||
struct drm_gem_dma_object *drm_gem_dma_create(struct drm_device *drm,
|
||||
size_t size)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
int ret;
|
||||
|
||||
size = round_up(size, PAGE_SIZE);
|
||||
|
||||
cma_obj = __drm_gem_cma_create(drm, size, false);
|
||||
if (IS_ERR(cma_obj))
|
||||
return cma_obj;
|
||||
dma_obj = __drm_gem_dma_create(drm, size, false);
|
||||
if (IS_ERR(dma_obj))
|
||||
return dma_obj;
|
||||
|
||||
if (cma_obj->map_noncoherent) {
|
||||
cma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size,
|
||||
&cma_obj->paddr,
|
||||
if (dma_obj->map_noncoherent) {
|
||||
dma_obj->vaddr = dma_alloc_noncoherent(drm->dev, size,
|
||||
&dma_obj->dma_addr,
|
||||
DMA_TO_DEVICE,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
} else {
|
||||
cma_obj->vaddr = dma_alloc_wc(drm->dev, size, &cma_obj->paddr,
|
||||
dma_obj->vaddr = dma_alloc_wc(drm->dev, size,
|
||||
&dma_obj->dma_addr,
|
||||
GFP_KERNEL | __GFP_NOWARN);
|
||||
}
|
||||
if (!cma_obj->vaddr) {
|
||||
if (!dma_obj->vaddr) {
|
||||
drm_dbg(drm, "failed to allocate buffer with size %zu\n",
|
||||
size);
|
||||
ret = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return cma_obj;
|
||||
return dma_obj;
|
||||
|
||||
error:
|
||||
drm_gem_object_put(&cma_obj->base);
|
||||
drm_gem_object_put(&dma_obj->base);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_create);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_create);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_create_with_handle - allocate an object with the given size and
|
||||
* drm_gem_dma_create_with_handle - allocate an object with the given size and
|
||||
* return a GEM handle to it
|
||||
* @file_priv: DRM file-private structure to register the handle for
|
||||
* @drm: DRM device
|
||||
* @size: size of the object to allocate
|
||||
* @handle: return location for the GEM handle
|
||||
*
|
||||
* This function creates a CMA GEM object, allocating a chunk of memory as
|
||||
* This function creates a DMA GEM object, allocating a chunk of memory as
|
||||
* backing store. The GEM object is then added to the list of object associated
|
||||
* with the given file and a handle to it is returned.
|
||||
*
|
||||
* The allocated memory will occupy a contiguous chunk of bus address space.
|
||||
* See drm_gem_cma_create() for more details.
|
||||
* See drm_gem_dma_create() for more details.
|
||||
*
|
||||
* Returns:
|
||||
* A struct drm_gem_cma_object * on success or an ERR_PTR()-encoded negative
|
||||
* A struct drm_gem_dma_object * on success or an ERR_PTR()-encoded negative
|
||||
* error code on failure.
|
||||
*/
|
||||
static struct drm_gem_cma_object *
|
||||
drm_gem_cma_create_with_handle(struct drm_file *file_priv,
|
||||
static struct drm_gem_dma_object *
|
||||
drm_gem_dma_create_with_handle(struct drm_file *file_priv,
|
||||
struct drm_device *drm, size_t size,
|
||||
uint32_t *handle)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
struct drm_gem_object *gem_obj;
|
||||
int ret;
|
||||
|
||||
cma_obj = drm_gem_cma_create(drm, size);
|
||||
if (IS_ERR(cma_obj))
|
||||
return cma_obj;
|
||||
dma_obj = drm_gem_dma_create(drm, size);
|
||||
if (IS_ERR(dma_obj))
|
||||
return dma_obj;
|
||||
|
||||
gem_obj = &cma_obj->base;
|
||||
gem_obj = &dma_obj->base;
|
||||
|
||||
/*
|
||||
* allocate a id of idr table where the obj is registered
|
||||
@ -214,44 +212,44 @@ drm_gem_cma_create_with_handle(struct drm_file *file_priv,
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
return cma_obj;
|
||||
return dma_obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_gem_cma_free - free resources associated with a CMA GEM object
|
||||
* @cma_obj: CMA GEM object to free
|
||||
* drm_gem_dma_free - free resources associated with a DMA GEM object
|
||||
* @dma_obj: DMA GEM object to free
|
||||
*
|
||||
* This function frees the backing memory of the CMA GEM object, cleans up the
|
||||
* This function frees the backing memory of the DMA GEM object, cleans up the
|
||||
* GEM object state and frees the memory used to store the object itself.
|
||||
* If the buffer is imported and the virtual address is set, it is released.
|
||||
*/
|
||||
void drm_gem_cma_free(struct drm_gem_cma_object *cma_obj)
|
||||
void drm_gem_dma_free(struct drm_gem_dma_object *dma_obj)
|
||||
{
|
||||
struct drm_gem_object *gem_obj = &cma_obj->base;
|
||||
struct iosys_map map = IOSYS_MAP_INIT_VADDR(cma_obj->vaddr);
|
||||
struct drm_gem_object *gem_obj = &dma_obj->base;
|
||||
struct iosys_map map = IOSYS_MAP_INIT_VADDR(dma_obj->vaddr);
|
||||
|
||||
if (gem_obj->import_attach) {
|
||||
if (cma_obj->vaddr)
|
||||
if (dma_obj->vaddr)
|
||||
dma_buf_vunmap(gem_obj->import_attach->dmabuf, &map);
|
||||
drm_prime_gem_destroy(gem_obj, cma_obj->sgt);
|
||||
} else if (cma_obj->vaddr) {
|
||||
if (cma_obj->map_noncoherent)
|
||||
dma_free_noncoherent(gem_obj->dev->dev, cma_obj->base.size,
|
||||
cma_obj->vaddr, cma_obj->paddr,
|
||||
drm_prime_gem_destroy(gem_obj, dma_obj->sgt);
|
||||
} else if (dma_obj->vaddr) {
|
||||
if (dma_obj->map_noncoherent)
|
||||
dma_free_noncoherent(gem_obj->dev->dev, dma_obj->base.size,
|
||||
dma_obj->vaddr, dma_obj->dma_addr,
|
||||
DMA_TO_DEVICE);
|
||||
else
|
||||
dma_free_wc(gem_obj->dev->dev, cma_obj->base.size,
|
||||
cma_obj->vaddr, cma_obj->paddr);
|
||||
dma_free_wc(gem_obj->dev->dev, dma_obj->base.size,
|
||||
dma_obj->vaddr, dma_obj->dma_addr);
|
||||
}
|
||||
|
||||
drm_gem_object_release(gem_obj);
|
||||
|
||||
kfree(cma_obj);
|
||||
kfree(dma_obj);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_free);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_free);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_dumb_create_internal - create a dumb buffer object
|
||||
* drm_gem_dma_dumb_create_internal - create a dumb buffer object
|
||||
* @file_priv: DRM file-private structure to create the dumb buffer for
|
||||
* @drm: DRM device
|
||||
* @args: IOCTL data
|
||||
@ -264,12 +262,12 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_free);
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv,
|
||||
int drm_gem_dma_dumb_create_internal(struct drm_file *file_priv,
|
||||
struct drm_device *drm,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
unsigned int min_pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
|
||||
if (args->pitch < min_pitch)
|
||||
args->pitch = min_pitch;
|
||||
@ -277,14 +275,14 @@ int drm_gem_cma_dumb_create_internal(struct drm_file *file_priv,
|
||||
if (args->size < args->pitch * args->height)
|
||||
args->size = args->pitch * args->height;
|
||||
|
||||
cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size,
|
||||
dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size,
|
||||
&args->handle);
|
||||
return PTR_ERR_OR_ZERO(cma_obj);
|
||||
return PTR_ERR_OR_ZERO(dma_obj);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_internal);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create_internal);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_dumb_create - create a dumb buffer object
|
||||
* drm_gem_dma_dumb_create - create a dumb buffer object
|
||||
* @file_priv: DRM file-private structure to create the dumb buffer for
|
||||
* @drm: DRM device
|
||||
* @args: IOCTL data
|
||||
@ -296,35 +294,35 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create_internal);
|
||||
*
|
||||
* For hardware with additional restrictions, drivers can adjust the fields
|
||||
* set up by userspace and pass the IOCTL data along to the
|
||||
* drm_gem_cma_dumb_create_internal() function.
|
||||
* drm_gem_dma_dumb_create_internal() function.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_cma_dumb_create(struct drm_file *file_priv,
|
||||
int drm_gem_dma_dumb_create(struct drm_file *file_priv,
|
||||
struct drm_device *drm,
|
||||
struct drm_mode_create_dumb *args)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
|
||||
args->pitch = DIV_ROUND_UP(args->width * args->bpp, 8);
|
||||
args->size = args->pitch * args->height;
|
||||
|
||||
cma_obj = drm_gem_cma_create_with_handle(file_priv, drm, args->size,
|
||||
dma_obj = drm_gem_dma_create_with_handle(file_priv, drm, args->size,
|
||||
&args->handle);
|
||||
return PTR_ERR_OR_ZERO(cma_obj);
|
||||
return PTR_ERR_OR_ZERO(dma_obj);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_dumb_create);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_dumb_create);
|
||||
|
||||
const struct vm_operations_struct drm_gem_cma_vm_ops = {
|
||||
const struct vm_operations_struct drm_gem_dma_vm_ops = {
|
||||
.open = drm_gem_vm_open,
|
||||
.close = drm_gem_vm_close,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_vm_ops);
|
||||
|
||||
#ifndef CONFIG_MMU
|
||||
/**
|
||||
* drm_gem_cma_get_unmapped_area - propose address for mapping in noMMU cases
|
||||
* drm_gem_dma_get_unmapped_area - propose address for mapping in noMMU cases
|
||||
* @filp: file object
|
||||
* @addr: memory address
|
||||
* @len: buffer size
|
||||
@ -339,13 +337,13 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_vm_ops);
|
||||
* Returns:
|
||||
* mapping address on success or a negative error code on failure.
|
||||
*/
|
||||
unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
|
||||
unsigned long drm_gem_dma_get_unmapped_area(struct file *filp,
|
||||
unsigned long addr,
|
||||
unsigned long len,
|
||||
unsigned long pgoff,
|
||||
unsigned long flags)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
struct drm_gem_object *obj = NULL;
|
||||
struct drm_file *priv = filp->private_data;
|
||||
struct drm_device *dev = priv->minor->dev;
|
||||
@ -384,35 +382,35 @@ unsigned long drm_gem_cma_get_unmapped_area(struct file *filp,
|
||||
return -EACCES;
|
||||
}
|
||||
|
||||
cma_obj = to_drm_gem_cma_obj(obj);
|
||||
dma_obj = to_drm_gem_dma_obj(obj);
|
||||
|
||||
drm_gem_object_put(obj);
|
||||
|
||||
return cma_obj->vaddr ? (unsigned long)cma_obj->vaddr : -EINVAL;
|
||||
return dma_obj->vaddr ? (unsigned long)dma_obj->vaddr : -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_get_unmapped_area);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_get_unmapped_area);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* drm_gem_cma_print_info() - Print &drm_gem_cma_object info for debugfs
|
||||
* @cma_obj: CMA GEM object
|
||||
* drm_gem_dma_print_info() - Print &drm_gem_dma_object info for debugfs
|
||||
* @dma_obj: DMA GEM object
|
||||
* @p: DRM printer
|
||||
* @indent: Tab indentation level
|
||||
*
|
||||
* This function prints paddr and vaddr for use in e.g. debugfs output.
|
||||
* This function prints dma_addr and vaddr for use in e.g. debugfs output.
|
||||
*/
|
||||
void drm_gem_cma_print_info(const struct drm_gem_cma_object *cma_obj,
|
||||
void drm_gem_dma_print_info(const struct drm_gem_dma_object *dma_obj,
|
||||
struct drm_printer *p, unsigned int indent)
|
||||
{
|
||||
drm_printf_indent(p, indent, "paddr=%pad\n", &cma_obj->paddr);
|
||||
drm_printf_indent(p, indent, "vaddr=%p\n", cma_obj->vaddr);
|
||||
drm_printf_indent(p, indent, "dma_addr=%pad\n", &dma_obj->dma_addr);
|
||||
drm_printf_indent(p, indent, "vaddr=%p\n", dma_obj->vaddr);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_cma_print_info);
|
||||
EXPORT_SYMBOL(drm_gem_dma_print_info);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_get_sg_table - provide a scatter/gather table of pinned
|
||||
* pages for a CMA GEM object
|
||||
* @cma_obj: CMA GEM object
|
||||
* drm_gem_dma_get_sg_table - provide a scatter/gather table of pinned
|
||||
* pages for a DMA GEM object
|
||||
* @dma_obj: DMA GEM object
|
||||
*
|
||||
* This function exports a scatter/gather table by calling the standard
|
||||
* DMA mapping API.
|
||||
@ -420,9 +418,9 @@ EXPORT_SYMBOL(drm_gem_cma_print_info);
|
||||
* Returns:
|
||||
* A pointer to the scatter/gather table of pinned pages or NULL on failure.
|
||||
*/
|
||||
struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj)
|
||||
struct sg_table *drm_gem_dma_get_sg_table(struct drm_gem_dma_object *dma_obj)
|
||||
{
|
||||
struct drm_gem_object *obj = &cma_obj->base;
|
||||
struct drm_gem_object *obj = &dma_obj->base;
|
||||
struct sg_table *sgt;
|
||||
int ret;
|
||||
|
||||
@ -430,8 +428,8 @@ struct sg_table *drm_gem_cma_get_sg_table(struct drm_gem_cma_object *cma_obj)
|
||||
if (!sgt)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
ret = dma_get_sgtable(obj->dev->dev, sgt, cma_obj->vaddr,
|
||||
cma_obj->paddr, obj->size);
|
||||
ret = dma_get_sgtable(obj->dev->dev, sgt, dma_obj->vaddr,
|
||||
dma_obj->dma_addr, obj->size);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
@ -441,10 +439,10 @@ out:
|
||||
kfree(sgt);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_get_sg_table);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_import_sg_table - produce a CMA GEM object from another
|
||||
* drm_gem_dma_prime_import_sg_table - produce a DMA GEM object from another
|
||||
* driver's scatter/gather table of pinned pages
|
||||
* @dev: device to import into
|
||||
* @attach: DMA-BUF attachment
|
||||
@ -453,7 +451,7 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table);
|
||||
* This function imports a scatter/gather table exported via DMA-BUF by
|
||||
* another driver. Imported buffers must be physically contiguous in memory
|
||||
* (i.e. the scatter/gather table must contain a single entry). Drivers that
|
||||
* use the CMA helpers should set this as their
|
||||
* use the DMA helpers should set this as their
|
||||
* &drm_driver.gem_prime_import_sg_table callback.
|
||||
*
|
||||
* Returns:
|
||||
@ -461,56 +459,57 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_get_sg_table);
|
||||
* error code on failure.
|
||||
*/
|
||||
struct drm_gem_object *
|
||||
drm_gem_cma_prime_import_sg_table(struct drm_device *dev,
|
||||
drm_gem_dma_prime_import_sg_table(struct drm_device *dev,
|
||||
struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
|
||||
/* check if the entries in the sg_table are contiguous */
|
||||
if (drm_prime_get_contiguous_size(sgt) < attach->dmabuf->size)
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Create a CMA GEM buffer. */
|
||||
cma_obj = __drm_gem_cma_create(dev, attach->dmabuf->size, true);
|
||||
if (IS_ERR(cma_obj))
|
||||
return ERR_CAST(cma_obj);
|
||||
/* Create a DMA GEM buffer. */
|
||||
dma_obj = __drm_gem_dma_create(dev, attach->dmabuf->size, true);
|
||||
if (IS_ERR(dma_obj))
|
||||
return ERR_CAST(dma_obj);
|
||||
|
||||
cma_obj->paddr = sg_dma_address(sgt->sgl);
|
||||
cma_obj->sgt = sgt;
|
||||
dma_obj->dma_addr = sg_dma_address(sgt->sgl);
|
||||
dma_obj->sgt = sgt;
|
||||
|
||||
DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &cma_obj->paddr, attach->dmabuf->size);
|
||||
DRM_DEBUG_PRIME("dma_addr = %pad, size = %zu\n", &dma_obj->dma_addr,
|
||||
attach->dmabuf->size);
|
||||
|
||||
return &cma_obj->base;
|
||||
return &dma_obj->base;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_prime_import_sg_table);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_prime_import_sg_table);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_vmap - map a CMA GEM object into the kernel's virtual
|
||||
* drm_gem_dma_vmap - map a DMA GEM object into the kernel's virtual
|
||||
* address space
|
||||
* @cma_obj: CMA GEM object
|
||||
* @map: Returns the kernel virtual address of the CMA GEM object's backing
|
||||
* @dma_obj: DMA GEM object
|
||||
* @map: Returns the kernel virtual address of the DMA GEM object's backing
|
||||
* store.
|
||||
*
|
||||
* This function maps a buffer into the kernel's virtual address space.
|
||||
* Since the CMA buffers are already mapped into the kernel virtual address
|
||||
* Since the DMA buffers are already mapped into the kernel virtual address
|
||||
* space this simply returns the cached virtual address.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, or a negative error code otherwise.
|
||||
*/
|
||||
int drm_gem_cma_vmap(struct drm_gem_cma_object *cma_obj,
|
||||
int drm_gem_dma_vmap(struct drm_gem_dma_object *dma_obj,
|
||||
struct iosys_map *map)
|
||||
{
|
||||
iosys_map_set_vaddr(map, cma_obj->vaddr);
|
||||
iosys_map_set_vaddr(map, dma_obj->vaddr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_vmap);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_vmap);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_mmap - memory-map an exported CMA GEM object
|
||||
* @cma_obj: CMA GEM object
|
||||
* drm_gem_dma_mmap - memory-map an exported DMA GEM object
|
||||
* @dma_obj: DMA GEM object
|
||||
* @vma: VMA for the area to be mapped
|
||||
*
|
||||
* This function maps a buffer into a userspace process's address space.
|
||||
@ -520,9 +519,9 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_vmap);
|
||||
* Returns:
|
||||
* 0 on success or a negative error code on failure.
|
||||
*/
|
||||
int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *vma)
|
||||
int drm_gem_dma_mmap(struct drm_gem_dma_object *dma_obj, struct vm_area_struct *vma)
|
||||
{
|
||||
struct drm_gem_object *obj = &cma_obj->base;
|
||||
struct drm_gem_object *obj = &dma_obj->base;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@ -534,37 +533,38 @@ int drm_gem_cma_mmap(struct drm_gem_cma_object *cma_obj, struct vm_area_struct *
|
||||
vma->vm_flags &= ~VM_PFNMAP;
|
||||
vma->vm_flags |= VM_DONTEXPAND;
|
||||
|
||||
if (cma_obj->map_noncoherent) {
|
||||
if (dma_obj->map_noncoherent) {
|
||||
vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
|
||||
|
||||
ret = dma_mmap_pages(cma_obj->base.dev->dev,
|
||||
ret = dma_mmap_pages(dma_obj->base.dev->dev,
|
||||
vma, vma->vm_end - vma->vm_start,
|
||||
virt_to_page(cma_obj->vaddr));
|
||||
virt_to_page(dma_obj->vaddr));
|
||||
} else {
|
||||
ret = dma_mmap_wc(cma_obj->base.dev->dev, vma, cma_obj->vaddr,
|
||||
cma_obj->paddr, vma->vm_end - vma->vm_start);
|
||||
ret = dma_mmap_wc(dma_obj->base.dev->dev, vma, dma_obj->vaddr,
|
||||
dma_obj->dma_addr,
|
||||
vma->vm_end - vma->vm_start);
|
||||
}
|
||||
if (ret)
|
||||
drm_gem_vm_close(vma);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
|
||||
EXPORT_SYMBOL_GPL(drm_gem_dma_mmap);
|
||||
|
||||
/**
|
||||
* drm_gem_cma_prime_import_sg_table_vmap - PRIME import another driver's
|
||||
* drm_gem_dma_prime_import_sg_table_vmap - PRIME import another driver's
|
||||
* scatter/gather table and get the virtual address of the buffer
|
||||
* @dev: DRM device
|
||||
* @attach: DMA-BUF attachment
|
||||
* @sgt: Scatter/gather table of pinned pages
|
||||
*
|
||||
* This function imports a scatter/gather table using
|
||||
* drm_gem_cma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel
|
||||
* virtual address. This ensures that a CMA GEM object always has its virtual
|
||||
* drm_gem_dma_prime_import_sg_table() and uses dma_buf_vmap() to get the kernel
|
||||
* virtual address. This ensures that a DMA GEM object always has its virtual
|
||||
* address set. This address is released when the object is freed.
|
||||
*
|
||||
* This function can be used as the &drm_driver.gem_prime_import_sg_table
|
||||
* callback. The &DRM_GEM_CMA_DRIVER_OPS_VMAP macro provides a shortcut to set
|
||||
* callback. The &DRM_GEM_DMA_DRIVER_OPS_VMAP macro provides a shortcut to set
|
||||
* the necessary DRM driver operations.
|
||||
*
|
||||
* Returns:
|
||||
@ -572,11 +572,11 @@ EXPORT_SYMBOL_GPL(drm_gem_cma_mmap);
|
||||
* error code on failure.
|
||||
*/
|
||||
struct drm_gem_object *
|
||||
drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev,
|
||||
drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev,
|
||||
struct dma_buf_attachment *attach,
|
||||
struct sg_table *sgt)
|
||||
{
|
||||
struct drm_gem_cma_object *cma_obj;
|
||||
struct drm_gem_dma_object *dma_obj;
|
||||
struct drm_gem_object *obj;
|
||||
struct iosys_map map;
|
||||
int ret;
|
||||
@ -587,19 +587,19 @@ drm_gem_cma_prime_import_sg_table_vmap(struct drm_device *dev,
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
obj = drm_gem_cma_prime_import_sg_table(dev, attach, sgt);
|
||||
obj = drm_gem_dma_prime_import_sg_table(dev, attach, sgt);
|
||||
if (IS_ERR(obj)) {
|
||||
dma_buf_vunmap(attach->dmabuf, &map);
|
||||
return obj;
|
||||
}
|
||||
|
||||
cma_obj = to_drm_gem_cma_obj(obj);
|
||||
cma_obj->vaddr = map.vaddr;
|
||||
dma_obj = to_drm_gem_dma_obj(obj);
|
||||
dma_obj->vaddr = map.vaddr;
|
||||
|
||||
return obj;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_cma_prime_import_sg_table_vmap);
|
||||
EXPORT_SYMBOL(drm_gem_dma_prime_import_sg_table_vmap);
|
||||
|
||||
MODULE_DESCRIPTION("DRM CMA memory-management helpers");
|
||||
MODULE_DESCRIPTION("DRM DMA memory-management helpers");
|
||||
MODULE_IMPORT_NS(DMA_BUF);
|
||||
MODULE_LICENSE("GPL");
|
@ -490,6 +490,8 @@ void drm_gem_fb_end_cpu_access(struct drm_framebuffer *fb, enum dma_data_directi
|
||||
}
|
||||
EXPORT_SYMBOL(drm_gem_fb_end_cpu_access);
|
||||
|
||||
// TODO Drop this function and replace by drm_format_info_bpp() once all
|
||||
// DRM_FORMAT_* provide proper block info in drivers/gpu/drm/drm_fourcc.c
|
||||
static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
|
||||
const struct drm_mode_fb_cmd2 *mode_cmd)
|
||||
{
|
||||
@ -497,11 +499,6 @@ static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
|
||||
|
||||
info = drm_get_format_info(dev, mode_cmd);
|
||||
|
||||
/* use whatever a driver has set */
|
||||
if (info->cpp[0])
|
||||
return info->cpp[0] * 8;
|
||||
|
||||
/* guess otherwise */
|
||||
switch (info->format) {
|
||||
case DRM_FORMAT_YUV420_8BIT:
|
||||
return 12;
|
||||
@ -510,11 +507,8 @@ static __u32 drm_gem_afbc_get_bpp(struct drm_device *dev,
|
||||
case DRM_FORMAT_VUY101010:
|
||||
return 30;
|
||||
default:
|
||||
break;
|
||||
return drm_format_info_bpp(info, 0);
|
||||
}
|
||||
|
||||
/* all attempts failed */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_gem_afbc_min_size(struct drm_device *dev,
|
||||
|
@ -663,7 +663,7 @@ EXPORT_SYMBOL(drm_gem_shmem_print_info);
|
||||
* drm_gem_shmem_get_pages_sgt() instead.
|
||||
*
|
||||
* Returns:
|
||||
* A pointer to the scatter/gather table of pinned pages or NULL on failure.
|
||||
* A pointer to the scatter/gather table of pinned pages or error pointer on failure.
|
||||
*/
|
||||
struct sg_table *drm_gem_shmem_get_sg_table(struct drm_gem_shmem_object *shmem)
|
||||
{
|
||||
|
@ -226,9 +226,9 @@ struct drm_gem_vram_object *drm_gem_vram_create(struct drm_device *dev,
|
||||
* A failing ttm_bo_init will call ttm_buffer_object_destroy
|
||||
* to release gbo->bo.base and kfree gbo.
|
||||
*/
|
||||
ret = ttm_bo_init(bdev, &gbo->bo, size, ttm_bo_type_device,
|
||||
&gbo->placement, pg_align, false, NULL, NULL,
|
||||
ttm_buffer_object_destroy);
|
||||
ret = ttm_bo_init_validate(bdev, &gbo->bo, ttm_bo_type_device,
|
||||
&gbo->placement, pg_align, false, NULL, NULL,
|
||||
ttm_buffer_object_destroy);
|
||||
if (ret)
|
||||
return ERR_PTR(ret);
|
||||
|
||||
|
@ -472,7 +472,13 @@ EXPORT_SYMBOL(drm_invalid_op);
|
||||
*/
|
||||
static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
|
||||
{
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
/* don't attempt to copy a NULL pointer */
|
||||
if (WARN_ONCE(!value, "BUG: the value to copy was not set!")) {
|
||||
*buf_len = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* don't overflow userbuf */
|
||||
len = strlen(value);
|
||||
|
@ -205,7 +205,7 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
|
||||
struct drm_gem_object *gem = drm_gem_fb_get_obj(fb, 0);
|
||||
struct iosys_map map[DRM_FORMAT_MAX_PLANES];
|
||||
struct iosys_map data[DRM_FORMAT_MAX_PLANES];
|
||||
void *src;
|
||||
struct iosys_map dst_map = IOSYS_MAP_INIT_VADDR(dst);
|
||||
int ret;
|
||||
|
||||
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
|
||||
@ -215,17 +215,16 @@ int mipi_dbi_buf_copy(void *dst, struct drm_framebuffer *fb,
|
||||
ret = drm_gem_fb_vmap(fb, map, data);
|
||||
if (ret)
|
||||
goto out_drm_gem_fb_end_cpu_access;
|
||||
src = data[0].vaddr; /* TODO: Use mapping abstraction properly */
|
||||
|
||||
switch (fb->format->format) {
|
||||
case DRM_FORMAT_RGB565:
|
||||
if (swap)
|
||||
drm_fb_swab(dst, 0, src, fb, clip, !gem->import_attach);
|
||||
drm_fb_swab(&dst_map, NULL, data, fb, clip, !gem->import_attach);
|
||||
else
|
||||
drm_fb_memcpy(dst, 0, src, fb, clip);
|
||||
drm_fb_memcpy(&dst_map, NULL, data, fb, clip);
|
||||
break;
|
||||
case DRM_FORMAT_XRGB8888:
|
||||
drm_fb_xrgb8888_to_rgb565(dst, 0, src, fb, clip, swap);
|
||||
drm_fb_xrgb8888_to_rgb565(&dst_map, NULL, data, fb, clip, swap);
|
||||
break;
|
||||
default:
|
||||
drm_err_once(fb->dev, "Format is not supported: %p4cc\n",
|
||||
@ -1136,7 +1135,7 @@ int mipi_dbi_spi_init(struct spi_device *spi, struct mipi_dbi *dbi,
|
||||
/*
|
||||
* 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 the GEM code
|
||||
* (e.g., drm_gem_cma_create()). The dma_addr returned will be a physical
|
||||
* (e.g., drm_gem_dma_create()). The dma_addr returned will be a physical
|
||||
* address which might be different from the bus address, but this is
|
||||
* not a problem since the address will not be used.
|
||||
* The virtual address is used in the transfer and the SPI core
|
||||
|
@ -346,6 +346,7 @@ static int mipi_dsi_remove_device_fn(struct device *dev, void *priv)
|
||||
{
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||
|
||||
mipi_dsi_detach(dsi);
|
||||
mipi_dsi_device_unregister(dsi);
|
||||
|
||||
return 0;
|
||||
@ -1236,7 +1237,9 @@ static int mipi_dsi_drv_remove(struct device *dev)
|
||||
struct mipi_dsi_driver *drv = to_mipi_dsi_driver(dev->driver);
|
||||
struct mipi_dsi_device *dsi = to_mipi_dsi_device(dev);
|
||||
|
||||
return drv->remove(dsi);
|
||||
drv->remove(dsi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mipi_dsi_drv_shutdown(struct device *dev)
|
||||
|
@ -412,8 +412,8 @@ int drmm_mode_config_init(struct drm_device *dev)
|
||||
INIT_LIST_HEAD(&dev->mode_config.property_blob_list);
|
||||
INIT_LIST_HEAD(&dev->mode_config.plane_list);
|
||||
INIT_LIST_HEAD(&dev->mode_config.privobj_list);
|
||||
idr_init(&dev->mode_config.object_idr);
|
||||
idr_init(&dev->mode_config.tile_idr);
|
||||
idr_init_base(&dev->mode_config.object_idr, 1);
|
||||
idr_init_base(&dev->mode_config.tile_idr, 1);
|
||||
ida_init(&dev->mode_config.connector_ida);
|
||||
spin_lock_init(&dev->mode_config.connector_list_lock);
|
||||
|
||||
|
@ -108,6 +108,12 @@ static const uint32_t safe_modeset_formats[] = {
|
||||
DRM_FORMAT_ARGB8888,
|
||||
};
|
||||
|
||||
static const struct drm_plane_funcs primary_plane_funcs = {
|
||||
.update_plane = drm_plane_helper_update_primary,
|
||||
.disable_plane = drm_plane_helper_disable_primary,
|
||||
.destroy = drm_plane_helper_destroy,
|
||||
};
|
||||
|
||||
static struct drm_plane *create_primary_plane(struct drm_device *dev)
|
||||
{
|
||||
struct drm_plane *primary;
|
||||
@ -127,7 +133,7 @@ static struct drm_plane *create_primary_plane(struct drm_device *dev)
|
||||
|
||||
/* possible_crtc's will be filled in later by crtc_init */
|
||||
ret = drm_universal_plane_init(dev, primary, 0,
|
||||
&drm_primary_helper_funcs,
|
||||
&primary_plane_funcs,
|
||||
safe_modeset_formats,
|
||||
ARRAY_SIZE(safe_modeset_formats),
|
||||
NULL,
|
||||
|
@ -145,13 +145,36 @@ static int drm_plane_helper_check_update(struct drm_plane *plane,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
/**
|
||||
* drm_plane_helper_update_primary - Helper for updating primary planes
|
||||
* @plane: plane to update
|
||||
* @crtc: the plane's new CRTC
|
||||
* @fb: the plane's new framebuffer
|
||||
* @crtc_x: x coordinate within CRTC
|
||||
* @crtc_y: y coordinate within CRTC
|
||||
* @crtc_w: width coordinate within CRTC
|
||||
* @crtc_h: height coordinate within CRTC
|
||||
* @src_x: x coordinate within source
|
||||
* @src_y: y coordinate within source
|
||||
* @src_w: width coordinate within source
|
||||
* @src_h: height coordinate within source
|
||||
* @ctx: modeset locking context
|
||||
*
|
||||
* This helper validates the given parameters and updates the primary plane.
|
||||
*
|
||||
* This function is only useful for non-atomic modesetting. Don't use
|
||||
* it in new drivers.
|
||||
*
|
||||
* Returns:
|
||||
* Zero on success, or an errno code otherwise.
|
||||
*/
|
||||
int drm_plane_helper_update_primary(struct drm_plane *plane, struct drm_crtc *crtc,
|
||||
struct drm_framebuffer *fb,
|
||||
int crtc_x, int crtc_y,
|
||||
unsigned int crtc_w, unsigned int crtc_h,
|
||||
uint32_t src_x, uint32_t src_y,
|
||||
uint32_t src_w, uint32_t src_h,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
struct drm_mode_set set = {
|
||||
.crtc = crtc,
|
||||
@ -179,8 +202,8 @@ static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *c
|
||||
ret = drm_plane_helper_check_update(plane, crtc, fb,
|
||||
&src, &dest,
|
||||
DRM_MODE_ROTATE_0,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, false, &visible);
|
||||
if (ret)
|
||||
return ret;
|
||||
@ -218,31 +241,40 @@ static int drm_primary_helper_update(struct drm_plane *plane, struct drm_crtc *c
|
||||
kfree(connector_list);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_helper_update_primary);
|
||||
|
||||
static int drm_primary_helper_disable(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
/**
|
||||
* drm_plane_helper_disable_primary - Helper for disabling primary planes
|
||||
* @plane: plane to disable
|
||||
* @ctx: modeset locking context
|
||||
*
|
||||
* This helper returns an error when trying to disable the primary
|
||||
* plane.
|
||||
*
|
||||
* This function is only useful for non-atomic modesetting. Don't use
|
||||
* it in new drivers.
|
||||
*
|
||||
* Returns:
|
||||
* An errno code.
|
||||
*/
|
||||
int drm_plane_helper_disable_primary(struct drm_plane *plane,
|
||||
struct drm_modeset_acquire_ctx *ctx)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_plane_helper_disable_primary);
|
||||
|
||||
/**
|
||||
* drm_primary_helper_destroy() - Helper for primary plane destruction
|
||||
* drm_plane_helper_destroy() - Helper for primary plane destruction
|
||||
* @plane: plane to destroy
|
||||
*
|
||||
* Provides a default plane destroy handler for primary planes. This handler
|
||||
* is called during CRTC destruction. We disable the primary plane, remove
|
||||
* it from the DRM plane list, and deallocate the plane structure.
|
||||
*/
|
||||
void drm_primary_helper_destroy(struct drm_plane *plane)
|
||||
void drm_plane_helper_destroy(struct drm_plane *plane)
|
||||
{
|
||||
drm_plane_cleanup(plane);
|
||||
kfree(plane);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_primary_helper_destroy);
|
||||
|
||||
const struct drm_plane_funcs drm_primary_helper_funcs = {
|
||||
.update_plane = drm_primary_helper_update,
|
||||
.disable_plane = drm_primary_helper_disable,
|
||||
.destroy = drm_primary_helper_destroy,
|
||||
};
|
||||
EXPORT_SYMBOL(drm_primary_helper_funcs);
|
||||
EXPORT_SYMBOL(drm_plane_helper_destroy);
|
||||
|
@ -12,7 +12,6 @@
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_atomic_helper.h>
|
||||
#include <drm/drm_managed.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_simple_kms_helper.h>
|
||||
|
||||
@ -223,8 +222,8 @@ static int drm_simple_kms_plane_atomic_check(struct drm_plane *plane,
|
||||
&pipe->crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(plane_state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
false, false);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/exynos_drm.h>
|
||||
|
||||
#include "exynos_drm_crtc.h"
|
||||
|
@ -3,7 +3,7 @@ config DRM_FSL_DCU
|
||||
tristate "DRM Support for Freescale DCU"
|
||||
depends on DRM && OF && ARM && COMMON_CLK
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_PANEL
|
||||
select REGMAP_MMIO
|
||||
|
@ -20,9 +20,8 @@
|
||||
|
||||
#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_dma_helper.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
@ -150,13 +149,13 @@ static void fsl_dcu_unload(struct drm_device *dev)
|
||||
dev->dev_private = NULL;
|
||||
}
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(fsl_dcu_drm_fops);
|
||||
DEFINE_DRM_GEM_DMA_FOPS(fsl_dcu_drm_fops);
|
||||
|
||||
static const struct drm_driver fsl_dcu_drm_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.load = fsl_dcu_load,
|
||||
.unload = fsl_dcu_unload,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
DRM_GEM_DMA_DRIVER_OPS,
|
||||
.fops = &fsl_dcu_drm_fops,
|
||||
.name = "fsl-dcu-drm",
|
||||
.desc = "Freescale DCU DRM",
|
||||
|
@ -6,7 +6,6 @@
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_fb_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
|
@ -10,10 +10,10 @@
|
||||
#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_fb_dma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
@ -84,7 +84,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,
|
||||
plane);
|
||||
struct drm_framebuffer *fb = plane->state->fb;
|
||||
struct drm_gem_cma_object *gem;
|
||||
struct drm_gem_dma_object *gem;
|
||||
unsigned int alpha = DCU_LAYER_AB_NONE, bpp;
|
||||
int index;
|
||||
|
||||
@ -95,7 +95,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
gem = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
gem = drm_fb_dma_get_gem_obj(fb, 0);
|
||||
|
||||
switch (fb->format->format) {
|
||||
case DRM_FORMAT_RGB565:
|
||||
@ -136,7 +136,7 @@ static void fsl_dcu_drm_plane_atomic_update(struct drm_plane *plane,
|
||||
DCU_LAYER_POSY(new_state->crtc_y) |
|
||||
DCU_LAYER_POSX(new_state->crtc_x));
|
||||
regmap_write(fsl_dev->regmap,
|
||||
DCU_CTRLDESCLN(index, 3), gem->paddr);
|
||||
DCU_CTRLDESCLN(index, 3), gem->dma_addr);
|
||||
regmap_write(fsl_dev->regmap, DCU_CTRLDESCLN(index, 4),
|
||||
DCU_LAYER_EN |
|
||||
DCU_LAYER_TRANS(0xff) |
|
||||
@ -171,16 +171,10 @@ static const struct drm_plane_helper_funcs fsl_dcu_drm_plane_helper_funcs = {
|
||||
.atomic_update = fsl_dcu_drm_plane_atomic_update,
|
||||
};
|
||||
|
||||
static void fsl_dcu_drm_plane_destroy(struct drm_plane *plane)
|
||||
{
|
||||
drm_plane_cleanup(plane);
|
||||
kfree(plane);
|
||||
}
|
||||
|
||||
static const struct drm_plane_funcs fsl_dcu_drm_plane_funcs = {
|
||||
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
|
||||
.destroy = fsl_dcu_drm_plane_destroy,
|
||||
.destroy = drm_plane_helper_destroy,
|
||||
.disable_plane = drm_atomic_helper_disable_plane,
|
||||
.reset = drm_atomic_helper_plane_reset,
|
||||
.update_plane = drm_atomic_helper_update_plane,
|
||||
|
@ -9,8 +9,6 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "framebuffer.h"
|
||||
#include "gem.h"
|
||||
#include "gma_display.h"
|
||||
|
@ -59,6 +59,7 @@ static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format
|
||||
unsigned int bits_per_pixel = 8 / block_width;
|
||||
unsigned int x, y, width, height;
|
||||
u8 pix, *pix8, *block = dst; /* Assign to silence compiler warning */
|
||||
struct iosys_map dst_map, vmap;
|
||||
size_t len;
|
||||
void *buf;
|
||||
|
||||
@ -74,7 +75,9 @@ static size_t gud_xrgb8888_to_r124(u8 *dst, const struct drm_format_info *format
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
drm_fb_xrgb8888_to_gray8(buf, 0, src, fb, rect);
|
||||
iosys_map_set_vaddr(&dst_map, buf);
|
||||
iosys_map_set_vaddr(&vmap, src);
|
||||
drm_fb_xrgb8888_to_gray8(&dst_map, NULL, &vmap, fb, rect);
|
||||
pix8 = buf;
|
||||
|
||||
for (y = 0; y < height; y++) {
|
||||
@ -105,7 +108,8 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma
|
||||
unsigned int bits_per_pixel = 8 / block_width;
|
||||
u8 r, g, b, pix, *block = dst; /* Assign to silence compiler warning */
|
||||
unsigned int x, y, width;
|
||||
u32 *pix32;
|
||||
__le32 *sbuf32;
|
||||
u32 pix32;
|
||||
size_t len;
|
||||
|
||||
/* Start on a byte boundary */
|
||||
@ -114,8 +118,8 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma
|
||||
len = drm_format_info_min_pitch(format, 0, width) * drm_rect_height(rect);
|
||||
|
||||
for (y = rect->y1; y < rect->y2; y++) {
|
||||
pix32 = src + (y * fb->pitches[0]);
|
||||
pix32 += rect->x1;
|
||||
sbuf32 = src + (y * fb->pitches[0]);
|
||||
sbuf32 += rect->x1;
|
||||
|
||||
for (x = 0; x < width; x++) {
|
||||
unsigned int pixpos = x % block_width; /* within byte from the left */
|
||||
@ -126,9 +130,10 @@ static size_t gud_xrgb8888_to_color(u8 *dst, const struct drm_format_info *forma
|
||||
*block = 0;
|
||||
}
|
||||
|
||||
r = *pix32 >> 16;
|
||||
g = *pix32 >> 8;
|
||||
b = *pix32++;
|
||||
pix32 = le32_to_cpu(*sbuf32++);
|
||||
r = pix32 >> 16;
|
||||
g = pix32 >> 8;
|
||||
b = pix32;
|
||||
|
||||
switch (format->format) {
|
||||
case GUD_DRM_FORMAT_XRGB1111:
|
||||
@ -154,6 +159,7 @@ static int gud_prep_flush(struct gud_device *gdrm, struct drm_framebuffer *fb,
|
||||
u8 compression = gdrm->compression;
|
||||
struct iosys_map map[DRM_FORMAT_MAX_PLANES];
|
||||
struct iosys_map map_data[DRM_FORMAT_MAX_PLANES];
|
||||
struct iosys_map dst;
|
||||
void *vaddr, *buf;
|
||||
size_t pitch, len;
|
||||
int ret = 0;
|
||||
@ -177,6 +183,7 @@ retry:
|
||||
buf = gdrm->compress_buf;
|
||||
else
|
||||
buf = gdrm->bulk_buf;
|
||||
iosys_map_set_vaddr(&dst, buf);
|
||||
|
||||
/*
|
||||
* Imported buffers are assumed to be write-combined and thus uncached
|
||||
@ -190,23 +197,24 @@ retry:
|
||||
goto end_cpu_access;
|
||||
}
|
||||
} else if (format->format == DRM_FORMAT_R8) {
|
||||
drm_fb_xrgb8888_to_gray8(buf, 0, vaddr, fb, rect);
|
||||
drm_fb_xrgb8888_to_gray8(&dst, NULL, map_data, fb, rect);
|
||||
} else if (format->format == DRM_FORMAT_RGB332) {
|
||||
drm_fb_xrgb8888_to_rgb332(buf, 0, vaddr, fb, rect);
|
||||
drm_fb_xrgb8888_to_rgb332(&dst, NULL, map_data, fb, rect);
|
||||
} else if (format->format == DRM_FORMAT_RGB565) {
|
||||
drm_fb_xrgb8888_to_rgb565(buf, 0, vaddr, fb, rect, gud_is_big_endian());
|
||||
drm_fb_xrgb8888_to_rgb565(&dst, NULL, map_data, fb, rect,
|
||||
gud_is_big_endian());
|
||||
} else if (format->format == DRM_FORMAT_RGB888) {
|
||||
drm_fb_xrgb8888_to_rgb888(buf, 0, vaddr, fb, rect);
|
||||
drm_fb_xrgb8888_to_rgb888(&dst, NULL, map_data, fb, rect);
|
||||
} else {
|
||||
len = gud_xrgb8888_to_color(buf, format, vaddr, fb, rect);
|
||||
}
|
||||
} else if (gud_is_big_endian() && format->cpp[0] > 1) {
|
||||
drm_fb_swab(buf, 0, vaddr, fb, rect, !import_attach);
|
||||
drm_fb_swab(&dst, NULL, map_data, fb, rect, !import_attach);
|
||||
} else if (compression && !import_attach && pitch == fb->pitches[0]) {
|
||||
/* can compress directly from the framebuffer */
|
||||
buf = vaddr + rect->y1 * pitch;
|
||||
} else {
|
||||
drm_fb_memcpy(buf, 0, vaddr, fb, rect);
|
||||
drm_fb_memcpy(&dst, NULL, map_data, fb, rect);
|
||||
}
|
||||
|
||||
memset(req, 0, sizeof(*req));
|
||||
|
@ -3,7 +3,7 @@ config DRM_HISI_KIRIN
|
||||
tristate "DRM Support for Hisilicon Kirin series SoCs Platform"
|
||||
depends on DRM && OF && ARM64
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_GEM_CMA_HELPER
|
||||
select DRM_GEM_DMA_HELPER
|
||||
select DRM_MIPI_DSI
|
||||
help
|
||||
Choose this option if you have a hisilicon Kirin chipsets(hi6220).
|
||||
|
@ -24,11 +24,10 @@
|
||||
#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_dma_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_framebuffer.h>
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_gem_dma_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
@ -549,13 +548,13 @@ static const struct drm_crtc_funcs ade_crtc_funcs = {
|
||||
static void ade_rdma_set(void __iomem *base, struct drm_framebuffer *fb,
|
||||
u32 ch, u32 y, u32 in_h, u32 fmt)
|
||||
{
|
||||
struct drm_gem_cma_object *obj = drm_fb_cma_get_gem_obj(fb, 0);
|
||||
struct drm_gem_dma_object *obj = drm_fb_dma_get_gem_obj(fb, 0);
|
||||
u32 reg_ctrl, reg_addr, reg_size, reg_stride, reg_space, reg_en;
|
||||
u32 stride = fb->pitches[0];
|
||||
u32 addr = (u32)obj->paddr + y * stride;
|
||||
u32 addr = (u32) obj->dma_addr + y * stride;
|
||||
|
||||
DRM_DEBUG_DRIVER("rdma%d: (y=%d, height=%d), stride=%d, paddr=0x%x\n",
|
||||
ch + 1, y, in_h, stride, (u32)obj->paddr);
|
||||
ch + 1, y, in_h, stride, (u32) obj->dma_addr);
|
||||
DRM_DEBUG_DRIVER("addr=0x%x, fb:%dx%d, pixel_format=%d(%p4cc)\n",
|
||||
addr, fb->width, fb->height, fmt,
|
||||
&fb->format->format);
|
||||
@ -920,12 +919,12 @@ static const struct drm_mode_config_funcs ade_mode_config_funcs = {
|
||||
|
||||
};
|
||||
|
||||
DEFINE_DRM_GEM_CMA_FOPS(ade_fops);
|
||||
DEFINE_DRM_GEM_DMA_FOPS(ade_fops);
|
||||
|
||||
static const struct drm_driver ade_driver = {
|
||||
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
|
||||
.fops = &ade_fops,
|
||||
DRM_GEM_CMA_DRIVER_OPS,
|
||||
DRM_GEM_DMA_DRIVER_OPS,
|
||||
.name = "kirin",
|
||||
.desc = "Hisilicon Kirin620 SoC DRM Driver",
|
||||
.date = "20150718",
|
||||
|
@ -19,9 +19,8 @@
|
||||
|
||||
#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_dma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_of.h>
|
||||
|
@ -21,19 +21,18 @@
|
||||
#include "hyperv_drm.h"
|
||||
|
||||
static int hyperv_blit_to_vram_rect(struct drm_framebuffer *fb,
|
||||
const struct iosys_map *map,
|
||||
const struct iosys_map *vmap,
|
||||
struct drm_rect *rect)
|
||||
{
|
||||
struct hyperv_drm_device *hv = to_hv(fb->dev);
|
||||
void __iomem *dst = hv->vram;
|
||||
void *vmap = map->vaddr; /* TODO: Use mapping abstraction properly */
|
||||
struct iosys_map dst = IOSYS_MAP_INIT_VADDR_IOMEM(hv->vram);
|
||||
int idx;
|
||||
|
||||
if (!drm_dev_enter(&hv->dev, &idx))
|
||||
return -ENODEV;
|
||||
|
||||
dst += drm_fb_clip_offset(fb->pitches[0], fb->format, rect);
|
||||
drm_fb_memcpy_toio(dst, fb->pitches[0], vmap, fb, rect);
|
||||
iosys_map_incr(&dst, drm_fb_clip_offset(fb->pitches[0], fb->format, rect));
|
||||
drm_fb_memcpy(&dst, fb->pitches, vmap, fb, rect);
|
||||
|
||||
drm_dev_exit(idx);
|
||||
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_blend.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "intel_atomic.h"
|
||||
#include "intel_atomic_plane.h"
|
||||
@ -326,8 +325,8 @@ i9xx_plane_check(struct intel_crtc_state *crtc_state,
|
||||
return ret;
|
||||
|
||||
ret = intel_atomic_plane_check_clipping(plane_state, crtc_state,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_HELPER_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
i9xx_plane_has_windowing(plane));
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
|
||||
#include "i915_drv.h"
|
||||
#include "i915_reg.h"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user