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:
Daniel Vetter 2022-09-06 10:56:03 +02:00
commit 8284bae723
478 changed files with 16334 additions and 14707 deletions

View File

@ -17,6 +17,8 @@ properties:
enum:
- ingenic,jz4740-lcd
- ingenic,jz4725b-lcd
- ingenic,jz4760-lcd
- ingenic,jz4760b-lcd
- ingenic,jz4770-lcd
- ingenic,jz4780-lcd

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -813,13 +813,14 @@ static int lt9611_connector_init(struct drm_bridge *bridge, struct lt9611 *lt961
drm_connector_helper_add(&lt9611->connector,
&lt9611_bridge_connector_helper_funcs);
drm_connector_attach_encoder(&lt9611->connector, bridge->encoder);
if (!bridge->encoder) {
DRM_ERROR("Parent encoder object not found");
return -ENODEV;
}
drm_connector_attach_encoder(&lt9611->connector, bridge->encoder);
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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