mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-19 10:44:14 +08:00
Merge tag 'drm-intel-gt-next-2022-02-17' of git://anongit.freedesktop.org/drm/drm-intel into drm-intel-next
UAPI Changes: - Weak parallel submission support for execlists Minimal implementation of the parallel submission support for execlists backend that was previously only implemented for GuC. Support one sibling non-virtual engine. Core Changes: - Two backmerges of drm/drm-next for header file renames/changes and i915_regs reorganization Driver Changes: - Add new DG2 subplatform: DG2-G12 (Matt R) - Add new DG2 workarounds (Matt R, Ram, Bruce) - Handle pre-programmed WOPCM registers for DG2+ (Daniele) - Update guc shim control programming on XeHP SDV+ (Daniele) - Add RPL-S C0/D0 stepping information (Anusha) - Improve GuC ADS initialization to work on ARM64 on dGFX (Lucas) - Fix KMD and GuC race on accessing PMU busyness (Umesh) - Use PM timestamp instead of RING TIMESTAMP for reference in PMU with GuC (Umesh) - Report error on invalid reset notification from GuC (John) - Avoid WARN splat by holding RPM wakelock during PXP unbind (Juston) - Fixes to parallel submission implementation (Matt B.) - Improve GuC loading status check/error reports (John) - Tweak TTM LRU priority hint selection (Matt A.) - Align the plane_vma to min_page_size of stolen mem (Ram) - Introduce vma resources and implement async unbinding (Thomas) - Use struct vma_resource instead of struct vma_snapshot (Thomas) - Return some TTM accel move errors instead of trying memcpy move (Thomas) - Fix a race between vma / object destruction and unbinding (Thomas) - Remove short-term pins from execbuf (Maarten) - Update to GuC version 69.0.3 (John, Michal Wa.) - Improvements to GT reset paths in GuC backend (Matt B.) - Use shrinker_release_pages instead of writeback in shmem object hooks (Matt A., Tvrtko) - Use trylock instead of blocking lock when freeing GEM objects (Maarten) - Allocate intel_engine_coredump_alloc with ALLOW_FAIL (Matt B.) - Fixes to object unmapping and purging (Matt A) - Check for wedged device in GuC backend (John) - Avoid lockdep splat by locking dpt_obj around set_cache_level (Maarten) - Allow dead vm to unbind vma's without lock (Maarten) - s/engine->i915/i915/ for DG2 engine workarounds (Matt R) - Use to_gt() helper for GGTT accesses (Michal Wi.) - Selftest improvements (Matt B., Thomas, Ram) - Coding style and compiler warning fixes (Matt B., Jasmine, Andi, Colin, Gustavo, Dan) From: Joonas Lahtinen <joonas.lahtinen@linux.intel.com> Link: https://patchwork.freedesktop.org/patch/msgid/Yg4i2aCZvvee5Eai@jlahtine-mobl.ger.corp.intel.com Signed-off-by: Rodrigo Vivi <rodrigo.vivi@intel.com> [Fixed conflicts while applying, using the fixups/drm-intel-gt-next.patch from drm-rerere's 1f2b1742abdd ("2022y-02m-23d-16h-07m-57s UTC: drm-tip rerere cache update")]
This commit is contained in:
commit
30424ebae8
@ -39,6 +39,7 @@ properties:
|
||||
- const: lvds-encoder # Generic LVDS encoder compatible fallback
|
||||
- items:
|
||||
- enum:
|
||||
- ti,ds90cf364a # For the DS90CF364A FPD-Link LVDS Receiver
|
||||
- ti,ds90cf384a # For the DS90CF384A FPD-Link LVDS Receiver
|
||||
- const: lvds-decoder # Generic LVDS decoders compatible fallback
|
||||
- enum:
|
||||
|
@ -32,6 +32,9 @@ properties:
|
||||
maxItems: 1
|
||||
description: GPIO specifier for bridge_en pin (active high).
|
||||
|
||||
vcc-supply:
|
||||
description: A 1.8V power supply (see regulator/regulator.yaml).
|
||||
|
||||
ports:
|
||||
$ref: /schemas/graph.yaml#/properties/ports
|
||||
|
||||
@ -91,7 +94,6 @@ properties:
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
- enable-gpios
|
||||
- ports
|
||||
|
||||
allOf:
|
||||
@ -133,6 +135,7 @@ examples:
|
||||
reg = <0x2d>;
|
||||
|
||||
enable-gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
|
||||
vcc-supply = <®_sn65dsi83_1v8>;
|
||||
|
||||
ports {
|
||||
#address-cells = <1>;
|
||||
|
@ -222,6 +222,8 @@ properties:
|
||||
- logictechno,lttd800480070-l6wh-rt
|
||||
# Mitsubishi "AA070MC01 7.0" WVGA TFT LCD panel
|
||||
- mitsubishi,aa070mc01-ca1
|
||||
# Multi-Inno Technology Co.,Ltd MI0700S4T-6 7" 800x480 TFT Resistive Touch Module
|
||||
- multi-inno,mi0700s4t-6
|
||||
# Multi-Inno Technology Co.,Ltd MI1010AIT-1CP 10.1" 1280x800 LVDS IPS Cap Touch Mod.
|
||||
- multi-inno,mi1010ait-1cp
|
||||
# NEC LCD Technologies, Ltd. 12.1" WXGA (1280x800) LVDS TFT LCD panel
|
||||
|
@ -4,7 +4,12 @@
|
||||
$id: http://devicetree.org/schemas/display/panel/sony,acx424akp.yaml#
|
||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||
|
||||
title: Sony ACX424AKP 4" 480x864 AMOLED panel
|
||||
title: Sony ACX424AKP/ACX424AKM 4" 480x864/480x854 AMOLED panel
|
||||
|
||||
description: The Sony ACX424AKP and ACX424AKM are panels built around
|
||||
the Novatek NT35560 display controller. The only difference is that
|
||||
the AKM is configured to use 10 pixels less in the Y axis than the
|
||||
AKP.
|
||||
|
||||
maintainers:
|
||||
- Linus Walleij <linus.walleij@linaro.org>
|
||||
@ -14,7 +19,9 @@ allOf:
|
||||
|
||||
properties:
|
||||
compatible:
|
||||
const: sony,acx424akp
|
||||
enum:
|
||||
- sony,acx424akp
|
||||
- sony,acx424akm
|
||||
reg: true
|
||||
reset-gpios: true
|
||||
vddi-supply:
|
||||
|
@ -75,6 +75,12 @@ update it, its value is mostly useless. The DRM core prints it to the
|
||||
kernel log at initialization time and passes it to userspace through the
|
||||
DRM_IOCTL_VERSION ioctl.
|
||||
|
||||
Module Initialization
|
||||
---------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_module.h
|
||||
:doc: overview
|
||||
|
||||
Managing Ownership of the Framebuffer Aperture
|
||||
----------------------------------------------
|
||||
|
||||
|
@ -232,34 +232,34 @@ HDCP Helper Functions Reference
|
||||
Display Port Helper Functions Reference
|
||||
=======================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp.c
|
||||
:doc: dp helpers
|
||||
|
||||
.. kernel-doc:: include/drm/drm_dp_helper.h
|
||||
.. kernel-doc:: include/drm/dp/drm_dp_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_helper.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp.c
|
||||
:export:
|
||||
|
||||
Display Port CEC Helper Functions Reference
|
||||
===========================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_cec.c
|
||||
:doc: dp cec helpers
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_cec.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_cec.c
|
||||
:export:
|
||||
|
||||
Display Port Dual Mode Adaptor Helper Functions Reference
|
||||
=========================================================
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_dual_mode_helper.c
|
||||
:doc: dp dual mode helpers
|
||||
|
||||
.. kernel-doc:: include/drm/drm_dp_dual_mode_helper.h
|
||||
.. kernel-doc:: include/drm/dp/drm_dp_dual_mode_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_dual_mode_helper.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_dual_mode_helper.c
|
||||
:export:
|
||||
|
||||
Display Port MST Helpers
|
||||
@ -268,19 +268,19 @@ Display Port MST Helpers
|
||||
Overview
|
||||
--------
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
|
||||
:doc: dp mst helper
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
|
||||
:doc: Branch device and port refcounting
|
||||
|
||||
Functions Reference
|
||||
-------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_dp_mst_helper.h
|
||||
.. kernel-doc:: include/drm/dp/drm_dp_mst_helper.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
|
||||
:export:
|
||||
|
||||
Topology Lifetime Internals
|
||||
@ -289,7 +289,7 @@ Topology Lifetime Internals
|
||||
These functions aren't exported to drivers, but are documented here to help make
|
||||
the MST topology helpers easier to understand
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_dp_mst_topology.c
|
||||
.. kernel-doc:: drivers/gpu/drm/dp/drm_dp_mst_topology.c
|
||||
:functions: drm_dp_mst_topology_try_get_mstb drm_dp_mst_topology_get_mstb
|
||||
drm_dp_mst_topology_put_mstb
|
||||
drm_dp_mst_topology_try_get_port drm_dp_mst_topology_get_port
|
||||
|
@ -423,12 +423,12 @@ Connector Functions Reference
|
||||
Writeback Connectors
|
||||
--------------------
|
||||
|
||||
.. kernel-doc:: include/drm/drm_writeback.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
|
||||
:doc: overview
|
||||
|
||||
.. kernel-doc:: include/drm/drm_writeback.h
|
||||
:internal:
|
||||
|
||||
.. kernel-doc:: drivers/gpu/drm/drm_writeback.c
|
||||
:export:
|
||||
|
||||
|
@ -8,7 +8,7 @@ the very dynamic nature of many of that data, managing graphics memory
|
||||
efficiently is thus crucial for the graphics stack and plays a central
|
||||
role in the DRM infrastructure.
|
||||
|
||||
The DRM core includes two memory managers, namely Translation Table Maps
|
||||
The DRM core includes two memory managers, namely Translation Table Manager
|
||||
(TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory
|
||||
manager to be developed and tried to be a one-size-fits-them all
|
||||
solution. It provides a single userspace API to accommodate the need of
|
||||
|
@ -539,6 +539,7 @@ GuC ABI
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_mmio_abi.h
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_communication_ctb_abi.h
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_actions_abi.h
|
||||
.. kernel-doc:: drivers/gpu/drm/i915/gt/uc/abi/guc_klvs_abi.h
|
||||
|
||||
HuC
|
||||
---
|
||||
|
@ -467,6 +467,21 @@ Contact: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
|
||||
Level: Intermediate
|
||||
|
||||
Request memory regions in all drivers
|
||||
-------------------------------------
|
||||
|
||||
Go through all drivers and add code to request the memory regions that the
|
||||
driver uses. This requires adding calls to request_mem_region(),
|
||||
pci_request_region() or similar functions. Use helpers for managed cleanup
|
||||
where possible.
|
||||
|
||||
Drivers are pretty bad at doing this and there used to be conflicts among
|
||||
DRM and fbdev drivers. Still, it's the correct thing to do.
|
||||
|
||||
Contact: Thomas Zimmermann <tzimmermann@suse.de>
|
||||
|
||||
Level: Starter
|
||||
|
||||
|
||||
Core refactorings
|
||||
=================
|
||||
|
@ -124,8 +124,6 @@ Add Plane Features
|
||||
|
||||
There's lots of plane features we could add support for:
|
||||
|
||||
- Multiple overlay planes. [Good to get started]
|
||||
|
||||
- Clearing primary plane: clear primary plane before plane composition (at the
|
||||
start) for correctness of pixel blend ops. It also guarantees alpha channel
|
||||
is cleared in the target buffer for stable crc. [Good to get started]
|
||||
|
@ -55,7 +55,7 @@ static struct _ati_generic_private {
|
||||
|
||||
static int ati_create_page_map(struct ati_page_map *page_map)
|
||||
{
|
||||
int i, err = 0;
|
||||
int i, err;
|
||||
|
||||
page_map->real = (unsigned long *) __get_free_page(GFP_KERNEL);
|
||||
if (page_map->real == NULL)
|
||||
@ -63,6 +63,10 @@ static int ati_create_page_map(struct ati_page_map *page_map)
|
||||
|
||||
set_memory_uc((unsigned long)page_map->real, 1);
|
||||
err = map_page_into_agp(virt_to_page(page_map->real));
|
||||
if (err) {
|
||||
free_page((unsigned long)page_map->real);
|
||||
return err;
|
||||
}
|
||||
page_map->remapped = page_map->real;
|
||||
|
||||
for (i = 0; i < PAGE_SIZE / sizeof(unsigned long); i++) {
|
||||
|
@ -62,6 +62,7 @@ EXPORT_SYMBOL(agp_find_bridge);
|
||||
|
||||
/**
|
||||
* agp_backend_acquire - attempt to acquire an agp backend.
|
||||
* @pdev: the PCI device
|
||||
*
|
||||
*/
|
||||
struct agp_bridge_data *agp_backend_acquire(struct pci_dev *pdev)
|
||||
@ -83,6 +84,7 @@ EXPORT_SYMBOL(agp_backend_acquire);
|
||||
|
||||
/**
|
||||
* agp_backend_release - release the lock on the agp backend.
|
||||
* @bridge: the AGP backend to release
|
||||
*
|
||||
* The caller must insure that the graphics aperture translation table
|
||||
* is read for use by another entity.
|
||||
|
@ -39,7 +39,9 @@
|
||||
#include <linux/fs.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/uaccess.h>
|
||||
|
||||
#include "agp.h"
|
||||
#include "compat_ioctl.h"
|
||||
|
||||
struct agp_front_data agp_fe;
|
||||
|
||||
|
@ -261,7 +261,8 @@ static int nvidia_remove_memory(struct agp_memory *mem, off_t pg_start, int type
|
||||
static void nvidia_tlbflush(struct agp_memory *mem)
|
||||
{
|
||||
unsigned long end;
|
||||
u32 wbc_reg, temp;
|
||||
u32 wbc_reg;
|
||||
u32 __maybe_unused temp;
|
||||
int i;
|
||||
|
||||
/* flush chipset */
|
||||
|
@ -262,13 +262,10 @@ static void serverworks_tlbflush(struct agp_memory *temp)
|
||||
|
||||
static int serverworks_configure(void)
|
||||
{
|
||||
struct aper_size_info_lvl2 *current_size;
|
||||
u32 temp;
|
||||
u8 enable_reg;
|
||||
u16 cap_reg;
|
||||
|
||||
current_size = A_SIZE_LVL2(agp_bridge->current_size);
|
||||
|
||||
/* Get the memory mapped registers */
|
||||
pci_read_config_dword(agp_bridge->dev, serverworks_private.mm_addr_ofs, &temp);
|
||||
temp = (temp & PCI_BASE_ADDRESS_MEM_MASK);
|
||||
|
@ -128,9 +128,6 @@ static int via_fetch_size_agp3(void)
|
||||
static int via_configure_agp3(void)
|
||||
{
|
||||
u32 temp;
|
||||
struct aper_size_info_16 *current_size;
|
||||
|
||||
current_size = A_SIZE_16(agp_bridge->current_size);
|
||||
|
||||
/* address to map to */
|
||||
agp_bridge->gart_bus_addr = pci_bus_address(agp_bridge->dev,
|
||||
|
@ -542,57 +542,45 @@ EXPORT_SYMBOL(dma_resv_copy_fences);
|
||||
* dma_resv_get_fences - Get an object's shared and exclusive
|
||||
* fences without update side lock held
|
||||
* @obj: the reservation object
|
||||
* @fence_excl: the returned exclusive fence (or NULL)
|
||||
* @shared_count: the number of shared fences returned
|
||||
* @shared: the array of shared fence ptrs returned (array is krealloc'd to
|
||||
* the required size, and must be freed by caller)
|
||||
* @write: true if we should return all fences
|
||||
* @num_fences: the number of fences returned
|
||||
* @fences: the array of fence ptrs returned (array is krealloc'd to the
|
||||
* required size, and must be freed by caller)
|
||||
*
|
||||
* Retrieve all fences from the reservation object. If the pointer for the
|
||||
* exclusive fence is not specified the fence is put into the array of the
|
||||
* shared fences as well. Returns either zero or -ENOMEM.
|
||||
* Retrieve all fences from the reservation object.
|
||||
* Returns either zero or -ENOMEM.
|
||||
*/
|
||||
int dma_resv_get_fences(struct dma_resv *obj, struct dma_fence **fence_excl,
|
||||
unsigned int *shared_count, struct dma_fence ***shared)
|
||||
int dma_resv_get_fences(struct dma_resv *obj, bool write,
|
||||
unsigned int *num_fences, struct dma_fence ***fences)
|
||||
{
|
||||
struct dma_resv_iter cursor;
|
||||
struct dma_fence *fence;
|
||||
|
||||
*shared_count = 0;
|
||||
*shared = NULL;
|
||||
*num_fences = 0;
|
||||
*fences = NULL;
|
||||
|
||||
if (fence_excl)
|
||||
*fence_excl = NULL;
|
||||
|
||||
dma_resv_iter_begin(&cursor, obj, true);
|
||||
dma_resv_iter_begin(&cursor, obj, write);
|
||||
dma_resv_for_each_fence_unlocked(&cursor, fence) {
|
||||
|
||||
if (dma_resv_iter_is_restarted(&cursor)) {
|
||||
unsigned int count;
|
||||
|
||||
while (*shared_count)
|
||||
dma_fence_put((*shared)[--(*shared_count)]);
|
||||
while (*num_fences)
|
||||
dma_fence_put((*fences)[--(*num_fences)]);
|
||||
|
||||
if (fence_excl)
|
||||
dma_fence_put(*fence_excl);
|
||||
|
||||
count = cursor.shared_count;
|
||||
count += fence_excl ? 0 : 1;
|
||||
count = cursor.shared_count + 1;
|
||||
|
||||
/* Eventually re-allocate the array */
|
||||
*shared = krealloc_array(*shared, count,
|
||||
*fences = krealloc_array(*fences, count,
|
||||
sizeof(void *),
|
||||
GFP_KERNEL);
|
||||
if (count && !*shared) {
|
||||
if (count && !*fences) {
|
||||
dma_resv_iter_end(&cursor);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
dma_fence_get(fence);
|
||||
if (dma_resv_iter_is_exclusive(&cursor) && fence_excl)
|
||||
*fence_excl = fence;
|
||||
else
|
||||
(*shared)[(*shared_count)++] = fence;
|
||||
(*fences)[(*num_fences)++] = dma_fence_get(fence);
|
||||
}
|
||||
dma_resv_iter_end(&cursor);
|
||||
|
||||
|
@ -275,7 +275,7 @@ static int test_shared_for_each_unlocked(void *arg)
|
||||
|
||||
static int test_get_fences(void *arg, bool shared)
|
||||
{
|
||||
struct dma_fence *f, *excl = NULL, **fences = NULL;
|
||||
struct dma_fence *f, **fences = NULL;
|
||||
struct dma_resv resv;
|
||||
int r, i;
|
||||
|
||||
@ -304,35 +304,19 @@ static int test_get_fences(void *arg, bool shared)
|
||||
}
|
||||
dma_resv_unlock(&resv);
|
||||
|
||||
r = dma_resv_get_fences(&resv, &excl, &i, &fences);
|
||||
r = dma_resv_get_fences(&resv, shared, &i, &fences);
|
||||
if (r) {
|
||||
pr_err("get_fences failed\n");
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (shared) {
|
||||
if (excl != NULL) {
|
||||
pr_err("get_fences returned unexpected excl fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
if (i != 1 || fences[0] != f) {
|
||||
pr_err("get_fences returned unexpected shared fence\n");
|
||||
pr_err("get_fences returned unexpected fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
} else {
|
||||
if (excl != f) {
|
||||
pr_err("get_fences returned unexpected excl fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
if (i != 0) {
|
||||
pr_err("get_fences returned unexpected shared fence\n");
|
||||
goto err_free;
|
||||
}
|
||||
}
|
||||
|
||||
dma_fence_signal(f);
|
||||
err_free:
|
||||
dma_fence_put(excl);
|
||||
while (i--)
|
||||
dma_fence_put(fences[i]);
|
||||
kfree(fences);
|
||||
|
@ -190,6 +190,10 @@ static long udmabuf_create(struct miscdevice *device,
|
||||
if (ubuf->pagecount > pglimit)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!ubuf->pagecount)
|
||||
goto err;
|
||||
|
||||
ubuf->pages = kmalloc_array(ubuf->pagecount, sizeof(*ubuf->pages),
|
||||
GFP_KERNEL);
|
||||
if (!ubuf->pages) {
|
||||
|
@ -99,7 +99,7 @@ __init int sysfb_create_simplefb(const struct screen_info *si,
|
||||
|
||||
/* setup IORESOURCE_MEM as framebuffer memory */
|
||||
memset(&res, 0, sizeof(res));
|
||||
res.flags = IORESOURCE_MEM | IORESOURCE_BUSY;
|
||||
res.flags = IORESOURCE_MEM;
|
||||
res.name = simplefb_resname;
|
||||
res.start = base;
|
||||
res.end = res.start + length - 1;
|
||||
|
@ -68,6 +68,7 @@ config DRM_DEBUG_SELFTEST
|
||||
depends on DRM
|
||||
depends on DEBUG_KERNEL
|
||||
select PRIME_NUMBERS
|
||||
select DRM_DP_HELPER
|
||||
select DRM_LIB_RANDOM
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_EXPORT_FOR_TESTS if m
|
||||
@ -80,6 +81,12 @@ config DRM_DEBUG_SELFTEST
|
||||
|
||||
If in doubt, say "N".
|
||||
|
||||
config DRM_DP_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
help
|
||||
DRM helpers for DisplayPort.
|
||||
|
||||
config DRM_KMS_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
@ -198,6 +205,12 @@ config DRM_TTM
|
||||
GPU memory types. Will be enabled automatically if a device driver
|
||||
uses it.
|
||||
|
||||
config DRM_BUDDY
|
||||
tristate
|
||||
depends on DRM
|
||||
help
|
||||
A page based buddy allocator
|
||||
|
||||
config DRM_VRAM_HELPER
|
||||
tristate
|
||||
depends on DRM
|
||||
@ -236,6 +249,7 @@ config DRM_RADEON
|
||||
depends on DRM && PCI && MMU
|
||||
depends on AGP || !AGP
|
||||
select FW_LOADER
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_TTM
|
||||
select DRM_TTM_HELPER
|
||||
@ -256,6 +270,7 @@ config DRM_AMDGPU
|
||||
tristate "AMD GPU"
|
||||
depends on DRM && PCI && MMU
|
||||
select FW_LOADER
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_SCHED
|
||||
select DRM_TTM
|
||||
|
@ -31,8 +31,6 @@ drm-$(CONFIG_DEBUG_FS) += drm_debugfs.o drm_debugfs_crc.o
|
||||
drm-$(CONFIG_DRM_LOAD_EDID_FIRMWARE) += drm_edid_load.o
|
||||
drm-$(CONFIG_DRM_PRIVACY_SCREEN) += drm_privacy_screen.o drm_privacy_screen_x86.o
|
||||
|
||||
obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
|
||||
|
||||
obj-$(CONFIG_DRM_NOMODESET) += drm_nomodeset.o
|
||||
|
||||
drm_cma_helper-y := drm_gem_cma_helper.o
|
||||
@ -42,27 +40,26 @@ obj-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_cma_helper.o
|
||||
drm_shmem_helper-y := drm_gem_shmem_helper.o
|
||||
obj-$(CONFIG_DRM_GEM_SHMEM_HELPER) += drm_shmem_helper.o
|
||||
|
||||
obj-$(CONFIG_DRM_BUDDY) += drm_buddy.o
|
||||
|
||||
drm_vram_helper-y := drm_gem_vram_helper.o
|
||||
obj-$(CONFIG_DRM_VRAM_HELPER) += drm_vram_helper.o
|
||||
|
||||
drm_ttm_helper-y := drm_gem_ttm_helper.o
|
||||
obj-$(CONFIG_DRM_TTM_HELPER) += drm_ttm_helper.o
|
||||
|
||||
drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o drm_dp_helper.o \
|
||||
drm_kms_helper-y := drm_bridge_connector.o drm_crtc_helper.o \
|
||||
drm_dsc.o drm_encoder_slave.o drm_flip_work.o drm_hdcp.o \
|
||||
drm_probe_helper.o \
|
||||
drm_plane_helper.o drm_dp_mst_topology.o drm_atomic_helper.o \
|
||||
drm_kms_helper_common.o drm_dp_dual_mode_helper.o \
|
||||
drm_plane_helper.o drm_atomic_helper.o \
|
||||
drm_kms_helper_common.o \
|
||||
drm_simple_kms_helper.o drm_modeset_helper.o \
|
||||
drm_scdc_helper.o drm_gem_atomic_helper.o \
|
||||
drm_gem_framebuffer_helper.o \
|
||||
drm_atomic_state_helper.o drm_damage_helper.o \
|
||||
drm_format_helper.o drm_self_refresh_helper.o drm_rect.o
|
||||
|
||||
drm_kms_helper-$(CONFIG_DRM_PANEL_BRIDGE) += bridge/panel.o
|
||||
drm_kms_helper-$(CONFIG_DRM_FBDEV_EMULATION) += drm_fb_helper.o
|
||||
drm_kms_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
|
||||
drm_kms_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
|
||||
|
||||
obj-$(CONFIG_DRM_KMS_HELPER) += drm_kms_helper.o
|
||||
obj-$(CONFIG_DRM_DEBUG_SELFTEST) += selftests/
|
||||
@ -72,6 +69,7 @@ obj-$(CONFIG_DRM_MIPI_DBI) += drm_mipi_dbi.o
|
||||
obj-$(CONFIG_DRM_MIPI_DSI) += drm_mipi_dsi.o
|
||||
obj-$(CONFIG_DRM_PANEL_ORIENTATION_QUIRKS) += drm_panel_orientation_quirks.o
|
||||
obj-y += arm/
|
||||
obj-y += dp/
|
||||
obj-$(CONFIG_DRM_TTM) += ttm/
|
||||
obj-$(CONFIG_DRM_SCHED) += scheduler/
|
||||
obj-$(CONFIG_DRM_TDFX) += tdfx/
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include "amdgpu.h"
|
||||
@ -175,7 +175,7 @@ int amdgpu_connector_get_monitor_bpc(struct drm_connector *connector)
|
||||
|
||||
/* Check if bpc is within clock limit. Try to degrade gracefully otherwise */
|
||||
if ((bpc == 12) && (mode_clock * 3/2 > max_tmds_clock)) {
|
||||
if ((connector->display_info.edid_hdmi_dc_modes & DRM_EDID_HDMI_DC_30) &&
|
||||
if ((connector->display_info.edid_hdmi_rgb444_dc_modes & DRM_EDID_HDMI_DC_30) &&
|
||||
(mode_clock * 5/4 <= max_tmds_clock))
|
||||
bpc = 10;
|
||||
else
|
||||
|
@ -1274,14 +1274,11 @@ static int amdgpu_cs_submit(struct amdgpu_cs_parser *p,
|
||||
/*
|
||||
* Work around dma_resv shortcommings by wrapping up the
|
||||
* submission in a dma_fence_chain and add it as exclusive
|
||||
* fence, but first add the submission as shared fence to make
|
||||
* sure that shared fences never signal before the exclusive
|
||||
* one.
|
||||
* fence.
|
||||
*/
|
||||
dma_fence_chain_init(chain, dma_resv_excl_fence(resv),
|
||||
dma_fence_get(p->fence), 1);
|
||||
|
||||
dma_resv_add_shared_fence(resv, p->fence);
|
||||
rcu_assign_pointer(resv->fence_excl, &chain->base);
|
||||
e->chain = NULL;
|
||||
}
|
||||
|
@ -200,8 +200,10 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
|
||||
goto unpin;
|
||||
}
|
||||
|
||||
r = dma_resv_get_fences(new_abo->tbo.base.resv, NULL,
|
||||
&work->shared_count, &work->shared);
|
||||
/* TODO: Unify this with other drivers */
|
||||
r = dma_resv_get_fences(new_abo->tbo.base.resv, true,
|
||||
&work->shared_count,
|
||||
&work->shared);
|
||||
if (unlikely(r != 0)) {
|
||||
DRM_ERROR("failed to get fences for buffer\n");
|
||||
goto unpin;
|
||||
|
@ -226,12 +226,6 @@ static void amdgpu_gem_object_close(struct drm_gem_object *obj,
|
||||
if (!amdgpu_vm_ready(vm))
|
||||
goto out_unlock;
|
||||
|
||||
fence = dma_resv_excl_fence(bo->tbo.base.resv);
|
||||
if (fence) {
|
||||
amdgpu_bo_fence(bo, fence, true);
|
||||
fence = NULL;
|
||||
}
|
||||
|
||||
r = amdgpu_vm_clear_freed(adev, vm, &fence);
|
||||
if (r || !fence)
|
||||
goto out_unlock;
|
||||
|
@ -167,6 +167,7 @@ static int amdgpu_gtt_mgr_new(struct ttm_resource_manager *man,
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
ttm_resource_fini(man, &node->base.base);
|
||||
kfree(node);
|
||||
|
||||
err_out:
|
||||
@ -198,6 +199,7 @@ static void amdgpu_gtt_mgr_del(struct ttm_resource_manager *man,
|
||||
if (!(res->placement & TTM_PL_FLAG_TEMPORARY))
|
||||
atomic64_sub(res->num_pages, &mgr->used);
|
||||
|
||||
ttm_resource_fini(man, res);
|
||||
kfree(node);
|
||||
}
|
||||
|
||||
@ -286,7 +288,8 @@ int amdgpu_gtt_mgr_init(struct amdgpu_device *adev, uint64_t gtt_size)
|
||||
man->use_tt = true;
|
||||
man->func = &amdgpu_gtt_mgr_func;
|
||||
|
||||
ttm_resource_manager_init(man, gtt_size >> PAGE_SHIFT);
|
||||
ttm_resource_manager_init(man, &adev->mman.bdev,
|
||||
gtt_size >> PAGE_SHIFT);
|
||||
|
||||
start = AMDGPU_GTT_MAX_TRANSFER_SIZE * AMDGPU_GTT_NUM_TRANSFER_WINDOWS;
|
||||
size = (adev->gmc.gart_size >> PAGE_SHIFT) - start;
|
||||
|
@ -112,7 +112,7 @@ void amdgpu_pasid_free_delayed(struct dma_resv *resv,
|
||||
unsigned count;
|
||||
int r;
|
||||
|
||||
r = dma_resv_get_fences(resv, NULL, &count, &fences);
|
||||
r = dma_resv_get_fences(resv, true, &count, &fences);
|
||||
if (r)
|
||||
goto fallback;
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_fixed.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
@ -44,7 +44,7 @@
|
||||
#include <linux/hrtimer.h>
|
||||
#include "amdgpu_irq.h"
|
||||
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
#include "modules/inc/mod_freesync.h"
|
||||
#include "amdgpu_dm_irq_params.h"
|
||||
|
||||
|
@ -95,6 +95,7 @@ static void amdgpu_preempt_mgr_del(struct ttm_resource_manager *man,
|
||||
struct amdgpu_preempt_mgr *mgr = to_preempt_mgr(man);
|
||||
|
||||
atomic64_sub(res->num_pages, &mgr->used);
|
||||
ttm_resource_fini(man, res);
|
||||
kfree(res);
|
||||
}
|
||||
|
||||
@ -152,7 +153,7 @@ int amdgpu_preempt_mgr_init(struct amdgpu_device *adev)
|
||||
man->use_tt = true;
|
||||
man->func = &amdgpu_preempt_mgr_func;
|
||||
|
||||
ttm_resource_manager_init(man, (1 << 30));
|
||||
ttm_resource_manager_init(man, &adev->mman.bdev, (1 << 30));
|
||||
|
||||
atomic64_set(&mgr->used, 0);
|
||||
|
||||
|
@ -2087,7 +2087,7 @@ static int amdgpu_mm_vram_table_show(struct seq_file *m, void *unused)
|
||||
TTM_PL_VRAM);
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
man->func->debug(man, &p);
|
||||
ttm_resource_manager_debug(man, &p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2105,7 +2105,7 @@ static int amdgpu_mm_tt_table_show(struct seq_file *m, void *unused)
|
||||
TTM_PL_TT);
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
man->func->debug(man, &p);
|
||||
ttm_resource_manager_debug(man, &p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2116,7 +2116,7 @@ static int amdgpu_mm_gds_table_show(struct seq_file *m, void *unused)
|
||||
AMDGPU_PL_GDS);
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
man->func->debug(man, &p);
|
||||
ttm_resource_manager_debug(man, &p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2127,7 +2127,7 @@ static int amdgpu_mm_gws_table_show(struct seq_file *m, void *unused)
|
||||
AMDGPU_PL_GWS);
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
man->func->debug(man, &p);
|
||||
ttm_resource_manager_debug(man, &p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2138,7 +2138,7 @@ static int amdgpu_mm_oa_table_show(struct seq_file *m, void *unused)
|
||||
AMDGPU_PL_OA);
|
||||
struct drm_printer p = drm_seq_file_printer(m);
|
||||
|
||||
man->func->debug(man, &p);
|
||||
ttm_resource_manager_debug(man, &p);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -472,6 +472,7 @@ error_free:
|
||||
while (i--)
|
||||
drm_mm_remove_node(&node->mm_nodes[i]);
|
||||
spin_unlock(&mgr->lock);
|
||||
ttm_resource_fini(man, &node->base);
|
||||
kvfree(node);
|
||||
|
||||
error_sub:
|
||||
@ -511,6 +512,7 @@ static void amdgpu_vram_mgr_del(struct ttm_resource_manager *man,
|
||||
atomic64_sub(usage, &mgr->usage);
|
||||
atomic64_sub(vis_usage, &mgr->vis_usage);
|
||||
|
||||
ttm_resource_fini(man, res);
|
||||
kvfree(node);
|
||||
}
|
||||
|
||||
@ -689,7 +691,8 @@ int amdgpu_vram_mgr_init(struct amdgpu_device *adev)
|
||||
struct amdgpu_vram_mgr *mgr = &adev->mman.vram_mgr;
|
||||
struct ttm_resource_manager *man = &mgr->manager;
|
||||
|
||||
ttm_resource_manager_init(man, adev->gmc.real_vram_size >> PAGE_SHIFT);
|
||||
ttm_resource_manager_init(man, &adev->mman.bdev,
|
||||
adev->gmc.real_vram_size >> PAGE_SHIFT);
|
||||
|
||||
man->func = &amdgpu_vram_mgr_func;
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "atombios_dp.h"
|
||||
#include "amdgpu_connectors.h"
|
||||
#include "amdgpu_atombios.h"
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
|
||||
/* move these to drm_dp_helper.c/h */
|
||||
#define DP_LINK_CONFIGURATION_SIZE 9
|
||||
|
@ -76,7 +76,7 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_uapi.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_fourcc.h>
|
||||
#include <drm/drm_edid.h>
|
||||
@ -5856,7 +5856,7 @@ static void fill_stream_properties_from_drm_display_mode(
|
||||
else if (drm_mode_is_420_also(info, mode_in)
|
||||
&& aconnector->force_yuv420_output)
|
||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR420;
|
||||
else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||
else if ((connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR444)
|
||||
&& stream->signal == SIGNAL_TYPE_HDMI_TYPE_A)
|
||||
timing_out->pixel_encoding = PIXEL_ENCODING_YCBCR444;
|
||||
else
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_plane.h>
|
||||
|
||||
/*
|
||||
|
@ -25,8 +25,8 @@
|
||||
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include "dm_services.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm.h"
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include <dc_link.h>
|
||||
#include <inc/link_hwss.h>
|
||||
#include <inc/link_dpcd.h>
|
||||
#include "drm/drm_dp_helper.h"
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <dc_dp_types.h>
|
||||
#include "dm_helpers.h"
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
#include <drm/drm_dsc.h>
|
||||
#include "dc_hw_types.h"
|
||||
#include "dsc.h"
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include "dc.h"
|
||||
#include "rc_calc.h"
|
||||
#include "fixed31_32.h"
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include <asm/byteorder.h>
|
||||
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
|
||||
#include "cgs_common.h"
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
#ifndef __DAL_DPCD_DEFS_H__
|
||||
#define __DAL_DPCD_DEFS_H__
|
||||
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#ifndef DP_SINK_HW_REVISION_START // can remove this once the define gets into linux drm_dp_helper.h
|
||||
#define DP_SINK_HW_REVISION_START 0x409
|
||||
#endif
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "hdcp_log.h"
|
||||
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
|
||||
enum mod_hdcp_trans_input_result {
|
||||
UNKNOWN = 0,
|
||||
|
@ -1078,11 +1078,11 @@ static void d71_improc_update(struct komeda_component *c,
|
||||
mask |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;
|
||||
|
||||
/* config color format */
|
||||
if (st->color_format == DRM_COLOR_FORMAT_YCRCB420)
|
||||
if (st->color_format == DRM_COLOR_FORMAT_YCBCR420)
|
||||
ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422 | IPS_CTRL_CHD420;
|
||||
else if (st->color_format == DRM_COLOR_FORMAT_YCRCB422)
|
||||
else if (st->color_format == DRM_COLOR_FORMAT_YCBCR422)
|
||||
ctrl |= IPS_CTRL_YUV | IPS_CTRL_CHD422;
|
||||
else if (st->color_format == DRM_COLOR_FORMAT_YCRCB444)
|
||||
else if (st->color_format == DRM_COLOR_FORMAT_YCBCR444)
|
||||
ctrl |= IPS_CTRL_YUV;
|
||||
|
||||
malidp_write32_mask(reg, BLK_CONTROL, mask, ctrl);
|
||||
@ -1144,11 +1144,11 @@ static int d71_improc_init(struct d71_dev *d71,
|
||||
improc = to_improc(c);
|
||||
improc->supported_color_depths = BIT(8) | BIT(10);
|
||||
improc->supported_color_formats = DRM_COLOR_FORMAT_RGB444 |
|
||||
DRM_COLOR_FORMAT_YCRCB444 |
|
||||
DRM_COLOR_FORMAT_YCRCB422;
|
||||
DRM_COLOR_FORMAT_YCBCR444 |
|
||||
DRM_COLOR_FORMAT_YCBCR422;
|
||||
value = malidp_read32(reg, BLK_INFO);
|
||||
if (value & IPS_INFO_CHD420)
|
||||
improc->supported_color_formats |= DRM_COLOR_FORMAT_YCRCB420;
|
||||
improc->supported_color_formats |= DRM_COLOR_FORMAT_YCBCR420;
|
||||
|
||||
improc->supports_csc = true;
|
||||
improc->supports_gamma = true;
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/component.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include "komeda_dev.h"
|
||||
#include "komeda_kms.h"
|
||||
@ -198,7 +199,7 @@ static struct platform_driver komeda_platform_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(komeda_platform_driver);
|
||||
drm_module_platform_driver(komeda_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("James.Qian.Wang <james.qian.wang@arm.com>");
|
||||
MODULE_DESCRIPTION("Komeda KMS driver");
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
@ -434,7 +435,7 @@ static struct platform_driver hdlcd_platform_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(hdlcd_platform_driver);
|
||||
drm_module_platform_driver(hdlcd_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Liviu Dudau");
|
||||
MODULE_DESCRIPTION("ARM HDLCD DRM driver");
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include <drm/drm_gem_cma_helper.h>
|
||||
#include <drm/drm_gem_framebuffer_helper.h>
|
||||
#include <drm/drm_modeset_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
@ -1008,7 +1009,7 @@ static struct platform_driver malidp_platform_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
module_platform_driver(malidp_platform_driver);
|
||||
drm_module_platform_driver(malidp_platform_driver);
|
||||
|
||||
MODULE_AUTHOR("Liviu Dudau <Liviu.Dudau@arm.com>");
|
||||
MODULE_DESCRIPTION("ARM Mali DP DRM driver");
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_gem_vram_helper.h>
|
||||
#include <drm/drm_module.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "ast_drv.h"
|
||||
@ -230,22 +231,7 @@ static struct pci_driver ast_pci_driver = {
|
||||
.driver.pm = &ast_pm_ops,
|
||||
};
|
||||
|
||||
static int __init ast_init(void)
|
||||
{
|
||||
if (drm_firmware_drivers_only() && ast_modeset == -1)
|
||||
return -EINVAL;
|
||||
|
||||
if (ast_modeset == 0)
|
||||
return -EINVAL;
|
||||
return pci_register_driver(&ast_pci_driver);
|
||||
}
|
||||
static void __exit ast_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&ast_pci_driver);
|
||||
}
|
||||
|
||||
module_init(ast_init);
|
||||
module_exit(ast_exit);
|
||||
drm_module_pci_driver_if_modeset(ast_pci_driver, ast_modeset);
|
||||
|
||||
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||
|
@ -209,6 +209,8 @@ static int ast_detect_chip(struct drm_device *dev, bool *need_post)
|
||||
if (ast->chip == AST2500 &&
|
||||
scu_rev == 0x100) /* ast2510 */
|
||||
ast->support_wide_screen = true;
|
||||
if (ast->chip == AST2600) /* ast2600 */
|
||||
ast->support_wide_screen = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -471,7 +471,10 @@ static void ast_set_color_reg(struct ast_private *ast,
|
||||
static void ast_set_crtthd_reg(struct ast_private *ast)
|
||||
{
|
||||
/* Set Threshold */
|
||||
if (ast->chip == AST2300 || ast->chip == AST2400 ||
|
||||
if (ast->chip == AST2600) {
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0xe0);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0xa0);
|
||||
} else if (ast->chip == AST2300 || ast->chip == AST2400 ||
|
||||
ast->chip == AST2500) {
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa7, 0x78);
|
||||
ast_set_index_reg(ast, AST_IO_CRTC_PORT, 0xa6, 0x60);
|
||||
|
@ -30,6 +30,7 @@ config DRM_CDNS_DSI
|
||||
config DRM_CHIPONE_ICN6211
|
||||
tristate "Chipone ICN6211 MIPI-DSI/RGB Converter bridge"
|
||||
depends on OF
|
||||
depends on DRM_KMS_HELPER
|
||||
select DRM_MIPI_DSI
|
||||
select DRM_PANEL_BRIDGE
|
||||
help
|
||||
@ -183,6 +184,7 @@ config DRM_PARADE_PS8640
|
||||
tristate "Parade PS8640 MIPI DSI to eDP Converter"
|
||||
depends on OF
|
||||
select DRM_DP_AUX_BUS
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_MIPI_DSI
|
||||
select DRM_PANEL
|
||||
@ -253,6 +255,7 @@ config DRM_TOSHIBA_TC358764
|
||||
config DRM_TOSHIBA_TC358767
|
||||
tristate "Toshiba TC358767 eDP bridge"
|
||||
depends on OF
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
select DRM_PANEL
|
||||
@ -272,6 +275,7 @@ config DRM_TOSHIBA_TC358768
|
||||
config DRM_TOSHIBA_TC358775
|
||||
tristate "Toshiba TC358775 DSI/LVDS bridge"
|
||||
depends on OF
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
select DRM_PANEL
|
||||
@ -299,6 +303,7 @@ config DRM_TI_SN65DSI83
|
||||
config DRM_TI_SN65DSI86
|
||||
tristate "TI SN65DSI86 DSI to eDP bridge"
|
||||
depends on OF
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
select DRM_PANEL
|
||||
|
@ -169,6 +169,7 @@
|
||||
#define ADV7511_PACKET_ENABLE_SPARE2 BIT(1)
|
||||
#define ADV7511_PACKET_ENABLE_SPARE1 BIT(0)
|
||||
|
||||
#define ADV7535_REG_POWER2_HPD_OVERRIDE BIT(6)
|
||||
#define ADV7511_REG_POWER2_HPD_SRC_MASK 0xc0
|
||||
#define ADV7511_REG_POWER2_HPD_SRC_BOTH 0x00
|
||||
#define ADV7511_REG_POWER2_HPD_SRC_HPD 0x40
|
||||
|
@ -223,7 +223,7 @@ static void adv7511_set_config_csc(struct adv7511 *adv7511,
|
||||
config.csc_coefficents = adv7511_csc_ycbcr_to_rgb;
|
||||
|
||||
if ((connector->display_info.color_formats &
|
||||
DRM_COLOR_FORMAT_YCRCB422) &&
|
||||
DRM_COLOR_FORMAT_YCBCR422) &&
|
||||
config.hdmi_mode) {
|
||||
config.csc_enable = false;
|
||||
config.avi_infoframe.colorspace =
|
||||
@ -351,8 +351,14 @@ static void __adv7511_power_on(struct adv7511 *adv7511)
|
||||
* from standby or are enabled. When the HPD goes low the adv7511 is
|
||||
* reset and the outputs are disabled which might cause the monitor to
|
||||
* go to standby again. To avoid this we ignore the HPD pin for the
|
||||
* first few seconds after enabling the output.
|
||||
* first few seconds after enabling the output. On the other hand
|
||||
* adv7535 require to enable HPD Override bit for proper HPD.
|
||||
*/
|
||||
if (adv7511->type == ADV7535)
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
||||
ADV7535_REG_POWER2_HPD_OVERRIDE,
|
||||
ADV7535_REG_POWER2_HPD_OVERRIDE);
|
||||
else
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
||||
ADV7511_REG_POWER2_HPD_SRC_MASK,
|
||||
ADV7511_REG_POWER2_HPD_SRC_NONE);
|
||||
@ -375,6 +381,10 @@ static void adv7511_power_on(struct adv7511 *adv7511)
|
||||
static void __adv7511_power_off(struct adv7511 *adv7511)
|
||||
{
|
||||
/* TODO: setup additional power down modes */
|
||||
if (adv7511->type == ADV7535)
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
||||
ADV7535_REG_POWER2_HPD_OVERRIDE, 0);
|
||||
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER,
|
||||
ADV7511_POWER_POWER_DOWN,
|
||||
ADV7511_POWER_POWER_DOWN);
|
||||
@ -672,6 +682,11 @@ adv7511_detect(struct adv7511 *adv7511, struct drm_connector *connector)
|
||||
status = connector_status_disconnected;
|
||||
} else {
|
||||
/* Renable HPD sensing */
|
||||
if (adv7511->type == ADV7535)
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
||||
ADV7535_REG_POWER2_HPD_OVERRIDE,
|
||||
ADV7535_REG_POWER2_HPD_OVERRIDE);
|
||||
else
|
||||
regmap_update_bits(adv7511->regmap, ADV7511_REG_POWER2,
|
||||
ADV7511_REG_POWER2_HPD_SRC_MASK,
|
||||
ADV7511_REG_POWER2_HPD_SRC_BOTH);
|
||||
|
@ -29,7 +29,7 @@ static void adv7511_dsi_config_timing_gen(struct adv7511 *adv)
|
||||
struct mipi_dsi_device *dsi = adv->dsi;
|
||||
struct drm_display_mode *mode = &adv->curr_mode;
|
||||
unsigned int hsw, hfp, hbp, vsw, vfp, vbp;
|
||||
u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
|
||||
static const u8 clock_div_by_lanes[] = { 6, 4, 3 }; /* 2, 3, 4 lanes */
|
||||
|
||||
hsw = mode->hsync_end - mode->hsync_start;
|
||||
hfp = mode->hsync_start - mode->hdisplay;
|
||||
|
@ -3,6 +3,7 @@ config DRM_ANALOGIX_ANX6345
|
||||
tristate "Analogix ANX6345 bridge"
|
||||
depends on OF
|
||||
select DRM_ANALOGIX_DP
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
help
|
||||
@ -14,6 +15,7 @@ config DRM_ANALOGIX_ANX6345
|
||||
config DRM_ANALOGIX_ANX78XX
|
||||
tristate "Analogix ANX78XX bridge"
|
||||
select DRM_ANALOGIX_DP
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select REGMAP_I2C
|
||||
help
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
@ -8,7 +8,7 @@
|
||||
#include <linux/regmap.h>
|
||||
|
||||
#include <drm/drm.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "analogix-i2c-dptx.h"
|
||||
|
@ -1537,9 +1537,9 @@ static void analogix_dp_bridge_mode_set(struct drm_bridge *bridge,
|
||||
video->color_depth = COLOR_8;
|
||||
break;
|
||||
}
|
||||
if (display_info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||
if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
|
||||
video->color_space = COLOR_YCBCR444;
|
||||
else if (display_info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
|
||||
else if (display_info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
|
||||
video->color_space = COLOR_YCBCR422;
|
||||
else
|
||||
video->color_space = COLOR_RGB;
|
||||
|
@ -10,7 +10,7 @@
|
||||
#define _ANALOGIX_DP_CORE_H
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
|
||||
#define DP_TIMEOUT_LOOP_COUNT 100
|
||||
#define MAX_CR_LOOP 5
|
||||
|
@ -24,8 +24,9 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
@ -213,6 +214,65 @@ static int wait_aux_op_finish(struct anx7625_data *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int anx7625_aux_dpcd_read(struct anx7625_data *ctx,
|
||||
u32 address, u8 len, u8 *buf)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
int ret;
|
||||
u8 addrh, addrm, addrl;
|
||||
u8 cmd;
|
||||
|
||||
if (len > MAX_DPCD_BUFFER_SIZE) {
|
||||
dev_err(dev, "exceed aux buffer len.\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
addrl = address & 0xFF;
|
||||
addrm = (address >> 8) & 0xFF;
|
||||
addrh = (address >> 16) & 0xFF;
|
||||
|
||||
cmd = DPCD_CMD(len, DPCD_READ);
|
||||
cmd = ((len - 1) << 4) | 0x09;
|
||||
|
||||
/* Set command and length */
|
||||
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
AP_AUX_COMMAND, cmd);
|
||||
|
||||
/* Set aux access address */
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
AP_AUX_ADDR_7_0, addrl);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
AP_AUX_ADDR_15_8, addrm);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
AP_AUX_ADDR_19_16, addrh);
|
||||
|
||||
/* Enable aux access */
|
||||
ret |= anx7625_write_or(ctx, ctx->i2c.rx_p0_client,
|
||||
AP_AUX_CTRL_STATUS, AP_AUX_CTRL_OP_EN);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "cannot access aux related register.\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
usleep_range(2000, 2100);
|
||||
|
||||
ret = wait_aux_op_finish(ctx);
|
||||
if (ret) {
|
||||
dev_err(dev, "aux IO error: wait aux op finish.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
|
||||
AP_AUX_BUFF_START, len, buf);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "read dpcd register failed\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int anx7625_video_mute_control(struct anx7625_data *ctx,
|
||||
u8 status)
|
||||
{
|
||||
@ -669,6 +729,165 @@ static int anx7625_dpi_config(struct anx7625_data *ctx)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int anx7625_read_flash_status(struct anx7625_data *ctx)
|
||||
{
|
||||
return anx7625_reg_read(ctx, ctx->i2c.rx_p0_client, R_RAM_CTRL);
|
||||
}
|
||||
|
||||
static int anx7625_hdcp_key_probe(struct anx7625_data *ctx)
|
||||
{
|
||||
int ret, val;
|
||||
struct device *dev = &ctx->client->dev;
|
||||
u8 ident[FLASH_BUF_LEN];
|
||||
|
||||
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
FLASH_ADDR_HIGH, 0x91);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
FLASH_ADDR_LOW, 0xA0);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "IO error : set key flash address.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
FLASH_LEN_HIGH, (FLASH_BUF_LEN - 1) >> 8);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
FLASH_LEN_LOW, (FLASH_BUF_LEN - 1) & 0xFF);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "IO error : set key flash len.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
R_FLASH_RW_CTRL, FLASH_READ);
|
||||
ret |= readx_poll_timeout(anx7625_read_flash_status,
|
||||
ctx, val,
|
||||
((val & FLASH_DONE) || (val < 0)),
|
||||
2000,
|
||||
2000 * 150);
|
||||
if (ret) {
|
||||
dev_err(dev, "flash read access fail!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
ret = anx7625_reg_block_read(ctx, ctx->i2c.rx_p0_client,
|
||||
FLASH_BUF_BASE_ADDR,
|
||||
FLASH_BUF_LEN, ident);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "read flash data fail!\n");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (ident[29] == 0xFF && ident[30] == 0xFF && ident[31] == 0xFF)
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int anx7625_hdcp_key_load(struct anx7625_data *ctx)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
/* Select HDCP 1.4 KEY */
|
||||
ret = anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
R_BOOT_RETRY, 0x12);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
FLASH_ADDR_HIGH, HDCP14KEY_START_ADDR >> 8);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
FLASH_ADDR_LOW, HDCP14KEY_START_ADDR & 0xFF);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
R_RAM_LEN_H, HDCP14KEY_SIZE >> 12);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
R_RAM_LEN_L, HDCP14KEY_SIZE >> 4);
|
||||
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
R_RAM_ADDR_H, 0);
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
R_RAM_ADDR_L, 0);
|
||||
/* Enable HDCP 1.4 KEY load */
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.rx_p0_client,
|
||||
R_RAM_CTRL, DECRYPT_EN | LOAD_START);
|
||||
dev_dbg(dev, "load HDCP 1.4 key done\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int anx7625_hdcp_disable(struct anx7625_data *ctx)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
dev_dbg(dev, "disable HDCP 1.4\n");
|
||||
|
||||
/* Disable HDCP */
|
||||
ret = anx7625_write_and(ctx, ctx->i2c.rx_p1_client, 0xee, 0x9f);
|
||||
/* Try auth flag */
|
||||
ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
|
||||
/* Interrupt for DRM */
|
||||
ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "fail to disable HDCP\n");
|
||||
|
||||
return anx7625_write_and(ctx, ctx->i2c.tx_p0_client,
|
||||
TX_HDCP_CTRL0, ~HARD_AUTH_EN & 0xFF);
|
||||
}
|
||||
|
||||
static int anx7625_hdcp_enable(struct anx7625_data *ctx)
|
||||
{
|
||||
u8 bcap;
|
||||
int ret;
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
ret = anx7625_hdcp_key_probe(ctx);
|
||||
if (ret) {
|
||||
dev_dbg(dev, "no key found, not to do hdcp\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Read downstream capability */
|
||||
anx7625_aux_dpcd_read(ctx, 0x68028, 1, &bcap);
|
||||
if (!(bcap & 0x01)) {
|
||||
pr_warn("downstream not support HDCP 1.4, cap(%x).\n", bcap);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "enable HDCP 1.4\n");
|
||||
|
||||
/* First clear HDCP state */
|
||||
ret = anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
|
||||
TX_HDCP_CTRL0,
|
||||
KSVLIST_VLD | BKSV_SRM_PASS | RE_AUTHEN);
|
||||
usleep_range(1000, 1100);
|
||||
/* Second clear HDCP state */
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
|
||||
TX_HDCP_CTRL0,
|
||||
KSVLIST_VLD | BKSV_SRM_PASS | RE_AUTHEN);
|
||||
|
||||
/* Set time for waiting KSVR */
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
|
||||
SP_TX_WAIT_KSVR_TIME, 0xc8);
|
||||
/* Set time for waiting R0 */
|
||||
ret |= anx7625_reg_write(ctx, ctx->i2c.tx_p0_client,
|
||||
SP_TX_WAIT_R0_TIME, 0xb0);
|
||||
ret |= anx7625_hdcp_key_load(ctx);
|
||||
if (ret) {
|
||||
pr_warn("prepare HDCP key failed.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xee, 0x20);
|
||||
|
||||
/* Try auth flag */
|
||||
ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xec, 0x10);
|
||||
/* Interrupt for DRM */
|
||||
ret |= anx7625_write_or(ctx, ctx->i2c.rx_p1_client, 0xff, 0x01);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "fail to enable HDCP\n");
|
||||
|
||||
return anx7625_write_or(ctx, ctx->i2c.tx_p0_client,
|
||||
TX_HDCP_CTRL0, HARD_AUTH_EN);
|
||||
}
|
||||
|
||||
static void anx7625_dp_start(struct anx7625_data *ctx)
|
||||
{
|
||||
int ret;
|
||||
@ -679,6 +898,9 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable HDCP */
|
||||
anx7625_write_and(ctx, ctx->i2c.rx_p1_client, 0xee, 0x9f);
|
||||
|
||||
if (ctx->pdata.is_dpi)
|
||||
ret = anx7625_dpi_config(ctx);
|
||||
else
|
||||
@ -686,6 +908,10 @@ static void anx7625_dp_start(struct anx7625_data *ctx)
|
||||
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(dev, "MIPI phy setup error.\n");
|
||||
|
||||
ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
|
||||
ctx->dp_en = 1;
|
||||
}
|
||||
|
||||
static void anx7625_dp_stop(struct anx7625_data *ctx)
|
||||
@ -705,6 +931,10 @@ static void anx7625_dp_stop(struct anx7625_data *ctx)
|
||||
ret |= anx7625_video_mute_control(ctx, 1);
|
||||
if (ret < 0)
|
||||
DRM_DEV_ERROR(dev, "IO error : mute video fail\n");
|
||||
|
||||
ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
|
||||
ctx->dp_en = 0;
|
||||
}
|
||||
|
||||
static int sp_tx_rst_aux(struct anx7625_data *ctx)
|
||||
@ -1098,9 +1328,18 @@ static void anx7625_init_gpio(struct anx7625_data *platform)
|
||||
/* Gpio for chip power enable */
|
||||
platform->pdata.gpio_p_on =
|
||||
devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_LOW);
|
||||
if (IS_ERR_OR_NULL(platform->pdata.gpio_p_on)) {
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "no enable gpio found\n");
|
||||
platform->pdata.gpio_p_on = NULL;
|
||||
}
|
||||
|
||||
/* Gpio for chip reset */
|
||||
platform->pdata.gpio_reset =
|
||||
devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
|
||||
if (IS_ERR_OR_NULL(platform->pdata.gpio_reset)) {
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "no reset gpio found\n");
|
||||
platform->pdata.gpio_reset = NULL;
|
||||
}
|
||||
|
||||
if (platform->pdata.gpio_p_on && platform->pdata.gpio_reset) {
|
||||
platform->pdata.low_power_mode = 1;
|
||||
@ -1601,9 +1840,27 @@ static int anx7625_audio_hook_plugged_cb(struct device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int anx7625_audio_get_eld(struct device *dev, void *data,
|
||||
u8 *buf, size_t len)
|
||||
{
|
||||
struct anx7625_data *ctx = dev_get_drvdata(dev);
|
||||
|
||||
if (!ctx->connector) {
|
||||
dev_err(dev, "connector not initial\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(dev, "audio copy eld\n");
|
||||
memcpy(buf, ctx->connector->eld,
|
||||
min(sizeof(ctx->connector->eld), len));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct hdmi_codec_ops anx7625_codec_ops = {
|
||||
.hw_params = anx7625_audio_hw_params,
|
||||
.audio_shutdown = anx7625_audio_shutdown,
|
||||
.get_eld = anx7625_audio_get_eld,
|
||||
.get_dai_id = anx7625_hdmi_i2s_get_dai_id,
|
||||
.hook_plugged_cb = anx7625_audio_hook_plugged_cb,
|
||||
};
|
||||
@ -1660,7 +1917,7 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
|
||||
host = of_find_mipi_dsi_host_by_node(ctx->pdata.mipi_host_node);
|
||||
if (!host) {
|
||||
DRM_DEV_ERROR(dev, "fail to find dsi host.\n");
|
||||
return -EINVAL;
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
dsi = devm_mipi_dsi_device_register_full(dev, host, &info);
|
||||
@ -1688,6 +1945,83 @@ static int anx7625_attach_dsi(struct anx7625_data *ctx)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hdcp_check_work_func(struct work_struct *work)
|
||||
{
|
||||
u8 status;
|
||||
struct delayed_work *dwork;
|
||||
struct anx7625_data *ctx;
|
||||
struct device *dev;
|
||||
struct drm_device *drm_dev;
|
||||
|
||||
dwork = to_delayed_work(work);
|
||||
ctx = container_of(dwork, struct anx7625_data, hdcp_work);
|
||||
dev = &ctx->client->dev;
|
||||
|
||||
if (!ctx->connector) {
|
||||
dev_err(dev, "HDCP connector is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
drm_dev = ctx->connector->dev;
|
||||
drm_modeset_lock(&drm_dev->mode_config.connection_mutex, NULL);
|
||||
mutex_lock(&ctx->hdcp_wq_lock);
|
||||
|
||||
status = anx7625_reg_read(ctx, ctx->i2c.tx_p0_client, 0);
|
||||
dev_dbg(dev, "sink HDCP status check: %.02x\n", status);
|
||||
if (status & BIT(1)) {
|
||||
ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_ENABLED;
|
||||
drm_hdcp_update_content_protection(ctx->connector,
|
||||
ctx->hdcp_cp);
|
||||
dev_dbg(dev, "update CP to ENABLE\n");
|
||||
}
|
||||
|
||||
mutex_unlock(&ctx->hdcp_wq_lock);
|
||||
drm_modeset_unlock(&drm_dev->mode_config.connection_mutex);
|
||||
}
|
||||
|
||||
static int anx7625_connector_atomic_check(struct anx7625_data *ctx,
|
||||
struct drm_connector_state *state)
|
||||
{
|
||||
struct device *dev = &ctx->client->dev;
|
||||
int cp;
|
||||
|
||||
dev_dbg(dev, "hdcp state check\n");
|
||||
cp = state->content_protection;
|
||||
|
||||
if (cp == ctx->hdcp_cp)
|
||||
return 0;
|
||||
|
||||
if (cp == DRM_MODE_CONTENT_PROTECTION_DESIRED) {
|
||||
if (ctx->dp_en) {
|
||||
dev_dbg(dev, "enable HDCP\n");
|
||||
anx7625_hdcp_enable(ctx);
|
||||
|
||||
queue_delayed_work(ctx->hdcp_workqueue,
|
||||
&ctx->hdcp_work,
|
||||
msecs_to_jiffies(2000));
|
||||
}
|
||||
}
|
||||
|
||||
if (cp == DRM_MODE_CONTENT_PROTECTION_UNDESIRED) {
|
||||
if (ctx->hdcp_cp != DRM_MODE_CONTENT_PROTECTION_ENABLED) {
|
||||
dev_err(dev, "current CP is not ENABLED\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
anx7625_hdcp_disable(ctx);
|
||||
ctx->hdcp_cp = DRM_MODE_CONTENT_PROTECTION_UNDESIRED;
|
||||
drm_hdcp_update_content_protection(ctx->connector,
|
||||
ctx->hdcp_cp);
|
||||
dev_dbg(dev, "update CP to UNDESIRE\n");
|
||||
}
|
||||
|
||||
if (cp == DRM_MODE_CONTENT_PROTECTION_ENABLED) {
|
||||
dev_err(dev, "Userspace illegal set to PROTECTION ENABLE\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int anx7625_bridge_attach(struct drm_bridge *bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
@ -1902,25 +2236,57 @@ static bool anx7625_bridge_mode_fixup(struct drm_bridge *bridge,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void anx7625_bridge_enable(struct drm_bridge *bridge)
|
||||
static int anx7625_bridge_atomic_check(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *bridge_state,
|
||||
struct drm_crtc_state *crtc_state,
|
||||
struct drm_connector_state *conn_state)
|
||||
{
|
||||
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "drm enable\n");
|
||||
dev_dbg(dev, "drm bridge atomic check\n");
|
||||
|
||||
anx7625_bridge_mode_fixup(bridge, &crtc_state->mode,
|
||||
&crtc_state->adjusted_mode);
|
||||
|
||||
return anx7625_connector_atomic_check(ctx, conn_state);
|
||||
}
|
||||
|
||||
static void anx7625_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *state)
|
||||
{
|
||||
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||
struct device *dev = &ctx->client->dev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
dev_dbg(dev, "drm atomic enable\n");
|
||||
|
||||
if (!bridge->encoder) {
|
||||
dev_err(dev, "Parent encoder object not found");
|
||||
return;
|
||||
}
|
||||
|
||||
connector = drm_atomic_get_new_connector_for_encoder(state->base.state,
|
||||
bridge->encoder);
|
||||
if (!connector)
|
||||
return;
|
||||
|
||||
ctx->connector = connector;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
anx7625_dp_start(ctx);
|
||||
}
|
||||
|
||||
static void anx7625_bridge_disable(struct drm_bridge *bridge)
|
||||
static void anx7625_bridge_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old)
|
||||
{
|
||||
struct anx7625_data *ctx = bridge_to_anx7625(bridge);
|
||||
struct device *dev = &ctx->client->dev;
|
||||
|
||||
DRM_DEV_DEBUG_DRIVER(dev, "drm disable\n");
|
||||
dev_dbg(dev, "drm atomic disable\n");
|
||||
|
||||
ctx->connector = NULL;
|
||||
anx7625_dp_stop(ctx);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
@ -1950,11 +2316,14 @@ static struct edid *anx7625_bridge_get_edid(struct drm_bridge *bridge,
|
||||
|
||||
static const struct drm_bridge_funcs anx7625_bridge_funcs = {
|
||||
.attach = anx7625_bridge_attach,
|
||||
.disable = anx7625_bridge_disable,
|
||||
.mode_valid = anx7625_bridge_mode_valid,
|
||||
.mode_set = anx7625_bridge_mode_set,
|
||||
.mode_fixup = anx7625_bridge_mode_fixup,
|
||||
.enable = anx7625_bridge_enable,
|
||||
.atomic_check = anx7625_bridge_atomic_check,
|
||||
.atomic_enable = anx7625_bridge_atomic_enable,
|
||||
.atomic_disable = anx7625_bridge_atomic_disable,
|
||||
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||
.detect = anx7625_bridge_detect,
|
||||
.get_edid = anx7625_bridge_get_edid,
|
||||
};
|
||||
@ -1962,40 +2331,54 @@ static const struct drm_bridge_funcs anx7625_bridge_funcs = {
|
||||
static int anx7625_register_i2c_dummy_clients(struct anx7625_data *ctx,
|
||||
struct i2c_client *client)
|
||||
{
|
||||
int err = 0;
|
||||
|
||||
ctx->i2c.tx_p0_client = i2c_new_dummy_device(client->adapter,
|
||||
TX_P0_ADDR >> 1);
|
||||
if (!ctx->i2c.tx_p0_client)
|
||||
return -ENOMEM;
|
||||
if (IS_ERR(ctx->i2c.tx_p0_client))
|
||||
return PTR_ERR(ctx->i2c.tx_p0_client);
|
||||
|
||||
ctx->i2c.tx_p1_client = i2c_new_dummy_device(client->adapter,
|
||||
TX_P1_ADDR >> 1);
|
||||
if (!ctx->i2c.tx_p1_client)
|
||||
if (IS_ERR(ctx->i2c.tx_p1_client)) {
|
||||
err = PTR_ERR(ctx->i2c.tx_p1_client);
|
||||
goto free_tx_p0;
|
||||
}
|
||||
|
||||
ctx->i2c.tx_p2_client = i2c_new_dummy_device(client->adapter,
|
||||
TX_P2_ADDR >> 1);
|
||||
if (!ctx->i2c.tx_p2_client)
|
||||
if (IS_ERR(ctx->i2c.tx_p2_client)) {
|
||||
err = PTR_ERR(ctx->i2c.tx_p2_client);
|
||||
goto free_tx_p1;
|
||||
}
|
||||
|
||||
ctx->i2c.rx_p0_client = i2c_new_dummy_device(client->adapter,
|
||||
RX_P0_ADDR >> 1);
|
||||
if (!ctx->i2c.rx_p0_client)
|
||||
if (IS_ERR(ctx->i2c.rx_p0_client)) {
|
||||
err = PTR_ERR(ctx->i2c.rx_p0_client);
|
||||
goto free_tx_p2;
|
||||
}
|
||||
|
||||
ctx->i2c.rx_p1_client = i2c_new_dummy_device(client->adapter,
|
||||
RX_P1_ADDR >> 1);
|
||||
if (!ctx->i2c.rx_p1_client)
|
||||
if (IS_ERR(ctx->i2c.rx_p1_client)) {
|
||||
err = PTR_ERR(ctx->i2c.rx_p1_client);
|
||||
goto free_rx_p0;
|
||||
}
|
||||
|
||||
ctx->i2c.rx_p2_client = i2c_new_dummy_device(client->adapter,
|
||||
RX_P2_ADDR >> 1);
|
||||
if (!ctx->i2c.rx_p2_client)
|
||||
if (IS_ERR(ctx->i2c.rx_p2_client)) {
|
||||
err = PTR_ERR(ctx->i2c.rx_p2_client);
|
||||
goto free_rx_p1;
|
||||
}
|
||||
|
||||
ctx->i2c.tcpc_client = i2c_new_dummy_device(client->adapter,
|
||||
TCPC_INTERFACE_ADDR >> 1);
|
||||
if (!ctx->i2c.tcpc_client)
|
||||
if (IS_ERR(ctx->i2c.tcpc_client)) {
|
||||
err = PTR_ERR(ctx->i2c.tcpc_client);
|
||||
goto free_rx_p2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@ -2012,7 +2395,7 @@ free_tx_p1:
|
||||
free_tx_p0:
|
||||
i2c_unregister_device(ctx->i2c.tx_p0_client);
|
||||
|
||||
return -ENOMEM;
|
||||
return err;
|
||||
}
|
||||
|
||||
static void anx7625_unregister_i2c_dummy_clients(struct anx7625_data *ctx)
|
||||
@ -2134,6 +2517,15 @@ static int anx7625_i2c_probe(struct i2c_client *client,
|
||||
anx7625_init_gpio(platform);
|
||||
|
||||
mutex_init(&platform->lock);
|
||||
mutex_init(&platform->hdcp_wq_lock);
|
||||
|
||||
INIT_DELAYED_WORK(&platform->hdcp_work, hdcp_check_work_func);
|
||||
platform->hdcp_workqueue = create_workqueue("hdcp workqueue");
|
||||
if (!platform->hdcp_workqueue) {
|
||||
dev_err(dev, "fail to create work queue\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_platform;
|
||||
}
|
||||
|
||||
platform->pdata.intp_irq = client->irq;
|
||||
if (platform->pdata.intp_irq) {
|
||||
@ -2143,7 +2535,7 @@ static int anx7625_i2c_probe(struct i2c_client *client,
|
||||
if (!platform->workqueue) {
|
||||
DRM_DEV_ERROR(dev, "fail to create work queue\n");
|
||||
ret = -ENOMEM;
|
||||
goto free_platform;
|
||||
goto free_hdcp_wq;
|
||||
}
|
||||
|
||||
ret = devm_request_threaded_irq(dev, platform->pdata.intp_irq,
|
||||
@ -2213,6 +2605,10 @@ free_wq:
|
||||
if (platform->workqueue)
|
||||
destroy_workqueue(platform->workqueue);
|
||||
|
||||
free_hdcp_wq:
|
||||
if (platform->hdcp_workqueue)
|
||||
destroy_workqueue(platform->hdcp_workqueue);
|
||||
|
||||
free_platform:
|
||||
kfree(platform);
|
||||
|
||||
@ -2228,6 +2624,12 @@ static int anx7625_i2c_remove(struct i2c_client *client)
|
||||
if (platform->pdata.intp_irq)
|
||||
destroy_workqueue(platform->workqueue);
|
||||
|
||||
if (platform->hdcp_workqueue) {
|
||||
cancel_delayed_work(&platform->hdcp_work);
|
||||
flush_workqueue(platform->workqueue);
|
||||
destroy_workqueue(platform->workqueue);
|
||||
}
|
||||
|
||||
if (!platform->pdata.low_power_mode)
|
||||
pm_runtime_put_sync_suspend(&client->dev);
|
||||
|
||||
|
@ -59,7 +59,20 @@
|
||||
|
||||
/***************************************************************/
|
||||
/* Register definition of device address 0x70 */
|
||||
#define I2C_ADDR_70_DPTX 0x70
|
||||
#define TX_HDCP_CTRL0 0x01
|
||||
#define STORE_AN BIT(7)
|
||||
#define RX_REPEATER BIT(6)
|
||||
#define RE_AUTHEN BIT(5)
|
||||
#define SW_AUTH_OK BIT(4)
|
||||
#define HARD_AUTH_EN BIT(3)
|
||||
#define ENC_EN BIT(2)
|
||||
#define BKSV_SRM_PASS BIT(1)
|
||||
#define KSVLIST_VLD BIT(0)
|
||||
|
||||
#define SP_TX_WAIT_R0_TIME 0x40
|
||||
#define SP_TX_WAIT_KSVR_TIME 0x42
|
||||
#define SP_TX_SYS_CTRL1_REG 0x80
|
||||
#define HDCP2TX_FW_EN BIT(4)
|
||||
|
||||
#define SP_TX_LINK_BW_SET_REG 0xA0
|
||||
#define SP_TX_LANE_COUNT_SET_REG 0xA1
|
||||
@ -71,6 +84,12 @@
|
||||
#define N_VID_1 0xC4
|
||||
#define N_VID_2 0xC5
|
||||
|
||||
#define KEY_START_ADDR 0x9000
|
||||
#define KEY_RESERVED 416
|
||||
|
||||
#define HDCP14KEY_START_ADDR (KEY_START_ADDR + KEY_RESERVED)
|
||||
#define HDCP14KEY_SIZE 624
|
||||
|
||||
/***************************************************************/
|
||||
/* Register definition of device address 0x72 */
|
||||
#define AUX_RST 0x04
|
||||
@ -155,9 +174,43 @@
|
||||
|
||||
#define I2C_ADDR_7E_FLASH_CONTROLLER 0x7E
|
||||
|
||||
#define R_BOOT_RETRY 0x00
|
||||
#define R_RAM_ADDR_H 0x01
|
||||
#define R_RAM_ADDR_L 0x02
|
||||
#define R_RAM_LEN_H 0x03
|
||||
#define R_RAM_LEN_L 0x04
|
||||
#define FLASH_LOAD_STA 0x05
|
||||
#define FLASH_LOAD_STA_CHK BIT(7)
|
||||
|
||||
#define R_RAM_CTRL 0x05
|
||||
/* bit positions */
|
||||
#define FLASH_DONE BIT(7)
|
||||
#define BOOT_LOAD_DONE BIT(6)
|
||||
#define CRC_OK BIT(5)
|
||||
#define LOAD_DONE BIT(4)
|
||||
#define O_RW_DONE BIT(3)
|
||||
#define FUSE_BUSY BIT(2)
|
||||
#define DECRYPT_EN BIT(1)
|
||||
#define LOAD_START BIT(0)
|
||||
|
||||
#define FLASH_ADDR_HIGH 0x0F
|
||||
#define FLASH_ADDR_LOW 0x10
|
||||
#define FLASH_LEN_HIGH 0x31
|
||||
#define FLASH_LEN_LOW 0x32
|
||||
#define R_FLASH_RW_CTRL 0x33
|
||||
/* bit positions */
|
||||
#define READ_DELAY_SELECT BIT(7)
|
||||
#define GENERAL_INSTRUCTION_EN BIT(6)
|
||||
#define FLASH_ERASE_EN BIT(5)
|
||||
#define RDID_READ_EN BIT(4)
|
||||
#define REMS_READ_EN BIT(3)
|
||||
#define WRITE_STATUS_EN BIT(2)
|
||||
#define FLASH_READ BIT(1)
|
||||
#define FLASH_WRITE BIT(0)
|
||||
|
||||
#define FLASH_BUF_BASE_ADDR 0x60
|
||||
#define FLASH_BUF_LEN 0x20
|
||||
|
||||
#define XTAL_FRQ_SEL 0x3F
|
||||
/* bit field positions */
|
||||
#define XTAL_FRQ_SEL_POS 5
|
||||
@ -188,6 +241,11 @@
|
||||
#define PIXEL_CLOCK_H 0x26
|
||||
|
||||
#define AP_AUX_COMMAND 0x27 /* com+len */
|
||||
#define LENGTH_SHIFT 4
|
||||
#define DPCD_READ 0x09
|
||||
#define DPCD_WRITE 0x08
|
||||
#define DPCD_CMD(len, cmd) ((((len) - 1) << LENGTH_SHIFT) | (cmd))
|
||||
|
||||
/* Bit 0&1: 3D video structure */
|
||||
/* 0x01: frame packing, 0x02:Line alternative, 0x03:Side-by-side(full) */
|
||||
#define AP_AV_STATUS 0x28
|
||||
@ -392,21 +450,29 @@ struct anx7625_data {
|
||||
struct platform_device *audio_pdev;
|
||||
int hpd_status;
|
||||
int hpd_high_cnt;
|
||||
int dp_en;
|
||||
int hdcp_cp;
|
||||
/* Lock for work queue */
|
||||
struct mutex lock;
|
||||
struct i2c_client *client;
|
||||
struct anx7625_i2c_client i2c;
|
||||
struct i2c_client *last_client;
|
||||
struct timer_list hdcp_timer;
|
||||
struct s_edid_data slimport_edid_p;
|
||||
struct device *codec_dev;
|
||||
hdmi_codec_plugged_cb plugged_cb;
|
||||
struct work_struct work;
|
||||
struct workqueue_struct *workqueue;
|
||||
struct delayed_work hdcp_work;
|
||||
struct workqueue_struct *hdcp_workqueue;
|
||||
/* Lock for hdcp work queue */
|
||||
struct mutex hdcp_wq_lock;
|
||||
char edid_block;
|
||||
struct display_timing dt;
|
||||
u8 display_timing_valid;
|
||||
struct drm_bridge bridge;
|
||||
u8 bridge_attached;
|
||||
struct drm_connector *connector;
|
||||
struct mipi_dsi_device *dsi;
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
config DRM_CDNS_MHDP8546
|
||||
tristate "Cadence DPI/DP bridge"
|
||||
select DRM_DP_HELPER
|
||||
select DRM_KMS_HELPER
|
||||
select DRM_PANEL_BRIDGE
|
||||
depends on OF
|
||||
|
@ -41,7 +41,7 @@
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_hdcp.h>
|
||||
#include <drm/drm_modeset_helper_vtables.h>
|
||||
#include <drm/drm_print.h>
|
||||
@ -1553,13 +1553,13 @@ static u32 cdns_mhdp_get_bpp(struct cdns_mhdp_display_fmt *fmt)
|
||||
|
||||
switch (fmt->color_format) {
|
||||
case DRM_COLOR_FORMAT_RGB444:
|
||||
case DRM_COLOR_FORMAT_YCRCB444:
|
||||
case DRM_COLOR_FORMAT_YCBCR444:
|
||||
bpp = fmt->bpc * 3;
|
||||
break;
|
||||
case DRM_COLOR_FORMAT_YCRCB422:
|
||||
case DRM_COLOR_FORMAT_YCBCR422:
|
||||
bpp = fmt->bpc * 2;
|
||||
break;
|
||||
case DRM_COLOR_FORMAT_YCRCB420:
|
||||
case DRM_COLOR_FORMAT_YCBCR420:
|
||||
bpp = fmt->bpc * 3 / 2;
|
||||
break;
|
||||
default:
|
||||
@ -1767,8 +1767,8 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
|
||||
* If YCBCR supported and stream not SD, use ITU709
|
||||
* Need to handle ITU version with YCBCR420 when supported
|
||||
*/
|
||||
if ((pxlfmt == DRM_COLOR_FORMAT_YCRCB444 ||
|
||||
pxlfmt == DRM_COLOR_FORMAT_YCRCB422) && mode->crtc_vdisplay >= 720)
|
||||
if ((pxlfmt == DRM_COLOR_FORMAT_YCBCR444 ||
|
||||
pxlfmt == DRM_COLOR_FORMAT_YCBCR422) && mode->crtc_vdisplay >= 720)
|
||||
misc0 = DP_YCBCR_COEFFICIENTS_ITU709;
|
||||
|
||||
bpp = cdns_mhdp_get_bpp(&mhdp->display_fmt);
|
||||
@ -1778,15 +1778,15 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
|
||||
pxl_repr = CDNS_DP_FRAMER_RGB << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||
misc0 |= DP_COLOR_FORMAT_RGB;
|
||||
break;
|
||||
case DRM_COLOR_FORMAT_YCRCB444:
|
||||
case DRM_COLOR_FORMAT_YCBCR444:
|
||||
pxl_repr = CDNS_DP_FRAMER_YCBCR444 << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||
misc0 |= DP_COLOR_FORMAT_YCbCr444 | DP_TEST_DYNAMIC_RANGE_CEA;
|
||||
break;
|
||||
case DRM_COLOR_FORMAT_YCRCB422:
|
||||
case DRM_COLOR_FORMAT_YCBCR422:
|
||||
pxl_repr = CDNS_DP_FRAMER_YCBCR422 << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||
misc0 |= DP_COLOR_FORMAT_YCbCr422 | DP_TEST_DYNAMIC_RANGE_CEA;
|
||||
break;
|
||||
case DRM_COLOR_FORMAT_YCRCB420:
|
||||
case DRM_COLOR_FORMAT_YCBCR420:
|
||||
pxl_repr = CDNS_DP_FRAMER_YCBCR420 << CDNS_DP_FRAMER_PXL_FORMAT;
|
||||
break;
|
||||
default:
|
||||
@ -1882,7 +1882,7 @@ static void cdns_mhdp_configure_video(struct cdns_mhdp_device *mhdp,
|
||||
if (mhdp->display_fmt.y_only)
|
||||
misc1 |= CDNS_DP_TEST_COLOR_FORMAT_RAW_Y_ONLY;
|
||||
/* Use VSC SDP for Y420 */
|
||||
if (pxlfmt == DRM_COLOR_FORMAT_YCRCB420)
|
||||
if (pxlfmt == DRM_COLOR_FORMAT_YCBCR420)
|
||||
misc1 = CDNS_DP_TEST_VSC_SDP;
|
||||
|
||||
cdns_mhdp_reg_write(mhdp, CDNS_DP_MSA_MISC(stream_id),
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
|
||||
struct clk;
|
||||
struct device;
|
||||
|
@ -4,6 +4,7 @@
|
||||
* Author: Jagan Teki <jagan@amarulasolutions.com>
|
||||
*/
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
@ -30,6 +31,7 @@
|
||||
struct chipone {
|
||||
struct device *dev;
|
||||
struct drm_bridge bridge;
|
||||
struct drm_display_mode mode;
|
||||
struct drm_bridge *panel_bridge;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct regulator *vdd1;
|
||||
@ -42,11 +44,6 @@ static inline struct chipone *bridge_to_chipone(struct drm_bridge *bridge)
|
||||
return container_of(bridge, struct chipone, bridge);
|
||||
}
|
||||
|
||||
static struct drm_display_mode *bridge_to_mode(struct drm_bridge *bridge)
|
||||
{
|
||||
return &bridge->encoder->crtc->state->adjusted_mode;
|
||||
}
|
||||
|
||||
static inline int chipone_dsi_write(struct chipone *icn, const void *seq,
|
||||
size_t len)
|
||||
{
|
||||
@ -61,10 +58,11 @@ static inline int chipone_dsi_write(struct chipone *icn, const void *seq,
|
||||
chipone_dsi_write(icn, d, ARRAY_SIZE(d)); \
|
||||
}
|
||||
|
||||
static void chipone_enable(struct drm_bridge *bridge)
|
||||
static void chipone_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
struct drm_display_mode *mode = bridge_to_mode(bridge);
|
||||
struct drm_display_mode *mode = &icn->mode;
|
||||
|
||||
ICN6211_DSI(icn, 0x7a, 0xc1);
|
||||
|
||||
@ -114,7 +112,8 @@ static void chipone_enable(struct drm_bridge *bridge)
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static void chipone_pre_enable(struct drm_bridge *bridge)
|
||||
static void chipone_atomic_pre_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
int ret;
|
||||
@ -145,7 +144,8 @@ static void chipone_pre_enable(struct drm_bridge *bridge)
|
||||
usleep_range(10000, 11000);
|
||||
}
|
||||
|
||||
static void chipone_post_disable(struct drm_bridge *bridge)
|
||||
static void chipone_atomic_post_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
|
||||
@ -161,6 +161,15 @@ static void chipone_post_disable(struct drm_bridge *bridge)
|
||||
gpiod_set_value(icn->enable_gpio, 0);
|
||||
}
|
||||
|
||||
static void chipone_mode_set(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *mode,
|
||||
const struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
|
||||
drm_mode_copy(&icn->mode, adjusted_mode);
|
||||
}
|
||||
|
||||
static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
struct chipone *icn = bridge_to_chipone(bridge);
|
||||
@ -169,10 +178,14 @@ static int chipone_attach(struct drm_bridge *bridge, enum drm_bridge_attach_flag
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs chipone_bridge_funcs = {
|
||||
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||
.atomic_pre_enable = chipone_atomic_pre_enable,
|
||||
.atomic_enable = chipone_atomic_enable,
|
||||
.atomic_post_disable = chipone_atomic_post_disable,
|
||||
.mode_set = chipone_mode_set,
|
||||
.attach = chipone_attach,
|
||||
.post_disable = chipone_post_disable,
|
||||
.pre_enable = chipone_pre_enable,
|
||||
.enable = chipone_enable,
|
||||
};
|
||||
|
||||
static int chipone_parse_dt(struct chipone *icn)
|
||||
|
@ -936,9 +936,6 @@ static int it66121_probe(struct i2c_client *client,
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
if (!ctx->next_bridge)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
i2c_set_clientdata(client, ctx);
|
||||
mutex_init(&ctx->lock);
|
||||
|
||||
|
@ -1090,7 +1090,7 @@ static int lt9611_probe(struct i2c_client *client,
|
||||
if (!lt9611)
|
||||
return -ENOMEM;
|
||||
|
||||
lt9611->dev = &client->dev;
|
||||
lt9611->dev = dev;
|
||||
lt9611->client = client;
|
||||
lt9611->sleep = false;
|
||||
|
||||
@ -1100,7 +1100,7 @@ static int lt9611_probe(struct i2c_client *client,
|
||||
return PTR_ERR(lt9611->regmap);
|
||||
}
|
||||
|
||||
ret = lt9611_parse_dt(&client->dev, lt9611);
|
||||
ret = lt9611_parse_dt(dev, lt9611);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to parse device tree\n");
|
||||
return ret;
|
||||
|
@ -860,7 +860,7 @@ static int lt9611uxc_probe(struct i2c_client *client,
|
||||
if (!lt9611uxc)
|
||||
return -ENOMEM;
|
||||
|
||||
lt9611uxc->dev = &client->dev;
|
||||
lt9611uxc->dev = dev;
|
||||
lt9611uxc->client = client;
|
||||
mutex_init(<9611uxc->ocm_lock);
|
||||
|
||||
@ -870,7 +870,7 @@ static int lt9611uxc_probe(struct i2c_client *client,
|
||||
return PTR_ERR(lt9611uxc->regmap);
|
||||
}
|
||||
|
||||
ret = lt9611uxc_parse_dt(&client->dev, lt9611uxc);
|
||||
ret = lt9611uxc_parse_dt(dev, lt9611uxc);
|
||||
if (ret) {
|
||||
dev_err(dev, "failed to parse device tree\n");
|
||||
return ret;
|
||||
|
@ -65,7 +65,6 @@ struct nwl_dsi_transfer {
|
||||
struct nwl_dsi {
|
||||
struct drm_bridge bridge;
|
||||
struct mipi_dsi_host dsi_host;
|
||||
struct drm_bridge *panel_bridge;
|
||||
struct device *dev;
|
||||
struct phy *phy;
|
||||
union phy_configure_opts phy_cfg;
|
||||
@ -924,13 +923,11 @@ static int nwl_dsi_bridge_attach(struct drm_bridge *bridge,
|
||||
if (IS_ERR(panel_bridge))
|
||||
return PTR_ERR(panel_bridge);
|
||||
}
|
||||
dsi->panel_bridge = panel_bridge;
|
||||
|
||||
if (!dsi->panel_bridge)
|
||||
if (!panel_bridge)
|
||||
return -EPROBE_DEFER;
|
||||
|
||||
return drm_bridge_attach(bridge->encoder, dsi->panel_bridge, bridge,
|
||||
flags);
|
||||
return drm_bridge_attach(bridge->encoder, panel_bridge, bridge, flags);
|
||||
}
|
||||
|
||||
static void nwl_dsi_bridge_detach(struct drm_bridge *bridge)
|
||||
@ -1206,6 +1203,7 @@ static int nwl_dsi_probe(struct platform_device *pdev)
|
||||
|
||||
ret = nwl_dsi_select_input(dsi);
|
||||
if (ret < 0) {
|
||||
pm_runtime_disable(dev);
|
||||
mipi_dsi_host_unregister(&dsi->dsi_host);
|
||||
return ret;
|
||||
}
|
||||
|
@ -14,8 +14,8 @@
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_dp_aux_bus.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_aux_bus.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
@ -102,6 +102,7 @@ struct ps8640 {
|
||||
struct regulator_bulk_data supplies[2];
|
||||
struct gpio_desc *gpio_reset;
|
||||
struct gpio_desc *gpio_powerdown;
|
||||
struct device_link *link;
|
||||
bool pre_enabled;
|
||||
};
|
||||
|
||||
@ -456,14 +457,36 @@ static int ps8640_bridge_attach(struct drm_bridge *bridge,
|
||||
return ret;
|
||||
}
|
||||
|
||||
ps_bridge->link = device_link_add(bridge->dev->dev, dev, DL_FLAG_STATELESS);
|
||||
if (!ps_bridge->link) {
|
||||
dev_err(dev, "failed to create device link");
|
||||
ret = -EINVAL;
|
||||
goto err_devlink;
|
||||
}
|
||||
|
||||
/* Attach the panel-bridge to the dsi bridge */
|
||||
return drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge,
|
||||
ret = drm_bridge_attach(bridge->encoder, ps_bridge->panel_bridge,
|
||||
&ps_bridge->bridge, flags);
|
||||
if (ret)
|
||||
goto err_bridge_attach;
|
||||
|
||||
return 0;
|
||||
|
||||
err_bridge_attach:
|
||||
device_link_del(ps_bridge->link);
|
||||
err_devlink:
|
||||
drm_dp_aux_unregister(&ps_bridge->aux);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void ps8640_bridge_detach(struct drm_bridge *bridge)
|
||||
{
|
||||
drm_dp_aux_unregister(&bridge_to_ps8640(bridge)->aux);
|
||||
struct ps8640 *ps_bridge = bridge_to_ps8640(bridge);
|
||||
|
||||
drm_dp_aux_unregister(&ps_bridge->aux);
|
||||
if (ps_bridge->link)
|
||||
device_link_del(ps_bridge->link);
|
||||
}
|
||||
|
||||
static struct edid *ps8640_bridge_get_edid(struct drm_bridge *bridge,
|
||||
|
@ -166,10 +166,12 @@ struct sii902x {
|
||||
struct i2c_client *i2c;
|
||||
struct regmap *regmap;
|
||||
struct drm_bridge bridge;
|
||||
struct drm_bridge *next_bridge;
|
||||
struct drm_connector connector;
|
||||
struct gpio_desc *reset_gpio;
|
||||
struct i2c_mux_core *i2cmux;
|
||||
struct regulator_bulk_data supplies[2];
|
||||
bool sink_is_hdmi;
|
||||
/*
|
||||
* Mutex protects audio and video functions from interfering
|
||||
* each other, by keeping their i2c command sequences atomic.
|
||||
@ -245,10 +247,8 @@ static void sii902x_reset(struct sii902x *sii902x)
|
||||
gpiod_set_value(sii902x->reset_gpio, 0);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
sii902x_connector_detect(struct drm_connector *connector, bool force)
|
||||
static enum drm_connector_status sii902x_detect(struct sii902x *sii902x)
|
||||
{
|
||||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
||||
unsigned int status;
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
@ -261,6 +261,14 @@ sii902x_connector_detect(struct drm_connector *connector, bool force)
|
||||
connector_status_connected : connector_status_disconnected;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
sii902x_connector_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
||||
|
||||
return sii902x_detect(sii902x);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs sii902x_connector_funcs = {
|
||||
.detect = sii902x_connector_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
@ -270,42 +278,40 @@ static const struct drm_connector_funcs sii902x_connector_funcs = {
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
};
|
||||
|
||||
static int sii902x_get_modes(struct drm_connector *connector)
|
||||
static struct edid *sii902x_get_edid(struct sii902x *sii902x,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
||||
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
|
||||
struct edid *edid;
|
||||
int num = 0, ret;
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
edid = drm_get_edid(connector, sii902x->i2cmux->adapter[0]);
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
if (edid) {
|
||||
if (drm_detect_hdmi_monitor(edid))
|
||||
output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
|
||||
sii902x->sink_is_hdmi = true;
|
||||
else
|
||||
sii902x->sink_is_hdmi = false;
|
||||
}
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
return edid;
|
||||
}
|
||||
|
||||
static int sii902x_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct sii902x *sii902x = connector_to_sii902x(connector);
|
||||
struct edid *edid;
|
||||
int num = 0;
|
||||
|
||||
edid = sii902x_get_edid(sii902x, connector);
|
||||
drm_connector_update_edid_property(connector, edid);
|
||||
if (edid) {
|
||||
num = drm_add_edid_modes(connector, edid);
|
||||
kfree(edid);
|
||||
}
|
||||
|
||||
ret = drm_display_info_set_bus_formats(&connector->display_info,
|
||||
&bus_format, 1);
|
||||
if (ret)
|
||||
goto error_out;
|
||||
|
||||
ret = regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_OUTPUT_MODE, output_mode);
|
||||
if (ret)
|
||||
goto error_out;
|
||||
|
||||
ret = num;
|
||||
|
||||
error_out:
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
return ret;
|
||||
return num;
|
||||
}
|
||||
|
||||
static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
|
||||
@ -354,12 +360,16 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||
const struct drm_display_mode *adj)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
u8 output_mode = SII902X_SYS_CTRL_OUTPUT_DVI;
|
||||
struct regmap *regmap = sii902x->regmap;
|
||||
u8 buf[HDMI_INFOFRAME_SIZE(AVI)];
|
||||
struct hdmi_avi_infoframe frame;
|
||||
u16 pixel_clock_10kHz = adj->clock / 10;
|
||||
int ret;
|
||||
|
||||
if (sii902x->sink_is_hdmi)
|
||||
output_mode = SII902X_SYS_CTRL_OUTPUT_HDMI;
|
||||
|
||||
buf[0] = pixel_clock_10kHz & 0xff;
|
||||
buf[1] = pixel_clock_10kHz >> 8;
|
||||
buf[2] = drm_mode_vrefresh(adj);
|
||||
@ -375,6 +385,11 @@ static void sii902x_bridge_mode_set(struct drm_bridge *bridge,
|
||||
|
||||
mutex_lock(&sii902x->mutex);
|
||||
|
||||
ret = regmap_update_bits(sii902x->regmap, SII902X_SYS_CTRL_DATA,
|
||||
SII902X_SYS_CTRL_OUTPUT_MODE, output_mode);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = regmap_bulk_write(regmap, SII902X_TPI_VIDEO_DATA, buf, 10);
|
||||
if (ret)
|
||||
goto out;
|
||||
@ -405,13 +420,13 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge,
|
||||
enum drm_bridge_attach_flags flags)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24;
|
||||
struct drm_device *drm = bridge->dev;
|
||||
int ret;
|
||||
|
||||
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR) {
|
||||
DRM_ERROR("Fix bridge driver to make connector optional!");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR)
|
||||
return drm_bridge_attach(bridge->encoder, sii902x->next_bridge,
|
||||
bridge, flags);
|
||||
|
||||
drm_connector_helper_add(&sii902x->connector,
|
||||
&sii902x_connector_helper_funcs);
|
||||
@ -433,16 +448,38 @@ static int sii902x_bridge_attach(struct drm_bridge *bridge,
|
||||
else
|
||||
sii902x->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
|
||||
|
||||
ret = drm_display_info_set_bus_formats(&sii902x->connector.display_info,
|
||||
&bus_format, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
drm_connector_attach_encoder(&sii902x->connector, bridge->encoder);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum drm_connector_status sii902x_bridge_detect(struct drm_bridge *bridge)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
|
||||
return sii902x_detect(sii902x);
|
||||
}
|
||||
|
||||
static struct edid *sii902x_bridge_get_edid(struct drm_bridge *bridge,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct sii902x *sii902x = bridge_to_sii902x(bridge);
|
||||
|
||||
return sii902x_get_edid(sii902x, connector);
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs sii902x_bridge_funcs = {
|
||||
.attach = sii902x_bridge_attach,
|
||||
.mode_set = sii902x_bridge_mode_set,
|
||||
.disable = sii902x_bridge_disable,
|
||||
.enable = sii902x_bridge_enable,
|
||||
.detect = sii902x_bridge_detect,
|
||||
.get_edid = sii902x_bridge_get_edid,
|
||||
};
|
||||
|
||||
static int sii902x_mute(struct sii902x *sii902x, bool mute)
|
||||
@ -829,8 +866,12 @@ static irqreturn_t sii902x_interrupt(int irq, void *data)
|
||||
|
||||
mutex_unlock(&sii902x->mutex);
|
||||
|
||||
if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev)
|
||||
if ((status & SII902X_HOTPLUG_EVENT) && sii902x->bridge.dev) {
|
||||
drm_helper_hpd_irq_event(sii902x->bridge.dev);
|
||||
drm_bridge_hpd_notify(&sii902x->bridge, (status & SII902X_PLUGGED_STATUS)
|
||||
? connector_status_connected
|
||||
: connector_status_disconnected);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@ -1001,6 +1042,11 @@ static int sii902x_init(struct sii902x *sii902x)
|
||||
sii902x->bridge.funcs = &sii902x_bridge_funcs;
|
||||
sii902x->bridge.of_node = dev->of_node;
|
||||
sii902x->bridge.timings = &default_sii902x_timings;
|
||||
sii902x->bridge.ops = DRM_BRIDGE_OP_DETECT | DRM_BRIDGE_OP_EDID;
|
||||
|
||||
if (sii902x->i2c->irq > 0)
|
||||
sii902x->bridge.ops |= DRM_BRIDGE_OP_HPD;
|
||||
|
||||
drm_bridge_add(&sii902x->bridge);
|
||||
|
||||
sii902x_audio_codec_init(sii902x, dev);
|
||||
@ -1022,6 +1068,7 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
struct device *dev = &client->dev;
|
||||
struct device_node *endpoint;
|
||||
struct sii902x *sii902x;
|
||||
int ret;
|
||||
|
||||
@ -1049,6 +1096,28 @@ static int sii902x_probe(struct i2c_client *client,
|
||||
return PTR_ERR(sii902x->reset_gpio);
|
||||
}
|
||||
|
||||
endpoint = of_graph_get_endpoint_by_regs(dev->of_node, 1, -1);
|
||||
if (endpoint) {
|
||||
struct device_node *remote = of_graph_get_remote_port_parent(endpoint);
|
||||
|
||||
of_node_put(endpoint);
|
||||
if (!remote) {
|
||||
dev_err(dev, "Endpoint in port@1 unconnected\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!of_device_is_available(remote)) {
|
||||
dev_err(dev, "port@1 remote device is disabled\n");
|
||||
of_node_put(remote);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
sii902x->next_bridge = of_drm_find_bridge(remote);
|
||||
of_node_put(remote);
|
||||
if (!sii902x->next_bridge)
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
mutex_init(&sii902x->mutex);
|
||||
|
||||
sii902x->supplies[0].supply = "iovcc";
|
||||
|
@ -2120,7 +2120,7 @@ static void sii8620_init_rcp_input_dev(struct sii8620 *ctx)
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Failed to register RC device\n");
|
||||
ctx->error = ret;
|
||||
rc_free_device(ctx->rc_dev);
|
||||
rc_free_device(rc_dev);
|
||||
return;
|
||||
}
|
||||
ctx->rc_dev = rc_dev;
|
||||
|
@ -2540,7 +2540,7 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
|
||||
struct drm_display_mode *mode = &crtc_state->mode;
|
||||
u8 max_bpc = conn_state->max_requested_bpc;
|
||||
bool is_hdmi2_sink = info->hdmi.scdc.supported ||
|
||||
(info->color_formats & DRM_COLOR_FORMAT_YCRCB420);
|
||||
(info->color_formats & DRM_COLOR_FORMAT_YCBCR420);
|
||||
u32 *output_fmts;
|
||||
unsigned int i = 0;
|
||||
|
||||
@ -2594,36 +2594,36 @@ static u32 *dw_hdmi_bridge_atomic_get_output_bus_fmts(struct drm_bridge *bridge,
|
||||
*/
|
||||
|
||||
if (max_bpc >= 16 && info->bpc == 16) {
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_YUV16_1X48;
|
||||
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_RGB161616_1X48;
|
||||
}
|
||||
|
||||
if (max_bpc >= 12 && info->bpc >= 12) {
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_UYVY12_1X24;
|
||||
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_YUV12_1X36;
|
||||
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_RGB121212_1X36;
|
||||
}
|
||||
|
||||
if (max_bpc >= 10 && info->bpc >= 10) {
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_UYVY10_1X20;
|
||||
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_YUV10_1X30;
|
||||
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_RGB101010_1X30;
|
||||
}
|
||||
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB422)
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR422)
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_UYVY8_1X16;
|
||||
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCRCB444)
|
||||
if (info->color_formats & DRM_COLOR_FORMAT_YCBCR444)
|
||||
output_fmts[i++] = MEDIA_BUS_FMT_YUV8_1X24;
|
||||
|
||||
/* Default 8bit RGB fallback */
|
||||
|
@ -871,7 +871,8 @@ static void dw_mipi_dsi_clear_err(struct dw_mipi_dsi *dsi)
|
||||
dsi_write(dsi, DSI_INT_MSK1, 0);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_post_disable(struct drm_bridge *bridge)
|
||||
static void dw_mipi_dsi_bridge_post_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
const struct dw_mipi_dsi_phy_ops *phy_ops = dsi->plat_data->phy_ops;
|
||||
@ -978,7 +979,8 @@ static void dw_mipi_dsi_bridge_mode_set(struct drm_bridge *bridge,
|
||||
dw_mipi_dsi_mode_set(dsi->slave, adjusted_mode);
|
||||
}
|
||||
|
||||
static void dw_mipi_dsi_bridge_enable(struct drm_bridge *bridge)
|
||||
static void dw_mipi_dsi_bridge_atomic_enable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct dw_mipi_dsi *dsi = bridge_to_dsi(bridge);
|
||||
|
||||
@ -998,7 +1000,10 @@ dw_mipi_dsi_bridge_mode_valid(struct drm_bridge *bridge,
|
||||
enum drm_mode_status mode_status = MODE_OK;
|
||||
|
||||
if (pdata->mode_valid)
|
||||
mode_status = pdata->mode_valid(pdata->priv_data, mode);
|
||||
mode_status = pdata->mode_valid(pdata->priv_data, mode,
|
||||
dsi->mode_flags,
|
||||
dw_mipi_dsi_get_lanes(dsi),
|
||||
dsi->format);
|
||||
|
||||
return mode_status;
|
||||
}
|
||||
@ -1032,9 +1037,12 @@ static int dw_mipi_dsi_bridge_attach(struct drm_bridge *bridge,
|
||||
}
|
||||
|
||||
static const struct drm_bridge_funcs dw_mipi_dsi_bridge_funcs = {
|
||||
.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
|
||||
.atomic_reset = drm_atomic_helper_bridge_reset,
|
||||
.atomic_enable = dw_mipi_dsi_bridge_atomic_enable,
|
||||
.atomic_post_disable = dw_mipi_dsi_bridge_post_atomic_disable,
|
||||
.mode_set = dw_mipi_dsi_bridge_mode_set,
|
||||
.enable = dw_mipi_dsi_bridge_enable,
|
||||
.post_disable = dw_mipi_dsi_bridge_post_disable,
|
||||
.mode_valid = dw_mipi_dsi_bridge_mode_valid,
|
||||
.attach = dw_mipi_dsi_bridge_attach,
|
||||
};
|
||||
@ -1199,6 +1207,7 @@ __dw_mipi_dsi_probe(struct platform_device *pdev,
|
||||
ret = mipi_dsi_host_register(&dsi->dsi_host);
|
||||
if (ret) {
|
||||
dev_err(dev, "Failed to register MIPI host: %d\n", ret);
|
||||
pm_runtime_disable(dev);
|
||||
dw_mipi_dsi_debugfs_remove(dsi);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_edid.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
@ -241,7 +241,7 @@ static inline u32 TC358775_LVCFG_PCLKDIV(uint32_t val)
|
||||
}
|
||||
|
||||
#define TC358775_LVCFG_LVDLINK__MASK 0x00000002
|
||||
#define TC358775_LVCFG_LVDLINK__SHIFT 0
|
||||
#define TC358775_LVCFG_LVDLINK__SHIFT 1
|
||||
static inline u32 TC358775_LVCFG_LVDLINK(uint32_t val)
|
||||
{
|
||||
return ((val) << TC358775_LVCFG_LVDLINK__SHIFT) &
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
@ -143,6 +144,7 @@ struct sn65dsi83 {
|
||||
struct mipi_dsi_device *dsi;
|
||||
struct drm_bridge *panel_bridge;
|
||||
struct gpio_desc *enable_gpio;
|
||||
struct regulator *vcc;
|
||||
int dsi_lanes;
|
||||
bool lvds_dual_link;
|
||||
bool lvds_dual_link_even_odd_swap;
|
||||
@ -337,6 +339,12 @@ static void sn65dsi83_atomic_enable(struct drm_bridge *bridge,
|
||||
u16 val;
|
||||
int ret;
|
||||
|
||||
ret = regulator_enable(ctx->vcc);
|
||||
if (ret) {
|
||||
dev_err(ctx->dev, "Failed to enable vcc: %d\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Deassert reset */
|
||||
gpiod_set_value(ctx->enable_gpio, 1);
|
||||
usleep_range(1000, 1100);
|
||||
@ -486,11 +494,16 @@ static void sn65dsi83_atomic_disable(struct drm_bridge *bridge,
|
||||
struct drm_bridge_state *old_bridge_state)
|
||||
{
|
||||
struct sn65dsi83 *ctx = bridge_to_sn65dsi83(bridge);
|
||||
int ret;
|
||||
|
||||
/* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
|
||||
gpiod_set_value(ctx->enable_gpio, 0);
|
||||
usleep_range(10000, 11000);
|
||||
|
||||
ret = regulator_disable(ctx->vcc);
|
||||
if (ret)
|
||||
dev_err(ctx->dev, "Failed to disable vcc: %d\n", ret);
|
||||
|
||||
regcache_mark_dirty(ctx->regmap);
|
||||
}
|
||||
|
||||
@ -560,10 +573,14 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
|
||||
ctx->host_node = of_graph_get_remote_port_parent(endpoint);
|
||||
of_node_put(endpoint);
|
||||
|
||||
if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4)
|
||||
return -EINVAL;
|
||||
if (!ctx->host_node)
|
||||
return -ENODEV;
|
||||
if (ctx->dsi_lanes < 0 || ctx->dsi_lanes > 4) {
|
||||
ret = -EINVAL;
|
||||
goto err_put_node;
|
||||
}
|
||||
if (!ctx->host_node) {
|
||||
ret = -ENODEV;
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
ctx->lvds_dual_link = false;
|
||||
ctx->lvds_dual_link_even_odd_swap = false;
|
||||
@ -590,16 +607,27 @@ static int sn65dsi83_parse_dt(struct sn65dsi83 *ctx, enum sn65dsi83_model model)
|
||||
|
||||
ret = drm_of_find_panel_or_bridge(dev->of_node, 2, 0, &panel, &panel_bridge);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
goto err_put_node;
|
||||
if (panel) {
|
||||
panel_bridge = devm_drm_panel_bridge_add(dev, panel);
|
||||
if (IS_ERR(panel_bridge))
|
||||
return PTR_ERR(panel_bridge);
|
||||
if (IS_ERR(panel_bridge)) {
|
||||
ret = PTR_ERR(panel_bridge);
|
||||
goto err_put_node;
|
||||
}
|
||||
}
|
||||
|
||||
ctx->panel_bridge = panel_bridge;
|
||||
|
||||
ctx->vcc = devm_regulator_get(dev, "vcc");
|
||||
if (IS_ERR(ctx->vcc))
|
||||
return dev_err_probe(dev, PTR_ERR(ctx->vcc),
|
||||
"Failed to get supply 'vcc'\n");
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_node:
|
||||
of_node_put(ctx->host_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int sn65dsi83_host_attach(struct sn65dsi83 *ctx)
|
||||
@ -662,7 +690,8 @@ static int sn65dsi83_probe(struct i2c_client *client,
|
||||
}
|
||||
|
||||
/* Put the chip in reset, pull EN line low, and assure 10ms reset low timing. */
|
||||
ctx->enable_gpio = devm_gpiod_get(ctx->dev, "enable", GPIOD_OUT_LOW);
|
||||
ctx->enable_gpio = devm_gpiod_get_optional(ctx->dev, "enable",
|
||||
GPIOD_OUT_LOW);
|
||||
if (IS_ERR(ctx->enable_gpio))
|
||||
return PTR_ERR(ctx->enable_gpio);
|
||||
|
||||
@ -673,8 +702,10 @@ static int sn65dsi83_probe(struct i2c_client *client,
|
||||
return ret;
|
||||
|
||||
ctx->regmap = devm_regmap_init_i2c(client, &sn65dsi83_regmap_config);
|
||||
if (IS_ERR(ctx->regmap))
|
||||
return PTR_ERR(ctx->regmap);
|
||||
if (IS_ERR(ctx->regmap)) {
|
||||
ret = PTR_ERR(ctx->regmap);
|
||||
goto err_put_node;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, ctx);
|
||||
i2c_set_clientdata(client, ctx);
|
||||
@ -691,6 +722,8 @@ static int sn65dsi83_probe(struct i2c_client *client,
|
||||
|
||||
err_remove_bridge:
|
||||
drm_bridge_remove(&ctx->bridge);
|
||||
err_put_node:
|
||||
of_node_put(ctx->host_node);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,8 @@
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_bridge.h>
|
||||
#include <drm/drm_dp_aux_bus.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_aux_bus.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_mipi_dsi.h>
|
||||
#include <drm/drm_of.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
9
drivers/gpu/drm/dp/Makefile
Normal file
9
drivers/gpu/drm/dp/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
obj-$(CONFIG_DRM_DP_AUX_BUS) += drm_dp_aux_bus.o
|
||||
|
||||
drm_dp_helper-y := drm_dp.o drm_dp_dual_mode_helper.o drm_dp_helper_mod.o drm_dp_mst_topology.o
|
||||
drm_dp_helper-$(CONFIG_DRM_DP_AUX_CHARDEV) += drm_dp_aux_dev.o
|
||||
drm_dp_helper-$(CONFIG_DRM_DP_CEC) += drm_dp_cec.o
|
||||
|
||||
obj-$(CONFIG_DRM_DP_HELPER) += drm_dp_helper.o
|
@ -29,13 +29,13 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_vblank.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_panel.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
#include "drm_dp_helper_internal.h"
|
||||
|
||||
struct dp_aux_backlight {
|
||||
struct backlight_device *base;
|
@ -19,8 +19,8 @@
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#include <drm/drm_dp_aux_bus.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_aux_bus.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
|
||||
/**
|
||||
* dp_aux_ep_match() - The match function for the dp_aux_bus.
|
@ -36,11 +36,11 @@
|
||||
#include <linux/uio.h>
|
||||
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
#include "drm_dp_helper_internal.h"
|
||||
|
||||
struct drm_dp_aux_dev {
|
||||
unsigned index;
|
@ -13,7 +13,7 @@
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
|
||||
/*
|
||||
* Unfortunately it turns out that we have a chicken-and-egg situation
|
@ -28,7 +28,7 @@
|
||||
#include <linux/string.h>
|
||||
|
||||
#include <drm/drm_device.h>
|
||||
#include <drm/drm_dp_dual_mode_helper.h>
|
||||
#include <drm/dp/drm_dp_dual_mode_helper.h>
|
||||
#include <drm/drm_print.h>
|
||||
|
||||
/**
|
33
drivers/gpu/drm/dp/drm_dp_helper_internal.h
Normal file
33
drivers/gpu/drm/dp/drm_dp_helper_internal.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* SPDX-License-Identifier: MIT */
|
||||
|
||||
#ifndef DRM_DP_HELPER_INTERNAL_H
|
||||
#define DRM_DP_HELPER_INTERNAL_H
|
||||
|
||||
struct drm_dp_aux;
|
||||
|
||||
#ifdef CONFIG_DRM_DP_AUX_CHARDEV
|
||||
int drm_dp_aux_dev_init(void);
|
||||
void drm_dp_aux_dev_exit(void);
|
||||
int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
|
||||
void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
|
||||
#else
|
||||
static inline int drm_dp_aux_dev_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void drm_dp_aux_dev_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
22
drivers/gpu/drm/dp/drm_dp_helper_mod.c
Normal file
22
drivers/gpu/drm/dp/drm_dp_helper_mod.c
Normal file
@ -0,0 +1,22 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#include <linux/module.h>
|
||||
|
||||
#include "drm_dp_helper_internal.h"
|
||||
|
||||
MODULE_DESCRIPTION("DRM DisplayPort helper");
|
||||
MODULE_LICENSE("GPL and additional rights");
|
||||
|
||||
static int __init drm_dp_helper_module_init(void)
|
||||
{
|
||||
return drm_dp_aux_dev_init();
|
||||
}
|
||||
|
||||
static void __exit drm_dp_helper_module_exit(void)
|
||||
{
|
||||
/* Call exit functions from specific dp helpers here */
|
||||
drm_dp_aux_dev_exit();
|
||||
}
|
||||
|
||||
module_init(drm_dp_helper_module_init);
|
||||
module_exit(drm_dp_helper_module_exit);
|
@ -38,14 +38,14 @@
|
||||
#include <linux/math64.h>
|
||||
#endif
|
||||
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_atomic.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/drm_drv.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_probe_helper.h>
|
||||
|
||||
#include "drm_crtc_helper_internal.h"
|
||||
#include "drm_dp_helper_internal.h"
|
||||
#include "drm_dp_mst_topology_internal.h"
|
||||
|
||||
/**
|
||||
@ -4196,7 +4196,7 @@ int drm_dp_mst_hpd_irq(struct drm_dp_mst_topology_mgr *mgr, u8 *esi, bool *handl
|
||||
int ret = 0;
|
||||
int sc;
|
||||
*handled = false;
|
||||
sc = esi[0] & 0x3f;
|
||||
sc = DP_GET_SINK_COUNT(esi[0]);
|
||||
|
||||
if (sc != mgr->sink_count) {
|
||||
mgr->sink_count = sc;
|
@ -10,7 +10,7 @@
|
||||
#ifndef _DRM_DP_MST_HELPER_INTERNAL_H_
|
||||
#define _DRM_DP_MST_HELPER_INTERNAL_H_
|
||||
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include <drm/dp/drm_dp_mst_helper.h>
|
||||
|
||||
void
|
||||
drm_dp_encode_sideband_req(const struct drm_dp_sideband_msg_req_body *req,
|
535
drivers/gpu/drm/drm_buddy.c
Normal file
535
drivers/gpu/drm/drm_buddy.c
Normal file
@ -0,0 +1,535 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
/*
|
||||
* Copyright © 2021 Intel Corporation
|
||||
*/
|
||||
|
||||
#include <linux/kmemleak.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
#include <drm/drm_buddy.h>
|
||||
|
||||
static struct kmem_cache *slab_blocks;
|
||||
|
||||
static struct drm_buddy_block *drm_block_alloc(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *parent,
|
||||
unsigned int order,
|
||||
u64 offset)
|
||||
{
|
||||
struct drm_buddy_block *block;
|
||||
|
||||
BUG_ON(order > DRM_BUDDY_MAX_ORDER);
|
||||
|
||||
block = kmem_cache_zalloc(slab_blocks, GFP_KERNEL);
|
||||
if (!block)
|
||||
return NULL;
|
||||
|
||||
block->header = offset;
|
||||
block->header |= order;
|
||||
block->parent = parent;
|
||||
|
||||
BUG_ON(block->header & DRM_BUDDY_HEADER_UNUSED);
|
||||
return block;
|
||||
}
|
||||
|
||||
static void drm_block_free(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *block)
|
||||
{
|
||||
kmem_cache_free(slab_blocks, block);
|
||||
}
|
||||
|
||||
static void mark_allocated(struct drm_buddy_block *block)
|
||||
{
|
||||
block->header &= ~DRM_BUDDY_HEADER_STATE;
|
||||
block->header |= DRM_BUDDY_ALLOCATED;
|
||||
|
||||
list_del(&block->link);
|
||||
}
|
||||
|
||||
static void mark_free(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *block)
|
||||
{
|
||||
block->header &= ~DRM_BUDDY_HEADER_STATE;
|
||||
block->header |= DRM_BUDDY_FREE;
|
||||
|
||||
list_add(&block->link,
|
||||
&mm->free_list[drm_buddy_block_order(block)]);
|
||||
}
|
||||
|
||||
static void mark_split(struct drm_buddy_block *block)
|
||||
{
|
||||
block->header &= ~DRM_BUDDY_HEADER_STATE;
|
||||
block->header |= DRM_BUDDY_SPLIT;
|
||||
|
||||
list_del(&block->link);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_buddy_init - init memory manager
|
||||
*
|
||||
* @mm: DRM buddy manager to initialize
|
||||
* @size: size in bytes to manage
|
||||
* @chunk_size: minimum page size in bytes for our allocations
|
||||
*
|
||||
* Initializes the memory manager and its resources.
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, error code on failure.
|
||||
*/
|
||||
int drm_buddy_init(struct drm_buddy *mm, u64 size, u64 chunk_size)
|
||||
{
|
||||
unsigned int i;
|
||||
u64 offset;
|
||||
|
||||
if (size < chunk_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (chunk_size < PAGE_SIZE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!is_power_of_2(chunk_size))
|
||||
return -EINVAL;
|
||||
|
||||
size = round_down(size, chunk_size);
|
||||
|
||||
mm->size = size;
|
||||
mm->avail = size;
|
||||
mm->chunk_size = chunk_size;
|
||||
mm->max_order = ilog2(size) - ilog2(chunk_size);
|
||||
|
||||
BUG_ON(mm->max_order > DRM_BUDDY_MAX_ORDER);
|
||||
|
||||
mm->free_list = kmalloc_array(mm->max_order + 1,
|
||||
sizeof(struct list_head),
|
||||
GFP_KERNEL);
|
||||
if (!mm->free_list)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i <= mm->max_order; ++i)
|
||||
INIT_LIST_HEAD(&mm->free_list[i]);
|
||||
|
||||
mm->n_roots = hweight64(size);
|
||||
|
||||
mm->roots = kmalloc_array(mm->n_roots,
|
||||
sizeof(struct drm_buddy_block *),
|
||||
GFP_KERNEL);
|
||||
if (!mm->roots)
|
||||
goto out_free_list;
|
||||
|
||||
offset = 0;
|
||||
i = 0;
|
||||
|
||||
/*
|
||||
* Split into power-of-two blocks, in case we are given a size that is
|
||||
* not itself a power-of-two.
|
||||
*/
|
||||
do {
|
||||
struct drm_buddy_block *root;
|
||||
unsigned int order;
|
||||
u64 root_size;
|
||||
|
||||
root_size = rounddown_pow_of_two(size);
|
||||
order = ilog2(root_size) - ilog2(chunk_size);
|
||||
|
||||
root = drm_block_alloc(mm, NULL, order, offset);
|
||||
if (!root)
|
||||
goto out_free_roots;
|
||||
|
||||
mark_free(mm, root);
|
||||
|
||||
BUG_ON(i > mm->max_order);
|
||||
BUG_ON(drm_buddy_block_size(mm, root) < chunk_size);
|
||||
|
||||
mm->roots[i] = root;
|
||||
|
||||
offset += root_size;
|
||||
size -= root_size;
|
||||
i++;
|
||||
} while (size);
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_roots:
|
||||
while (i--)
|
||||
drm_block_free(mm, mm->roots[i]);
|
||||
kfree(mm->roots);
|
||||
out_free_list:
|
||||
kfree(mm->free_list);
|
||||
return -ENOMEM;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_init);
|
||||
|
||||
/**
|
||||
* drm_buddy_fini - tear down the memory manager
|
||||
*
|
||||
* @mm: DRM buddy manager to free
|
||||
*
|
||||
* Cleanup memory manager resources and the freelist
|
||||
*/
|
||||
void drm_buddy_fini(struct drm_buddy *mm)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < mm->n_roots; ++i) {
|
||||
WARN_ON(!drm_buddy_block_is_free(mm->roots[i]));
|
||||
drm_block_free(mm, mm->roots[i]);
|
||||
}
|
||||
|
||||
WARN_ON(mm->avail != mm->size);
|
||||
|
||||
kfree(mm->roots);
|
||||
kfree(mm->free_list);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_fini);
|
||||
|
||||
static int split_block(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *block)
|
||||
{
|
||||
unsigned int block_order = drm_buddy_block_order(block) - 1;
|
||||
u64 offset = drm_buddy_block_offset(block);
|
||||
|
||||
BUG_ON(!drm_buddy_block_is_free(block));
|
||||
BUG_ON(!drm_buddy_block_order(block));
|
||||
|
||||
block->left = drm_block_alloc(mm, block, block_order, offset);
|
||||
if (!block->left)
|
||||
return -ENOMEM;
|
||||
|
||||
block->right = drm_block_alloc(mm, block, block_order,
|
||||
offset + (mm->chunk_size << block_order));
|
||||
if (!block->right) {
|
||||
drm_block_free(mm, block->left);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mark_free(mm, block->left);
|
||||
mark_free(mm, block->right);
|
||||
|
||||
mark_split(block);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct drm_buddy_block *
|
||||
get_buddy(struct drm_buddy_block *block)
|
||||
{
|
||||
struct drm_buddy_block *parent;
|
||||
|
||||
parent = block->parent;
|
||||
if (!parent)
|
||||
return NULL;
|
||||
|
||||
if (parent->left == block)
|
||||
return parent->right;
|
||||
|
||||
return parent->left;
|
||||
}
|
||||
|
||||
static void __drm_buddy_free(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *block)
|
||||
{
|
||||
struct drm_buddy_block *parent;
|
||||
|
||||
while ((parent = block->parent)) {
|
||||
struct drm_buddy_block *buddy;
|
||||
|
||||
buddy = get_buddy(block);
|
||||
|
||||
if (!drm_buddy_block_is_free(buddy))
|
||||
break;
|
||||
|
||||
list_del(&buddy->link);
|
||||
|
||||
drm_block_free(mm, block);
|
||||
drm_block_free(mm, buddy);
|
||||
|
||||
block = parent;
|
||||
}
|
||||
|
||||
mark_free(mm, block);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_buddy_free_block - free a block
|
||||
*
|
||||
* @mm: DRM buddy manager
|
||||
* @block: block to be freed
|
||||
*/
|
||||
void drm_buddy_free_block(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *block)
|
||||
{
|
||||
BUG_ON(!drm_buddy_block_is_allocated(block));
|
||||
mm->avail += drm_buddy_block_size(mm, block);
|
||||
__drm_buddy_free(mm, block);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_free_block);
|
||||
|
||||
/**
|
||||
* drm_buddy_free_list - free blocks
|
||||
*
|
||||
* @mm: DRM buddy manager
|
||||
* @objects: input list head to free blocks
|
||||
*/
|
||||
void drm_buddy_free_list(struct drm_buddy *mm, struct list_head *objects)
|
||||
{
|
||||
struct drm_buddy_block *block, *on;
|
||||
|
||||
list_for_each_entry_safe(block, on, objects, link) {
|
||||
drm_buddy_free_block(mm, block);
|
||||
cond_resched();
|
||||
}
|
||||
INIT_LIST_HEAD(objects);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_free_list);
|
||||
|
||||
/**
|
||||
* drm_buddy_alloc_blocks - allocate power-of-two blocks
|
||||
*
|
||||
* @mm: DRM buddy manager to allocate from
|
||||
* @order: size of the allocation
|
||||
*
|
||||
* The order value here translates to:
|
||||
*
|
||||
* 0 = 2^0 * mm->chunk_size
|
||||
* 1 = 2^1 * mm->chunk_size
|
||||
* 2 = 2^2 * mm->chunk_size
|
||||
*
|
||||
* Returns:
|
||||
* allocated ptr to the &drm_buddy_block on success
|
||||
*/
|
||||
struct drm_buddy_block *
|
||||
drm_buddy_alloc_blocks(struct drm_buddy *mm, unsigned int order)
|
||||
{
|
||||
struct drm_buddy_block *block = NULL;
|
||||
unsigned int i;
|
||||
int err;
|
||||
|
||||
for (i = order; i <= mm->max_order; ++i) {
|
||||
block = list_first_entry_or_null(&mm->free_list[i],
|
||||
struct drm_buddy_block,
|
||||
link);
|
||||
if (block)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!block)
|
||||
return ERR_PTR(-ENOSPC);
|
||||
|
||||
BUG_ON(!drm_buddy_block_is_free(block));
|
||||
|
||||
while (i != order) {
|
||||
err = split_block(mm, block);
|
||||
if (unlikely(err))
|
||||
goto out_free;
|
||||
|
||||
/* Go low */
|
||||
block = block->left;
|
||||
i--;
|
||||
}
|
||||
|
||||
mark_allocated(block);
|
||||
mm->avail -= drm_buddy_block_size(mm, block);
|
||||
kmemleak_update_trace(block);
|
||||
return block;
|
||||
|
||||
out_free:
|
||||
if (i != order)
|
||||
__drm_buddy_free(mm, block);
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_alloc_blocks);
|
||||
|
||||
static inline bool overlaps(u64 s1, u64 e1, u64 s2, u64 e2)
|
||||
{
|
||||
return s1 <= e2 && e1 >= s2;
|
||||
}
|
||||
|
||||
static inline bool contains(u64 s1, u64 e1, u64 s2, u64 e2)
|
||||
{
|
||||
return s1 <= s2 && e1 >= e2;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_buddy_alloc_range - allocate range
|
||||
*
|
||||
* @mm: DRM buddy manager to allocate from
|
||||
* @blocks: output list head to add allocated blocks
|
||||
* @start: start of the allowed range for this block
|
||||
* @size: size of the allocation
|
||||
*
|
||||
* Intended for pre-allocating portions of the address space, for example to
|
||||
* reserve a block for the initial framebuffer or similar, hence the expectation
|
||||
* here is that drm_buddy_alloc_blocks() is still the main vehicle for
|
||||
* allocations, so if that's not the case then the drm_mm range allocator is
|
||||
* probably a much better fit, and so you should probably go use that instead.
|
||||
*
|
||||
* Note that it's safe to chain together multiple alloc_ranges
|
||||
* with the same blocks list
|
||||
*
|
||||
* Returns:
|
||||
* 0 on success, error code on failure.
|
||||
*/
|
||||
int drm_buddy_alloc_range(struct drm_buddy *mm,
|
||||
struct list_head *blocks,
|
||||
u64 start, u64 size)
|
||||
{
|
||||
struct drm_buddy_block *block;
|
||||
struct drm_buddy_block *buddy;
|
||||
LIST_HEAD(allocated);
|
||||
LIST_HEAD(dfs);
|
||||
u64 end;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
if (size < mm->chunk_size)
|
||||
return -EINVAL;
|
||||
|
||||
if (!IS_ALIGNED(size | start, mm->chunk_size))
|
||||
return -EINVAL;
|
||||
|
||||
if (range_overflows(start, size, mm->size))
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < mm->n_roots; ++i)
|
||||
list_add_tail(&mm->roots[i]->tmp_link, &dfs);
|
||||
|
||||
end = start + size - 1;
|
||||
|
||||
do {
|
||||
u64 block_start;
|
||||
u64 block_end;
|
||||
|
||||
block = list_first_entry_or_null(&dfs,
|
||||
struct drm_buddy_block,
|
||||
tmp_link);
|
||||
if (!block)
|
||||
break;
|
||||
|
||||
list_del(&block->tmp_link);
|
||||
|
||||
block_start = drm_buddy_block_offset(block);
|
||||
block_end = block_start + drm_buddy_block_size(mm, block) - 1;
|
||||
|
||||
if (!overlaps(start, end, block_start, block_end))
|
||||
continue;
|
||||
|
||||
if (drm_buddy_block_is_allocated(block)) {
|
||||
err = -ENOSPC;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
if (contains(start, end, block_start, block_end)) {
|
||||
if (!drm_buddy_block_is_free(block)) {
|
||||
err = -ENOSPC;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
mark_allocated(block);
|
||||
mm->avail -= drm_buddy_block_size(mm, block);
|
||||
list_add_tail(&block->link, &allocated);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!drm_buddy_block_is_split(block)) {
|
||||
err = split_block(mm, block);
|
||||
if (unlikely(err))
|
||||
goto err_undo;
|
||||
}
|
||||
|
||||
list_add(&block->right->tmp_link, &dfs);
|
||||
list_add(&block->left->tmp_link, &dfs);
|
||||
} while (1);
|
||||
|
||||
list_splice_tail(&allocated, blocks);
|
||||
return 0;
|
||||
|
||||
err_undo:
|
||||
/*
|
||||
* We really don't want to leave around a bunch of split blocks, since
|
||||
* bigger is better, so make sure we merge everything back before we
|
||||
* free the allocated blocks.
|
||||
*/
|
||||
buddy = get_buddy(block);
|
||||
if (buddy &&
|
||||
(drm_buddy_block_is_free(block) &&
|
||||
drm_buddy_block_is_free(buddy)))
|
||||
__drm_buddy_free(mm, block);
|
||||
|
||||
err_free:
|
||||
drm_buddy_free_list(mm, &allocated);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_alloc_range);
|
||||
|
||||
/**
|
||||
* drm_buddy_block_print - print block information
|
||||
*
|
||||
* @mm: DRM buddy manager
|
||||
* @block: DRM buddy block
|
||||
* @p: DRM printer to use
|
||||
*/
|
||||
void drm_buddy_block_print(struct drm_buddy *mm,
|
||||
struct drm_buddy_block *block,
|
||||
struct drm_printer *p)
|
||||
{
|
||||
u64 start = drm_buddy_block_offset(block);
|
||||
u64 size = drm_buddy_block_size(mm, block);
|
||||
|
||||
drm_printf(p, "%#018llx-%#018llx: %llu\n", start, start + size, size);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_block_print);
|
||||
|
||||
/**
|
||||
* drm_buddy_print - print allocator state
|
||||
*
|
||||
* @mm: DRM buddy manager
|
||||
* @p: DRM printer to use
|
||||
*/
|
||||
void drm_buddy_print(struct drm_buddy *mm, struct drm_printer *p)
|
||||
{
|
||||
int order;
|
||||
|
||||
drm_printf(p, "chunk_size: %lluKiB, total: %lluMiB, free: %lluMiB\n",
|
||||
mm->chunk_size >> 10, mm->size >> 20, mm->avail >> 20);
|
||||
|
||||
for (order = mm->max_order; order >= 0; order--) {
|
||||
struct drm_buddy_block *block;
|
||||
u64 count = 0, free;
|
||||
|
||||
list_for_each_entry(block, &mm->free_list[order], link) {
|
||||
BUG_ON(!drm_buddy_block_is_free(block));
|
||||
count++;
|
||||
}
|
||||
|
||||
drm_printf(p, "order-%d ", order);
|
||||
|
||||
free = count * (mm->chunk_size << order);
|
||||
if (free < SZ_1M)
|
||||
drm_printf(p, "free: %lluKiB", free >> 10);
|
||||
else
|
||||
drm_printf(p, "free: %lluMiB", free >> 20);
|
||||
|
||||
drm_printf(p, ", pages: %llu\n", count);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(drm_buddy_print);
|
||||
|
||||
static void drm_buddy_module_exit(void)
|
||||
{
|
||||
kmem_cache_destroy(slab_blocks);
|
||||
}
|
||||
|
||||
static int __init drm_buddy_module_init(void)
|
||||
{
|
||||
slab_blocks = KMEM_CACHE(drm_buddy_block, 0);
|
||||
if (!slab_blocks)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
module_init(drm_buddy_module_init);
|
||||
module_exit(drm_buddy_module_exit);
|
||||
|
||||
MODULE_DESCRIPTION("DRM Buddy Allocator");
|
||||
MODULE_LICENSE("Dual MIT/GPL");
|
@ -82,6 +82,10 @@
|
||||
* driver boot-up state too. Drivers can access this blob through
|
||||
* &drm_crtc_state.gamma_lut.
|
||||
*
|
||||
* Note that for mostly historical reasons stemming from Xorg heritage,
|
||||
* this is also used to store the color map (also sometimes color lut, CLUT
|
||||
* or color palette) for indexed formats like DRM_FORMAT_C8.
|
||||
*
|
||||
* “GAMMA_LUT_SIZE”:
|
||||
* Unsigned range property to give the size of the lookup table to be set
|
||||
* on the GAMMA_LUT property (the size depends on the underlying hardware).
|
||||
|
@ -28,36 +28,9 @@
|
||||
|
||||
#include <drm/drm_connector.h>
|
||||
#include <drm/drm_crtc.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/drm_encoder.h>
|
||||
#include <drm/drm_modes.h>
|
||||
|
||||
/* drm_dp_aux_dev.c */
|
||||
#ifdef CONFIG_DRM_DP_AUX_CHARDEV
|
||||
int drm_dp_aux_dev_init(void);
|
||||
void drm_dp_aux_dev_exit(void);
|
||||
int drm_dp_aux_register_devnode(struct drm_dp_aux *aux);
|
||||
void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux);
|
||||
#else
|
||||
static inline int drm_dp_aux_dev_init(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void drm_dp_aux_dev_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline int drm_dp_aux_register_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void drm_dp_aux_unregister_devnode(struct drm_dp_aux *aux)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* drm_probe_helper.c */
|
||||
enum drm_mode_status drm_crtc_mode_valid(struct drm_crtc *crtc,
|
||||
const struct drm_display_mode *mode);
|
||||
|
@ -12,7 +12,7 @@
|
||||
#include <linux/errno.h>
|
||||
#include <linux/byteorder/generic.h>
|
||||
#include <drm/drm_print.h>
|
||||
#include <drm/drm_dp_helper.h>
|
||||
#include <drm/dp/drm_dp_helper.h>
|
||||
#include <drm/drm_dsc.h>
|
||||
|
||||
/**
|
||||
|
@ -93,6 +93,8 @@ static int oui(u8 first, u8 second, u8 third)
|
||||
/* Non desktop display (i.e. HMD) */
|
||||
#define EDID_QUIRK_NON_DESKTOP (1 << 12)
|
||||
|
||||
#define MICROSOFT_IEEE_OUI 0xca125c
|
||||
|
||||
struct detailed_mode_closure {
|
||||
struct drm_connector *connector;
|
||||
struct edid *edid;
|
||||
@ -212,9 +214,7 @@ static const struct edid_quirk {
|
||||
|
||||
/* Windows Mixed Reality Headsets */
|
||||
EDID_QUIRK('A', 'C', 'R', 0x7fce, EDID_QUIRK_NON_DESKTOP),
|
||||
EDID_QUIRK('H', 'P', 'N', 0x3515, EDID_QUIRK_NON_DESKTOP),
|
||||
EDID_QUIRK('L', 'E', 'N', 0x0408, EDID_QUIRK_NON_DESKTOP),
|
||||
EDID_QUIRK('L', 'E', 'N', 0xb800, EDID_QUIRK_NON_DESKTOP),
|
||||
EDID_QUIRK('F', 'U', 'J', 0x1970, EDID_QUIRK_NON_DESKTOP),
|
||||
EDID_QUIRK('D', 'E', 'L', 0x7fce, EDID_QUIRK_NON_DESKTOP),
|
||||
EDID_QUIRK('S', 'E', 'C', 0x144a, EDID_QUIRK_NON_DESKTOP),
|
||||
@ -3776,7 +3776,7 @@ static int do_y420vdb_modes(struct drm_connector *connector,
|
||||
}
|
||||
|
||||
if (modes > 0)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
|
||||
return modes;
|
||||
}
|
||||
|
||||
@ -4222,6 +4222,17 @@ static bool cea_db_is_hdmi_forum_vsdb(const u8 *db)
|
||||
return oui(db[3], db[2], db[1]) == HDMI_FORUM_IEEE_OUI;
|
||||
}
|
||||
|
||||
static bool cea_db_is_microsoft_vsdb(const u8 *db)
|
||||
{
|
||||
if (cea_db_tag(db) != VENDOR_BLOCK)
|
||||
return false;
|
||||
|
||||
if (cea_db_payload_len(db) != 21)
|
||||
return false;
|
||||
|
||||
return oui(db[3], db[2], db[1]) == MICROSOFT_IEEE_OUI;
|
||||
}
|
||||
|
||||
static bool cea_db_is_vcdb(const u8 *db)
|
||||
{
|
||||
if (cea_db_tag(db) != USE_EXTENDED_TAG)
|
||||
@ -4279,7 +4290,7 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
|
||||
if (map_len == 0) {
|
||||
/* All CEA modes support ycbcr420 sampling also.*/
|
||||
hdmi->y420_cmdb_map = U64_MAX;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -4302,7 +4313,7 @@ static void drm_parse_y420cmdb_bitmap(struct drm_connector *connector,
|
||||
map |= (u64)db[2 + count] << (8 * count);
|
||||
|
||||
if (map)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB420;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCBCR420;
|
||||
|
||||
hdmi->y420_cmdb_map = map;
|
||||
}
|
||||
@ -5075,21 +5086,21 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
|
||||
|
||||
if (hdmi[6] & DRM_EDID_HDMI_DC_30) {
|
||||
dc_bpc = 10;
|
||||
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_30;
|
||||
info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_30;
|
||||
DRM_DEBUG("%s: HDMI sink does deep color 30.\n",
|
||||
connector->name);
|
||||
}
|
||||
|
||||
if (hdmi[6] & DRM_EDID_HDMI_DC_36) {
|
||||
dc_bpc = 12;
|
||||
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_36;
|
||||
info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_36;
|
||||
DRM_DEBUG("%s: HDMI sink does deep color 36.\n",
|
||||
connector->name);
|
||||
}
|
||||
|
||||
if (hdmi[6] & DRM_EDID_HDMI_DC_48) {
|
||||
dc_bpc = 16;
|
||||
info->edid_hdmi_dc_modes |= DRM_EDID_HDMI_DC_48;
|
||||
info->edid_hdmi_rgb444_dc_modes |= DRM_EDID_HDMI_DC_48;
|
||||
DRM_DEBUG("%s: HDMI sink does deep color 48.\n",
|
||||
connector->name);
|
||||
}
|
||||
@ -5104,16 +5115,9 @@ static void drm_parse_hdmi_deep_color_info(struct drm_connector *connector,
|
||||
connector->name, dc_bpc);
|
||||
info->bpc = dc_bpc;
|
||||
|
||||
/*
|
||||
* Deep color support mandates RGB444 support for all video
|
||||
* modes and forbids YCRCB422 support for all video modes per
|
||||
* HDMI 1.3 spec.
|
||||
*/
|
||||
info->color_formats = DRM_COLOR_FORMAT_RGB444;
|
||||
|
||||
/* YCRCB444 is optional according to spec. */
|
||||
if (hdmi[6] & DRM_EDID_HDMI_DC_Y444) {
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
|
||||
info->edid_hdmi_ycbcr444_dc_modes = info->edid_hdmi_rgb444_dc_modes;
|
||||
DRM_DEBUG("%s: HDMI sink does YCRCB444 in deep color.\n",
|
||||
connector->name);
|
||||
}
|
||||
@ -5149,6 +5153,25 @@ drm_parse_hdmi_vsdb_video(struct drm_connector *connector, const u8 *db)
|
||||
drm_parse_hdmi_deep_color_info(connector, db);
|
||||
}
|
||||
|
||||
/*
|
||||
* See EDID extension for head-mounted and specialized monitors, specified at:
|
||||
* https://docs.microsoft.com/en-us/windows-hardware/drivers/display/specialized-monitors-edid-extension
|
||||
*/
|
||||
static void drm_parse_microsoft_vsdb(struct drm_connector *connector,
|
||||
const u8 *db)
|
||||
{
|
||||
struct drm_display_info *info = &connector->display_info;
|
||||
u8 version = db[4];
|
||||
bool desktop_usage = db[5] & BIT(6);
|
||||
|
||||
/* Version 1 and 2 for HMDs, version 3 flags desktop usage explicitly */
|
||||
if (version == 1 || version == 2 || (version == 3 && !desktop_usage))
|
||||
info->non_desktop = true;
|
||||
|
||||
drm_dbg_kms(connector->dev, "HMD or specialized display VSDB version %u: 0x%02x\n",
|
||||
version, db[5]);
|
||||
}
|
||||
|
||||
static void drm_parse_cea_ext(struct drm_connector *connector,
|
||||
const struct edid *edid)
|
||||
{
|
||||
@ -5165,9 +5188,9 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
|
||||
/* The existence of a CEA block should imply RGB support */
|
||||
info->color_formats = DRM_COLOR_FORMAT_RGB444;
|
||||
if (edid_ext[3] & EDID_CEA_YCRCB444)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
|
||||
if (edid_ext[3] & EDID_CEA_YCRCB422)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
|
||||
|
||||
if (cea_db_offsets(edid_ext, &start, &end))
|
||||
return;
|
||||
@ -5179,6 +5202,8 @@ static void drm_parse_cea_ext(struct drm_connector *connector,
|
||||
drm_parse_hdmi_vsdb_video(connector, db);
|
||||
if (cea_db_is_hdmi_forum_vsdb(db))
|
||||
drm_parse_hdmi_forum_vsdb(connector, db);
|
||||
if (cea_db_is_microsoft_vsdb(db))
|
||||
drm_parse_microsoft_vsdb(connector, db);
|
||||
if (cea_db_is_y420cmdb(db))
|
||||
drm_parse_y420cmdb_bitmap(connector, db);
|
||||
if (cea_db_is_vcdb(db))
|
||||
@ -5333,17 +5358,13 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
|
||||
info->width_mm = edid->width_cm * 10;
|
||||
info->height_mm = edid->height_cm * 10;
|
||||
|
||||
info->non_desktop = !!(quirks & EDID_QUIRK_NON_DESKTOP);
|
||||
|
||||
drm_get_monitor_range(connector, edid);
|
||||
|
||||
DRM_DEBUG_KMS("non_desktop set to %d\n", info->non_desktop);
|
||||
|
||||
if (edid->revision < 3)
|
||||
return quirks;
|
||||
goto out;
|
||||
|
||||
if (!(edid->input & DRM_EDID_INPUT_DIGITAL))
|
||||
return quirks;
|
||||
goto out;
|
||||
|
||||
drm_parse_cea_ext(connector, edid);
|
||||
|
||||
@ -5363,7 +5384,7 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
|
||||
|
||||
/* Only defined for 1.4 with digital displays */
|
||||
if (edid->revision < 4)
|
||||
return quirks;
|
||||
goto out;
|
||||
|
||||
switch (edid->input & DRM_EDID_DIGITAL_DEPTH_MASK) {
|
||||
case DRM_EDID_DIGITAL_DEPTH_6:
|
||||
@ -5395,17 +5416,25 @@ u32 drm_add_display_info(struct drm_connector *connector, const struct edid *edi
|
||||
|
||||
info->color_formats |= DRM_COLOR_FORMAT_RGB444;
|
||||
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB444)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB444;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCBCR444;
|
||||
if (edid->features & DRM_EDID_FEATURE_RGB_YCRCB422)
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCRCB422;
|
||||
info->color_formats |= DRM_COLOR_FORMAT_YCBCR422;
|
||||
|
||||
drm_update_mso(connector, edid);
|
||||
|
||||
out:
|
||||
if (quirks & EDID_QUIRK_NON_DESKTOP) {
|
||||
drm_dbg_kms(connector->dev, "Non-desktop display%s\n",
|
||||
info->non_desktop ? " (redundant quirk)" : "");
|
||||
info->non_desktop = true;
|
||||
}
|
||||
|
||||
return quirks;
|
||||
}
|
||||
|
||||
static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *dev,
|
||||
struct displayid_detailed_timings_1 *timings)
|
||||
struct displayid_detailed_timings_1 *timings,
|
||||
bool type_7)
|
||||
{
|
||||
struct drm_display_mode *mode;
|
||||
unsigned pixel_clock = (timings->pixel_clock[0] |
|
||||
@ -5426,7 +5455,8 @@ static struct drm_display_mode *drm_mode_displayid_detailed(struct drm_device *d
|
||||
if (!mode)
|
||||
return NULL;
|
||||
|
||||
mode->clock = pixel_clock * 10;
|
||||
/* resolution is kHz for type VII, and 10 kHz for type I */
|
||||
mode->clock = type_7 ? pixel_clock : pixel_clock * 10;
|
||||
mode->hdisplay = hactive;
|
||||
mode->hsync_start = mode->hdisplay + hsync;
|
||||
mode->hsync_end = mode->hsync_start + hsync_width;
|
||||
@ -5457,6 +5487,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector,
|
||||
int num_timings;
|
||||
struct drm_display_mode *newmode;
|
||||
int num_modes = 0;
|
||||
bool type_7 = block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING;
|
||||
/* blocks must be multiple of 20 bytes length */
|
||||
if (block->num_bytes % 20)
|
||||
return 0;
|
||||
@ -5465,7 +5496,7 @@ static int add_displayid_detailed_1_modes(struct drm_connector *connector,
|
||||
for (i = 0; i < num_timings; i++) {
|
||||
struct displayid_detailed_timings_1 *timings = &det->timings[i];
|
||||
|
||||
newmode = drm_mode_displayid_detailed(connector->dev, timings);
|
||||
newmode = drm_mode_displayid_detailed(connector->dev, timings, type_7);
|
||||
if (!newmode)
|
||||
continue;
|
||||
|
||||
@ -5484,7 +5515,8 @@ static int add_displayid_detailed_modes(struct drm_connector *connector,
|
||||
|
||||
displayid_iter_edid_begin(edid, &iter);
|
||||
displayid_iter_for_each(block, &iter) {
|
||||
if (block->tag == DATA_BLOCK_TYPE_1_DETAILED_TIMING)
|
||||
if (block->tag == DATA_BLOCK_TYPE_1_DETAILED_TIMING ||
|
||||
block->tag == DATA_BLOCK_2_TYPE_7_DETAILED_TIMING)
|
||||
num_modes += add_displayid_detailed_1_modes(connector, block);
|
||||
}
|
||||
displayid_iter_end(&iter);
|
||||
@ -5652,7 +5684,7 @@ static bool is_hdmi2_sink(const struct drm_connector *connector)
|
||||
return true;
|
||||
|
||||
return connector->display_info.hdmi.scdc.supported ||
|
||||
connector->display_info.color_formats & DRM_COLOR_FORMAT_YCRCB420;
|
||||
connector->display_info.color_formats & DRM_COLOR_FORMAT_YCBCR420;
|
||||
}
|
||||
|
||||
static inline bool is_eotf_supported(u8 output_eotf, u8 sink_eotf)
|
||||
@ -5891,13 +5923,13 @@ static const u32 hdmi_colorimetry_val[] = {
|
||||
#undef ACE
|
||||
|
||||
/**
|
||||
* drm_hdmi_avi_infoframe_colorspace() - fill the HDMI AVI infoframe
|
||||
* colorspace information
|
||||
* drm_hdmi_avi_infoframe_colorimetry() - fill the HDMI AVI infoframe
|
||||
* colorimetry information
|
||||
* @frame: HDMI AVI infoframe
|
||||
* @conn_state: connector state
|
||||
*/
|
||||
void
|
||||
drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
|
||||
drm_hdmi_avi_infoframe_colorimetry(struct hdmi_avi_infoframe *frame,
|
||||
const struct drm_connector_state *conn_state)
|
||||
{
|
||||
u32 colorimetry_val;
|
||||
@ -5916,7 +5948,7 @@ drm_hdmi_avi_infoframe_colorspace(struct hdmi_avi_infoframe *frame,
|
||||
frame->extended_colorimetry = (colorimetry_val >> 2) &
|
||||
EXTENDED_COLORIMETRY_MASK;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorspace);
|
||||
EXPORT_SYMBOL(drm_hdmi_avi_infoframe_colorimetry);
|
||||
|
||||
/**
|
||||
* drm_hdmi_avi_infoframe_quant_range() - fill the HDMI AVI infoframe
|
||||
|
@ -61,17 +61,3 @@ MODULE_PARM_DESC(edid_firmware,
|
||||
"DEPRECATED. Use drm.edid_firmware module parameter instead.");
|
||||
|
||||
#endif
|
||||
|
||||
static int __init drm_kms_helper_init(void)
|
||||
{
|
||||
return drm_dp_aux_dev_init();
|
||||
}
|
||||
|
||||
static void __exit drm_kms_helper_exit(void)
|
||||
{
|
||||
/* Call exit functions from specific kms helpers here */
|
||||
drm_dp_aux_dev_exit();
|
||||
}
|
||||
|
||||
module_init(drm_kms_helper_init);
|
||||
module_exit(drm_kms_helper_exit);
|
||||
|
@ -202,17 +202,13 @@ static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane
|
||||
|
||||
memcpy(formats_ptr(blob_data), plane->format_types, formats_size);
|
||||
|
||||
/* If we can't determine support, just bail */
|
||||
if (!plane->funcs->format_mod_supported)
|
||||
goto done;
|
||||
|
||||
mod = modifiers_ptr(blob_data);
|
||||
for (i = 0; i < plane->modifier_count; i++) {
|
||||
for (j = 0; j < plane->format_count; j++) {
|
||||
if (plane->funcs->format_mod_supported(plane,
|
||||
if (!plane->funcs->format_mod_supported ||
|
||||
plane->funcs->format_mod_supported(plane,
|
||||
plane->format_types[j],
|
||||
plane->modifiers[i])) {
|
||||
|
||||
mod->formats |= 1ULL << j;
|
||||
}
|
||||
}
|
||||
@ -223,7 +219,6 @@ static int create_in_format_blob(struct drm_device *dev, struct drm_plane *plane
|
||||
mod++;
|
||||
}
|
||||
|
||||
done:
|
||||
drm_object_attach_property(&plane->base, config->modifiers_property,
|
||||
blob->base.id);
|
||||
|
||||
|
@ -387,7 +387,8 @@ static void drm_privacy_screen_device_release(struct device *dev)
|
||||
* * An ERR_PTR(errno) on failure.
|
||||
*/
|
||||
struct drm_privacy_screen *drm_privacy_screen_register(
|
||||
struct device *parent, const struct drm_privacy_screen_ops *ops)
|
||||
struct device *parent, const struct drm_privacy_screen_ops *ops,
|
||||
void *data)
|
||||
{
|
||||
struct drm_privacy_screen *priv;
|
||||
int ret;
|
||||
@ -404,6 +405,7 @@ struct drm_privacy_screen *drm_privacy_screen_register(
|
||||
priv->dev.parent = parent;
|
||||
priv->dev.release = drm_privacy_screen_device_release;
|
||||
dev_set_name(&priv->dev, "privacy_screen-%s", dev_name(parent));
|
||||
priv->drvdata = data;
|
||||
priv->ops = ops;
|
||||
|
||||
priv->ops->get_hw_state(priv);
|
||||
@ -439,6 +441,7 @@ void drm_privacy_screen_unregister(struct drm_privacy_screen *priv)
|
||||
mutex_unlock(&drm_privacy_screen_devs_lock);
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
priv->drvdata = NULL;
|
||||
priv->ops = NULL;
|
||||
mutex_unlock(&priv->lock);
|
||||
|
||||
|
@ -50,6 +50,13 @@ static bool __init detect_thinkpad_privacy_screen(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN)
|
||||
static bool __init detect_chromeos_privacy_screen(void)
|
||||
{
|
||||
return acpi_dev_present("GOOG0010", NULL, -1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct arch_init_data arch_init_data[] __initconst = {
|
||||
#if IS_ENABLED(CONFIG_THINKPAD_ACPI)
|
||||
{
|
||||
@ -61,6 +68,16 @@ static const struct arch_init_data arch_init_data[] __initconst = {
|
||||
.detect = detect_thinkpad_privacy_screen,
|
||||
},
|
||||
#endif
|
||||
#if IS_ENABLED(CONFIG_CHROMEOS_PRIVACY_SCREEN)
|
||||
{
|
||||
.lookup = {
|
||||
.dev_id = NULL,
|
||||
.con_id = NULL,
|
||||
.provider = "privacy_screen-GOOG0010:00",
|
||||
},
|
||||
.detect = detect_chromeos_privacy_screen,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
void __init drm_privacy_screen_lookup_init(void)
|
||||
|
@ -189,8 +189,7 @@ static int submit_fence_sync(struct etnaviv_gem_submit *submit)
|
||||
continue;
|
||||
|
||||
if (bo->flags & ETNA_SUBMIT_BO_WRITE) {
|
||||
ret = dma_resv_get_fences(robj, NULL,
|
||||
&bo->nr_shared,
|
||||
ret = dma_resv_get_fences(robj, true, &bo->nr_shared,
|
||||
&bo->shared);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
@ -66,6 +66,7 @@ config DRM_EXYNOS_DP
|
||||
bool "Exynos specific extensions for Analogix DP driver"
|
||||
depends on DRM_EXYNOS_FIMD || DRM_EXYNOS7_DECON
|
||||
select DRM_ANALOGIX_DP
|
||||
select DRM_DP_HELPER
|
||||
default DRM_EXYNOS
|
||||
select DRM_PANEL
|
||||
help
|
||||
|
@ -258,6 +258,7 @@ struct exynos_dsi {
|
||||
struct list_head bridge_chain;
|
||||
struct drm_bridge *out_bridge;
|
||||
struct device *dev;
|
||||
struct drm_display_mode mode;
|
||||
|
||||
void __iomem *reg_base;
|
||||
struct phy *phy;
|
||||
@ -881,7 +882,7 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
|
||||
|
||||
static void exynos_dsi_set_display_mode(struct exynos_dsi *dsi)
|
||||
{
|
||||
struct drm_display_mode *m = &dsi->encoder.crtc->state->adjusted_mode;
|
||||
struct drm_display_mode *m = &dsi->mode;
|
||||
unsigned int num_bits_resol = dsi->driver_data->num_bits_resol;
|
||||
u32 reg;
|
||||
|
||||
@ -1446,6 +1447,15 @@ static void exynos_dsi_disable(struct drm_encoder *encoder)
|
||||
pm_runtime_put_sync(dsi->dev);
|
||||
}
|
||||
|
||||
static void exynos_dsi_mode_set(struct drm_encoder *encoder,
|
||||
struct drm_display_mode *mode,
|
||||
struct drm_display_mode *adjusted_mode)
|
||||
{
|
||||
struct exynos_dsi *dsi = encoder_to_dsi(encoder);
|
||||
|
||||
drm_mode_copy(&dsi->mode, adjusted_mode);
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
exynos_dsi_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
@ -1513,6 +1523,7 @@ static int exynos_dsi_create_connector(struct drm_encoder *encoder)
|
||||
static const struct drm_encoder_helper_funcs exynos_dsi_encoder_helper_funcs = {
|
||||
.enable = exynos_dsi_enable,
|
||||
.disable = exynos_dsi_disable,
|
||||
.mode_set = exynos_dsi_mode_set,
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user